111 private $_typeNode = null;
112 private $_isTypeNodeInQuery =
false;
113 private $_rootNodes = array();
114 private $_conditions = array();
115 private $_groups = array();
116 private $_groupedOIDs = array();
117 private $_processedNodes = array();
118 private $_involvedTypes = array();
119 private $_aliasCounter = 1;
120 private $_observedObjects = array();
121 private $_bindOrder = array();
132 $this->_rootNodes[] = $this->_typeNode;
135 array($this,
'valueChanged'));
143 array($this,
'valueChanged'));
167 $fqType = $persistenceFacade->getFullyQualifiedType($type);
168 if ($fqType == $this->_typeNode->getType() && !$this->_isTypeNodeInQuery) {
169 $template = $this->_typeNode;
170 $this->_isTypeNodeInQuery =
true;
177 $this->_rootNodes[] = $template;
179 $template->setProperty(self::PROPERTY_COMBINE_OPERATOR, $combineOperator);
180 if ($alias != null) {
181 $template->setProperty(self::PROPERTY_TABLE_NAME, $alias);
183 $initialOid = $template->getOID()->__toString();
184 $template->setProperty(self::PROPERTY_INITIAL_OID, $initialOid);
185 $this->_observedObjects[$initialOid] = $template;
197 if ($template != null) {
198 $initialOid = $template->
getOID()->__toString();
199 $template->
setProperty(self::PROPERTY_INITIAL_OID, $initialOid);
200 $this->_observedObjects[$initialOid] = $template;
205 $template->
setProperty(self::PROPERTY_COMBINE_OPERATOR, $combineOperator);
206 if ($alias != null) {
207 $template->
setProperty(self::PROPERTY_TABLE_NAME, $alias);
211 if ($template->
getType() == $this->_typeNode->getType() && !$this->_isTypeNodeInQuery) {
212 $newRootNodes = array($template);
213 foreach($this->_rootNodes as $node) {
214 if ($node != $this->_typeNode) {
215 $newRootNodes[] = $node;
218 $this->_rootNodes = $newRootNodes;
219 $this->_isTypeNodeInQuery =
true;
222 $this->_rootNodes[] = $template;
234 $this->_groups[] = array(
'tpls' => $templates, self::PROPERTY_COMBINE_OPERATOR => $combineOperator);
236 for ($i=0; $i<
sizeof($templates); $i++) {
237 if ($templates[$i] != null) {
238 $this->_groupedOIDs[] = $templates[$i]->getOID();
253 $tmp = preg_split(
"/ WHERE /i", $query);
254 if (
sizeof($tmp) > 1) {
255 $tmp = preg_split(
"/ ORDER /i", $tmp[1]);
265 return $this->_typeNode->getType();
272 $type = $this->_typeNode->getType();
273 $mapper = self::getMapper($type);
274 $this->_involvedTypes[$type] =
true;
278 $tableName = self::processTableName($this->_typeNode);
279 $selectStmt = $mapper->getSelectSQL(null, $tableName[
'alias'], array(), $pagingInfo, $this->
getId());
280 if (!$selectStmt->isCached()) {
282 $selectStmt->distinct(
true);
285 foreach ($this->_rootNodes as $curNode) {
286 if (!in_array($curNode->getOID(), $this->_groupedOIDs)) {
292 for ($i=0, $countI=
sizeof($this->_groups); $i<$countI; $i++) {
293 $group = $this->_groups[$i];
295 $tmpSelectStmt->from($this->_typeNode->getProperty(self::PROPERTY_TABLE_NAME));
296 for ($j=0, $countJ=
sizeof($group[
'tpls']); $j<$countJ; $j++) {
297 $tpl = $group[
'tpls'][$j];
301 $wherePart = $tmpSelectStmt->getPart(SelectStatement::WHERE);
302 foreach($wherePart as $where) {
303 $condition .=
" ".$where;
305 $condition = trim($condition);
306 if (strlen($condition) > 0) {
307 $combineOperator = $group[self::PROPERTY_COMBINE_OPERATOR];
309 $selectStmt->orWhere($condition);
312 $selectStmt->where($condition);
322 $selectStmt->setMeta(
'bindOrder', $this->_bindOrder);
326 $selectStmt->bind($this->
getBind($this->_conditions, $selectStmt->getMeta(
'bindOrder')));
341 $oidStr = $tpl->
getOID()->__toString();
342 if (isset($this->_processedNodes[$oidStr])) {
346 $mapper = self::getMapper($tpl->
getType());
347 $tableName = self::processTableName($tpl);
348 $this->_involvedTypes[$tpl->
getType()] =
true;
353 foreach($iter as $valueName => $value) {
355 if (isset($this->_conditions[$oidStr][$valueName])) {
356 $criterion = $this->_conditions[$oidStr][$valueName];
357 if ($criterion instanceof
Criteria) {
358 $attributeDesc = $mapper->getAttribute($valueName);
359 if ($attributeDesc) {
361 if (strlen($condition) > 0) {
362 $condition .=
' '.$criterion->getCombineOperator().
' ';
365 $condition .= $mapper->renderCriteria($criterion,
'?',
366 $tpl->
getProperty(self::PROPERTY_TABLE_NAME), $attributeDesc->getColumn());
367 $this->_bindOrder[] = $this->
getBindPosition($criterion, $this->_conditions);
372 if (strlen($condition) > 0) {
373 $combineOperator = $tpl->
getProperty(self::PROPERTY_COMBINE_OPERATOR);
375 $selectStmt->orWhere($condition);
378 $selectStmt->where($condition);
383 $this->_processedNodes[$oidStr] = $tpl;
387 foreach ($mapper->getRelations() as $relationDescription) {
388 $children = $tpl->
getValue($relationDescription->getOtherRole());
389 if ($children != null && !is_array($children)) {
390 $children = array($children);
392 for($i=0, $count=
sizeof($children); $i<$count; $i++) {
393 $curChild = $children[$i];
394 if ($curChild instanceof
Node) {
399 if (!isset($this->_processedNodes[$curChild->getOID()->__toString()])) {
401 $childTableName = self::processTableName($curChild);
402 $fromPart = $selectStmt->getPart(SelectStatement::FROM);
403 if (!isset($fromPart[$childTableName[
'alias']])) {
404 $childMapper = self::getMapper($curChild->getType());
406 $idAttr = $childMapper->getAttribute($relationDescription->getIdName());
407 $fkAttr = $mapper->getAttribute($relationDescription->getFkName());
408 $joinCondition = $mapper->quoteIdentifier($tpl->
getProperty(self::PROPERTY_TABLE_NAME)).
'.'.
409 $mapper->quoteIdentifier($fkAttr->getColumn()).
' = '.
410 $childMapper->quoteIdentifier($curChild->getProperty(self::PROPERTY_TABLE_NAME)).
'.'.
411 $childMapper->quoteIdentifier($idAttr->getColumn());
413 $selectStmt->join(array($childTableName[
'alias'] => $childTableName[
'name']), $joinCondition,
'');
416 $idAttr = $mapper->getAttribute($relationDescription->getIdName());
417 $fkAttr = $childMapper->getAttribute($relationDescription->getFkName());
418 $joinCondition = $childMapper->quoteIdentifier($curChild->getProperty(self::PROPERTY_TABLE_NAME)).
'.'.
419 $childMapper->quoteIdentifier($fkAttr->getColumn()).
' = '.
420 $mapper->quoteIdentifier($tpl->
getProperty(self::PROPERTY_TABLE_NAME)).
'.'.
421 $mapper->quoteIdentifier($idAttr->getColumn());
423 $selectStmt->join(array($childTableName[
'alias'] => $childTableName[
'name']), $joinCondition,
'');
426 $thisRelationDescription = $relationDescription->getThisEndRelation();
427 $otherRelationDescription = $relationDescription->getOtherEndRelation();
429 $nmMapper = self::getMapper($thisRelationDescription->getOtherType());
430 $otherFkAttr = $nmMapper->getAttribute($otherRelationDescription->getFkName());
431 $otherIdAttr = $childMapper->getAttribute($otherRelationDescription->getIdName());
432 $thisFkAttr = $nmMapper->getAttribute($thisRelationDescription->getFkName());
433 $thisIdAttr = $mapper->getAttribute($thisRelationDescription->getIdName());
435 $joinCondition1 = $nmMapper->quoteIdentifier($nmMapper->getRealTableName()).
'.'.
436 $nmMapper->quoteIdentifier($thisFkAttr->getColumn()).
' = '.
437 $mapper->quoteIdentifier($tpl->
getProperty(self::PROPERTY_TABLE_NAME)).
'.'.
438 $mapper->quoteIdentifier($thisIdAttr->getColumn());
439 $joinCondition2 = $childMapper->quoteIdentifier($curChild->getProperty(self::PROPERTY_TABLE_NAME)).
'.'.
440 $childMapper->quoteIdentifier($otherIdAttr->getColumn()).
' = '.
441 $nmMapper->quoteIdentifier($nmMapper->getRealTableName()).
'.'.
442 $nmMapper->quoteIdentifier($otherFkAttr->getColumn());
444 $selectStmt->join($nmMapper->getRealTableName(), $joinCondition1,
'');
445 $selectStmt->join(array($childTableName[
'alias'] => $childTableName[
'name']), $joinCondition2,
'');
448 $this->_involvedTypes[$nmMapper->getType()] =
true;
454 if (!in_array($curChild->getOID(), $this->_groupedOIDs)) {
472 $selectStmt->reset(SelectStatement::ORDER);
475 foreach ($orderby as $curOrderBy) {
476 $orderByParts = preg_split(
'/ /', $curOrderBy);
477 $orderAttribute = $orderByParts[0];
478 $orderDirection =
sizeof($orderByParts) > 1 ? $orderByParts[1] :
'ASC';
481 if (strpos($orderAttribute,
'.') > 0) {
483 $orderAttributeParts = preg_split(
'/\./', $orderAttribute);
484 $orderAttribute = array_pop($orderAttributeParts);
485 $orderType = join(
'.', $orderAttributeParts);
486 $orderTypeMapper = $persistenceFacade->getMapper($orderType);
490 foreach (array_keys($this->_involvedTypes) as $curType) {
491 $mapper = $persistenceFacade->getMapper($curType);
492 if ($mapper->hasAttribute($orderAttribute)) {
493 $orderTypeMapper = $mapper;
498 if ($orderTypeMapper) {
499 $orderTableName = $orderTypeMapper->getRealTableName();
500 $orderAttributeDesc = $orderTypeMapper->getAttribute($orderAttribute);
501 $orderColumnName = $orderAttributeDesc->getColumn();
503 if ($orderTableName) {
504 $orderAttributeFinal = $orderTableName.
'.'.$orderColumnName;
505 $selectStmt->order(array($orderAttributeFinal.
' '.$orderDirection));
511 throw new UnknownFieldException($orderAttribute,
"The sort field name '"+$orderAttribute+
"' is unknown");
522 protected function getBind($criteria, array $bindOrder) {
525 $criteriaFlat = array();
527 foreach ($criteria as $key => $curCriteria) {
528 foreach ($curCriteria as $criterion) {
529 if ($criterion instanceof
Criteria) {
530 $mapper = $persistenceFacade->getMapper($criterion->getType());
531 $valueName = $criterion->getAttribute();
532 $attributeDesc = $mapper->getAttribute($valueName);
533 if ($attributeDesc) {
534 $criteriaFlat[] = $criterion;
540 foreach ($bindOrder as $index) {
541 $bind[] = $criteriaFlat[$index]->getValue();
548 foreach ($criteria as $key => $curCriteria) {
549 foreach ($curCriteria as $curCriterion) {
550 if ($curCriterion instanceof
Criteria) {
551 if ($curCriterion->__toString() === $criterion->__toString()) {
564 $this->_processedNodes = array();
565 $this->_bindOrder = array();
566 $this->_involvedTypes = array();
567 $this->_aliasCounter = 1;
577 $mapper = self::getMapper($tpl->
getType());
578 $mapperTableName = $mapper->getRealTableName();
580 $tableName = $tpl->
getProperty(self::PROPERTY_TABLE_NAME);
581 if ($tableName == null) {
582 $tableName = $mapperTableName;
587 foreach ($parents as $curParent) {
588 $curParentTableName = $curParent->getProperty(self::PROPERTY_TABLE_NAME);
589 if ($curParentTableName == $tableName) {
590 $tableName .=
'_'.($this->_aliasCounter++);
594 $tpl->
setProperty(self::PROPERTY_TABLE_NAME, $tableName);
597 return array(
'name' => $mapperTableName,
'alias' => $tableName);
607 $initialOid = $object->getProperty(self::PROPERTY_INITIAL_OID);
608 if (isset($this->_observedObjects[$initialOid])) {
611 if (!($newValue instanceof
Criteria)) {
613 $mapper = self::getMapper($object->getType());
614 $pkNames = $mapper->getPkNames();
615 if (!in_array($name, $pkNames)) {
618 if (is_string($newValue)) {
619 $newValue =
new Criteria($object->getType(), $name,
'LIKE',
'%'.$newValue.
'%');
624 $newValue =
new Criteria($object->getType(), $name,
'=', $newValue);
630 $newValue->setType($object->getType());
631 $newValue->setAttribute($name);
634 $oid = $object->getOID()->__toString();
636 if (!isset($this->_conditions[$oid])) {
637 $this->_conditions[$oid] = array();
639 $this->_conditions[$oid][$name] = $newValue;
getType()
Get the type of the object.
resetInternals()
Reset internal variables.
Node related interfaces and classes.
getParentsEx(ObjectId $oid=null, $role=null, $type=null, $values=null, $properties=null, $useRegExp=true)
Get the parents that match given conditions.
getOID()
Get the object id of the PersistentObject.
getObject()
Get the object whose value has changed.
makeGroup($templates, $combineOperator=Criteria::OPERATOR_AND)
Group different templates together to realize brackets in the query.
processTableName(Node $tpl)
Get the table name for the template and calculate an alias if necessary.
getValueName()
Get the name of the value that has changed.
const PROPERTY_INITIAL_OID
IllegalArgumentException signals an exception in method arguments.
copyValues(PersistentObject $object, $copyPkValues=true)
NodeValueIterator is used to iterate over all persistent values of a Node (not including relations)...
getQueryString($orderby=null)
Get the query serialized to a string.
ObjectQuery implements a template based object query.
getProperty($name)
Get the value of a named property in the object.
setProperty($name, $value)
UnknownFieldException signals an exception in a message.
static get(RDBMapper $mapper, $id=self::NO_CACHE)
Get the SelectStatement instance with the given id.
getNewValue()
Get the new value.
ValueChangeEvent signals a change of a value of a PersistentObject instance.
const PROPERTY_COMBINE_OPERATOR
processOrderBy($orderby, SelectStatement $selectStmt)
Process an object template.
Criteria defines a condition on a PersistentObject's attribute used to select specific instances...
__construct($type, $queryId=SelectStatement::NO_CACHE)
Constructor.
static getInstance($name, $dynamicConfiguration=array())
PagingInfo contains information about a paged list.
processObjectTemplate(PersistentObject $tpl, SelectStatement $selectStmt)
Process an object template.
getObjectTemplate($type, $alias=null, $combineOperator=Criteria::OPERATOR_AND)
Get an object template for a given type.
getBindPosition($criterion, $criteria)
Instances of RDBManyToOneRelationDescription describe a many to one relation from 'this' end (many) t...
getQueryCondition()
Get the condition part of the query.
registerObjectTemplate(Node $template, $alias=null, $combineOperator=Criteria::OPERATOR_AND)
Register an object template at the query.
getValue($name)
Get the value of a named item.
getBind($criteria, array $bindOrder)
Get an array of values for bind.
Instances of RDBManyToManyRelationDescription describe a many to many relation from 'this' end to 'ot...
static getMapper($type)
Get the mapper for a Node and check if it is a supported one.
const PROPERTY_TABLE_NAME
buildQuery($orderby=null, PagingInfo $pagingInfo=null)
AbstractQuery is the base class for all query classes.
Instances of RDBOneToManyRelationDescription describe a one to many relation from 'this' end (one) to...
valueChanged(ValueChangeEvent $event)
Listen to ValueChangeEvents.
Node adds the concept of relations to PersistentObject.
PersistentObject defines the interface of all persistent objects.