Пример #1
0
        private FromElement CreateCollectionJoin(JoinSequence collectionJoinSequence, string tableAlias)
        {
            string      text        = _queryableCollection.TableName;
            IASTNode    ast         = CreateFromElement(text);
            FromElement destination = (FromElement)ast;
            IType       elementType = _queryableCollection.ElementType;

            if (elementType.IsCollectionType)
            {
                throw new SemanticException("Collections of collections are not supported!");
            }

            destination.InitializeCollection(_fromClause, _classAlias, tableAlias);
            destination.Type = HqlSqlWalker.JOIN_FRAGMENT;              // Tag this node as a JOIN.
            destination.SetIncludeSubclasses(false);                    // Don't include subclasses in the join.
            destination.CollectionJoin = true;                          // This is a clollection join.
            destination.JoinSequence   = collectionJoinSequence;
            destination.SetOrigin(_origin, false);
            destination.CollectionTableAlias = tableAlias;
            //		origin.addDestination( destination );
            // This was the cause of HHH-242
            //		origin.setType( FROM_FRAGMENT );			// Set the parent node type so that the AST is properly formed.
            _origin.Text           = "";                                // The destination node will have all the FROM text.
            _origin.CollectionJoin = true;                              // The parent node is a collection join too (voodoo - see JoinProcessor)
            _fromClause.AddCollectionJoinFromElementByPath(_path, destination);
            _fromClause.Walker.AddQuerySpaces(_queryableCollection.CollectionSpaces);
            return(destination);
        }
		/// <summary>
		/// Generate a join sequence representing the given association type.
		/// </summary>
		/// <param name="implicitJoin">Should implicit joins (theta-style) or explicit joins (ANSI-style) be rendered</param>
		/// <param name="associationType">The type representing the thing to be joined into.</param>
		/// <param name="tableAlias">The table alias to use in qualifing the join conditions</param>
		/// <param name="joinType">The type of join to render (inner, outer, etc)</param>
		/// <param name="columns">The columns making up the condition of the join.</param>
		/// <returns>The generated join sequence.</returns>
		public JoinSequence CreateJoinSequence(bool implicitJoin, IAssociationType associationType, string tableAlias, JoinType joinType, string[] columns) 
		{
			JoinSequence joinSequence = CreateJoinSequence();
			joinSequence.SetUseThetaStyle(implicitJoin);	// Implicit joins use theta style (WHERE pk = fk), explicit joins use JOIN (after from)
			joinSequence.AddJoin( associationType, tableAlias, joinType, columns );
			return joinSequence;
		}
Пример #3
0
        private FromElement CreateManyToMany(
            string role,
            string associatedEntityName,
            string roleAlias,
            IEntityPersister entityPersister,
            EntityType type,
            JoinType joinType)
        {
            FromElement elem;
            SessionFactoryHelperExtensions sfh = _fromClause.SessionFactoryHelper;

            if (_inElementsFunction /*implied*/)
            {
                // For implied many-to-many, just add the end join.
                JoinSequence joinSequence = CreateJoinSequence(roleAlias, joinType);
                elem = CreateJoin(associatedEntityName, roleAlias, joinSequence, type, true);
            }
            else
            {
                // For an explicit many-to-many relationship, add a second join from the intermediate
                // (many-to-many) table to the destination table.  Also, make sure that the from element's
                // idea of the destination is the destination table.
                string   tableAlias        = _fromClause.AliasGenerator.CreateName(entityPersister.EntityName);
                string[] secondJoinColumns = sfh.GetCollectionElementColumns(role, roleAlias);

                // Add the second join, the one that ends in the destination table.
                JoinSequence joinSequence = CreateJoinSequence(roleAlias, joinType);
                joinSequence.AddJoin(sfh.GetElementAssociationType(_collectionType), tableAlias, joinType, secondJoinColumns);
                elem = CreateJoin(associatedEntityName, tableAlias, joinSequence, type, false);
                elem.UseFromFragment = true;
            }
            return(elem);
        }
Пример #4
0
        private FromElement CreateEntityAssociation(
            string role,
            string roleAlias,
            JoinType joinType)
        {
            FromElement elem;
            IQueryable  entityPersister      = (IQueryable)_queryableCollection.ElementPersister;
            string      associatedEntityName = entityPersister.EntityName;

            // Get the class name of the associated entity.
            if (_queryableCollection.IsOneToMany)
            {
                if (Log.IsDebugEnabled)
                {
                    Log.Debug("createEntityAssociation() : One to many - path = " + _path + " role = " + role + " associatedEntityName = " + associatedEntityName);
                }

                JoinSequence joinSequence = CreateJoinSequence(roleAlias, joinType);

                elem = CreateJoin(associatedEntityName, roleAlias, joinSequence, (EntityType)_queryableCollection.ElementType, false);
            }
            else
            {
                if (Log.IsDebugEnabled)
                {
                    Log.Debug("createManyToMany() : path = " + _path + " role = " + role + " associatedEntityName = " + associatedEntityName);
                }

                elem = CreateManyToMany(role, associatedEntityName,
                                        roleAlias, entityPersister, (EntityType)_queryableCollection.ElementType, joinType);
                _fromClause.Walker.AddQuerySpaces(_queryableCollection.CollectionSpaces);
            }
            elem.CollectionTableAlias = roleAlias;
            return(elem);
        }
Пример #5
0
        public FromElement CreateCollectionElementsJoin(IQueryableCollection queryableCollection,
                                                        String collectionName)
        {
            JoinSequence collectionJoinSequence = _fromClause.SessionFactoryHelper.CreateCollectionJoinSequence(queryableCollection, collectionName);

            _queryableCollection = queryableCollection;
            return(CreateCollectionJoin(collectionJoinSequence, null));
        }
Пример #6
0
 /// <summary>
 ///
 /// </summary>
 /// <param name="q"></param>
 public void Start(QueryTranslator q)
 {
     if (!continuation)
     {
         Reset(q);
         path.Length  = 0;
         joinSequence = new JoinSequence(q.Factory).SetUseThetaStyle(useThetaStyleJoin);
     }
 }
Пример #7
0
        public FromElement CreateElementJoin(IQueryableCollection queryableCollection)
        {
            _implied            = true;  //TODO: always true for now, but not if we later decide to support elements() in the from clause
            _inElementsFunction = true;

            IType elementType = queryableCollection.ElementType;

            if (!elementType.IsEntityType)
            {
                throw new InvalidOperationException("Cannot create element join for a collection of non-entities!");
            }

            _queryableCollection = queryableCollection;

            SessionFactoryHelperExtensions sfh     = _fromClause.SessionFactoryHelper;
            IEntityPersister entityPersister       = queryableCollection.ElementPersister;
            string           tableAlias            = _fromClause.AliasGenerator.CreateName(entityPersister.EntityName);
            string           associatedEntityName  = entityPersister.EntityName;
            IEntityPersister targetEntityPersister = sfh.RequireClassPersister(associatedEntityName);

            // Create the FROM element for the target (the elements of the collection).
            FromElement destination = CreateAndAddFromElement(
                associatedEntityName,
                _classAlias,
                targetEntityPersister,
                (EntityType)queryableCollection.ElementType,
                tableAlias
                );

            // If the join is implied, then don't include sub-classes on the element.
            if (_implied)
            {
                destination.IncludeSubclasses = false;
            }

            _fromClause.AddCollectionJoinFromElementByPath(_path, destination);
            //		origin.addDestination(destination);
            // Add the query spaces.
            _fromClause.Walker.AddQuerySpaces(entityPersister.QuerySpaces);

            CollectionType type      = queryableCollection.CollectionType;
            string         role      = type.Role;
            string         roleAlias = _origin.TableAlias;

            string[]         targetColumns          = sfh.GetCollectionElementColumns(role, roleAlias);
            IAssociationType elementAssociationType = sfh.GetElementAssociationType(type);

            // Create the join element under the from element.
            JoinSequence joinSequence = sfh.CreateJoinSequence(_implied, elementAssociationType, tableAlias, JoinType.InnerJoin, targetColumns);
            FromElement  elem         = InitializeJoin(_path, destination, joinSequence, targetColumns, _origin, false);

            elem.UseFromFragment      = true;           // The associated entity is implied, but it must be included in the FROM.
            elem.CollectionTableAlias = roleAlias;      // The collection alias is the role.
            return(elem);
        }
Пример #8
0
        private static SqlString ProcessFromFragment(SqlString frag, JoinSequence join)
        {
            SqlString fromFragment = frag.Trim();

            // The FROM fragment will probably begin with ', '.  Remove this if it is present.
            if (fromFragment.StartsWithCaseInsensitive(", "))
            {
                fromFragment = fromFragment.Substring(2);
            }
            return(fromFragment);
        }
Пример #9
0
 private void AddJoin(JoinSequence joinSequence, QueryTranslator q)
 {
     q.AddFromJoinOnly(pathExpressionParser.Name, joinSequence);
     try
     {
         AddToCurrentJoin(joinSequence.ToJoinFragment(q.EnabledFilters, true).ToWhereFragmentString);
     }
     catch (MappingException me)
     {
         throw new QueryException(me);
     }
 }
		/// <summary>
		/// Create a join sequence rooted at the given collection.
		/// </summary>
		/// <param name="collPersister">The persister for the collection at which the join should be rooted.</param>
		/// <param name="collectionName">The alias to use for qualifying column references.</param>
		/// <returns>The generated join sequence.</returns>
		public JoinSequence CreateCollectionJoinSequence(IQueryableCollection collPersister, String collectionName)
		{
			JoinSequence joinSequence = CreateJoinSequence();
			joinSequence.SetRoot(collPersister, collectionName);
			joinSequence.SetUseThetaStyle(true);		// TODO: figure out how this should be set.

			///////////////////////////////////////////////////////////////////////////////
			// This was the reason for failures regarding INDEX_OP and subclass joins on
			// theta-join dialects; not sure what behaviour we were trying to emulate ;)
			//		joinSequence = joinSequence.getFromPart();	// Emulate the old addFromOnly behavior.
			return joinSequence;
		}
Пример #11
0
        IASTNode CreateFromFilterElement(IASTNode filterEntity, IASTNode alias)
        {
            var fromElementFound = true;

            var fromElement = _currentFromClause.GetFromElement(alias.Text) ??
                              _currentFromClause.GetFromElementByClassName(filterEntity.Text);

            if (fromElement == null)
            {
                fromElementFound = false;
                fromElement      = _currentFromClause.AddFromElement(filterEntity.Text, alias);
            }

            FromClause           fromClause = fromElement.FromClause;
            IQueryableCollection persister  = _sessionFactoryHelper.GetCollectionPersister(_collectionFilterRole);

            // Get the names of the columns used to link between the collection
            // owner and the collection elements.
            String[] keyColumnNames = persister.KeyColumnNames;
            String   fkTableAlias   = persister.IsOneToMany
                                        ? fromElement.TableAlias
                                        : fromClause.AliasGenerator.CreateName(_collectionFilterRole);

            JoinSequence join = _sessionFactoryHelper.CreateJoinSequence();

            join.SetRoot(persister, fkTableAlias);

            if (!persister.IsOneToMany)
            {
                join.AddJoin((IAssociationType)persister.ElementType,
                             fromElement.TableAlias,
                             JoinType.InnerJoin,
                             persister.GetElementColumnNames(fkTableAlias));
            }

            join.AddCondition(fkTableAlias, keyColumnNames, " = ", true);
            fromElement.JoinSequence = join;
            fromElement.Filter       = true;

            if (log.IsDebugEnabled())
            {
                log.Debug("createFromFilterElement() : processed filter FROM element.");
            }

            if (fromElementFound)
            {
                return((IASTNode)adaptor.Nil());
            }

            return(fromElement);
        }
Пример #12
0
        public FromElement CreateEntityJoin(
            string entityClass,
            string tableAlias,
            JoinSequence joinSequence,
            bool fetchFlag,
            bool inFrom,
            EntityType type)
        {
            FromElement elem = CreateJoin(entityClass, tableAlias, joinSequence, type, false);

            elem.Fetch = fetchFlag;

            //if (numberOfTables > 1 && _implied && !elem.UseFromFragment)
            // NH Different behavior: numberOfTables was removed because an
            // implicit join is an implicit join even if it not come from a
            // multi-table entity
            if (_implied && !elem.UseFromFragment)
            {
                if (Log.IsDebugEnabled)
                {
                    Log.Debug("createEntityJoin() : Implied entity join");
                }
                elem.UseFromFragment = true;
            }

            // If this is an implied join in a FROM clause, then use ANSI-style joining, and set the
            // flag on the FromElement that indicates that it was implied in the FROM clause itself.
            if (_implied && inFrom)
            {
                joinSequence.SetUseThetaStyle(false);
                elem.UseFromFragment = true;
                elem.SetImpliedInFromClause(true);
            }
            if (elem.Walker.IsSubQuery)
            {
                // two conditions where we need to transform this to a theta-join syntax:
                //      1) 'elem' is the "root from-element" in correlated subqueries
                //      2) The DotNode.useThetaStyleImplicitJoins has been set to true
                //          and 'elem' represents an implicit join
                if (elem.FromClause != elem.Origin.FromClause || DotNode.UseThetaStyleImplicitJoins)
                {
                    // the "root from-element" in correlated subqueries do need this piece
                    elem.Type = HqlSqlWalker.FROM_FRAGMENT;
                    joinSequence.SetUseThetaStyle(true);
                    elem.UseFromFragment = false;
                }
            }

            return(elem);
        }
Пример #13
0
 private FromElement InitializeJoin(
     string path,
     FromElement destination,
     JoinSequence joinSequence,
     string[] columns,
     FromElement origin,
     bool manyToMany)
 {
     destination.Type         = HqlSqlWalker.JOIN_FRAGMENT;
     destination.JoinSequence = joinSequence;
     destination.Columns      = columns;
     destination.SetOrigin(origin, manyToMany);
     _fromClause.AddJoinByPathMap(path, destination);
     return(destination);
 }
Пример #14
0
        public EntityJoinFromElement(FromClause fromClause, IQueryable entityPersister, JoinType joinType, string alias)
            : base(new CommonToken(HqlSqlWalker.ENTITY_JOIN, entityPersister.TableName))
        {
            string tableAlias = fromClause.AliasGenerator.CreateName(entityPersister.EntityName);

            EntityType entityType = (EntityType)entityPersister.Type;

            InitializeEntity(fromClause, entityPersister.EntityName, entityPersister, entityType, alias, tableAlias);

            //NH Specific: hibernate uses special class EntityJoinJoinSequenceImpl
            JoinSequence = new JoinSequence(SessionFactoryHelper.Factory)
                           .AddJoin(entityType, tableAlias, joinType, Array.Empty <string>());

            fromClause.Walker.AddQuerySpaces(entityPersister.QuerySpaces);
        }
Пример #15
0
        private FromElement CreateJoin(
            string entityClass,
            string tableAlias,
            JoinSequence joinSequence,
            EntityType type,
            bool manyToMany)
        {
            //  origin, path, implied, columns, classAlias,
            IEntityPersister entityPersister = _fromClause.SessionFactoryHelper.RequireClassPersister(entityClass);
            FromElement      destination     = CreateAndAddFromElement(entityClass,
                                                                       _classAlias,
                                                                       entityPersister,
                                                                       type,
                                                                       tableAlias);

            return(InitializeJoin(_path, destination, joinSequence, Columns, _origin, manyToMany));
        }
Пример #16
0
        private void AddJoinNodes(QueryNode query, JoinSequence join, FromElement fromElement)
        {
            JoinFragment joinFragment = join.ToJoinFragment(
                _walker.EnabledFilters,
                fromElement.UseFromFragment || fromElement.IsDereferencedBySuperclassOrSubclassProperty,
                fromElement.WithClauseFragment,
                fromElement.WithClauseJoinAlias
                );

            SqlString frag      = joinFragment.ToFromFragmentString;
            SqlString whereFrag = joinFragment.ToWhereFragmentString;

            // If the from element represents a JOIN_FRAGMENT and it is
            // a theta-style join, convert its type from JOIN_FRAGMENT
            // to FROM_FRAGMENT
            if (fromElement.Type == HqlSqlWalker.JOIN_FRAGMENT &&
                (join.IsThetaStyle || StringHelper.IsNotEmpty(whereFrag)))
            {
                fromElement.Type = HqlSqlWalker.FROM_FRAGMENT;
                fromElement.JoinSequence.SetUseThetaStyle(true);                   // this is used during SqlGenerator processing
            }

            // If there is a FROM fragment and the FROM element is an explicit, then add the from part.
            if (fromElement.UseFromFragment /*&& StringHelper.isNotEmpty( frag )*/)
            {
                SqlString fromFragment = ProcessFromFragment(frag, join).Trim();
                if (log.IsDebugEnabled)
                {
                    log.Debug("Using FROM fragment [" + fromFragment + "]");
                }

                ProcessDynamicFilterParameters(
                    fromFragment,
                    fromElement,
                    _walker
                    );
            }

            _syntheticAndFactory.AddWhereFragment(
                joinFragment,
                whereFrag,
                query,
                fromElement,
                _walker
                );
        }
Пример #17
0
        public void ProcessJoins(IRestrictableStatement query)
        {
            FromClause fromClause       = query.FromClause;
            var        supportRootAlias = !(query is DeleteStatement || query is UpdateStatement);

            IList <FromElement> fromElements;

            if (DotNode.UseThetaStyleImplicitJoins)
            {
                // for regression testing against output from the old parser...
                // found it easiest to simply reorder the FromElements here into ascending order
                // in terms of injecting them into the resulting sql ast in orders relative to those
                // expected by the old parser; this is definitely another of those "only needed
                // for regression purposes".  The SyntheticAndFactory, then, simply injects them as it
                // encounters them.
                fromElements = new List <FromElement>();
                var t = fromClause.GetFromElementsTyped();

                for (int i = t.Count - 1; i >= 0; i--)
                {
                    fromElements.Add(t[i]);
                }
            }
            else
            {
                fromElements = fromClause.GetFromElementsTyped();
            }

            // Iterate through the alias,JoinSequence pairs and generate SQL token nodes.
            foreach (FromElement fromElement in fromElements)
            {
                JoinSequence join = fromElement.JoinSequence;

                join.SetSelector(new JoinSequenceSelector(_walker, fromClause, fromElement));

                // the delete and update statements created here will never be executed when IsMultiTable is true,
                // only the where clause will be used by MultiTableUpdateExecutor/MultiTableDeleteExecutor. In that case
                // we have to use the alias from the persister.
                AddJoinNodes(query, join, fromElement, supportRootAlias || fromElement.Queryable.IsMultiTable);
            }
        }
 public static string CreateCollectionSubquery(
     JoinSequence joinSequence,
     IDictionary <string, IFilter> enabledFilters,
     String[] columns)
 {
     try
     {
         JoinFragment join = joinSequence.ToJoinFragment(enabledFilters, true);
         return(new StringBuilder()
                .Append("select ")
                .Append(StringHelper.Join(", ", columns))
                .Append(" from ")
                .Append(join.ToFromFragmentString.Substring(2))                  // remove initial ", "
                .Append(" where ")
                .Append(join.ToWhereFragmentString.Substring(5))                 // remove initial " and "
                .ToString());
     }
     catch (MappingException me)
     {
         throw new QueryException(me);
     }
 }
Пример #19
0
        private void PrepareForIndex(QueryTranslator q)
        {
            IQueryableCollection collPersister = q.GetCollectionPersister(collectionRole);

            if (!collPersister.HasIndex)
            {
                throw new QueryException("unindexed collection before []");
            }
            string[] indexCols = collPersister.IndexColumnNames;
            if (indexCols.Length != 1)
            {
                throw new QueryException("composite-index appears in []: " + path);
            }

            JoinSequence fromJoins = new JoinSequence(q.Factory)
                                     .SetUseThetaStyle(useThetaStyleJoin)
                                     .SetRoot(collPersister, collectionName)
                                     .SetNext(joinSequence.Copy());

            if (!continuation)
            {
                AddJoin(collectionName, collPersister.CollectionType);
            }
            joinSequence.AddCondition(new SqlString(collectionName + '.' + indexCols[0] + " = "));

            CollectionElement elem = new CollectionElement();

            elem.ElementColumns = collPersister.GetElementColumnNames(collectionName);
            elem.Type           = collPersister.ElementType;
            elem.IsOneToMany    = collPersister.IsOneToMany;
            elem.Alias          = collectionName;
            elem.JoinSequence   = joinSequence;
            collectionElements.Add(elem);             //addlast
            SetExpectingCollectionIndex();

            q.AddCollection(collectionName, collectionRole);
            q.AddJoin(collectionName, fromJoins);
        }
Пример #20
0
        public void ProcessJoins(QueryNode query)
        {
            FromClause fromClause = query.FromClause;

            IList <IASTNode> fromElements;

            if (DotNode.UseThetaStyleImplicitJoins)
            {
                // for regression testing against output from the old parser...
                // found it easiest to simply reorder the FromElements here into ascending order
                // in terms of injecting them into the resulting sql ast in orders relative to those
                // expected by the old parser; this is definitely another of those "only needed
                // for regression purposes".  The SyntheticAndFactory, then, simply injects them as it
                // encounters them.
                fromElements = new List <IASTNode>();
                IList <IASTNode> t = fromClause.GetFromElements();

                for (int i = t.Count - 1; i >= 0; i--)
                {
                    fromElements.Add(t[i]);
                }
            }
            else
            {
                fromElements = fromClause.GetFromElements();
            }

            // Iterate through the alias,JoinSequence pairs and generate SQL token nodes.
            foreach (FromElement fromElement in fromElements)
            {
                JoinSequence join = fromElement.JoinSequence;

                join.SetSelector(new JoinSequenceSelector(_walker, fromClause, fromElement));

                AddJoinNodes(query, join, fromElement);
            }
        }
Пример #21
0
        public override void  Resolve(bool generateJoin, bool implicitJoin, string classAlias, IASTNode parent)
        {
            if (IsResolved)
            {
                return;
            }

            FromReferenceNode collectionNode = ( FromReferenceNode )GetChild(0);
            SessionFactoryHelperExtensions sessionFactoryHelper = SessionFactoryHelper;

            collectionNode.ResolveIndex(this);                          // Fully resolve the map reference, create implicit joins.

            IType type = collectionNode.DataType;

            if (!type.IsCollectionType)
            {
                throw new SemanticException("The [] operator cannot be applied to type " + type);
            }

            string collectionRole = (( CollectionType )type).Role;
            IQueryableCollection queryableCollection = sessionFactoryHelper.RequireQueryableCollection(collectionRole);

            if (!queryableCollection.HasIndex)
            {
                throw new QueryException("unindexed fromElement before []: " + collectionNode.Path);
            }

            // Generate the inner join -- The elements need to be joined to the collection they are in.
            FromElement fromElement  = collectionNode.FromElement;
            String      elementTable = fromElement.TableAlias;
            FromClause  fromClause   = fromElement.FromClause;
            String      path         = collectionNode.Path;

            FromElement elem = fromClause.FindCollectionJoin(path);

            if (elem == null)
            {
                FromElementFactory factory = new FromElementFactory(fromClause, fromElement, path);
                elem = factory.CreateCollectionElementsJoin(queryableCollection, elementTable);
                if (Log.IsDebugEnabled)
                {
                    Log.Debug("No FROM element found for the elements of collection join path " + path
                              + ", created " + elem);
                }
            }
            else
            {
                if (Log.IsDebugEnabled)
                {
                    Log.Debug("FROM element found for collection join path " + path);
                }
            }

            // The 'from element' that represents the elements of the collection.
            FromElement = fromElement;

            // Add the condition to the join sequence that qualifies the indexed element.
            IASTNode selector = GetChild(1);

            if (selector == null)
            {
                throw new QueryException("No index value!");
            }

            // Sometimes use the element table alias, sometimes use the... umm... collection table alias (many to many)
            String collectionTableAlias = elementTable;

            if (elem.CollectionTableAlias != null)
            {
                collectionTableAlias = elem.CollectionTableAlias;
            }

            // TODO: get SQL rendering out of here, create an AST for the join expressions.
            // Use the SQL generator grammar to generate the SQL text for the index expression.
            JoinSequence joinSequence = fromElement.JoinSequence;

            string[] indexCols = queryableCollection.IndexColumnNames;
            if (indexCols.Length != 1)
            {
                throw new QueryException("composite-index appears in []: " + collectionNode.Path);
            }

            SqlGenerator gen = new SqlGenerator(SessionFactoryHelper.Factory, new CommonTreeNodeStream(selector));

            try
            {
                gen.simpleExpr();                 //TODO: used to be exprNoParens! was this needed?
            }
            catch (RecognitionException e)
            {
                throw new QueryException(e.Message, e);
            }

            string selectorExpression = gen.GetSQL().ToString();

            joinSequence.AddCondition(new SqlString(collectionTableAlias + '.' + indexCols[0] + " = " + selectorExpression));
            //joinSequence.AddCondition(collectionTableAlias, new string[] { indexCols[0] }, selectorExpression, false);

            IList <IParameterSpecification> paramSpecs = gen.GetCollectedParameters();

            if (paramSpecs != null)
            {
                switch (paramSpecs.Count)
                {
                case 0:
                    // nothing to do
                    break;

                case 1:
                    IParameterSpecification paramSpec = paramSpecs[0];
                    paramSpec.ExpectedType = queryableCollection.IndexType;
                    fromElement.SetIndexCollectionSelectorParamSpec(paramSpec);
                    break;

                default:
                    fromElement.SetIndexCollectionSelectorParamSpec(
                        new AggregatedIndexCollectionSelectorParameterSpecifications(paramSpecs)
                        );
                    break;
                }
            }

            // Now, set the text for this node.  It should be the element columns.
            String[] elementColumns = queryableCollection.GetElementColumnNames(elementTable);
            Text = elementColumns[0];

            IsResolved = true;
        }
Пример #22
0
        public void Token(string token, QueryTranslator q)
        {
            if (token != null)
            {
                path.Append(token);
            }

            string alias = q.GetPathAlias(path.ToString());

            if (alias != null)
            {
                Reset(q);                       //reset the dotcount (but not the path)
                currentName            = alias; //after reset!
                currentPropertyMapping = q.GetPropertyMapping(currentName);
                if (!ignoreInitialJoin)
                {
                    JoinSequence ojf = q.GetPathJoin(path.ToString());
                    try
                    {
                        joinSequence.AddCondition(ojf.ToJoinFragment(q.EnabledFilters, true).ToWhereFragmentString);                         //after reset!
                    }
                    catch (MappingException me)
                    {
                        throw new QueryException(me);
                    }
                    // we don't need to worry about any condition in the ON clause
                    // here (toFromFragmentString), since anything in the ON condition
                    // is already applied to the whole query
                }
            }
            else if (".".Equals(token))
            {
                dotcount++;
            }
            else
            {
                if (dotcount == 0)
                {
                    if (!continuation)
                    {
                        if (!q.IsName(token))
                        {
                            throw new QueryException("undefined alias or unknown mapping: " + token);
                        }
                        currentName            = token;
                        currentPropertyMapping = q.GetPropertyMapping(currentName);
                    }
                }
                else if (dotcount == 1)
                {
                    if (currentName != null)
                    {
                        currentProperty = token;
                    }
                    else if (collectionName != null)
                    {
                        //IQueryableCollection p = q.GetCollectionPersister( collectionRole );
                        //DoCollectionProperty( token, p, collectionName );
                        continuation = false;
                    }
                    else
                    {
                        throw new QueryException("unexpected");
                    }
                }
                else
                {
                    // dotcount>=2

                    // Do the corresponding RHS
                    IType propertyType = PropertyType;

                    if (propertyType == null)
                    {
                        throw new QueryException("unresolved property: " + currentProperty);
                    }

                    if (propertyType.IsComponentType)
                    {
                        DereferenceComponent(token);
                    }
                    else if (propertyType.IsEntityType)
                    {
                        DereferenceEntity(token, (EntityType)propertyType, q);
                    }
                    else if (propertyType.IsCollectionType)
                    {
                        DereferenceCollection(token, ((CollectionType)propertyType).Role, q);
                    }
                    else if (token != null)
                    {
                        throw new QueryException("dereferenced: " + currentProperty);
                    }
                }
            }
        }
Пример #23
0
        public FromElement CreateCollection(IQueryableCollection queryableCollection,
                                            string role,
                                            JoinType joinType,
                                            bool fetchFlag,
                                            bool indexed)
        {
            if (!_collection)
            {
                throw new InvalidOperationException("FromElementFactory not initialized for collections!");
            }

            _inElementsFunction = indexed;
            FromElement elem;

            _queryableCollection = queryableCollection;
            _collectionType      = queryableCollection.CollectionType;
            string roleAlias = _fromClause.AliasGenerator.CreateName(role);

            // Correlated subqueries create 'special' implied from nodes
            // because correlated subselects can't use an ANSI-style join
            bool explicitSubqueryFromElement = _fromClause.IsSubQuery && !_implied;

            if (explicitSubqueryFromElement)
            {
                string      pathRoot = StringHelper.Root(_path);
                FromElement origin   = _fromClause.GetFromElement(pathRoot);
                if (origin == null || origin.FromClause != _fromClause)
                {
                    _implied = true;
                }
            }

            // super-duper-classic-parser-regression-testing-mojo-magic...
            if (explicitSubqueryFromElement && DotNode.UseThetaStyleImplicitJoins)
            {
                _implied = true;
            }

            IType elementType = queryableCollection.ElementType;

            if (elementType.IsEntityType)
            {
                // A collection of entities...
                elem = CreateEntityAssociation(role, roleAlias, joinType);
            }
            else if (elementType.IsComponentType)
            {
                // A collection of components...
                JoinSequence joinSequence = CreateJoinSequence(roleAlias, joinType);
                elem = CreateCollectionJoin(joinSequence, roleAlias);
            }
            else
            {
                // A collection of scalar elements...
                JoinSequence joinSequence = CreateJoinSequence(roleAlias, joinType);
                elem = CreateCollectionJoin(joinSequence, roleAlias);
            }

            elem.SetRole(role);
            elem.QueryableCollection = queryableCollection;
            // Don't include sub-classes for implied collection joins or subquery joins.
            if (_implied)
            {
                elem.IncludeSubclasses = false;
            }

            if (explicitSubqueryFromElement)
            {
                elem.InProjectionList = true;                   // Treat explict from elements in sub-queries properly.
            }

            if (fetchFlag)
            {
                elem.Fetch = true;
            }
            return(elem);
        }
Пример #24
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.
        }
Пример #25
0
        public void ProcessJoins(IRestrictableStatement query)
        {
            FromClause          fromClause = query.FromClause;
            IList <FromElement> fromElements;

            if (DotNode.UseThetaStyleImplicitJoins)
            {
                // for regression testing against output from the old parser...
                // found it easiest to simply reorder the FromElements here into ascending order
                // in terms of injecting them into the resulting sql ast in orders relative to those
                // expected by the old parser; this is definitely another of those "only needed
                // for regression purposes".  The SyntheticAndFactory, then, simply injects them as it
                // encounters them.
                fromElements = new List <FromElement>();
                var t = fromClause.GetFromElementsTyped();

                for (int i = t.Count - 1; i >= 0; i--)
                {
                    fromElements.Add(t[i]);
                }
            }
            else
            {
                fromElements = fromClause.GetFromElementsTyped();

                for (var index = fromElements.Count - 1; index >= 0; index--)
                {
                    var fromElement = fromElements[index];
                    // We found an implied from element that is used in the WITH clause of another from element, so it need to become part of it's join sequence
                    if (fromElement.IsImplied && fromElement.IsPartOfJoinSequence == null)
                    {
                        var origin = fromElement.Origin;
                        while (origin.IsImplied)
                        {
                            origin = origin.Origin;
                            origin.IsPartOfJoinSequence = false;
                        }

                        if (origin.WithClauseFragment?.Contains(fromElement.TableAlias + ".") == true)
                        {
                            List <FromElement> elements = new List <FromElement>();
                            while (fromElement.IsImplied)
                            {
                                elements.Add(fromElement);
                                // This from element will be rendered as part of the origins join sequence
                                fromElement.Text = string.Empty;
                                fromElement.IsPartOfJoinSequence = true;
                                fromElement = fromElement.Origin;
                            }

                            for (var i = elements.Count - 1; i >= 0; i--)
                            {
                                origin.JoinSequence.AddJoin(elements[i]);
                            }
                        }
                    }
                }
            }

            // Iterate through the alias,JoinSequence pairs and generate SQL token nodes.
            foreach (FromElement fromElement in fromElements)
            {
                if (fromElement.IsPartOfJoinSequence == true)
                {
                    continue;
                }

                JoinSequence join = fromElement.JoinSequence;

                join.SetSelector(new JoinSequenceSelector(_walker, fromClause, fromElement));

                // the delete and update statements created here will never be executed when IsMultiTable is true,
                // only the where clause will be used by MultiTableUpdateExecutor/MultiTableDeleteExecutor. In that case
                // we have to use the alias from the persister.
                AddJoinNodes(query, join, fromElement);
            }
        }