コード例 #1
0
        private void DereferenceEntityJoin(string classAlias, EntityType propertyType, bool impliedJoin, IASTNode parent)
        {
            _dereferenceType = DerefEntity;
            if (Log.IsDebugEnabled)
            {
                Log.Debug("dereferenceEntityJoin() : generating join for " + _propertyName + " in "
                          + FromElement.ClassName + " "
                          + ((classAlias == null) ? "{no alias}" : "(" + classAlias + ")")
                          + " parent = " + ASTUtil.GetDebugstring(parent)
                          );
            }

            // Create a new FROM node for the referenced class.
            string associatedEntityName = propertyType.GetAssociatedEntityName();
            string tableAlias           = AliasGenerator.CreateName(associatedEntityName);

            string[] joinColumns = GetColumns();
            string   joinPath    = Path;

            if (impliedJoin && Walker.IsInFrom)
            {
                _joinType = Walker.ImpliedJoinType;
            }

            FromClause  currentFromClause = Walker.CurrentFromClause;
            FromElement elem = currentFromClause.FindJoinByPath(joinPath);

            ///////////////////////////////////////////////////////////////////////////////
            //
            // This is the piece which recognizes the condition where an implicit join path
            // resolved earlier in a correlated subquery is now being referenced in the
            // outer query.  For 3.0final, we just let this generate a second join (which
            // is exactly how the old parser handles this).  Eventually we need to add this
            // logic back in and complete the logic in FromClause.promoteJoin; however,
            // FromClause.promoteJoin has its own difficulties (see the comments in
            // FromClause.promoteJoin).
            //
            //		if ( elem == null ) {
            //			// see if this joinPath has been used in a "child" FromClause, and if so
            //			// promote that element to the outer query
            //			FromClause currentNodeOwner = getFromElement().getFromClause();
            //			FromClause currentJoinOwner = currentNodeOwner.locateChildFromClauseWithJoinByPath( joinPath );
            //			if ( currentJoinOwner != null && currentNodeOwner != currentJoinOwner ) {
            //				elem = currentJoinOwner.findJoinByPathLocal( joinPath );
            //				if ( elem != null ) {
            //					currentFromClause.promoteJoin( elem );
            //					// EARLY EXIT!!!
            //					return;
            //				}
            //			}
            //		}
            //
            ///////////////////////////////////////////////////////////////////////////////

            bool found = elem != null;
            // even though we might find a pre-existing element by join path, for FromElements originating in a from-clause
            // we should only ever use the found element if the aliases match (null != null here).  Implied joins are
            // always (?) ok to reuse.
            bool useFoundFromElement = found && (elem.IsImplied || (AreSame(classAlias, elem.ClassAlias)));

            if (!useFoundFromElement)
            {
                // If this is an implied join in a from element, then use the impled join type which is part of the
                // tree parser's state (set by the gramamar actions).
                JoinSequence joinSequence = SessionFactoryHelper
                                            .CreateJoinSequence(impliedJoin, propertyType, tableAlias, _joinType, joinColumns);

                FromElementFactory factory = new FromElementFactory(
                    currentFromClause,
                    GetLhs().FromElement,
                    joinPath,
                    classAlias,
                    joinColumns,
                    impliedJoin
                    );
                elem = factory.CreateEntityJoin(
                    associatedEntityName,
                    tableAlias,
                    joinSequence,
                    _fetch,
                    Walker.IsInFrom,
                    propertyType
                    );
            }
            else
            {
                currentFromClause.AddDuplicateAlias(classAlias, elem);
            }


            SetImpliedJoin(elem);
            Walker.AddQuerySpaces(elem.EntityPersister.QuerySpaces);
            FromElement = elem;                 // This 'dot' expression now refers to the resulting from element.
        }