Пример #1
0
        /// <summary>
        /// For a collection role, return a list of associations to be fetched by outerjoin
        /// </summary>
        private void WalkCollectionTree(IQueryableCollection persister, string alias, string path, string subPathAlias, int currentDepth)
        {
            if (persister.IsOneToMany)
            {
                WalkEntityTree((IOuterJoinLoadable)persister.ElementPersister, alias, path, currentDepth);
            }
            else
            {
                IType type = persister.ElementType;
                if (type.IsAssociationType)
                {
                    // a many-to-many
                    // decrement currentDepth here to allow join across the association table
                    // without exceeding MAX_FETCH_DEPTH (i.e. the "currentDepth - 1" bit)
                    IAssociationType associationType   = (IAssociationType)type;
                    string[]         aliasedLhsColumns = persister.GetElementColumnNames(alias);
                    string[]         lhsColumns        = persister.ElementColumnNames;

                    // if the current depth is 0, the root thing being loaded is the
                    // many-to-many collection itself.  Here, it is alright to use
                    // an inner join...
                    bool useInnerJoin = currentDepth == 0;

                    var joinType =
                        GetJoinType(
                            associationType,
                            persister.FetchMode,
                            path,
                            subPathAlias,
                            persister.TableName,
                            lhsColumns,
                            !useInnerJoin,
                            currentDepth - 1,
                            null);

                    AddAssociationToJoinTreeIfNecessary(
                        associationType,
                        aliasedLhsColumns,
                        alias,
                        path,
                        subPathAlias,
                        currentDepth - 1,
                        joinType);
                }
                else if (type.IsComponentType)
                {
                    WalkCompositeElementTree(
                        (IAbstractComponentType)type,
                        persister.ElementColumnNames,
                        persister,
                        alias,
                        path,
                        subPathAlias,
                        currentDepth);
                }
            }
        }
Пример #2
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);
        }
Пример #3
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);
        }
Пример #4
0
		/// <summary>
		/// For a collection role, return a list of associations to be fetched by outerjoin
		/// </summary>
		private void WalkCollectionTree(IQueryableCollection persister, string alias, string path, int currentDepth)
		{
			if (persister.IsOneToMany)
			{
				WalkEntityTree((IOuterJoinLoadable)persister.ElementPersister, alias, path, currentDepth);
			}
			else
			{
				IType type = persister.ElementType;
				if (type.IsAssociationType)
				{
					// a many-to-many
					// decrement currentDepth here to allow join across the association table
					// without exceeding MAX_FETCH_DEPTH (i.e. the "currentDepth - 1" bit)
					IAssociationType associationType = (IAssociationType)type;
					string[] aliasedLhsColumns = persister.GetElementColumnNames(alias);
					string[] lhsColumns = persister.ElementColumnNames;

					// if the current depth is 0, the root thing being loaded is the
					// many-to-many collection itself.  Here, it is alright to use
					// an inner join...
					bool useInnerJoin = currentDepth == 0;

					JoinType joinType =
						GetJoinType(associationType, persister.FetchMode, path, persister.TableName, lhsColumns, !useInnerJoin,
												currentDepth - 1, null);

					AddAssociationToJoinTreeIfNecessary(associationType, aliasedLhsColumns, alias, path, currentDepth - 1, joinType);
				}
				else if (type.IsComponentType)
				{
					WalkCompositeElementTree((IAbstractComponentType)type, persister.ElementColumnNames, persister, alias, path,
																	 currentDepth);
				}
			}
		}
Пример #5
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;
        }
        public string[] ToColumns(string alias, string propertyName)
        {
            string[] cols;
            switch (propertyName)
            {
            case CollectionPropertyNames.Elements:
                return(memberPersister.GetElementColumnNames(alias));

            case CollectionPropertyNames.Indices:
                if (!memberPersister.HasIndex)
                {
                    throw new QueryException("unindexed collection before indices()");
                }
                return(memberPersister.GetIndexColumnNames(alias));

            case CollectionPropertyNames.Size:
                cols = memberPersister.KeyColumnNames;
                return(new string[] { "count(" + alias + '.' + cols[0] + ')' });

            case CollectionPropertyNames.MaxIndex:
                if (!memberPersister.HasIndex)
                {
                    throw new QueryException("unindexed collection in maxIndex()");
                }
                cols = memberPersister.GetIndexColumnNames(alias);
                if (cols.Length != 1)
                {
                    throw new QueryException("composite collection index in maxIndex()");
                }
                return(new string[] { "max(" + cols[0] + ')' });

            case CollectionPropertyNames.MinIndex:
                if (!memberPersister.HasIndex)
                {
                    throw new QueryException("unindexed collection in minIndex()");
                }
                cols = memberPersister.GetIndexColumnNames(alias);
                if (cols.Length != 1)
                {
                    throw new QueryException("composite collection index in minIndex()");
                }
                return(new string[] { "min(" + cols[0] + ')' });

            case CollectionPropertyNames.MaxElement:
                cols = memberPersister.GetElementColumnNames(alias);
                if (cols.Length != 1)
                {
                    throw new QueryException("composite collection element in maxElement()");
                }
                return(new string[] { "max(" + cols[0] + ')' });

            case CollectionPropertyNames.MinElement:
                cols = memberPersister.GetElementColumnNames(alias);
                if (cols.Length != 1)
                {
                    throw new QueryException("composite collection element in minElement()");
                }
                return(new System.String[] { "min(" + cols[0] + ')' });

            default:
                throw new QueryException("illegal syntax near collection: " + propertyName);
            }
        }