Squiz Matrix  4.12.2
 All Data Structures Namespaces Functions Variables Pages
DALQueryParser.inc
1 <?php
13 require_once 'DAL/Exceptions/DALParserException.inc';
14 require_once 'DAL/Parsers/DALSelectParser.inc';
15 require_once 'DAL/Parsers/DALFromParser.inc';
16 require_once 'DAL/Parsers/DALAlterParser.inc';
17 require_once 'DAL/Parsers/DALSchemaParser.inc';
18 require_once 'DAL/Parsers/DALWithParser.inc';
19 require_once 'DAL/Parsers/DALDeleteParser.inc';
20 require_once 'DAL/Parsers/DALDropParser.inc';
21 require_once 'DAL/Parsers/DALInsertParser.inc';
22 require_once 'DAL/Parsers/DALUpdateParser.inc';
23 require_once 'DAL/Parsers/DALWhereParser.inc';
24 require_once 'DAL/Parsers/DALGroupByParser.inc';
25 require_once 'DAL/Parsers/DALOrderByParser.inc';
26 require_once 'DAL/Parsers/DALTruncateParser.inc';
27 require_once 'DAL/Parsers/DALUnionParser.inc';
28 require_once 'DAL/DALBaker.inc';
29 require_once 'XML/XML.inc';
30 
39 {
40 
41 
50  private function __construct()
51  {
52 
53  }//end __construct()
54 
55 
69  public static function parse(DomElement $query)
70  {
71  $firstChild = $query->firstChild;
72  if ($firstChild === NULL) {
73  throw new DALParserException('Invalid query element.');
74  }
75 
76  foreach ($query->childNodes as $childNode) {
77  if ($childNode->nodeType === XML_ELEMENT_NODE) {
78  $type = $childNode->tagName;
79  break;
80  }
81  }
82 
83  $sqlArray = array();
84 
85  switch ($type) {
86  case 'select' :
88  $sql = DALSelectParser::parse($query);
89  break;
90  case 'insert' :
92  $sql = DALInsertParser::parse($query);
93  break;
94  case 'update' :
96  $sql = DALUpdateParser::parse($query);
97  break;
98  case 'delete' :
100  $sql = DALDeleteParser::parse($query);
101  break;
102  case 'truncate' :
104  $sql = DALTruncateParser::parse($query);
105  break;
106  case 'union' :
107  case 'union-all' :
108  DALUnionParser::validate($query);
109  $sql = DALUnionParser::parse($query);
110  break;
111  case 'alter' :
112  DALAlterParser::validate($query);
113  $sql = DALAlterParser::parse($query);
114  break;
115  case 'drop' :
116  DALDropParser::validate($query);
117  $sql = DALDropParser::parse($query);
118  break;
119  case 'function' :
120  $function = $query->getElementsByTagName('function')->item(0);
121  self::validateFunctionTag($function);
122  $sql = self::parseSqlFunction($function);
123  break;
124  case 'with' :
125  DALWithParser::validate($query);
126  $sql = DALWithParser::parse($query);
127  break;
128  case 'call' :
129  $sql = self::parseCallQuery($query);
130  break;
131  case 'where' :
132  $sql = DALWhereParser::parse($query);
133  $sql = current($sql);
134  break;
135  case 'from' :
136  $sql = DALFromParser::parse($query);
137  break;
138 
139  default:
140  throw new DALParserException('Invalid query type:'.$type);
141  break;
142  }//end switch
143 
144  // Add Query type.
145  if (is_array($sql) === TRUE) {
146  $sqlArray['query'] = $sql;
147  $aliases = array();
148  self::_convertAliases($sqlArray['query'], $aliases);
149  $sqlArray['query_type'] = $type;
150  }
151 
152  return $sqlArray;
153 
154  }//end parse()
155 
156 
168  private static function _convertAliases(array &$sqlArray, array &$aliases)
169  {
170  $vars = array();
171  foreach ($sqlArray as $key => $value) {
172  if (is_array($value) === FALSE) {
173  continue;
174  }
175 
176  if (isset($value['alias']) === TRUE) {
177  $clonedArray = array();
178  $clonedArray = array_merge($clonedArray, $sqlArray);
179  unset($clonedArray[$key]['alias']);
180  $aliases[$value['alias']] = $clonedArray;
181  }
182 
183  if (array_key_exists('isalias', $value) === TRUE) {
184  $sqlArray[$key] = $aliases[$value['name']];
185  }
186 
187  if (is_array($value) === TRUE) {
188  self::_convertAliases($sqlArray[$key], $aliases);
189  }
190  }
191 
192  }//end _convertAliases()
193 
194 
211  protected static function parseLimitClause(DomElement $select)
212  {
213  $query = array();
214  $limit = $select->getElementsByTagName('limit')->item(0);
215  if ($limit !== NULL) {
216  $query['LIMIT'] = array();
217  $query['LIMIT']['rows'] = $limit->nodeValue;
218  $query['LIMIT']['offset'] = $limit->getAttribute('offset');
219  }
220 
221  return $query;
222 
223  }//end parseLimitClause()
224 
225 
247  protected static function parseInClause(DomElement $inCond, $level=0)
248  {
249  $conditions = array();
250  if ($inCond !== NULL) {
251  $type = strtoupper($inCond->tagName);
252 
253  $conditions[$type] = array();
254  $conditions[$type]['table'] = $inCond->getAttribute('table');
255  $conditions[$type]['column'] = $inCond->getAttribute('column');
256  $conditions[$type]['CONDITIONS'] = array();
257 
258  // Check if this IN statement is using inner select.
259  $select = $inCond->getElementsByTagName('select')->item(0);
260  if ($select === NULL) {
261  // Must be using values.
262  // There could be a single value with no value tag.
263  if (XML::hasChildElements($inCond) === FALSE) {
264  $conditions[$type]['CONDITIONS'][] = $inCond->nodeValue;
265  } else {
266  foreach ($inCond->childNodes as $child) {
267  if ($child->nodeType === XML_ELEMENT_NODE) {
268  $val = self::parseSingleField($child);
269  // Add field value to the list.
270  $conditions[$type]['CONDITIONS'][] = $val;
271  }
272  }
273  }
274  } else {
275  // Inner Select.
276  $conditions[$type]['CONDITIONS'] = DALSelectParser::parse($select);
277  }
278  }//end if
279 
280  return $conditions;
281 
282  }//end parseInClause()
283 
284 
302  protected static function parseExistsClause(DomElement $existsCond, $level=0)
303  {
304  $conditions = array();
305  if ($existsCond !== NULL) {
306  $type = strtoupper($existsCond->tagName);
307  $select = $existsCond->getElementsByTagName('select')->item(0);
308 
309  if ($select !== NULL) {
310  // Parse the inner select for this exists clause...
311  $conditions[$type] = array(
312  'CONDITIONS' => DALSelectParser::parse($select),
313  );
314  }
315  }
316 
317  return $conditions;
318 
319  }//end parseExistsClause()
320 
321 
330  public static function parseCallQuery(DomElement $call)
331  {
332  $query = array();
333  $query['CALL'] = array();
334 
335  // Get the function tag.
336  $function = $call->getElementsByTagName('function')->item(0);
337  $query['CALL'] = self::parseSqlFunction($function);
338 
339  return $query;
340 
341  }//end parseCallQuery()
342 
343 
354  protected static function parseChildFields(DomElement $parent)
355  {
356  $fields = array();
357  foreach ($parent->childNodes as $field) {
358  if ($field->nodeType !== XML_ELEMENT_NODE) {
359  continue;
360  }
361 
362  $newField = self::parseSingleField($field);
363  if ($newField !== FALSE) {
364  $fields[] = $newField;
365  }
366  }//end foreach
367 
368  return $fields;
369 
370  }//end parseChildFields()
371 
372 
384  protected static function parseSingleField(DomElement $fieldXML)
385  {
386  $field = FALSE;
387  if ($fieldXML->tagName === 'field') {
388  $field = array();
389  $field['table'] = $fieldXML->getAttribute('table');
390  $field['column'] = $fieldXML->getAttribute('column');
391  if ($fieldXML->nodeValue !== '') {
392  $field['alias'] = $fieldXML->nodeValue;
393  }
394  } else if ($fieldXML->tagName === 'value') {
395  $nodeValue = $fieldXML->nodeValue;
396  if ($fieldXML->getAttribute('type') === 'integer') {
397  $nodeValue = (int)$nodeValue;
398  }
399 
400  if ($fieldXML->getAttribute('alias') === '') {
401  $field = $nodeValue;
402  } else {
403  $field = array();
404  $field['alias'] = $fieldXML->getAttribute('alias');
405  $field['value'] = $nodeValue;
406  }
407  } else if ($fieldXML->tagName === 'alias') {
408  $field = array();
409  $field['name'] = $fieldXML->getAttribute('name');
410  $field['isalias'] = TRUE;
411  } else if ($fieldXML->tagName === 'literal') {
412  $field = $fieldXML->nodeValue;
413  } else if ($fieldXML->tagName === 'function') {
414  $field = self::parseSqlFunction($fieldXML);
415  } else if ($fieldXML->tagName === 'hook') {
416  $field = DALBaker::getHookPrefix().$fieldXML->getAttribute('id');
417  } else if ($fieldXML->tagName === 'math-op') {
418  $field = self::parseMathOperation($fieldXML);
419  } else if ($fieldXML->tagName === 'select') {
420  $field = DALSelectParser::parse($fieldXML);
421  }//end if
422 
423  return $field;
424 
425  }//end parseSingleField()
426 
427 
437  protected static function parseMathOperation(DomElement $parent, $op='MATH-OP')
438  {
439  $query = array();
440  $query[$op] = array();
441  if (($op === 'MATH-OP') && ($parent->getAttribute('alias') !== '')) {
442  $query[$op]['alias'] = $parent->getAttribute('alias');
443  }
444 
445  foreach ($parent->childNodes as $node) {
446  if ($node->nodeType === XML_ELEMENT_NODE) {
447  switch ($node->tagName) {
448  case 'add' :
449  case 'divide' :
450  case 'subtract':
451  case 'multiply':
452  $query[$op][] = self::parseMathOperation($node, strtoupper($node->tagName));
453  break;
454  default :
455  if ($node->tagName === 'select') {
456  $query[$op][] = DALSelectParser::parse($node);
457  } else {
458  $query[$op][] = self::parseSingleField($node);
459  }
460  }
461  }
462  }
463 
464  return $query;
465 
466  }//end parseMathOperation()
467 
468 
486  protected static function parseSqlFunction(DomElement $function)
487  {
488  $query = array();
489  if ($function !== NULL) {
490  $query['FUNCTION'] = array();
491  $query['FUNCTION']['function'] = $function->getAttribute('function');
492  $query['FUNCTION']['ARGS'] = array();
493 
494  if ($function->getAttribute('alias') !== '') {
495  $query['FUNCTION']['alias'] = $function->getAttribute('alias');
496  }
497 
498  foreach ($function->childNodes as $arg) {
499  if ($arg->nodeType === XML_ELEMENT_NODE) {
500  $field = XML::getFirstChildElement($arg);
501  if ($field !== NULL) {
502  switch ($field->tagName) {
503  case 'select':
504  $query['FUNCTION']['ARGS'][] = DALSelectParser::parse($field);
505  break;
506 
507  default:
508  $fields = self::parseChildFields($arg);
509  $query['FUNCTION']['ARGS'][] = array_shift($fields);
510 
511  }
512  } else {
513  $query['FUNCTION']['ARGS'][] = $arg->nodeValue;
514  }
515  }
516  }
517  }//end if
518 
519  return $query;
520 
521  }//end parseSqlFunction()
522 
523 
538  public static function validateField(DomElement $field, $allowAlias=FALSE)
539  {
540  // Field must have table and column attribute.
541  if ($field->hasAttribute('table') === FALSE) {
542  throw new DALParserException('field tag must have table attr.');
543  } else if ($field->getAttribute('column') === '') {
544  throw new DALParserException('field tag must have column attr.');
545  } else if (($allowAlias === FALSE) && ($field->nodeValue !== '')) {
546  $msg = 'alias for field is not allowed here.';
547  throw new DALParserException($msg);
548  }
549 
550  }//end validateField()
551 
552 
564  protected static function validateFieldsTag(DomElement $fields)
565  {
566  // Fields tag must have table attribute.
567  if ($fields->getAttribute('table') === FALSE) {
568  $msg = 'Fields tag must have table attribute.';
569  throw new DALParserException($msg);
570  }
571 
572  // Make sure fields tag have field tags with values.
573  $fields = $fields->getElementsByTagName('field');
574  if ($fields->length === 0) {
575  $msg = 'Fields tag with no field tags.';
576  throw new DALParserException($msg);
577  }
578 
579  // Field tags must have values.
580  foreach ($fields as $field) {
581  if ($field->nodeValue === '') {
582  $msg = 'Field with no value.';
583  throw new DALParserException($msg);
584  }
585  }
586 
587  }//end validateFieldsTag()
588 
589 
602  public static function validateValuesTag(DomElement $valuesTag)
603  {
604  $foundValue = FALSE;
605  foreach ($valuesTag->childNodes as $value) {
606  if ($value->nodeType === XML_ELEMENT_NODE) {
607  if ($value->tagName === 'value') {
608  $foundValue = TRUE;
609  self::validateValueTag($value);
610  } else if ($value->tagName === 'select') {
611  $foundValue = TRUE;
612  DALSelectParser::validate($valuesTag);
613  }
614  }
615  }
616 
617  if ($foundValue === FALSE) {
618  $msg = 'Values tag with no value/select tags.';
619  throw new DALParserException($msg);
620  }
621 
622  }//end validateValuesTag()
623 
624 
637  protected static function validateValueTag(DomElement $value)
638  {
639  if ($value->getAttribute('column') === '') {
640  $msg = 'Update query value tags must have column attribute.';
641  throw new DALParserException($msg);
642  }
643 
644  }//end validateValueTag()
645 
646 
655  protected static function getUnionTag(DomElement $parentNode)
656  {
657  $unionTag = $parentNode->getElementsByTagName('union')->item(0);
658  if ($unionTag === NULL) {
659  $unionTag = $parentNode->getElementsByTagName('union-all')->item(0);
660  }
661 
662  return $unionTag;
663 
664  }//end getUnionTag()
665 
666 
675  protected static function addHookIds(DomElement $xmlQuery)
676  {
677  $list = array();
678  foreach ($xmlQuery->childNodes as $child) {
679  if ($child->nodeType !== XML_ELEMENT_NODE) {
680  continue;
681  }
682 
683  if ($child->tagName === 'hook') {
684  $list[] = $child->getAttribute('id');
685  }
686  }
687 
688  return $list;
689 
690  }//end addHookIds()
691 
692 
703  public static function validateFunctionTag(DomElement $function)
704  {
705  if ($function->getAttribute('function') === '') {
706  $msg = 'function tag must have \'function\' attribute.';
707  throw new DALParserException($msg);
708  }
709 
710  }//end validateFunctionTag()
711 
712 
724  public static function validateHook(DomElement $hook)
725  {
726  // Hook must have an id attribute.
727  if ($hook->getAttribute('id') === '') {
728  throw new DALParserException('hook tag must have an id attribute.');
729  }
730 
731  }//end validateHook()
732 
733 
734 }//end class
735 
736 
737 ?>