Cache a single relationship.

@param string       $parentKey
@param string       $relation
@param Mappable     $result
@param Relationship $relationship

@throws MappingException
187590
protected function cacheSingleRelationResult(string $parentKey, string $relation, $result, Relationship $relationship)
    {
        $this->cache[$parentKey][$relation] = $this->getCachedRelationship($relation, $result, $relationship);
    }
19982
public function eagerlyResult(&$result, $relation, $subRelation, $closure)
    {
        $pk = $result->getPk();

        if (isset($result->$pk)) {
            $pk = $result->$pk;
            // 查询管理数据
            $data = $this->eagerlyManyToMany([
                ['pivot.' . $this->localKey, '=', $pk],
            ], $relation, $subRelation, $closure);

            // 关联数据封装
            if (!isset($data[$pk])) {
                $data[$pk] = [];
            }

            $result->setRelation(Db::parseName($relation), $this->resultSetBuild($data[$pk]));
        }
    }
1052949
protected function getRelationshipValue(string $relation)
    {
        $value = $this->getEntityAttribute($relation);

        if (is_scalar($value)) {
            throw new MappingException("Entity's attribute $relation should be array, object, collection or null");
        }

        return $value;
    }
178523
private function findChildNodeWithKey($parentId, $key)
	{
        $result = array();
        $relations = $this->getRelations();

        if (isset($relations[RelationBuilder::TREE_PARAM_PARENTS][$parentId])) {
            foreach ($relations[RelationBuilder::TREE_PARAM_PARENTS][$parentId] as $id) {
                // Current found node
                $node = $relations[RelationBuilder::TREE_PARAM_ITEMS][$id][$key];

                $result = array_merge($result, $this->findChildNodeWithKey($id, $key));
                $result[] = $node;
            }
        }

        return $result;
    }
1009676
protected function insertRelated(PersistenceContext $context, ParentChildMap $map)
    {
        /** @var Row[] $parents */
        $parents = [];
        /** @var array $children */
        $children = [];

        foreach ($map->getItems() as $key => $item) {
            $parents[$key]  = $item->getParent();
            $children[$key] = $item->getChild();
        }

        $primaryKey = $this->mapper->getPrimaryTable()->getPrimaryKeyColumnName();
        $rows       = $this->reference->syncRelated($context, [], $children);

        foreach ($rows as $key => $row) {
            $parent = $parents[$key];

            if ($row->hasColumn($primaryKey)) {
                $this->setForeignKey([$parent], $this->foreignKeyToRelated, $row->getColumn($primaryKey));
            } else {
                $row->onInsertPrimaryKey(function ($id) use ($parent) {
                    $this->setForeignKey([$parent], $this->foreignKeyToRelated, $id);
                });
            }
        }
    }
575387
@Override
	public void cacheResult(
		List<CommercePaymentMethodGroupRel> commercePaymentMethodGroupRels) {
		for (CommercePaymentMethodGroupRel commercePaymentMethodGroupRel : commercePaymentMethodGroupRels) {
			if (entityCache.getResult(
						CommercePaymentMethodGroupRelModelImpl.ENTITY_CACHE_ENABLED,
						CommercePaymentMethodGroupRelImpl.class,
						commercePaymentMethodGroupRel.getPrimaryKey()) == null) {
				cacheResult(commercePaymentMethodGroupRel);
			}
			else {
				commercePaymentMethodGroupRel.resetOriginalValues();
			}
		}
	}
393218
protected function setListParentDataInMemory($relation, $key, $subContext, $context = null)
    {
        $memory = $this->getListMemory();

        $oldContext    = $memory->getContext();
        $oldSubContext = $memory->getSubContext();

        if (null !== $context) {
            $memory->setContext($context);
        }

        $memory->setSubContext($subContext);

        $memory->setListParent($relation, $key);

        if (null !== $context) {
            $memory->setContext($oldContext);
        }

        $memory->setSubContext($oldSubContext);
    }
1285819
public static function buildRelationQuery($entity, Relation $relation) {
        $relQuery = "";
        $getid = "getId";
        if ($relation->getCardinality() == Relation::$manyToMany) {
            $m = "get" . $relation->getName();
            $relQuery .= "INSERT INTO " . $relation->getTable() . " (" . $relation->getLocalColumn() . ", " . $relation->getForeignColumn() . ") ";
            $relQuery .= "VALUES (:" . $relation->getLocalColumn() . ", :" . $relation->getForeignColumn() . ");";
        }
        if ($relation->getCardinality() == Relation::$oneToMany) {
            $relMapper = MapperBuilder::buildFromName($this->mapping, $relation->getEntity());
            $m = "get" . $relation->getName();
            foreach ($entity->$m() as $rel) {
                $setid = "set" . $relMapper->getNameForColumn($relation->getForeignColumn());
                $rel->$setid($entity->$getid());
                $relQuery .= $this->buildInsertQuery($rel);
            }
        }


        return $relQuery;
    }
1277864
public function match(array $results, $relation)
    {
        foreach (array_keys($this->dictionary) as $type) {
            $results = $this->matchToMorphParents($type, $this->getResultsByType($type), $results);
        }

        return $results;
    }
499417
protected function insertRelated(PersistenceContext $context, ParentChildMap $map)
    {
        $primaryKey = $map->getPrimaryKeyColumn();
        /** @var Row[] $parents */
        $parents = [];
        /** @var array $children */
        $children = [];

        foreach ($map->getItems() as $key => $item) {
            $parents[$key]  = $item->getParent();
            $children[$key] = $item->getChild();
        }

        $rows = $this->reference->syncRelated($context, [$this->foreignKeyColumn], $children);

        $selfReferencingChildRows = [];

        foreach ($rows as $key => $row) {
            $parent = $parents[$key];

            if ($parent->hasColumn($primaryKey)) {
                $this->setForeignKey([$row], $this->foreignKeyToParent, $parent->getColumn($primaryKey));
            } else {
                $parent->onInsertPrimaryKey(function ($id) use ($row) {
                    $this->setForeignKey([$row], $this->foreignKeyToParent, $id);
                });

                if ($parent === $row) {
                    $selfReferencingChildRows[] = $row;
                }
            }
        }

        if ($selfReferencingChildRows) {
            // If the rows are self-referencing and need to be inserted
            // an extra step must be taken because the primary key will
            // only be known after inserting so the foreign key to itself
            // will have to be updated separately afterwards
            $context->bulkUpdate(new RowSet($this->relatedTable->withColumnsButIgnoringConstraints([
                $this->relatedPrimaryKey,
                $this->foreignKeyColumn,
            ]), $selfReferencingChildRows));
        }
    }
321932
protected function synchronize(string $relation)
    {
        $actualContent = $this->relationships[$relation];

        $relationshipObject = $this->entityMap->$relation($this->getEntityObject());
        $relationshipObject->setParent($this->wrappedEntity);
        $relationshipObject->sync($actualContent);
    }
1036793
protected function joinIntermediate(Model $parent, Relation $relation, $type)
    {
        if ($relation instanceof BelongsToMany) {
            $table = $relation->getTable();
            $fk = $relation->getQualifiedForeignPivotKeyName();
        } else {
            $table = $relation->getParent()->getTable();
            $fk = $relation->getQualifiedFirstKeyName();
        }

        $pk = $parent->getQualifiedKeyName();

        if (!$this->alreadyJoined($join = (new Join($this->query, $type, $table))->on($fk, '=', $pk))) {
            $this->query->joins[] = $join;
        }
    }
1372426
public function match(array $models, Collection $results, $relation)
    {
        // We will need the parent node placeholder so that we use it to extract related results.
        $parent = $this->query->getQuery()->modelAsNode($this->parent->getTable());

        /**
         * Looping into all the parents to match back onto their children using
         * the primary key to map them onto the correct instances, every single
         * result will be having both instances at each Collection item, held by their
         * node placeholder.
         */
        foreach ($models as $model)
        {
            $matched = $results->filter(function($result) use($parent, $model)
            {
                if ($result[$parent] instanceof Model)
                {
                    // In the case of fetching nested relations, we will get an array
                    // with the first key being the model we need, and the other being
                    // the related model so we'll just take the first model out of the array.
                    if (is_array($model)) $model = reset($model);

                    return $model->getKey() == $result[$parent]->getKey();
                }
            });

            // Now that we have the matched parents we know where to add the relations.
            // Sometimes we have more than a match so we gotta catch them all!
            foreach ($matched as $match)
            {
                // In the case of fetching nested relations, we will get an array
                // with the first key being the model we need, and the other being
                // the related model so we'll just take the first model out of the array.
                if (is_array($model)) $model = reset($model);

                $model->setRelation($relation, $match[$relation]);
            }
        }

        return $models;
    }
969067
private void readRelation(Relationship relation)
   {
      Task predecessor = m_activityMap.get(relation.getPredecessor());
      Task successor = m_activityMap.get(relation.getSuccessor());
      if (predecessor != null && successor != null)
      {
         Duration lag = relation.getLag();
         RelationType type = relation.getType();
         successor.addPredecessor(predecessor, type, lag);
      }
   }
1038836
public function getEmptyValueForRelationship(string $relation)
    {
        if ($this->isSingleRelationship($relation)) {
            return;
        }

        if ($this->isManyRelationship($relation)) {
            return new Collection();
        }

        throw new MappingException("Cannot determine default value of $relation");
    }
967146
public static function loadPivotAttribute(Model $model, Relation $parentRelation = null)
    {
        $attributes = $model->getAttributes();

        foreach ($attributes as $key => $value) {
            if ($key === 'pivot') {
                unset($model[$key]);
                $pivot = $parentRelation->newExistingPivot($value);
                $model->setRelation($key, $pivot);
            }
        }
    }
1301234
public function assignChildren ($relationIdentifier, $id, $childIds, $subtractive = true)
		{
			$relation = $this->getRelation($relationIdentifier);
			$childIds = (array)$childIds;

			if (! $relation) {
				throw new RelationException('Invalid relation `' . $relationIdentifier);
			}

			if ($relation instanceof OneToMany) {
				$this->database->createQuery()
					->update()
					->table($relation->getRelatedTable())
					->set(
						array(
							$relation->getRelatedKey() => $id,
						)
					)
					->whereIn($this->database->primaryKey($relation->getRelatedTable()), $childIds)
					->execute();

				if ($subtractive) {
					$this->database->createQuery()
						->update()
						->table($relation->getRelatedTable())
						->set(
							array(
								$relation->getRelatedKey() => null,
							)
						)
						->whereEqual($relation->getRelatedKey(), $id)
						->whereNotIn($this->database->primaryKey($relation->getRelatedTable()), $childIds)
						->execute();
				}
			} else if ($relation instanceof ManyToMany) {
				if ($subtractive) {
					$this->database->createQuery()
						->delete()
						->from($relation->getRelationalTable())
						->whereEqual($relation->getKey(), $id)
						->whereNotIn($relation->getRelatedKey(), $childIds)
						->execute();
				}

				$query = $this->database->createQuery();

				$assignedIds =
					$query->select($relation->getRelatedKey())
						->from($relation->getRelationalTable())
						->whereEqual($relation->getKey(), $id)
						->execute()
						->fetchColumn();

				$newIds = array_diff($childIds, $assignedIds);

				foreach ($newIds as $newId) {
					$this->database->createQuery()
						->insert()
						->into($relation->getRelationalTable())
						->set(
							array(
								$relation->getKey()        => $id,
								$relation->getRelatedKey() => $newId,
							)
						)
						->execute();
				}
			} else {
				throw new RelationException('Invalid relation type `' . gettype($relation) . '`');
			}
		}