1: <?php
   2: 
   3:        4:    5:    6:    7: 
   8: 
   9: 
  10:       11:   12:   13:   14:   15:   16:   17:   18:   19:   20:   21:   22:   23:   24:   25:   26:   27:   28:   29: 
  30:     abstract class QQNode extends QBaseClass {
  31:         
  32:         protected $objParentNode;
  33:         
  34:         protected $strType;
  35:         
  36:         protected $strName;
  37:         
  38:         protected $strAlias;
  39:         
  40:         protected $strFullAlias;
  41:         
  42:         protected $strPropertyName;
  43:         
  44:         protected $strRootTableName;
  45:         
  46:         protected $strTableName;
  47: 
  48:         
  49:         protected $strPrimaryKey;
  50:         
  51:         protected $strClassName;
  52: 
  53:         
  54:         
  55:         protected $blnExpandAsArray;
  56:         
  57:         protected $objChildNodeArray;
  58:         
  59:         protected $blnIsType;
  60: 
  61:         abstract public function Join(QQueryBuilder $objBuilder, $blnExpandSelection = false, QQCondition $objJoinCondition = null, QQSelect $objSelect = null);
  62: 
  63:           64:   65:   66: 
  67:         public function GetType() {
  68:             return $this->strType;
  69:         }
  70: 
  71:           72:   73:   74:   75:   76:   77: 
  78:         public function SetAlias($strAlias) {
  79:             if ($this->strFullAlias) {
  80:                 throw new Exception ("You cannot set an alias on a node after you have used it in a query. See the examples doc. You must set the alias while creating the node.");
  81:             }
  82:             try {
  83:                 
  84:                 $strNewAlias = QType::Cast($strAlias, QType::String);
  85:                 if ($this->objParentNode) {
  86:                     assert (is_object($this->objParentNode));
  87:                     unset($this->objParentNode->objChildNodeArray[$this->strAlias]);
  88:                     $this->objParentNode->objChildNodeArray[$strNewAlias] = $this;
  89:                 }
  90:                 $this->strAlias = $strNewAlias;
  91:             } catch (QCallerException $objExc) {
  92:                 $objExc->IncrementOffset();
  93:                 throw $objExc;
  94:             }
  95:         }
  96: 
  97:           98:   99:  100:  101: 
 102:         public function FullAlias() {
 103:             if ($this->strFullAlias) {
 104:                 return $this->strFullAlias;
 105:             } else {
 106:                 assert (!empty($this->strAlias));   
 107:                 if ($this->objParentNode) {
 108:                     assert (is_object($this->objParentNode));
 109:                     return $this->objParentNode->FullAlias() . '__' . $this->strAlias;
 110:                 }
 111:                 else {
 112:                     return $this->strAlias;
 113:                 }
 114:             }
 115:         }
 116: 
 117:          118:  119:  120: 
 121:         public function Fields() {return [];}
 122: 
 123:          124:  125:  126: 
 127:         public function PrimaryKeyFields() {return [];}
 128: 
 129:          130:  131:  132:  133:  134:  135:  136:  137:  138: 
 139:         public function _MergeExpansionNode (QQNode $objNewNode) {
 140:             if (!$objNewNode || empty($objNewNode->objChildNodeArray)) {
 141:                 return;
 142:             }
 143:             if ($objNewNode->strName != $this->strName) {
 144:                 throw new QCallerException('Expansion node tables must match.');
 145:             }
 146: 
 147:             if (!$this->objChildNodeArray) {
 148:                 $this->objChildNodeArray = $objNewNode->objChildNodeArray;
 149:             } else {
 150:                 $objChildNode = reset($objNewNode->objChildNodeArray);
 151:                 if (isset ($this->objChildNodeArray[$objChildNode->strAlias])) {
 152:                     if ($objChildNode->blnExpandAsArray) {
 153:                         $this->objChildNodeArray[$objChildNode->strAlias]->blnExpandAsArray = true;
 154:                         
 155:                     }
 156:                     else {
 157:                         $this->objChildNodeArray[$objChildNode->strAlias]->_MergeExpansionNode ($objChildNode);
 158:                     }
 159:                 } else {
 160:                     $this->objChildNodeArray[$objChildNode->strAlias] = $objChildNode;
 161:                 }
 162:             }
 163:         }
 164: 
 165:          166:  167:  168:  169:  170:  171: 
 172:         public function PutSelectFields($objBuilder, $strPrefix = null, $objSelect = null) {
 173:             if ($strPrefix) {
 174:                 $strTableName = $strPrefix;
 175:                 $strAliasPrefix = $strPrefix . '__';
 176:             } else {
 177:                 $strTableName = $this->strTableName;
 178:                 $strAliasPrefix = '';
 179:             }
 180: 
 181:             if ($objSelect) {
 182:                 if (!$objSelect->SkipPrimaryKey()) {
 183:                     $strFields = $this->PrimaryKeyFields();
 184:                     foreach ($strFields as $strField) {
 185:                         $objBuilder->AddSelectItem($strTableName, $strField, $strAliasPrefix . $strField);
 186:                     }
 187:                 }
 188:                 $objSelect->AddSelectItems($objBuilder, $strTableName, $strAliasPrefix);
 189:             } else {
 190:                 $strFields = $this->Fields();
 191:                 foreach ($strFields as $strField) {
 192:                     $objBuilder->AddSelectItem($strTableName, $strField, $strAliasPrefix . $strField);
 193:                 }
 194:             }
 195:         }
 196: 
 197:          198:  199: 
 200:         public function FirstChild() {
 201:             $a = $this->objChildNodeArray;
 202:             if ($a) {
 203:                 return reset ($a);
 204:             } else {
 205:                 return null;
 206:             }
 207:         }
 208: 
 209:          210:  211:  212: 
 213:         public function GetTable() {
 214:             return $this->FullAlias();
 215:         }
 216: 
 217:          218:  219:  220:  221:  222:  223:  224: 
 225:         public static function GetValue($mixValue, QQueryBuilder $objBuilder, $blnEqualityType = null) {
 226:             if ($mixValue instanceof QQNamedValue) {
 227:                 
 228:                 return $mixValue->Parameter($blnEqualityType);
 229:             }
 230: 
 231:             if ($mixValue instanceof QQNode) {
 232:                 
 233:                 if ($n = $mixValue->_PrimaryKeyNode) {
 234:                     $mixValue = $n; 
 235:                 }
 236:                 
 237:                 if (is_null($blnEqualityType))
 238:                     $strToReturn = '';
 239:                 else if ($blnEqualityType)
 240:                     $strToReturn = '= ';
 241:                 else
 242:                     $strToReturn = '!= ';
 243: 
 244:                 try {
 245:                     return $strToReturn . $mixValue->GetColumnAlias($objBuilder);
 246:                 } catch (QCallerException $objExc) {
 247:                     $objExc->IncrementOffset();
 248:                     throw $objExc;
 249:                 }
 250:             } else {
 251:                 if (is_null($blnEqualityType)) {
 252:                     $blnIncludeEquality = false;
 253:                     $blnReverseEquality = false;
 254:                 } else {
 255:                     $blnIncludeEquality = true;
 256:                     if ($blnEqualityType)
 257:                         $blnReverseEquality = false;
 258:                     else
 259:                         $blnReverseEquality = true;
 260:                 }
 261: 
 262:                 return $objBuilder->Database->SqlVariable($mixValue, $blnIncludeEquality, $blnReverseEquality);
 263:             }
 264:         }
 265: 
 266:         public function __get($strName) {
 267:             switch ($strName) {
 268:                 case '_ParentNode':
 269:                     return $this->objParentNode;
 270:                 case '_Name':
 271:                     return $this->strName;
 272:                 case '_Alias':
 273:                     return $this->strAlias;
 274:                 case '_PropertyName':
 275:                     return $this->strPropertyName;
 276:                 case '_Type':
 277:                     return $this->strType;
 278:                 case '_RootTableName':
 279:                     return $this->strRootTableName;
 280:                 case '_TableName':
 281:                     return $this->strTableName;
 282:                 case '_PrimaryKey':
 283:                     return $this->strPrimaryKey;
 284:                 case '_ClassName':
 285:                     return $this->strClassName;
 286:                 case '_PrimaryKeyNode':
 287:                     return null;
 288:                     
 289:                 case 'ExpandAsArray':
 290:                     return $this->blnExpandAsArray;
 291:                 case 'IsType':
 292:                     return $this->blnIsType;
 293:                     
 294:                 case 'ChildNodeArray':
 295:                     return $this->objChildNodeArray;
 296:                     
 297:                 default:
 298:                     try {
 299:                         return parent::__get($strName);
 300:                     } catch (QCallerException $objExc) {
 301:                         $objExc->IncrementOffset();
 302:                         throw $objExc;
 303:                     }
 304:             }
 305:         }
 306: 
 307:         public function __set($strName, $mixValue) {
 308:             switch ($strName) {
 309:                 case 'ExpandAsArray':
 310:                     try {
 311:                         return ($this->blnExpandAsArray = QType::Cast($mixValue, QType::Boolean));
 312:                     } catch (QCallerException $objExc) {
 313:                         $objExc->IncrementOffset();
 314:                         throw $objExc;
 315:                     }
 316:                                         
 317:                 default:
 318:                     try {
 319:                         return parent::__set($strName, $mixValue);
 320:                     } catch (QCallerException $objExc) {
 321:                         $objExc->IncrementOffset();
 322:                         throw $objExc;
 323:                     }
 324:             }
 325:         }
 326: 
 327:         
 328:         
 329: 
 330:         
 331:         
 332:          333:  334:  335: 
 336:         public function GetDataGridHtml() {
 337:             
 338:             $objNodeArray = array();
 339: 
 340:             $objNodeArray[] = $this;
 341:             while ($objNodeArray[count($objNodeArray) - 1]->objParentNode)
 342:                 $objNodeArray[] = $objNodeArray[count($objNodeArray) - 1]->objParentNode;
 343: 
 344:             $objNodeArray = array_reverse($objNodeArray, false);
 345: 
 346:             
 347: 
 348:             
 349:             if (count($objNodeArray) < 2)
 350:                 throw new Exception('Invalid QQNode to GetDataGridHtml on');
 351: 
 352:             
 353:             else if (count($objNodeArray) == 2) {
 354:                 $strToReturn = '$_ITEM->' . $objNodeArray[1]->strPropertyName;
 355:                 if (class_exists($this->strClassName)) {
 356:                     $strToReturn = sprintf('(%s) ? %s->__toString() : null;', $strToReturn, $strToReturn);
 357:                 }
 358:             }
 359:             
 360:             else {
 361:                 $strNodeLabelArray[0] = '$_ITEM->' . $objNodeArray[1]->strPropertyName;
 362:                 for ($intIndex = 2; $intIndex < count($objNodeArray); $intIndex++) {
 363:                     $strNodeLabelArray[$intIndex - 1] = $strNodeLabelArray[$intIndex - 2] . '->' . $objNodeArray[$intIndex]->strPropertyName;
 364:                 }
 365: 
 366:                 $slice_count = count ($objNodeArray) - 2;
 367:                 $blnIsClass = class_exists($this->strClassName);
 368: 
 369:                 if ($blnIsClass) {
 370:                     $slice_count++;
 371:                 }
 372: 
 373:                 $aTest = array_slice ($strNodeLabelArray, 0, $slice_count);
 374:                 $strTest = implode (' && ', $aTest);
 375:                 $strLastNode = $strNodeLabelArray[count($strNodeLabelArray) - 1];
 376: 
 377:                 if ($blnIsClass) {
 378:                     return sprintf ('(%s) ? %s->__toString() : null', $strTest, $strLastNode);
 379:                 } else {
 380:                     $strToReturn = sprintf ('(%s) ? %s : null', $strTest, $strLastNode);
 381:                 }
 382:             }
 383: 
 384:             if($this->strType == QDatabaseFieldType::Time)
 385:                 return sprintf('(%s) ? %s->qFormat(QDateTime::$DefaultTimeFormat) : null', $strToReturn, $strToReturn);
 386: 
 387:             if ($this->strType == QDatabaseFieldType::Bit)
 388:                 return sprintf('(null === %s)? "" : ((%s)? "%s" : "%s")', $strToReturn, $strToReturn, QApplication::Translate('True'), QApplication::Translate('False'));
 389: 
 390: 
 391:             return $strToReturn;
 392:         }
 393: 
 394:         public function GetDataGridOrderByNode() {
 395:             if ($this instanceof QQReverseReferenceNode)
 396:                 return $this->_PrimaryKeyNode;
 397:             else
 398:                 return $this;
 399:         }
 400: 
 401:         public function SetFilteredDataGridColumnFilter(QDataGridLegacyColumn $col)
 402:         {
 403:             if ($this->_PrimaryKeyNode) {
 404:                 $objNode = $this->_PrimaryKeyNode;
 405:             } else {
 406:                 $objNode = $this;
 407:             }
 408: 
 409:             switch($objNode->strType)
 410:             {
 411:                 case QDatabaseFieldType::Bit:
 412:                     
 413:                     $col->FilterType = QFilterType::ListFilter;
 414:                     $col->FilterAddListItem("True", QQ::Equal($objNode, true));
 415:                     $col->FilterAddListItem("False", QQ::Equal($objNode, false));
 416:                     $col->FilterAddListItem("Set", QQ::IsNotNull($objNode));
 417:                     $col->FilterAddListItem("Unset", QQ::IsNull($objNode));
 418:                     break;
 419:                 case QDatabaseFieldType::Blob:
 420:                 case QDatabaseFieldType::Char:
 421:                 case QDatabaseFieldType::Time:
 422:                 case QDatabaseFieldType::VarChar:
 423:                 case QDatabaseFieldType::Date:
 424:                 case QDatabaseFieldType::DateTime:
 425:                     
 426:                     $col->FilterType = QFilterType::TextFilter;
 427:                     $col->FilterPrefix = '%';
 428:                     $col->FilterPostfix = '%';
 429:                     $col->Filter = QQ::Like($objNode, null);
 430:                     break;
 431:                 case QDatabaseFieldType::Float:
 432:                 case QDatabaseFieldType::Integer:
 433:                     
 434:                     $col->FilterType = QFilterType::TextFilter;
 435:                     $col->Filter = QQ::Equal($objNode, null);
 436:                     break;
 437:                 case QType::Object:
 438:                 case QType::Resource:
 439:                 default:
 440:                     
 441:                     $col->FilterType = QFilterType::None;
 442:                     $col->ClearFilter();
 443:                     break;
 444:             }
 445:         }
 446: 
 447:     }
 448: 
 449:      450:  451:  452: 
 453:     class QQColumnNode extends QQNode {
 454:          455:  456:  457:  458:  459:  460: 
 461:         public function __construct($strName, $strPropertyName, $strType, QQNode $objParentNode = null) {
 462:             $this->objParentNode = $objParentNode;
 463:             $this->strName = $strName;
 464:             $this->strAlias = $strName;
 465:             if ($objParentNode) $objParentNode->objChildNodeArray[$strName] = $this;
 466: 
 467:             $this->strPropertyName = $strPropertyName;
 468:             $this->strType = $strType;
 469:             if ($objParentNode) {
 470:                 $this->strRootTableName = $objParentNode->strRootTableName;
 471:             } else
 472:                 $this->strRootTableName = $strName;
 473:         }
 474: 
 475:          476:  477: 
 478:         public function GetColumnAlias(QQueryBuilder $objBuilder) {
 479:             $this->Join($objBuilder);
 480:             $strParentAlias = $this->objParentNode->FullAlias();
 481:             $strTableAlias = $objBuilder->GetTableAlias($strParentAlias);
 482:             
 483:             return $this->MakeColumnAlias($objBuilder, $strTableAlias);
 484:         }
 485: 
 486:          487:  488: 
 489:         public function MakeColumnAlias(QQueryBuilder $objBuilder, $strTableAlias) {
 490:             $strBegin = $objBuilder->Database->EscapeIdentifierBegin;
 491:             $strEnd = $objBuilder->Database->EscapeIdentifierEnd;
 492: 
 493:             return sprintf('%s%s%s.%s%s%s',
 494:                 $strBegin, $strTableAlias, $strEnd,
 495:                 $strBegin, $this->strName, $strEnd);
 496:         }
 497: 
 498: 
 499:          500:  501: 
 502:         public function GetTable() {
 503:             return $this->objParentNode->FullAlias();
 504:         }
 505: 
 506:          507:  508:  509:  510:  511:  512:  513:  514: 
 515:         public function Join(QQueryBuilder $objBuilder, $blnExpandSelection = false, QQCondition $objJoinCondition = null, QQSelect $objSelect = null) {
 516:             $objParentNode = $this->objParentNode;
 517:             if (!$objParentNode) {
 518:                 throw new QCallerException('A column node must have a parent node.');
 519:             } else {
 520:                 
 521:                 $objParentNode->Join($objBuilder, $blnExpandSelection, $objJoinCondition, $objSelect);
 522:             }
 523:         }
 524: 
 525:          526:  527:  528: 
 529:         public function GetAsManualSqlColumn() {
 530:             if ($this->strTableName)
 531:                 return $this->strTableName . '.' . $this->strName;
 532:             else if (($this->objParentNode) && ($this->objParentNode->strTableName))
 533:                 return $this->objParentNode->strTableName . '.' . $this->strName;
 534:             else
 535:                 return $this->strName;
 536:         }
 537: 
 538:     }
 539: 
 540:      541:  542:  543:  544: 
 545:     abstract class QQTableNode extends QQNode {
 546:          547:  548:  549:  550:  551:  552:  553: 
 554:         public function __construct($strName, $strPropertyName = null, $strType = null, QQNode $objParentNode = null) {
 555:             $this->objParentNode = $objParentNode;
 556:             $this->strName = $strName;
 557:             $this->strAlias = $strName;
 558:             if ($objParentNode) $objParentNode->objChildNodeArray[$strName] = $this;
 559: 
 560:             $this->strPropertyName = $strPropertyName;
 561:             $this->strType = $strType;
 562:             if ($objParentNode) {
 563:                 $this->strRootTableName = $objParentNode->strRootTableName;
 564:             } else
 565:                 $this->strRootTableName = $strName;
 566:         }
 567: 
 568:          569:  570:  571:  572:  573:  574:  575:  576:  577:  578:  579:  580: 
 581:         public function Join(QQueryBuilder $objBuilder, $blnExpandSelection = false, QQCondition $objJoinCondition = null, QQSelect $objSelect = null) {
 582:             $objParentNode = $this->objParentNode;
 583:             if (!$objParentNode) {
 584:                 if ($this->strTableName != $objBuilder->RootTableName) {
 585:                     throw new QCallerException('Cannot use QQNode for "' . $this->strTableName . '" when querying against the "' . $objBuilder->RootTableName . '" table', 3);
 586:                 }
 587:             } else {
 588: 
 589:                 
 590:                 
 591:                 if ($objJoinCondition &&
 592:                     $this->objParentNode instanceof QQAssociationNode &&
 593:                     $objJoinCondition->EqualTables($this->objParentNode->FullAlias())) {
 594: 
 595:                     $objParentNode->Join($objBuilder, $blnExpandSelection, $objJoinCondition, $objSelect);
 596:                     $objJoinCondition = null; 
 597:                 } else {
 598:                     $objParentNode->Join($objBuilder, $blnExpandSelection, null, $objSelect);
 599:                     if ($objJoinCondition && !$objJoinCondition->EqualTables($this->FullAlias())) {
 600:                         throw new QCallerException("The join condition on the \"" . $this->strTableName . "\" table must only contain conditions for that table.");
 601:                     }
 602:                 }
 603: 
 604:                 try {
 605:                     $strParentAlias = $objParentNode->FullAlias();
 606:                     $strAlias = $this->FullAlias();
 607:                     
 608:                     $objBuilder->AddJoinItem($this->strTableName, $strAlias,
 609:                         $strParentAlias, $this->strName, $this->strPrimaryKey, $objJoinCondition);
 610: 
 611:                     if ($blnExpandSelection) {
 612:                         $this->PutSelectFields($objBuilder, $strAlias, $objSelect);
 613:                     }
 614:                 } catch (QCallerException $objExc) {
 615:                     $objExc->IncrementOffset();
 616:                     throw $objExc;
 617:                 }
 618:             }
 619:         }
 620:     }
 621: 
 622:      623:  624:  625:  626:  627: 
 628:     class QQReverseReferenceNode extends QQTableNode {
 629:         
 630:         protected $strForeignKey;
 631: 
 632:          633:  634:  635:  636:  637:  638:  639:  640:  641: 
 642:         public function __construct(QQNode $objParentNode, $strName, $strType, $strForeignKey, $strPropertyName = null) {
 643:             parent::__construct($strName, $strPropertyName, $strType, $objParentNode);
 644:             if (!$objParentNode) {
 645:                 throw new QCallerException('ReverseReferenceNodes must have a Parent Node');
 646:             }
 647:             $objParentNode->objChildNodeArray[$strName] = $this;
 648:             $this->strForeignKey = $strForeignKey;
 649:         }
 650: 
 651:          652:  653:  654:  655: 
 656:         public function IsUnique() {
 657:             return !empty($this->strPropertyName);
 658:         }
 659: 
 660:          661:  662:  663:  664:  665:  666:  667:  668:  669: 
 670:         public function Join(QQueryBuilder $objBuilder, $blnExpandSelection = false, QQCondition $objJoinCondition = null, QQSelect $objSelect = null) {
 671:             $objParentNode = $this->objParentNode;
 672:             $objParentNode->Join($objBuilder, $blnExpandSelection, null, $objSelect);
 673:             if ($objJoinCondition && !$objJoinCondition->EqualTables($this->FullAlias())) {
 674:                 throw new QCallerException("The join condition on the \"" . $this->strTableName . "\" table must only contain conditions for that table.");
 675:             }
 676: 
 677:             try {
 678:                 $strParentAlias = $objParentNode->FullAlias();
 679:                 $strAlias = $this->FullAlias();
 680:                 
 681:                 $objBuilder->AddJoinItem($this->strTableName, $strAlias,
 682:                     $strParentAlias, $this->objParentNode->_PrimaryKey, $this->strForeignKey, $objJoinCondition);
 683: 
 684:                 if ($blnExpandSelection) {
 685:                     $this->PutSelectFields($objBuilder, $strAlias, $objSelect);
 686:                 }
 687:             } catch (QCallerException $objExc) {
 688:                 $objExc->IncrementOffset();
 689:                 throw $objExc;
 690:             }
 691:         }
 692: 
 693:     }
 694: 
 695:      696:  697:  698:  699: 
 700:     class QQAssociationNode extends QQNode {
 701:          702:  703:  704: 
 705:         public function __construct(QQNode $objParentNode) {
 706:             $this->objParentNode = $objParentNode;
 707:             if ($objParentNode) {
 708:                 $this->strRootTableName = $objParentNode->_RootTableName;
 709:                 $this->strAlias = $this->strName;
 710:                 $objParentNode->objChildNodeArray[$this->strAlias] = $this;
 711:             } else {
 712:                 throw new Exception ("Association Nodes must always have a parent node");
 713:             }
 714:         }
 715: 
 716:          717:  718:  719:  720:  721:  722:  723:  724:  725: 
 726:         public function Join(QQueryBuilder $objBuilder, $blnExpandSelection = false, QQCondition $objJoinCondition = null, QQSelect $objSelect = null) {
 727:             $objParentNode = $this->objParentNode;
 728:             $objParentNode->Join($objBuilder, $blnExpandSelection, null, $objSelect);
 729:             if ($objJoinCondition && !$objJoinCondition->EqualTables($this->FullAlias())) {
 730:                 throw new QCallerException("The join condition on the \"" . $this->strTableName . "\" table must only contain conditions for that table.");
 731:             }
 732: 
 733:             try {
 734:                 $strParentAlias = $objParentNode->FullAlias();
 735:                 $strAlias = $this->FullAlias();
 736:                 
 737:                 $objBuilder->AddJoinItem($this->strTableName, $strAlias,
 738:                     $strParentAlias, $objParentNode->_PrimaryKey, $this->strPrimaryKey, $objJoinCondition);
 739: 
 740:                 if ($blnExpandSelection) {
 741:                     $this->PutSelectFields($objBuilder, $strAlias, $objSelect);
 742:                 }
 743:             } catch (QCallerException $objExc) {
 744:                 $objExc->IncrementOffset();
 745:                 throw $objExc;
 746:             }
 747:         }
 748:     }
 749: 
 750: 
 751:      752:  753:  754:  755: 
 756:     class QQNamedValue extends QQNode
 757:     {
 758:         const DelimiterCode = 3;
 759: 
 760:          761:  762: 
 763:         public function __construct($strName) {
 764:             $this->strName = $strName;
 765:         }
 766: 
 767:          768:  769:  770: 
 771:         public function Parameter($blnEqualityType = null)
 772:         {
 773:             if (is_null($blnEqualityType))
 774:                 return chr(QQNamedValue::DelimiterCode) . '{' . $this->strName . '}';
 775:             else if ($blnEqualityType)
 776:                 return chr(QQNamedValue::DelimiterCode) . '{=' . $this->strName . '=}';
 777:             else
 778:                 return chr(QQNamedValue::DelimiterCode) . '{!' . $this->strName . '!}';
 779:         }
 780: 
 781:          782:  783:  784:  785:  786: 
 787:         public function Join(QQueryBuilder $objBuilder, $blnExpandSelection = false, QQCondition $objJoinCondition = null, QQSelect $objSelect = null) {
 788:             assert(0);    
 789:         }
 790:     }
 791: 
 792:     abstract class QQCondition extends QBaseClass {
 793:         protected $strOperator;
 794:         abstract public function UpdateQueryBuilder(QQueryBuilder $objBuilder);
 795:         public function __toString() {
 796:             return 'QQCondition Object';
 797:         }
 798: 
 799:         protected $blnProcessed;
 800: 
 801:          802:  803:  804:  805:  806:  807:  808:  809:  810: 
 811:         public function GetWhereClause(QQueryBuilder $objBuilder, $blnProcessOnce = false) {
 812:             if ($blnProcessOnce && $this->blnProcessed)
 813:                 return null;
 814: 
 815:             $this->blnProcessed = true;
 816: 
 817:             try {
 818:                 $objConditionBuilder = new QPartialQueryBuilder($objBuilder);
 819:                 $this->UpdateQueryBuilder($objConditionBuilder);
 820:                 return $objConditionBuilder->GetWhereStatement();
 821:             } catch (QCallerException $objExc) {
 822:                 $objExc->IncrementOffset();
 823:                 $objExc->IncrementOffset();
 824:                 throw $objExc;
 825:             }
 826:         }
 827: 
 828:          829:  830:  831: 
 832:         public function EqualTables($strTableName) {
 833:             return true;
 834:         }
 835:     }
 836:     class QQConditionAll extends QQCondition {
 837:          838:  839:  840: 
 841:         public function __construct($mixParameterArray) {
 842:             if (count($mixParameterArray))
 843:                 throw new QCallerException('All clause takes in no parameters', 3);
 844:         }
 845: 
 846:          847:  848: 
 849:         public function UpdateQueryBuilder(QQueryBuilder $objBuilder) {
 850:             $objBuilder->AddWhereItem('1=1');
 851:         }
 852:     }
 853:     class QQConditionNone extends QQCondition {
 854:          855:  856:  857: 
 858:         public function __construct($mixParameterArray) {
 859:             if (count($mixParameterArray))
 860:                 throw new QCallerException('None clause takes in no parameters', 3);
 861:         }
 862:         public function UpdateQueryBuilder(QQueryBuilder $objBuilder) {
 863:             $objBuilder->AddWhereItem('1=0');
 864:         }
 865:     }
 866:     abstract class QQConditionLogical extends QQCondition {
 867:         
 868:         protected $objConditionArray;
 869:         protected function CollapseConditions($mixParameterArray) {
 870:             $objConditionArray = array();
 871:             foreach ($mixParameterArray as $mixParameter) {
 872:                 if (is_array($mixParameter))
 873:                     $objConditionArray = array_merge($objConditionArray, $mixParameter);
 874:                 else
 875:                     array_push($objConditionArray, $mixParameter);
 876:             }
 877: 
 878:             foreach ($objConditionArray as $objCondition)
 879:                 if (!($objCondition instanceof QQCondition))
 880:                     throw new QCallerException('Logical Or/And clause parameters must all be QQCondition objects', 3);
 881: 
 882:             if (count($objConditionArray))
 883:                 return $objConditionArray;
 884:             else
 885:                 throw new QCallerException('No parameters passed in to logical Or/And clause', 3);
 886:         }
 887:         public function __construct($mixParameterArray) {
 888:             $objConditionArray = $this->CollapseConditions($mixParameterArray);
 889:             try {
 890:                 $this->objConditionArray = QType::Cast($objConditionArray, QType::ArrayType);
 891:             } catch (QCallerException $objExc) {
 892:                 $objExc->IncrementOffset();
 893:                 throw $objExc;
 894:             }
 895:         }
 896:         public function UpdateQueryBuilder(QQueryBuilder $objBuilder) {
 897:             $intLength = count($this->objConditionArray);
 898:             if ($intLength) {
 899:                 $objBuilder->AddWhereItem('(');
 900:                 for ($intIndex = 0; $intIndex < $intLength; $intIndex++) {
 901:                     if (!($this->objConditionArray[$intIndex] instanceof QQCondition))
 902:                         throw new QCallerException($this->strOperator . ' clause has elements that are not Conditions');
 903:                     try {
 904:                         $this->objConditionArray[$intIndex]->UpdateQueryBuilder($objBuilder);
 905:                     } catch (QCallerException $objExc) {
 906:                         $objExc->IncrementOffset();
 907:                         throw $objExc;
 908:                     }
 909:                     if (($intIndex + 1) != $intLength)
 910:                         $objBuilder->AddWhereItem($this->strOperator);
 911:                 }
 912:                 $objBuilder->AddWhereItem(')');
 913:             }
 914:         }
 915: 
 916:         public function EqualTables($strTableName) {
 917:             foreach ($this->objConditionArray as $objCondition) {
 918:                 if (!$objCondition->EqualTables($strTableName)) {
 919:                     return false;
 920:                 }
 921:             }
 922:             return true;
 923:         }
 924:     }
 925:     class QQConditionOr extends QQConditionLogical {
 926:         protected $strOperator = 'OR';
 927:     }
 928:     class QQConditionAnd extends QQConditionLogical {
 929:         protected $strOperator = 'AND';
 930:     }
 931: 
 932:     class QQConditionNot extends QQCondition {
 933:         protected $objCondition;
 934:         public function __construct(QQCondition $objCondition) {
 935:             $this->objCondition = $objCondition;
 936:         }
 937:         public function UpdateQueryBuilder(QQueryBuilder $objBuilder) {
 938:             $objBuilder->AddWhereItem('(NOT');
 939:             try {
 940:                 $this->objCondition->UpdateQueryBuilder($objBuilder);
 941:             } catch (QCallerException $objExc) {
 942:                 $objExc->IncrementOffset();
 943:                 throw $objExc;
 944:             }
 945:             $objBuilder->AddWhereItem(')');
 946:         }
 947:     }
 948: 
 949:     abstract class QQConditionComparison extends QQCondition {
 950:         
 951:         public $objQueryNode;
 952:         public $mixOperand;
 953: 
 954:          955:  956:  957:  958: 
 959:         public function __construct(QQColumnNode $objQueryNode, $mixOperand = null) {
 960:             $this->objQueryNode = $objQueryNode;
 961: 
 962:             if ($mixOperand instanceof QQNamedValue || $mixOperand === null)
 963:                 $this->mixOperand = $mixOperand;
 964:             else if ($mixOperand instanceof QQAssociationNode)
 965:                 throw new QInvalidCastException('Comparison operand cannot be an Association-based QQNode', 3);
 966:             else if ($mixOperand instanceof QQCondition)
 967:                 throw new QInvalidCastException('Comparison operand cannot be a QQCondition', 3);
 968:             else if ($mixOperand instanceof QQClause)
 969:                 throw new QInvalidCastException('Comparison operand cannot be a QQClause', 3);
 970:             else if (!($mixOperand instanceof QQNode)) {
 971:                 $this->mixOperand = $mixOperand;
 972:             } else {
 973:                 if (!($mixOperand instanceof QQColumnNode))
 974:                     throw new QInvalidCastException('Unable to cast "' . $mixOperand->_Name . '" table to Column-based QQNode', 3);
 975:                 $this->mixOperand = $mixOperand;
 976:             }
 977:         }
 978:         public function UpdateQueryBuilder(QQueryBuilder $objBuilder) {
 979:             $objBuilder->AddWhereItem($this->objQueryNode->GetColumnAlias($objBuilder) . $this->strOperator . QQNode::GetValue($this->mixOperand, $objBuilder));
 980:         }
 981: 
 982:          983:  984:  985:  986: 
 987:         public function EqualTables($strTableName) {
 988:             return $this->objQueryNode->GetTable() == $strTableName;
 989:         }
 990:     }
 991: 
 992:      993:  994:  995: 
 996:     class QQConditionIsNull extends QQConditionComparison {
 997:          998:  999: 
1000:         public function __construct(QQColumnNode $objQueryNode) {
1001:             parent::__construct($objQueryNode);
1002:         }
1003: 
1004:         1005: 1006: 
1007:         public function UpdateQueryBuilder(QQueryBuilder $objBuilder) {
1008:             $objBuilder->AddWhereItem($this->objQueryNode->GetColumnAlias($objBuilder) . ' IS NULL');
1009:         }
1010:     }
1011: 
1012:     class QQConditionIsNotNull extends QQConditionComparison {
1013:         public function __construct(QQColumnNode $objQueryNode) {
1014:             parent::__construct($objQueryNode);
1015:         }
1016: 
1017:         1018: 1019: 
1020:         public function UpdateQueryBuilder(QQueryBuilder $objBuilder) {
1021:             $objBuilder->AddWhereItem($this->objQueryNode->GetColumnAlias($objBuilder) . ' IS NOT NULL');
1022:         }
1023:     }
1024: 
1025:     class QQConditionIn extends QQConditionComparison {
1026:         1027: 1028: 1029: 1030: 1031: 1032: 
1033:         public function __construct(QQColumnNode $objQueryNode, $mixValuesArray) {
1034:             parent::__construct($objQueryNode);
1035: 
1036:             if ($mixValuesArray instanceof QQNamedValue)
1037:                 $this->mixOperand = $mixValuesArray;
1038:             else if ($mixValuesArray instanceof QQSubQueryNode)
1039:                 $this->mixOperand = $mixValuesArray;
1040:             else {
1041:                 try {
1042:                     $this->mixOperand = QType::Cast($mixValuesArray, QType::ArrayType);
1043:                 } catch (QCallerException $objExc) {
1044:                     $objExc->IncrementOffset();
1045:                     $objExc->IncrementOffset();
1046:                     throw $objExc;
1047:                 }
1048:             }
1049:         }
1050: 
1051:         1052: 1053: 
1054:         public function UpdateQueryBuilder(QQueryBuilder $objBuilder) {
1055:             $mixOperand = $this->mixOperand;
1056:             if ($mixOperand instanceof QQNamedValue) {
1057:                 
1058:                 $objBuilder->AddWhereItem($this->objQueryNode->GetColumnAlias($objBuilder) . ' IN (' . $mixOperand->Parameter() . ')');
1059:             } else if ($mixOperand instanceof QQSubQueryNode) {
1060:                 
1061:                 $objBuilder->AddWhereItem($this->objQueryNode->GetColumnAlias($objBuilder) . ' IN ' . $mixOperand->GetColumnAlias($objBuilder));
1062:             } else {
1063:                 $strParameters = array();
1064:                 foreach ($mixOperand as $mixParameter) {
1065:                     array_push($strParameters, $objBuilder->Database->SqlVariable($mixParameter));
1066:                 }
1067:                 if (count($strParameters))
1068:                     $objBuilder->AddWhereItem($this->objQueryNode->GetColumnAlias($objBuilder) . ' IN (' . implode(',', $strParameters) . ')');
1069:                 else
1070:                     $objBuilder->AddWhereItem('1=0');
1071:             }
1072:         }
1073:     }
1074: 
1075:     class QQConditionNotIn extends QQConditionComparison {
1076:         1077: 1078: 1079: 1080: 1081: 
1082:         public function __construct(QQColumnNode $objQueryNode, $mixValuesArray) {
1083:             parent::__construct($objQueryNode);
1084: 
1085:             if ($mixValuesArray instanceof QQNamedValue)
1086:                 $this->mixOperand = $mixValuesArray;
1087:             else if ($mixValuesArray instanceof QQSubQueryNode)
1088:                 $this->mixOperand = $mixValuesArray;
1089:             else {
1090:                 try {
1091:                     $this->mixOperand = QType::Cast($mixValuesArray, QType::ArrayType);
1092:                 } catch (QCallerException $objExc) {
1093:                     $objExc->IncrementOffset();
1094:                     $objExc->IncrementOffset();
1095:                     throw $objExc;
1096:                 }
1097:             }
1098:         }
1099: 
1100:         1101: 1102: 
1103:         public function UpdateQueryBuilder(QQueryBuilder $objBuilder) {
1104:             $mixOperand = $this->mixOperand;
1105:             if ($mixOperand instanceof QQNamedValue) {
1106:                 
1107:                 $objBuilder->AddWhereItem($this->objQueryNode->GetColumnAlias($objBuilder) . ' NOT IN (' . $mixOperand->Parameter() . ')');
1108:             } else if ($mixOperand instanceof QQSubQueryNode) {
1109:                 
1110:                 $objBuilder->AddWhereItem($this->objQueryNode->GetColumnAlias($objBuilder) . ' NOT IN ' . $mixOperand->GetColumnAlias($objBuilder));
1111:             } else {
1112:                 $strParameters = array();
1113:                 foreach ($mixOperand as $mixParameter) {
1114:                     array_push($strParameters, $objBuilder->Database->SqlVariable($mixParameter));
1115:                 }
1116:                 if (count($strParameters))
1117:                     $objBuilder->AddWhereItem($this->objQueryNode->GetColumnAlias($objBuilder) . ' NOT IN (' . implode(',', $strParameters) . ')');
1118:                 else
1119:                     $objBuilder->AddWhereItem('1=1');
1120:             }
1121:         }
1122:     }
1123: 
1124:     class QQConditionLike extends QQConditionComparison {
1125:         1126: 1127: 1128: 1129: 1130: 1131: 
1132:         public function __construct(QQColumnNode $objQueryNode, $strValue) {
1133:             parent::__construct($objQueryNode);
1134: 
1135:             if ($strValue instanceof QQNamedValue)
1136:                 $this->mixOperand = $strValue;
1137:             else {
1138:                 try {
1139:                     $this->mixOperand = QType::Cast($strValue, QType::String);
1140:                 } catch (QCallerException $objExc) {
1141:                     $objExc->IncrementOffset();
1142:                     $objExc->IncrementOffset();
1143:                     throw $objExc;
1144:                 }
1145:             }
1146:         }
1147: 
1148:         1149: 1150: 
1151:         public function UpdateQueryBuilder(QQueryBuilder $objBuilder) {
1152:             $mixOperand = $this->mixOperand;
1153:             if ($mixOperand instanceof QQNamedValue) {
1154:                 
1155:                 $objBuilder->AddWhereItem($this->objQueryNode->GetColumnAlias($objBuilder) . ' LIKE ' . $mixOperand->Parameter());
1156:             } else {
1157:                 $objBuilder->AddWhereItem($this->objQueryNode->GetColumnAlias($objBuilder) . ' LIKE ' . $objBuilder->Database->SqlVariable($mixOperand));
1158:             }
1159:         }
1160:     }
1161: 
1162:     class QQConditionNotLike extends QQConditionComparison {
1163:         1164: 1165: 1166: 1167: 1168: 
1169:         public function __construct(QQColumnNode $objQueryNode, $strValue) {
1170:             parent::__construct($objQueryNode);
1171: 
1172:             if ($strValue instanceof QQNamedValue)
1173:                 $this->mixOperand = $strValue;
1174:             else {
1175:                 try {
1176:                     $this->mixOperand = QType::Cast($strValue, QType::String);
1177:                 } catch (QCallerException $objExc) {
1178:                     $objExc->IncrementOffset();
1179:                     $objExc->IncrementOffset();
1180:                     throw $objExc;
1181:                 }
1182:             }
1183:         }
1184: 
1185:         1186: 1187: 
1188:         public function UpdateQueryBuilder(QQueryBuilder $objBuilder) {
1189:             $mixOperand = $this->mixOperand;
1190:             if ($mixOperand instanceof QQNamedValue) {
1191:                 
1192:                 $objBuilder->AddWhereItem($this->objQueryNode->GetColumnAlias($objBuilder) . ' NOT LIKE ' . $mixOperand->Parameter());
1193:             } else {
1194:                 $objBuilder->AddWhereItem($this->objQueryNode->GetColumnAlias($objBuilder) . ' NOT LIKE ' . $objBuilder->Database->SqlVariable($mixOperand));
1195:             }
1196:         }
1197:     }
1198: 
1199:     class QQConditionBetween extends QQConditionComparison {
1200:         
1201:         protected $mixOperandTwo;
1202: 
1203:         1204: 1205: 1206: 1207: 1208: 1209: 
1210:         public function __construct(QQColumnNode $objQueryNode, $mixMinValue, $mixMaxValue) {
1211:             parent::__construct($objQueryNode);
1212:             try {
1213:                 $this->mixOperand = $mixMinValue;
1214:                 $this->mixOperandTwo = $mixMaxValue;
1215:             } catch (QCallerException $objExc) {
1216:                 $objExc->IncrementOffset();
1217:                 $objExc->IncrementOffset();
1218:                 throw $objExc;
1219:             }
1220:         }
1221: 
1222:         1223: 1224: 
1225:         public function UpdateQueryBuilder(QQueryBuilder $objBuilder) {
1226:             $mixOperand = $this->mixOperand;
1227:             $mixOperandTwo = $this->mixOperandTwo;
1228:             if ($mixOperand instanceof QQNamedValue) {
1229:                 
1230:                 
1231:                 $objBuilder->AddWhereItem($this->objQueryNode->GetColumnAlias($objBuilder) . ' BETWEEN ' . $mixOperand->Parameter() . ' AND ' . $mixOperandTwo->Parameter());
1232:             } else {
1233:                 $objBuilder->AddWhereItem($this->objQueryNode->GetColumnAlias($objBuilder) . ' BETWEEN ' . $objBuilder->Database->SqlVariable($mixOperand) . ' AND ' . $objBuilder->Database->SqlVariable($mixOperandTwo));
1234:             }
1235:         }
1236:     }
1237: 
1238:     class QQConditionNotBetween extends QQConditionComparison {
1239:         
1240:         protected $mixOperandTwo;
1241: 
1242:         1243: 1244: 1245: 1246: 1247: 1248: 
1249:         public function __construct(QQColumnNode $objQueryNode, $strMinValue, $strMaxValue) {
1250:             parent::__construct($objQueryNode);
1251:             try {
1252:                 $this->mixOperand = QType::Cast($strMinValue, QType::String);
1253:                 $this->mixOperandTwo = QType::Cast($strMaxValue, QType::String);
1254:             } catch (QCallerException $objExc) {
1255:                 $objExc->IncrementOffset();
1256:                 $objExc->IncrementOffset();
1257:                 throw $objExc;
1258:             }
1259: 
1260:             if ($strMinValue instanceof QQNamedValue)
1261:                 $this->mixOperand = $strMinValue;
1262:             if ($strMaxValue instanceof QQNamedValue)
1263:                 $this->mixOperandTwo = $strMaxValue;
1264: 
1265:         }
1266: 
1267:         1268: 1269: 
1270:         public function UpdateQueryBuilder(QQueryBuilder $objBuilder) {
1271:             $mixOperand = $this->mixOperand;
1272:             $mixOperandTwo = $this->mixOperandTwo;
1273:             if ($mixOperand instanceof QQNamedValue) {
1274:                 
1275:                 
1276:                 $objBuilder->AddWhereItem($this->objQueryNode->GetColumnAlias($objBuilder) . ' NOT BETWEEN ' . $mixOperand->Parameter() . ' AND ' . $mixOperandTwo->Parameter());
1277:             } else {
1278:                 $objBuilder->AddWhereItem($this->objQueryNode->GetColumnAlias($objBuilder) . ' NOT BETWEEN ' . $objBuilder->Database->SqlVariable($mixOperand) . ' AND ' . $objBuilder->Database->SqlVariable($mixOperandTwo));
1279:             }
1280:         }
1281:     }
1282: 
1283:     class QQConditionEqual extends QQConditionComparison {
1284:         protected $strOperator = ' = ';
1285: 
1286:         1287: 1288: 1289: 1290: 
1291:         public function UpdateQueryBuilder(QQueryBuilder $objBuilder) {
1292:             $objBuilder->AddWhereItem($this->objQueryNode->GetColumnAlias($objBuilder) . ' ' . QQNode::GetValue($this->mixOperand, $objBuilder, true));
1293:         }
1294:     }
1295:     class QQConditionNotEqual extends QQConditionComparison {
1296:         protected $strOperator = ' != ';
1297: 
1298:         1299: 1300: 1301: 1302: 
1303:         public function UpdateQueryBuilder(QQueryBuilder $objBuilder) {
1304:             $objBuilder->AddWhereItem($this->objQueryNode->GetColumnAlias($objBuilder) . ' ' . QQNode::GetValue($this->mixOperand, $objBuilder, false));
1305:         }
1306:     }
1307: 
1308:     class QQConditionExists extends QQCondition {
1309:         
1310:         protected $objNode;
1311: 
1312:         1313: 1314: 
1315:         public function __construct(QQSubQuerySqlNode $objNode) {
1316:             $this->objNode = $objNode;
1317:         }
1318: 
1319:         1320: 1321: 
1322:         public function UpdateQueryBuilder(QQueryBuilder $objBuilder) {
1323:             $objBuilder->AddWhereItem('EXISTS ' . $this->objNode->GetColumnAlias($objBuilder));
1324:         }
1325:     }
1326: 
1327:     class QQConditionNotExists extends QQCondition {
1328:         
1329:         protected $objNode;
1330: 
1331:         1332: 1333: 
1334:         public function __construct(QQSubQuerySqlNode $objNode) {
1335:             $this->objNode = $objNode;
1336:         }
1337: 
1338:         1339: 1340: 
1341:         public function UpdateQueryBuilder(QQueryBuilder $objBuilder) {
1342:             $objBuilder->AddWhereItem('NOT EXISTS ' . $this->objNode->GetColumnAlias($objBuilder));
1343:         }
1344:     }
1345: 
1346: 
1347: 
1348:     class QQConditionGreaterThan extends QQConditionComparison {
1349:         protected $strOperator = ' > ';
1350:     }
1351:     class QQConditionLessThan extends QQConditionComparison {
1352:         protected $strOperator = ' < ';
1353:     }
1354:     class QQConditionGreaterOrEqual extends QQConditionComparison {
1355:         protected $strOperator = ' >= ';
1356:     }
1357:     class QQConditionLessOrEqual extends QQConditionComparison {
1358:         protected $strOperator = ' <= ';
1359:     }
1360: 
1361:     class QQ {
1362:         
1363:         
1364:         
1365: 
1366:         static public function All() {
1367:             return new QQConditionAll(func_get_args());
1368:         }
1369: 
1370:         static public function None() {
1371:             return new QQConditionNone(func_get_args());
1372:         }
1373: 
1374:         static public function OrCondition() {
1375:             return new QQConditionOr(func_get_args());
1376:         }
1377: 
1378:         static public function AndCondition() {
1379:             return new QQConditionAnd(func_get_args());
1380:         }
1381: 
1382:         static public function Not(QQCondition $objCondition) {
1383:             return new QQConditionNot($objCondition);
1384:         }
1385: 
1386:         static public function Equal(QQColumnNode $objQueryNode, $mixValue) {
1387:             return new QQConditionEqual($objQueryNode, $mixValue);
1388:         }
1389:         static public function NotEqual(QQColumnNode $objQueryNode, $mixValue) {
1390:             return new QQConditionNotEqual($objQueryNode, $mixValue);
1391:         }
1392:         static public function GreaterThan(QQColumnNode $objQueryNode, $mixValue) {
1393:             return new QQConditionGreaterThan($objQueryNode, $mixValue);
1394:         }
1395:         static public function GreaterOrEqual(QQColumnNode $objQueryNode, $mixValue) {
1396:             return new QQConditionGreaterOrEqual($objQueryNode, $mixValue);
1397:         }
1398:         static public function LessThan(QQColumnNode $objQueryNode, $mixValue) {
1399:             return new QQConditionLessThan($objQueryNode, $mixValue);
1400:         }
1401:         static public function LessOrEqual(QQColumnNode $objQueryNode, $mixValue) {
1402:             return new QQConditionLessOrEqual($objQueryNode, $mixValue);
1403:         }
1404:         static public function IsNull(QQColumnNode $objQueryNode) {
1405:             return new QQConditionIsNull($objQueryNode);
1406:         }
1407:         static public function IsNotNull(QQColumnNode $objQueryNode) {
1408:             return new QQConditionIsNotNull($objQueryNode);
1409:         }
1410:         static public function In(QQColumnNode $objQueryNode, $mixValuesArray) {
1411:             return new QQConditionIn($objQueryNode, $mixValuesArray);
1412:         }
1413:         static public function NotIn(QQColumnNode $objQueryNode, $mixValuesArray) {
1414:             return new QQConditionNotIn($objQueryNode, $mixValuesArray);
1415:         }
1416:         static public function Like(QQColumnNode $objQueryNode, $strValue) {
1417:             return new QQConditionLike($objQueryNode, $strValue);
1418:         }
1419:         static public function NotLike(QQColumnNode $objQueryNode, $strValue) {
1420:             return new QQConditionNotLike($objQueryNode, $strValue);
1421:         }
1422:         static public function Between(QQColumnNode $objQueryNode, $mixMinValue, $mixMaxValue) {
1423:             return new QQConditionBetween($objQueryNode, $mixMinValue, $mixMaxValue);
1424:         }
1425:         static public function NotBetween(QQColumnNode $objQueryNode, $strMinValue, $strMaxValue) {
1426:             return new QQConditionNotBetween($objQueryNode, $strMinValue, $strMaxValue);
1427:         }
1428:         static public function Exists(QQSubQuerySqlNode $objQueryNode) {
1429:             return new QQConditionExists($objQueryNode);
1430:         }
1431:         static public function NotExists(QQSubQuerySqlNode $objQueryNode) {
1432:             return new QQConditionNotExists($objQueryNode);
1433:         }
1434: 
1435: 
1436:         
1437:         
1438:         
1439:         1440: 1441: 1442: 1443: 1444: 1445: 1446: 1447: 
1448:         static public function _(QQColumnNode $objQueryNode, $strSymbol, $mixValue = null, $mixValueTwo = null) {
1449:             try {
1450:                 switch(strtolower(trim($strSymbol))) {
1451:                     case '=': return QQ::Equal($objQueryNode, $mixValue);
1452:                     case '!=': return QQ::NotEqual($objQueryNode, $mixValue);
1453:                     case '>': return QQ::GreaterThan($objQueryNode, $mixValue);
1454:                     case '<': return QQ::LessThan($objQueryNode, $mixValue);
1455:                     case '>=': return QQ::GreaterOrEqual($objQueryNode, $mixValue);
1456:                     case '<=': return QQ::LessOrEqual($objQueryNode, $mixValue);
1457:                     case 'in': return QQ::In($objQueryNode, $mixValue);
1458:                     case 'not in': return QQ::NotIn($objQueryNode, $mixValue);
1459:                     case 'like': return QQ::Like($objQueryNode, $mixValue);
1460:                     case 'not like': return QQ::NotLike($objQueryNode, $mixValue);
1461:                     case 'is null': return QQ::IsNull($objQueryNode);
1462:                     case 'is not null': return QQ::IsNotNull($objQueryNode);
1463:                     case 'between': return QQ::Between($objQueryNode, $mixValue, $mixValueTwo);
1464:                     case 'not between': return QQ::NotBetween($objQueryNode, $mixValue, $mixValueTwo);
1465:                     default:
1466:                         throw new QCallerException('Unknown Query Comparison Operation: ' . $strSymbol, 0);
1467:                 }
1468:             } catch (QCallerException $objExc) {
1469:                 $objExc->IncrementOffset();
1470:                 throw $objExc;
1471:             }
1472:         }
1473: 
1474:         
1475:         
1476:         
1477: 
1478:         1479: 1480: 1481: 1482: 
1483:         static public function SubSql($strSql, $objParentQueryNodes = null) {
1484:             $objParentQueryNodeArray = func_get_args();
1485:             return new QQSubQuerySqlNode($strSql, $objParentQueryNodeArray);
1486:         }
1487: 
1488:         static public function Virtual($strName, QQSubQueryNode $objSubQueryDefinition = null) {
1489:             return new QQVirtualNode($strName, $objSubQueryDefinition);
1490:         }
1491: 
1492:         1493: 1494: 1495: 1496: 1497: 1498: 1499: 
1500:         static public function GetVirtualAlias($strName) {
1501:             $strName = trim($strName);
1502:             $strName = str_replace(" ", "_", $strName);
1503:             $strName = strtolower($strName);
1504:             return $strName;
1505:         }
1506: 
1507:         
1508:         
1509:         
1510: 
1511:         static public function Clause() {
1512:             $objClauseArray = array();
1513: 
1514:             foreach (func_get_args() as $objClause)
1515:                 if ($objClause) {
1516:                     if (!($objClause instanceof QQClause))
1517:                         throw new QCallerException('Non-QQClause object was passed in to QQ::Clause');
1518:                     else
1519:                         array_push($objClauseArray, $objClause);
1520:                 }
1521: 
1522:             return $objClauseArray;
1523:         }
1524: 
1525:         static public function OrderBy() {
1526:             return new QQOrderBy(func_get_args());
1527:         }
1528: 
1529:         static public function GroupBy() {
1530:             return new QQGroupBy(func_get_args());
1531:         }
1532: 
1533:         static public function Having(QQSubQuerySqlNode $objNode) {
1534:             return new QQHavingClause($objNode);
1535:         }
1536: 
1537:         static public function Count(QQColumnNode $objNode, $strAttributeName) {
1538:             return new QQCount($objNode, $strAttributeName);
1539:         }
1540: 
1541:         static public function Sum(QQColumnNode $objNode, $strAttributeName) {
1542:             return new QQSum($objNode, $strAttributeName);
1543:         }
1544: 
1545:         static public function Minimum(QQColumnNode $objNode, $strAttributeName) {
1546:             return new QQMinimum($objNode, $strAttributeName);
1547:         }
1548: 
1549:         static public function Maximum(QQColumnNode $objNode, $strAttributeName) {
1550:             return new QQMaximum($objNode, $strAttributeName);
1551:         }
1552: 
1553:         static public function Average(QQColumnNode $objNode, $strAttributeName) {
1554:             return new QQAverage($objNode, $strAttributeName);
1555:         }
1556: 
1557:         static public function Expand(QQNode $objNode, QQCondition $objJoinCondition = null, QQSelect $objSelect = null) {
1558: 
1559: 
1560: 
1561:             if ($objNode instanceof QQVirtualNode)
1562:                 return new QQExpandVirtualNode($objNode);
1563:             else
1564:                 return new QQExpand($objNode, $objJoinCondition, $objSelect);
1565:         }
1566: 
1567:         static public function ExpandAsArray(QQNode $objNode, $objCondition = null, QQSelect $objSelect = null) {
1568:             return new QQExpandAsArray($objNode, $objCondition, $objSelect);
1569:         }
1570: 
1571:         static public function Select() {
1572:             if (func_num_args() == 1 && is_array($a = func_get_arg(0))) {
1573:                 return new QQSelect($a);
1574:             } else {
1575:                 return new QQSelect(func_get_args());
1576:             }
1577:         }
1578: 
1579:         static public function LimitInfo($intMaxRowCount, $intOffset = 0) {
1580:             return new QQLimitInfo($intMaxRowCount, $intOffset);
1581:         }
1582: 
1583:         static public function Distinct() {
1584:             return new QQDistinct();
1585:         }
1586: 
1587:         1588: 1589: 1590: 1591: 1592: 1593: 1594: 
1595:         public static function ExtractSelectClause($objClauses) {
1596:             if ($objClauses instanceof QQSelect)
1597:                 return $objClauses;
1598: 
1599:             if (is_array($objClauses)) {
1600:                 $hasSelects = false;
1601:                 $objSelect = QQuery::Select();
1602:                 foreach ($objClauses as $objClause) {
1603:                     if ($objClause instanceof QQSelect) {
1604:                         $hasSelects = true;
1605:                         $objSelect->Merge($objClause);
1606:                     }
1607:                 }
1608:                 if (!$hasSelects)
1609:                     return null;
1610:                 return $objSelect;
1611:             }
1612:             return null;
1613:         }
1614: 
1615:         
1616:         
1617:         
1618:         1619: 1620: 1621: 1622: 1623: 1624: 1625: 
1626:         static public function Alias(QQNode $objNode, $strAlias)
1627:         {
1628:             $objNode->SetAlias($strAlias);
1629:             return $objNode;
1630:         }
1631: 
1632:         
1633:         
1634:         
1635:         static public function NamedValue($strName) {
1636:             return new QQNamedValue($strName);
1637:         }
1638: 
1639:         1640: 1641: 1642: 1643: 1644: 1645: 1646: 1647: 1648: 
1649:         static public function Func($strName, $param1 ) {
1650:             $args = func_get_args();
1651:             $strFunc = array_shift($args);
1652:             return new QQFunctionNode($strFunc, $args);
1653:         }
1654: 
1655:         
1656:         
1657:         
1658: 
1659:         1660: 1661: 1662: 1663: 1664: 
1665:         static public function Abs($param) {
1666:             return QQ::Func('ABS', $param);
1667:         }
1668:         1669: 1670: 1671: 1672: 1673: 
1674:         static public function Ceil($param) {
1675:             return QQ::Func('CEIL', $param);
1676:         }
1677:         1678: 1679: 1680: 1681: 1682: 
1683:         static public function Floor($param) {
1684:             return QQ::Func('FLOOR', $param);
1685:         }
1686:         1687: 1688: 1689: 1690: 1691: 
1692:         static public function Mod($dividend, $divider) {
1693:             return QQ::Func('MOD', $dividend, $divider);
1694:         }
1695:         1696: 1697: 1698: 1699: 1700: 
1701:         static public function Power($base, $exponent) {
1702:             return QQ::Func('POWER', $base, $exponent);
1703:         }
1704:         1705: 1706: 1707: 1708: 1709: 
1710:         static public function Sqrt($param) {
1711:             return QQ::Func('SQRT', $param);
1712:         }
1713: 
1714:         1715: 1716: 1717: 1718: 1719: 1720: 
1721:         static public function MathOp($strOperation, $param1 ) {
1722:             $args = func_get_args();
1723:             $strFunc = array_shift($args);
1724:             return new QQMathNode($strFunc, $args);
1725:         }
1726: 
1727:         1728: 1729: 1730: 1731: 1732: 1733: 
1734:         static public function Mul($op1, $op2 ) {
1735:             return new QQMathNode('*', func_get_args());
1736:         }
1737:         1738: 1739: 1740: 1741: 1742: 1743: 
1744:         static public function Div($op1, $op2 ) {
1745:             return new QQMathNode('/', func_get_args());
1746:         }
1747:         1748: 1749: 1750: 1751: 1752: 1753: 
1754:         static public function Sub($op1, $op2 ) {
1755:             return new QQMathNode('-', func_get_args());
1756:         }
1757:         1758: 1759: 1760: 1761: 1762: 1763: 
1764:         static public function Add($op1, $op2 ) {
1765:             return new QQMathNode('+', func_get_args());
1766:         }
1767:         1768: 1769: 1770: 1771: 1772: 
1773:         static public function Neg($op1) {
1774:             return new QQMathNode('-', [$op1]);
1775:         }
1776: 
1777:     }
1778: 
1779:     abstract class QQSubQueryNode extends QQColumnNode {
1780:     }
1781: 
1782:     abstract class QQNoParentNode extends QQSubQueryNode {
1783:         1784: 1785: 
1786:         public function GetTable() {
1787:             return $this->FullAlias();
1788:         }
1789:         1790: 1791: 1792: 1793: 1794: 1795: 
1796:         public function SetAlias($strAlias) {
1797:             if ($this->strFullAlias) {
1798:                 throw new Exception ("You cannot set an alias on a node after you have used it in a query. See the examples doc. You must set the alias while creating the node.");
1799:             }
1800:             try {
1801:                 
1802:                 $strNewAlias = QType::Cast($strAlias, QType::String);
1803:                 $this->strAlias = $strNewAlias;
1804:             } catch (QCallerException $objExc) {
1805:                 $objExc->IncrementOffset();
1806:                 throw $objExc;
1807:             }
1808:         }
1809:         1810: 1811: 1812: 1813: 
1814:         public function FullAlias() {
1815:             if ($this->strFullAlias) {
1816:                 return $this->strFullAlias;
1817:             } else {
1818:                 assert (!empty($this->strAlias));   
1819:                 return $this->strAlias;
1820:             }
1821:         }
1822:     }
1823: 
1824:     class QQSubQueryCountNode extends QQSubQueryNode {
1825:         protected $strFunctionName = 'COUNT';
1826:     }
1827: 
1828:     class QQSubQuerySqlNode extends QQNoParentNode {
1829:         protected $strSql;
1830:         
1831:         protected $objParentQueryNodes;
1832:         1833: 1834: 1835: 
1836:         public function __construct($strSql, $objParentQueryNodes = null) {
1837:             parent::__construct('', '', '');
1838:             $this->objParentNode = true;
1839:             $this->objParentQueryNodes = $objParentQueryNodes;
1840:             $this->strSql = $strSql;
1841:         }
1842: 
1843:         1844: 1845: 1846: 
1847:         public function GetColumnAlias(QQueryBuilder $objBuilder) {
1848:             $strSql = $this->strSql;
1849:             for ($intIndex = 1; $intIndex < count($this->objParentQueryNodes); $intIndex++) {
1850:                 if (!is_null($this->objParentQueryNodes[$intIndex]))
1851:                     $strSql = str_replace('{' . $intIndex . '}', $this->objParentQueryNodes[$intIndex]->GetColumnAlias($objBuilder), $strSql);
1852:             }
1853:             return '(' . $strSql . ')';
1854:         }
1855:     }
1856: 
1857:     class QQVirtualNode extends QQNoParentNode {
1858:         protected $objSubQueryDefinition;
1859: 
1860:         1861: 1862: 1863: 
1864:         public function __construct($strName, QQSubQueryNode $objSubQueryDefinition = null) {
1865:             parent::__construct('', '', '');
1866:             $this->objParentNode = true;
1867:             $this->strName = QQ::GetVirtualAlias($strName);
1868:             $this->strAlias = $this->strName;
1869:             $this->objSubQueryDefinition = $objSubQueryDefinition;
1870:         }
1871: 
1872:         1873: 1874: 1875: 1876: 1877: 
1878:         public function GetColumnAlias(QQueryBuilder $objBuilder) {
1879:             if ($this->objSubQueryDefinition) {
1880:                 $objBuilder->SetVirtualNode($this->strName, $this->objSubQueryDefinition);
1881:                 return $this->objSubQueryDefinition->GetColumnAlias($objBuilder);
1882:             } else {
1883:                 try {
1884:                     $objNode = $objBuilder->GetVirtualNode($this->strName);
1885:                     return $objNode->GetColumnAlias($objBuilder);
1886:                 } catch (QCallerException $objExc) {
1887:                     $objExc->IncrementOffset();
1888:                     $objExc->IncrementOffset();
1889:                     throw $objExc;
1890:                 }
1891:             }
1892:         }
1893:         public function GetAttributeName() {
1894:             return $this->strName;
1895:         }
1896: 
1897:         public function HasSubquery() {
1898:             return $this->objSubQueryDefinition != null;
1899:         }
1900:     }
1901: 
1902:     class QQFunctionNode extends QQSubQueryNode {
1903:         
1904:         protected $strFunctionName;
1905:         
1906:         protected $params;
1907: 
1908:         1909: 1910: 1911: 
1912:         public function __construct($strFunctionName, $params) {
1913:             parent::__construct('', '', '');
1914:             $this->strFunctionName = $strFunctionName;
1915:             $this->params = $params;
1916:         }
1917: 
1918:         1919: 1920: 1921: 
1922:         public function GetColumnAlias(QQueryBuilder $objBuilder) {
1923:             $strSql = $this->strFunctionName . '(';
1924:             foreach ($this->params as $param) {
1925:                 if ($param instanceof QQColumnNode) {
1926:                     $strSql .= $param->GetColumnAlias($objBuilder);
1927:                 }
1928:                 else {
1929:                     
1930:                     $strSql .= $param;
1931:                 }
1932:                 $strSql .= ',';
1933:             }
1934:             $strSql = substr($strSql, 0, -1);   
1935:             $strSql .= ')';
1936:             return $strSql;
1937:         }
1938: 
1939:         public function __toString() {
1940:             return 'QQFunctionNode ' . $this->strFunctionName;
1941:         }
1942:     }
1943: 
1944:     class QQMathNode extends QQSubQueryNode {
1945:         
1946:         protected $strOperation;
1947:         
1948:         protected $params;
1949: 
1950:         1951: 1952: 1953: 
1954:         public function __construct($strOperation, $params) {
1955:             parent::__construct('', '', '');
1956:             $this->strOperation = $strOperation;
1957:             $this->params = $params;
1958:         }
1959: 
1960:         1961: 1962: 1963: 
1964:         public function GetColumnAlias(QQueryBuilder $objBuilder) {
1965:             if (count($this->params) == 0) return '';
1966: 
1967:             $strSql = '(';
1968: 
1969:             if (count($this->params) == 1) {
1970:                 
1971:                 $strSql .= $this->strOperation;
1972:             }
1973:             foreach ($this->params as $param) {
1974:                 if ($param instanceof QQColumnNode) {
1975:                     $strSql .= $param->GetColumnAlias($objBuilder);
1976:                 }
1977:                 else {
1978:                     
1979:                     $strSql .= $param;
1980:                 }
1981:                 $strSql .= ' ' . $this->strOperation . ' ';
1982:             }
1983:             $strSql = substr($strSql, 0, -(strlen($this->strOperation) + 2));   
1984:             $strSql .= ')';
1985:             return $strSql;
1986:         }
1987: 
1988:         public function __toString() {
1989:             return 'QQMathNode ' . $this->strOperation;
1990:         }
1991: 
1992:     }
1993: 
1994: 
1995:     abstract class QQClause extends QBaseClass {
1996:         abstract public function UpdateQueryBuilder(QQueryBuilder $objBuilder);
1997:         abstract public function __toString();
1998:     }
1999: 
2000:     2001: 2002: 
2003:     class QQOrderBy extends QQClause {
2004:         
2005:         protected $objNodeArray;
2006: 
2007:         2008: 2009: 2010: 2011: 2012: 2013: 2014: 2015: 2016: 
2017:         protected function CollapseNodes($mixParameterArray) {
2018:             
2019:             $objNodeArray = array();
2020:             foreach ($mixParameterArray as $mixParameter) {
2021:                 if (is_array($mixParameter)) {
2022:                     $objNodeArray = array_merge($objNodeArray, $mixParameter);
2023:                 } else {
2024:                     array_push($objNodeArray, $mixParameter);
2025:                 }
2026:             }
2027: 
2028:             $blnPreviousIsNode = false;
2029:             $objFinalNodeArray = array();
2030:             foreach ($objNodeArray as $objNode) {
2031:                 if (!($objNode instanceof QQNode || $objNode instanceof QQCondition)) {
2032:                     if (!$blnPreviousIsNode)
2033:                         throw new QCallerException('OrderBy clause parameters must all be QQNode or QQCondition objects followed by an optional true/false "Ascending Order" option', 3);
2034:                     $blnPreviousIsNode = false;
2035:                     array_push($objFinalNodeArray, $objNode);
2036:                 } elseif ($objNode instanceof QQCondition) {
2037:                     $blnPreviousIsNode = true;
2038:                     array_push($objFinalNodeArray, $objNode);
2039:                 } else {
2040:                     if (!$objNode->_ParentNode) {
2041:                         throw new QInvalidCastException('Unable to cast "' . $objNode->_Name . '" table to Column-based QQNode', 4);
2042:                     }
2043:                     if ($objNode->_PrimaryKeyNode) { 
2044:                         array_push($objFinalNodeArray, $objNode->_PrimaryKeyNode);
2045:                     } else {
2046:                         array_push($objFinalNodeArray, $objNode);
2047:                     }
2048:                     $blnPreviousIsNode = true;
2049:                 }
2050:             }
2051: 
2052:             if (count($objFinalNodeArray)) {
2053:                 return $objFinalNodeArray;
2054:             } else {
2055:                 throw new QCallerException('No parameters passed in to OrderBy clause', 3);
2056:             }
2057:         }
2058: 
2059:         2060: 2061: 2062: 2063: 2064: 2065: 
2066:         public function __construct($mixParameterArray) {
2067:             $this->objNodeArray = $this->CollapseNodes($mixParameterArray);
2068:         }
2069: 
2070:         2071: 2072: 2073: 2074: 
2075:         public function UpdateQueryBuilder(QQueryBuilder $objBuilder) {
2076:             $objBuilder->SetOrderByClause($this);
2077:         }
2078: 
2079:         2080: 2081: 2082: 2083: 2084: 2085: 
2086:         public function _UpdateQueryBuilder(QQueryBuilder $objBuilder) {
2087:             $intLength = count($this->objNodeArray);
2088:             for ($intIndex = 0; $intIndex < $intLength; $intIndex++) {
2089:                 $objNode = $this->objNodeArray[$intIndex];
2090:                 if ($objNode instanceof QQVirtualNode) {
2091:                     if ($objNode->HasSubquery()) {
2092:                         throw new QCallerException('You cannot define a virtual node in an order by clause. You must use an Expand clause to define it.');
2093:                     }
2094:                     $strOrderByCommand = '__' . $objNode->GetAttributeName();
2095:                 } elseif ($objNode instanceof QQColumnNode) {
2096:                     
2097:                     $strOrderByCommand = $objNode->GetColumnAlias($objBuilder);
2098:                 } elseif ($objNode instanceof QQCondition) {
2099:                     
2100:                     $strOrderByCommand = $objNode->GetWhereClause($objBuilder);
2101:                 } else {
2102:                     $strOrderByCommand = '';
2103:                 }
2104: 
2105:                 
2106:                 if ((($intIndex + 1) < $intLength) &&
2107:                     !($this->objNodeArray[$intIndex + 1] instanceof QQNode)) {
2108:                     if ((!$this->objNodeArray[$intIndex + 1]) ||
2109:                         (trim(strtolower($this->objNodeArray[$intIndex + 1])) == 'desc'))
2110:                         $strOrderByCommand .= ' DESC';
2111:                     else
2112:                         $strOrderByCommand .= ' ASC';
2113:                     $intIndex++;
2114:                 }
2115: 
2116:                 $objBuilder->AddOrderByItem($strOrderByCommand);
2117:             }
2118:         }
2119: 
2120: 
2121: 
2122:         2123: 2124: 2125: 2126: 2127: 2128: 
2129:         public function GetAsManualSql() {
2130:             $strOrderByArray = array();
2131:             $intLength = count($this->objNodeArray);
2132:             for ($intIndex = 0; $intIndex < $intLength; $intIndex++) {
2133:                 $strOrderByCommand = $this->objNodeArray[$intIndex]->GetAsManualSqlColumn();
2134: 
2135:                 
2136:                 if ((($intIndex + 1) < $intLength) &&
2137:                     !($this->objNodeArray[$intIndex + 1] instanceof QQNode)) {
2138:                     if ((!$this->objNodeArray[$intIndex + 1]) ||
2139:                         (trim(strtolower($this->objNodeArray[$intIndex + 1])) == 'desc'))
2140:                         $strOrderByCommand .= ' DESC';
2141:                     else
2142:                         $strOrderByCommand .= ' ASC';
2143:                     $intIndex++;
2144:                 }
2145: 
2146:                 array_push($strOrderByArray, $strOrderByCommand);
2147:             }
2148: 
2149:             return implode(',', $strOrderByArray);
2150:         }
2151: 
2152:         public function __toString() {
2153:             return 'QQOrderBy Clause';
2154:         }
2155:     }
2156: 
2157:     class QQDistinct extends QQClause {
2158:         public function UpdateQueryBuilder(QQueryBuilder $objBuilder) {
2159:             $objBuilder->SetDistinctFlag();
2160:         }
2161:         public function __toString() {
2162:             return 'QQDistinct Clause';
2163:         }
2164:     }
2165: 
2166:     class QQLimitInfo extends QQClause {
2167:         protected $intMaxRowCount;
2168:         protected $intOffset;
2169:         public function __construct($intMaxRowCount, $intOffset = 0) {
2170:             try {
2171:                 $this->intMaxRowCount = QType::Cast($intMaxRowCount, QType::Integer);
2172:                 $this->intOffset = QType::Cast($intOffset, QType::Integer);
2173:             } catch (QCallerException $objExc) {
2174:                 $objExc->IncrementOffset();
2175:                 throw $objExc;
2176:             }
2177:         }
2178:         public function UpdateQueryBuilder(QQueryBuilder $objBuilder) {
2179:             if ($this->intOffset)
2180:                 $objBuilder->SetLimitInfo($this->intOffset . ',' . $this->intMaxRowCount);
2181:             else
2182:                 $objBuilder->SetLimitInfo($this->intMaxRowCount);
2183:         }
2184:         public function __toString() {
2185:             return 'QQLimitInfo Clause';
2186:         }
2187: 
2188:         public function __get($strName) {
2189:             switch ($strName) {
2190:                 case 'MaxRowCount':
2191:                     return $this->intMaxRowCount;
2192:                 case 'Offset':
2193:                     return $this->intOffset;
2194:             default:
2195:                 try {
2196:                     return parent::__get($strName);
2197:                 } catch (QCallerException $objExc) {
2198:                     $objExc->IncrementOffset();
2199:                     throw $objExc;
2200:                 }
2201:             }
2202:         }
2203:     }
2204: 
2205:     class QQExpandVirtualNode extends QQClause {
2206:         protected $objNode;
2207:         public function __construct(QQVirtualNode $objNode) {
2208:             $this->objNode = $objNode;
2209:         }
2210:         public function UpdateQueryBuilder(QQueryBuilder $objBuilder) {
2211:             try {
2212:                 $objBuilder->AddSelectFunction(null, $this->objNode->GetColumnAlias($objBuilder), $this->objNode->GetAttributeName());
2213:             } catch (QCallerException $objExc) {
2214:                 $objExc->IncrementOffset();
2215:                 throw $objExc;
2216:             }
2217:         }
2218:         public function __toString() {
2219:             return 'QQExpandVirtualNode Clause';
2220:         }
2221:     }
2222:     class QQExpand extends QQClause {
2223:         
2224:         protected $objNode;
2225:         protected $objJoinCondition;
2226:         protected $objSelect;
2227: 
2228:         public function __construct($objNode, QQCondition $objJoinCondition = null, QQSelect $objSelect  = null) {
2229:             
2230:             if ($objNode instanceof QQAssociationNode)
2231:                 throw new QCallerException('Expand clause parameter cannot be an association table node. Try expanding one level deeper.', 2);
2232:             else if (!($objNode instanceof QQNode))
2233:                 throw new QCallerException('Expand clause parameter must be a QQNode object', 2);
2234:             else if (!$objNode->_ParentNode)
2235:                 throw new QInvalidCastException('Cannot expand on this kind of node.', 3);
2236: 
2237:             $this->objNode = $objNode;
2238:             $this->objJoinCondition = $objJoinCondition;
2239:             $this->objSelect = $objSelect;
2240:         }
2241:         public function UpdateQueryBuilder(QQueryBuilder $objBuilder) {
2242:             $this->objNode->Join($objBuilder, true, $this->objJoinCondition, $this->objSelect);
2243:         }
2244:         public function __toString() {
2245:             return 'QQExpand Clause';
2246:         }
2247:     }
2248: 
2249:     2250: 2251: 2252: 
2253:     class QQHavingClause extends QQClause {
2254:         protected $objNode;
2255:         public function __construct(QQSubQueryNode $objSubQueryDefinition) {
2256:             $this->objNode = $objSubQueryDefinition;
2257:         }
2258:         public function UpdateQueryBuilder(QQueryBuilder $objBuilder) {
2259:             $objBuilder->AddHavingItem (
2260:                 $this->objNode->GetColumnAlias($objBuilder)
2261:             );
2262:         }
2263:         public function GetAttributeName() {
2264:             return $this->objNode->strName;
2265:         }
2266:         public function __toString() {
2267:             return "Having Clause";
2268:         }
2269: 
2270:     }
2271: 
2272:     abstract class QQAggregationClause extends QQClause {
2273:         
2274:         protected $objNode;
2275:         protected $strAttributeName;
2276:         protected $strFunctionName;
2277:         public function __construct(QQColumnNode $objNode, $strAttributeName) {
2278:             $this->objNode = QQ::Func($this->strFunctionName, $objNode);
2279:             $this->strAttributeName = QQ::GetVirtualAlias($strAttributeName); 
2280:         }
2281:         public function UpdateQueryBuilder(QQueryBuilder $objBuilder) {
2282:             $objBuilder->SetVirtualNode($this->strAttributeName, $this->objNode);
2283:             $objBuilder->AddSelectFunction(null, $this->objNode->GetColumnAlias($objBuilder), $this->strAttributeName);
2284:         }
2285:     }
2286:     class QQCount extends QQAggregationClause {
2287:         protected $strFunctionName = 'COUNT';
2288:         public function __toString() {
2289:             return 'QQCount Clause';
2290:         }
2291:     }
2292:     class QQSum extends QQAggregationClause {
2293:         protected $strFunctionName = 'SUM';
2294:         public function __toString() {
2295:             return 'QQSum Clause';
2296:         }
2297:     }
2298:     class QQMinimum extends QQAggregationClause {
2299:         protected $strFunctionName = 'MIN';
2300:         public function __toString() {
2301:             return 'QQMinimum Clause';
2302:         }
2303:     }
2304:     class QQMaximum extends QQAggregationClause {
2305:         protected $strFunctionName = 'MAX';
2306:         public function __toString() {
2307:             return 'QQMaximum Clause';
2308:         }
2309:     }
2310:     class QQAverage extends QQAggregationClause {
2311:         protected $strFunctionName = 'AVG';
2312:         public function __toString() {
2313:             return 'QQAverage Clause';
2314:         }
2315:     }
2316: 
2317:     class QQExpandAsArray extends QQClause {
2318:         
2319:         protected $objNode;
2320:         protected $objCondition;
2321:         protected $objSelect;
2322: 
2323:         2324: 2325: 2326: 2327: 2328: 
2329:         public function __construct(QQNode $objNode, $objCondition = null, QQSelect $objSelect = null) {
2330:             
2331:             
2332:             if ((!($objNode instanceof QQAssociationNode)) && (!($objNode instanceof QQReverseReferenceNode)))
2333:                 throw new QCallerException('ExpandAsArray clause parameter must be an Association or ReverseReference node', 2);
2334: 
2335:             if ($objCondition instanceof QQSelect) {
2336:                 $this->objNode = $objNode;
2337:                 $this->objSelect = $objCondition;
2338:             } else {
2339:                 if (!is_null($objCondition)) {
2340:                     2341: 2342: 2343: 
2344:                     if (!($objCondition instanceof QQCondition)) {
2345:                         throw new QCallerException('Condition clause parameter must be a QQCondition dervied class.', 2);
2346:                     }
2347:                 }
2348:                 $this->objNode = $objNode;
2349:                 $this->objSelect = $objSelect;
2350:                 $this->objCondition = $objCondition;
2351:             }
2352: 
2353:         }
2354:         public function UpdateQueryBuilder(QQueryBuilder $objBuilder) {
2355:             if ($this->objNode instanceof QQAssociationNode) {
2356:                 
2357:                 $this->objNode->_ChildTableNode->Join($objBuilder, true, $this->objCondition, $this->objSelect);
2358:             }
2359:             else {
2360:                 $this->objNode->Join($objBuilder, true, $this->objCondition, $this->objSelect);
2361:             }
2362:             $objBuilder->AddExpandAsArrayNode($this->objNode);
2363:         }
2364:         public function __toString() {
2365:             return 'QQExpandAsArray Clause';
2366:         }
2367:     }
2368: 
2369:     class QQGroupBy extends QQClause {
2370:         
2371:         protected $objNodeArray;
2372: 
2373:         2374: 2375: 2376: 2377: 2378: 2379: 2380: 2381: 2382: 
2383:         protected function CollapseNodes($mixParameterArray) {
2384:             $objNodeArray = array();
2385:             foreach ($mixParameterArray as $mixParameter) {
2386:                 if (is_array($mixParameter)) {
2387:                     $objNodeArray = array_merge($objNodeArray, $mixParameter);
2388:                 } else {
2389:                     array_push($objNodeArray, $mixParameter);
2390:                 }
2391:             }
2392: 
2393:             $objFinalNodeArray = array();
2394:             foreach ($objNodeArray as $objNode) {
2395:                 
2396:                 if ($objNode instanceof QQAssociationNode)
2397:                     throw new QCallerException('GroupBy clause parameter cannot be an association table node.', 3);
2398:                 else if (!($objNode instanceof QQNode))
2399:                     throw new QCallerException('GroupBy clause parameters must all be QQNode objects.', 3);
2400: 
2401:                 if (!$objNode->_ParentNode)
2402:                     throw new QInvalidCastException('Unable to cast "' . $objNode->_Name . '" table to Column-based QQNode', 4);
2403: 
2404:                 if ($objNode->_PrimaryKeyNode) {
2405:                     array_push($objFinalNodeArray, $objNode->_PrimaryKeyNode);  
2406:                 } else
2407:                     array_push($objFinalNodeArray, $objNode);
2408:             }
2409: 
2410:             if (count($objFinalNodeArray))
2411:                 return $objFinalNodeArray;
2412:             else
2413:                 throw new QCallerException('No parameters passed in to Expand clause', 3);
2414:         }
2415:         public function __construct($mixParameterArray) {
2416:             $this->objNodeArray = $this->CollapseNodes($mixParameterArray);
2417:         }
2418:         public function UpdateQueryBuilder(QQueryBuilder $objBuilder) {
2419:             $intLength = count($this->objNodeArray);
2420:             for ($intIndex = 0; $intIndex < $intLength; $intIndex++)
2421:                 $objBuilder->AddGroupByItem($this->objNodeArray[$intIndex]->GetColumnAlias($objBuilder));
2422:         }
2423:         public function __toString() {
2424:             return 'QQGroupBy Clause';
2425:         }
2426:     }
2427: 
2428: 
2429:     class QQSelect extends QQClause {
2430:         
2431:         protected $arrNodeObj = array();
2432:         protected $blnSkipPrimaryKey = false;
2433: 
2434:         2435: 2436: 2437: 
2438:         public function __construct($arrNodeObj) {
2439:             $this->arrNodeObj = $arrNodeObj;
2440:             foreach ($this->arrNodeObj as $objNode) {
2441:                 if (!($objNode instanceof QQColumnNode)) {
2442:                     throw new QCallerException('Select nodes must be column nodes.', 3);
2443:                 }
2444:             }
2445:         }
2446: 
2447:         public function UpdateQueryBuilder(QQueryBuilder $objBuilder) {
2448:         }
2449: 
2450:         public function AddSelectItems(QQueryBuilder $objBuilder, $strTableName, $strAliasPrefix) {
2451:             foreach ($this->arrNodeObj as $objNode) {
2452:                 $strNodeTable = $objNode->GetTable();
2453:                 if ($strNodeTable == $strTableName) {
2454:                     $objBuilder->AddSelectItem($strTableName, $objNode->_Name, $strAliasPrefix . $objNode->_Name);
2455:                 }
2456:             }
2457:         }
2458: 
2459:         public function Merge(QQSelect $objSelect = null) {
2460:             if ($objSelect) {
2461:                 foreach ($objSelect->arrNodeObj as $objNode) {
2462:                     array_push($this->arrNodeObj, $objNode);
2463:                 }
2464:                 if ($objSelect->blnSkipPrimaryKey) {
2465:                     $this->blnSkipPrimaryKey = true;
2466:                 }
2467:             }
2468:         }
2469: 
2470:         2471: 2472: 
2473:         public function SkipPrimaryKey() {
2474:             return $this->blnSkipPrimaryKey;
2475:         }
2476: 
2477:         2478: 2479: 
2480:         public function SetSkipPrimaryKey($blnSkipPrimaryKey) {
2481:             $this->blnSkipPrimaryKey = $blnSkipPrimaryKey;
2482:         }
2483: 
2484:         public function __toString() {
2485:             return 'QQSelectColumn Clause';
2486:         }
2487:     }
2488: 
2489:     
2490:     class QQuery extends QQ {}
2491: 
2492:     2493: 2494: 2495: 2496: 2497: 2498: 
2499:     class QQueryBuilder extends QBaseClass {
2500:         
2501:         protected $strSelectArray;
2502:         
2503:         protected $strColumnAliasArray;
2504:         
2505:         protected $intColumnAliasCount = 0;
2506:         
2507:         protected $strTableAliasArray;
2508:         
2509:         protected $intTableAliasCount = 0;
2510:         
2511:         protected $strFromArray;
2512:         
2513:         protected $strJoinArray;
2514:         
2515:         protected $strJoinConditionArray;
2516:         
2517:         protected $strWhereArray;
2518:         
2519:         protected $strOrderByArray;
2520:         
2521:         protected $strGroupByArray;
2522:         
2523:         protected $strHavingArray;
2524:         
2525:         protected $objVirtualNodeArray;
2526:         
2527:         protected $strLimitInfo;
2528:         
2529:         protected $blnDistinctFlag;
2530:         
2531:         protected $objExpandAsArrayNode;
2532:         
2533:         protected $blnCountOnlyFlag;
2534: 
2535:         
2536:         protected $objDatabase;
2537:         
2538:         protected $strRootTableName;
2539:         
2540:         protected $strEscapeIdentifierBegin;
2541:         
2542:         protected $strEscapeIdentifierEnd;
2543:         
2544:         protected $objOrderByClause;
2545: 
2546:         2547: 2548: 2549: 
2550:         public function __construct(QDatabaseBase $objDatabase, $strRootTableName) {
2551:             $this->objDatabase = $objDatabase;
2552:             $this->strEscapeIdentifierBegin = $objDatabase->EscapeIdentifierBegin;
2553:             $this->strEscapeIdentifierEnd = $objDatabase->EscapeIdentifierEnd;
2554:             $this->strRootTableName = $strRootTableName;
2555: 
2556:             $this->strSelectArray = array();
2557:             $this->strColumnAliasArray = array();
2558:             $this->strTableAliasArray = array();
2559:             $this->strFromArray = array();
2560:             $this->strJoinArray = array();
2561:             $this->strJoinConditionArray = array();
2562:             $this->strWhereArray = array();
2563:             $this->strOrderByArray = array();
2564:             $this->strGroupByArray = array();
2565:             $this->strHavingArray = array();
2566:             $this->objVirtualNodeArray = array();
2567:         }
2568: 
2569:         2570: 2571: 2572: 2573: 
2574:         public function AddSelectItem($strTableName, $strColumnName, $strFullAlias) {
2575:             $strTableAlias = $this->GetTableAlias($strTableName);
2576: 
2577:             if (!array_key_exists($strFullAlias, $this->strColumnAliasArray)) {
2578:                 $strColumnAlias = 'a' . $this->intColumnAliasCount++;
2579:                 $this->strColumnAliasArray[$strFullAlias] = $strColumnAlias;
2580:             } else {
2581:                 $strColumnAlias = $this->strColumnAliasArray[$strFullAlias];
2582:             }
2583: 
2584:             $this->strSelectArray[$strFullAlias] = sprintf('%s%s%s.%s%s%s AS %s%s%s',
2585:                 $this->strEscapeIdentifierBegin, $strTableAlias, $this->strEscapeIdentifierEnd,
2586:                 $this->strEscapeIdentifierBegin, $strColumnName, $this->strEscapeIdentifierEnd,
2587:                 $this->strEscapeIdentifierBegin, $strColumnAlias, $this->strEscapeIdentifierEnd);
2588:         }
2589: 
2590:         2591: 2592: 2593: 2594: 
2595:         public function AddSelectFunction($strFunctionName, $strColumnName, $strFullAlias) {
2596:             $this->strSelectArray[$strFullAlias] = sprintf('%s(%s) AS %s__%s%s',
2597:                 $strFunctionName, $strColumnName,
2598:                 $this->strEscapeIdentifierBegin, $strFullAlias, $this->strEscapeIdentifierEnd);
2599:         }
2600: 
2601:         2602: 2603: 
2604:         public function AddFromItem($strTableName) {
2605:             $strTableAlias = $this->GetTableAlias($strTableName);
2606: 
2607:             $this->strFromArray[$strTableName] = sprintf('%s%s%s AS %s%s%s',
2608:                 $this->strEscapeIdentifierBegin, $strTableName, $this->strEscapeIdentifierEnd,
2609:                 $this->strEscapeIdentifierBegin, $strTableAlias, $this->strEscapeIdentifierEnd);
2610:         }
2611: 
2612:         2613: 2614: 2615: 
2616:         public function GetTableAlias($strTableName) {
2617:             if (!array_key_exists($strTableName, $this->strTableAliasArray)) {
2618:                 $strTableAlias = 't' . $this->intTableAliasCount++;
2619:                 $this->strTableAliasArray[$strTableName] = $strTableAlias;
2620:                 return $strTableAlias;
2621:             } else {
2622:                 return $this->strTableAliasArray[$strTableName];
2623:             }
2624:         }
2625: 
2626:         2627: 2628: 2629: 2630: 2631: 2632: 2633: 2634: 2635: 
2636:         public function AddJoinItem($strJoinTableName, $strJoinTableAlias, $strTableName, $strColumnName, $strLinkedColumnName, QQCondition $objJoinCondition = null) {
2637:             $strJoinItem = sprintf('LEFT JOIN %s%s%s AS %s%s%s ON %s%s%s.%s%s%s = %s%s%s.%s%s%s',
2638:                 $this->strEscapeIdentifierBegin, $strJoinTableName, $this->strEscapeIdentifierEnd,
2639:                 $this->strEscapeIdentifierBegin, $this->GetTableAlias($strJoinTableAlias), $this->strEscapeIdentifierEnd,
2640: 
2641:                 $this->strEscapeIdentifierBegin, $this->GetTableAlias($strTableName), $this->strEscapeIdentifierEnd,
2642:                 $this->strEscapeIdentifierBegin, $strColumnName, $this->strEscapeIdentifierEnd,
2643: 
2644:                 $this->strEscapeIdentifierBegin, $this->GetTableAlias($strJoinTableAlias), $this->strEscapeIdentifierEnd,
2645:                 $this->strEscapeIdentifierBegin, $strLinkedColumnName, $this->strEscapeIdentifierEnd);
2646: 
2647:                 $strJoinIndex = $strJoinItem;
2648:             try {
2649:                 $strConditionClause = null;
2650:                 if ($objJoinCondition &&
2651:                     ($strConditionClause = $objJoinCondition->GetWhereClause($this, false)))
2652:                     $strJoinItem .= ' AND ' . $strConditionClause;
2653:             } catch (QCallerException $objExc) {
2654:                 $objExc->IncrementOffset();
2655:                 throw $objExc;
2656:             }
2657: 
2658:             2659: 2660: 2661: 2662: 2663: 2664: 2665: 2666: 2667: 2668: 2669: 
2670:             if (array_key_exists($strJoinIndex, $this->strJoinArray)) {
2671:                 
2672:                 if (!array_key_exists($strJoinIndex, $this->strJoinConditionArray)) {
2673: 
2674:                     
2675:                     if (!$strConditionClause) {
2676:                         return;
2677: 
2678:                     
2679:                     } else {
2680:                         $this->strJoinArray[$strJoinIndex] = $strJoinItem;
2681:                         $this->strJoinConditionArray[$strJoinIndex] = $strConditionClause;
2682:                         return;
2683:                     }
2684:                 }
2685: 
2686:                 
2687:                 if (!$strConditionClause)
2688:                     return;
2689: 
2690:                 
2691:                 if ($strConditionClause == $this->strJoinConditionArray[$strJoinIndex])
2692:                     return;
2693: 
2694:                 
2695:                 throw new QCallerException('You have two different Join Conditions on the same Expanded Table: ' . $strJoinIndex . "\r\n[" . $this->strJoinConditionArray[$strJoinIndex] . ']   vs.   [' . $strConditionClause . ']');
2696:             }
2697: 
2698:             
2699:             $this->strJoinArray[$strJoinIndex] = $strJoinItem;
2700: 
2701:             
2702:             if ($strConditionClause)
2703:                 $this->strJoinConditionArray[$strJoinIndex] = $strConditionClause;
2704:         }
2705: 
2706:         2707: 2708: 2709: 2710: 2711: 2712: 
2713:         public function AddJoinCustomItem($strJoinTableName, $strJoinTableAlias, QQCondition $objJoinCondition) {
2714:             $strJoinItem = sprintf('LEFT JOIN %s%s%s AS %s%s%s ON ',
2715:                 $this->strEscapeIdentifierBegin, $strJoinTableName, $this->strEscapeIdentifierEnd,
2716:                 $this->strEscapeIdentifierBegin, $this->GetTableAlias($strJoinTableAlias), $this->strEscapeIdentifierEnd
2717:             );
2718: 
2719:             $strJoinIndex = $strJoinItem;
2720: 
2721:             try {
2722:                 if (($strConditionClause = $objJoinCondition->GetWhereClause($this, true)))
2723:                     $strJoinItem .= ' AND ' . $strConditionClause;
2724:             } catch (QCallerException $objExc) {
2725:                 $objExc->IncrementOffset();
2726:                 throw $objExc;
2727:             }
2728: 
2729:             $this->strJoinArray[$strJoinIndex] = $strJoinItem;
2730:         }
2731: 
2732:         2733: 2734: 
2735:         public function AddJoinCustomSqlItem($strSql) {
2736:             $this->strJoinArray[$strSql] = $strSql;
2737:         }
2738: 
2739:         2740: 2741: 
2742:         public function AddWhereItem($strItem) {
2743:             array_push($this->strWhereArray, $strItem);
2744:         }
2745: 
2746:         2747: 2748: 
2749:         public function AddOrderByItem($strItem) {
2750:             array_push($this->strOrderByArray, $strItem);
2751:         }
2752: 
2753:         2754: 2755: 
2756:         public function AddGroupByItem($strItem) {
2757:             array_push($this->strGroupByArray, $strItem);
2758:         }
2759: 
2760:         2761: 2762: 
2763:         public function AddHavingItem ($strItem) {
2764:             array_push($this->strHavingArray, $strItem);
2765:         }
2766: 
2767:         2768: 2769: 
2770:         public function SetLimitInfo($strLimitInfo) {
2771:             $this->strLimitInfo = $strLimitInfo;
2772:         }
2773: 
2774:         public function SetDistinctFlag() {
2775:             $this->blnDistinctFlag = true;
2776:         }
2777: 
2778:         public function SetCountOnlyFlag() {
2779:             $this->blnCountOnlyFlag = true;
2780:         }
2781: 
2782:         2783: 2784: 2785: 
2786:         public function SetVirtualNode($strName, QQColumnNode $objNode) {
2787:             $this->objVirtualNodeArray[QQ::GetVirtualAlias($strName)] = $objNode;
2788:         }
2789: 
2790:         2791: 2792: 2793: 2794: 
2795:         public function GetVirtualNode($strName) {
2796:             $strName = QQ::GetVirtualAlias($strName);
2797:             if (isset($this->objVirtualNodeArray[$strName])) {
2798:                 return $this->objVirtualNodeArray[$strName];
2799:             }
2800:             else throw new QCallerException('Undefined Virtual Node: ' . $strName);
2801:         }
2802: 
2803:         2804: 2805: 2806: 
2807:         public function AddExpandAsArrayNode(QQNode $objNode) {
2808:             
2809:             
2810:             $objNode->ExpandAsArray = true;
2811:             while ($objNode->_ParentNode) {
2812:                 $objNode = $objNode->_ParentNode;
2813:             }
2814: 
2815:             if (!$this->objExpandAsArrayNode) {
2816:                 $this->objExpandAsArrayNode = $objNode;
2817:             }
2818:             else {
2819:                 
2820:                 $this->objExpandAsArrayNode->_MergeExpansionNode ($objNode);
2821:             }
2822:         }
2823: 
2824:         2825: 2826: 
2827:         public function GetStatement() {
2828:             $this->ProcessClauses();
2829: 
2830:             
2831:             if ($this->blnCountOnlyFlag) {
2832:                 if ($this->blnDistinctFlag) {
2833:                     $strSql = "SELECT\r\n    COUNT(*) AS q_row_count\r\n" .
2834:                         "FROM    (SELECT DISTINCT ";
2835:                     $strSql .= "    " . implode(",\r\n    ", $this->strSelectArray);
2836:                 } else
2837:                     $strSql = "SELECT\r\n    COUNT(*) AS q_row_count\r\n";
2838:             } else {
2839:                 if ($this->blnDistinctFlag)
2840:                     $strSql = "SELECT DISTINCT\r\n";
2841:                 else
2842:                     $strSql = "SELECT\r\n";
2843:                 if ($this->strLimitInfo)
2844:                     $strSql .= $this->objDatabase->SqlLimitVariablePrefix($this->strLimitInfo) . "\r\n";
2845:                 $strSql .= "    " . implode(",\r\n    ", $this->strSelectArray);
2846:             }
2847: 
2848:             
2849:             $strSql .= sprintf("\r\nFROM\r\n    %s\r\n    %s",
2850:                 implode(",\r\n    ", $this->strFromArray),
2851:                 implode("\r\n    ", $this->strJoinArray));
2852: 
2853:             
2854:             if (count($this->strWhereArray)) {
2855:                 $strWhere = implode("\r\n    ", $this->strWhereArray);
2856:                 if (trim($strWhere) != '1=1')
2857:                     $strSql .= "\r\nWHERE\r\n    " . $strWhere;
2858:             }
2859: 
2860:             
2861:             if (count($this->strGroupByArray))
2862:                 $strSql .= "\r\nGROUP BY\r\n    " . implode(",\r\n    ", $this->strGroupByArray);
2863:             if (count($this->strHavingArray)) {
2864:                 $strHaving = implode("\r\n    ", $this->strHavingArray);
2865:                 $strSql .= "\r\nHaving\r\n    " . $strHaving;
2866:             }
2867:             if (count($this->strOrderByArray))
2868:                 $strSql .= "\r\nORDER BY\r\n    " . implode(",\r\n    ", $this->strOrderByArray);
2869: 
2870:             
2871:             if ($this->strLimitInfo)
2872:                 $strSql .= "\r\n" . $this->objDatabase->SqlLimitVariableSuffix($this->strLimitInfo);
2873: 
2874:             
2875:             if ($this->blnCountOnlyFlag && $this->blnDistinctFlag)
2876:                 $strSql .= "\r\n) as q_count_table";
2877: 
2878:             return $strSql;
2879:         }
2880: 
2881:         2882: 2883: 2884: 2885: 
2886:         public function SetOrderByClause(QQOrderBy $objOrderByClause) {
2887:             if ($this->objOrderByClause) {
2888:                 throw new QCallerException('You can only have one OrderBy clause in a query.');
2889:             }
2890:             $this->objOrderByClause = $objOrderByClause;
2891:         }
2892:         2893: 2894: 2895: 
2896:         protected function ProcessClauses() {
2897:             if ($this->objOrderByClause) {
2898:                 $this->objOrderByClause->_UpdateQueryBuilder($this);
2899:             }
2900:         }
2901: 
2902:         public function __get($strName) {
2903:             switch ($strName) {
2904:                 case 'Database':
2905:                     return $this->objDatabase;
2906:                 case 'RootTableName':
2907:                     return $this->strRootTableName;
2908:                 case 'ColumnAliasArray':
2909:                     return $this->strColumnAliasArray;
2910:                 case 'ExpandAsArrayNode':
2911:                     return $this->objExpandAsArrayNode;
2912: 
2913:                 default:
2914:                     try {
2915:                         return parent::__get($strName);
2916:                     } catch (QCallerException $objExc) {
2917:                         $objExc->IncrementOffset();
2918:                         throw $objExc;
2919:                     }
2920:             }
2921:         }
2922:     }
2923: 
2924:     2925: 2926: 2927: 2928: 
2929:     class QPartialQueryBuilder extends QQueryBuilder {
2930:         protected $objParentBuilder;
2931: 
2932:         2933: 2934: 
2935:         public function __construct(QQueryBuilder $objBuilder) {
2936:             parent::__construct($objBuilder->objDatabase, $objBuilder->strRootTableName);
2937:             $this->objParentBuilder = $objBuilder;
2938:             $this->strColumnAliasArray = &$objBuilder->strColumnAliasArray;
2939:             $this->strTableAliasArray = &$objBuilder->strTableAliasArray;
2940: 
2941:             $this->intTableAliasCount = &$objBuilder->intTableAliasCount;
2942:             $this->intColumnAliasCount = &$objBuilder->intColumnAliasCount;
2943:         }
2944: 
2945:         2946: 2947: 
2948:         public function GetWhereStatement() {
2949:             return implode(' ', $this->strWhereArray);
2950:         }
2951: 
2952:         2953: 2954: 
2955:         public function GetFromStatement() {
2956:             return implode(' ', $this->strFromArray) . ' ' . implode(' ', $this->strJoinArray);
2957:         }
2958:     }
2959: 
2960: