Example #1
0
        public override void PrepareForDot(string propertyName)
        {
            FromElement fromElement = FromElement;

            if (fromElement == null)
            {
                throw new InvalidOperationException("No FROM element for index operator!");
            }

            IQueryableCollection queryableCollection = fromElement.QueryableCollection;

            if (queryableCollection != null && !queryableCollection.IsOneToMany)
            {
                FromReferenceNode collectionNode = ( FromReferenceNode )GetChild(0);
                String            path           = collectionNode.Path + "[]." + propertyName;

                if (Log.IsDebugEnabled)
                {
                    Log.Debug("Creating join for many-to-many elements for " + path);
                }

                FromElementFactory factory = new FromElementFactory(fromElement.FromClause, fromElement, path);

                // This will add the new from element to the origin.
                FromElement elementJoin = factory.CreateElementJoin(queryableCollection);
                FromElement = elementJoin;
            }
        }
Example #2
0
        /// <summary>
        /// Adds a new from element to the from node.
        /// </summary>
        /// <param name="path">The reference to the class.</param>
        /// <param name="alias">The alias AST.</param>
        /// <returns>The new FROM element.</returns>
        public FromElement AddFromElement(string path, IASTNode alias)
        {
            // The path may be a reference to an alias defined in the parent query.
            string classAlias = (alias == null) ? null : alias.Text;

            CheckForDuplicateClassAlias(classAlias);
            var factory = new FromElementFactory(this, null, path, classAlias, null, false);

            return(factory.AddFromElement());
        }
Example #3
0
        public override void ResolveIndex(IASTNode parent)
        {
            // An ident node can represent an index expression if the ident
            // represents a naked property ref
            //      *Note: this makes the assumption (which is currently the case
            //      in the hql-sql grammar) that the ident is first resolved
            //      itself (addrExpr -> resolve()).  The other option, if that
            //      changes, is to call resolve from here; but it is
            //      currently un-needed overhead.
            if (!(IsResolved && _nakedPropertyRef))
            {
                throw new InvalidOperationException();
            }

            string propertyName = OriginalText;

            if (!DataType.IsCollectionType)
            {
                throw new SemanticException("Collection expected; [" + propertyName + "] does not refer to a collection property");
            }

            // TODO : most of below was taken verbatim from DotNode; should either delegate this logic or super-type it
            CollectionType       type = (CollectionType)DataType;
            string               role = type.Role;
            IQueryableCollection queryableCollection = SessionFactoryHelper.RequireQueryableCollection(role);

            string columnTableAlias = FromElement.TableAlias;

            FromElementFactory factory = new FromElementFactory(
                Walker.CurrentFromClause,
                FromElement,
                propertyName,
                null,
                FromElement.ToColumns(columnTableAlias, propertyName, false),
                true
                );

            FromElement elem = factory.CreateCollection(queryableCollection, role, JoinType.InnerJoin, false, true);

            FromElement = elem;
            Walker.AddQuerySpaces(queryableCollection.CollectionSpaces);                // Always add the collection's query spaces.
        }
Example #4
0
		/// <summary>
		/// Adds a new from element to the from node.
		/// </summary>
		/// <param name="path">The reference to the class.</param>
		/// <param name="alias">The alias AST.</param>
		/// <returns>The new FROM element.</returns>
		public FromElement AddFromElement(string path, IASTNode alias)
		{
			// The path may be a reference to an alias defined in the parent query.
			string classAlias = ( alias == null ) ? null : alias.Text;
			CheckForDuplicateClassAlias( classAlias );
			var factory = new FromElementFactory(this, null, path, classAlias, null, false);
			return factory.AddFromElement();
		}
Example #5
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.
        }
Example #6
0
        private void DereferenceCollection(CollectionType collectionType, bool implicitJoin, bool indexed, string classAlias)
        {
            _dereferenceType = DerefCollection;
            string role = collectionType.Role;

            //foo.bars.size (also handles deprecated stuff like foo.bars.maxelement for backwardness)
            IASTNode sibling        = NextSibling;
            bool     isSizeProperty = sibling != null && CollectionProperties.IsAnyCollectionProperty(sibling.Text);

            if (isSizeProperty)
            {
                indexed = true;                 //yuck!}
            }

            IQueryableCollection queryableCollection = SessionFactoryHelper.RequireQueryableCollection(role);
            string     propName          = Path;
            FromClause currentFromClause = Walker.CurrentFromClause;

            if (Walker.StatementType != HqlSqlWalker.SELECT && indexed && classAlias == null)
            {
                // should indicate that we are processing an INSERT/UPDATE/DELETE
                // query with a subquery implied via a collection property
                // function. Here, we need to use the table name itself as the
                // qualification alias.
                // TODO : verify this works for all databases...
                // TODO : is this also the case in non-"indexed" scenarios?
                string alias = GetLhs().FromElement.Queryable.TableName;
                _columns = FromElement.ToColumns(alias, _propertyPath, false, true);
            }

            //We do not look for an existing join on the same path, because
            //it makes sense to join twice on the same collection role
            FromElementFactory factory = new FromElementFactory(
                currentFromClause,
                GetLhs().FromElement,
                propName,
                classAlias,
                GetColumns(),
                implicitJoin
                );
            FromElement elem = factory.CreateCollection(queryableCollection, role, _joinType, _fetch, indexed);

            if (Log.IsDebugEnabled)
            {
                Log.Debug("dereferenceCollection() : Created new FROM element for " + propName + " : " + elem);
            }

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

            if (isSizeProperty)
            {
                elem.Text             = "";
                elem.UseWhereFragment = false;
            }

            if (!implicitJoin)
            {
                IEntityPersister entityPersister = elem.EntityPersister;
                if (entityPersister != null)
                {
                    Walker.AddQuerySpaces(entityPersister.QuerySpaces);
                }
            }
            Walker.AddQuerySpaces(queryableCollection.CollectionSpaces);                // Always add the collection's query spaces.
        }
Example #7
0
		void CreateFromJoinElement(
				IASTNode path,
				IASTNode alias,
				int joinType,
				IASTNode fetchNode,
				IASTNode propertyFetch,
				IASTNode with)
		{
			bool fetch = fetchNode != null;
			if ( fetch && IsSubQuery ) 
			{
				throw new QueryException( "fetch not allowed in subquery from-elements" );
			}
			// The path AST should be a DotNode, and it should have been evaluated already.
			if ( path.Type != DOT ) 
			{
				throw new SemanticException( "Path expected for join!" );
			}

			DotNode dot = ( DotNode ) path;
			//JoinType hibernateJoinType = JoinProcessor.ToHibernateJoinType( joinType );
			JoinType hibernateJoinType = _impliedJoinType;

			dot.JoinType = hibernateJoinType;	// Tell the dot node about the join type.
			dot.Fetch = fetch;

			// Generate an explicit join for the root dot node.   The implied joins will be collected and passed up
			// to the root dot node.
			dot.Resolve( true, false, alias == null ? null : alias.Text );

			FromElement fromElement;
			if (dot.DataType != null && dot.DataType.IsComponentType)
			{
				var factory = new FromElementFactory(CurrentFromClause, dot.GetLhs().FromElement, dot.PropertyPath, alias == null ? null : alias.Text, null, false);
				fromElement = factory.CreateComponentJoin((ComponentType) dot.DataType);
			}
			else
			{
				fromElement = dot.GetImpliedJoin();
				if (fromElement == null)
				{
					throw new InvalidPathException("Invalid join: " + dot.Path);
				}
				fromElement.SetAllPropertyFetch(propertyFetch != null);

				if (with != null)
				{
					if (fetch)
					{
						throw new SemanticException("with-clause not allowed on fetched associations; use filters");
					}

					HandleWithFragment(fromElement, with);
				}
			}

			if ( log.IsDebugEnabled )
			{
				log.Debug( "createFromJoinElement() : " + _printer.ShowAsString( fromElement, "-- join tree --" ) );
			}
		}
Example #8
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;
        }
Example #9
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.
		}
Example #10
0
		private void DereferenceCollection(CollectionType collectionType, bool implicitJoin, bool indexed, string classAlias)
		{
			_dereferenceType = DerefCollection;
			string role = collectionType.Role;

			//foo.bars.size (also handles deprecated stuff like foo.bars.maxelement for backwardness)
			IASTNode sibling = NextSibling;
			bool isSizeProperty = sibling != null && CollectionProperties.IsAnyCollectionProperty( sibling.Text );

			if (isSizeProperty)
			{
				indexed = true; //yuck!}
			}

			IQueryableCollection queryableCollection = SessionFactoryHelper.RequireQueryableCollection( role );
			string propName = Path;
			FromClause currentFromClause = Walker.CurrentFromClause;

			if ( Walker.StatementType != HqlSqlWalker.SELECT && indexed && classAlias == null ) 
			{
				// should indicate that we are processing an INSERT/UPDATE/DELETE
				// query with a subquery implied via a collection property
				// function. Here, we need to use the table name itself as the
				// qualification alias.
				// TODO : verify this works for all databases...
				// TODO : is this also the case in non-"indexed" scenarios?
				string alias = GetLhs().FromElement.Queryable.TableName;
				_columns = FromElement.ToColumns(alias, _propertyPath, false, true);
			}

			//We do not look for an existing join on the same path, because
			//it makes sense to join twice on the same collection role
			FromElementFactory factory = new FromElementFactory(
					currentFromClause,
					GetLhs().FromElement,
					propName,
					classAlias,
					GetColumns(),
					implicitJoin
			);
			FromElement elem = factory.CreateCollection( queryableCollection, role, _joinType, _fetch, indexed );

			if ( Log.IsDebugEnabled ) 
			{
				Log.Debug( "dereferenceCollection() : Created new FROM element for " + propName + " : " + elem );
			}

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

			if ( isSizeProperty ) 
			{
				elem.Text = "";
				elem.UseWhereFragment = false;
			}

			if ( !implicitJoin ) 
			{
				IEntityPersister entityPersister = elem.EntityPersister;
				if ( entityPersister != null ) 
				{
					Walker.AddQuerySpaces( entityPersister.QuerySpaces );
				}
			}
			Walker.AddQuerySpaces( queryableCollection.CollectionSpaces );	// Always add the collection's query spaces.
		}
Example #11
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;
		}
Example #12
0
    	public override void PrepareForDot(string propertyName) 
        {
    	    FromElement fromElement = FromElement;

		    if ( fromElement == null ) 
            {
			    throw new InvalidOperationException( "No FROM element for index operator!" );
		    }

		    IQueryableCollection queryableCollection = fromElement.QueryableCollection;

		    if ( queryableCollection != null && !queryableCollection.IsOneToMany) 
            {
			    FromReferenceNode collectionNode = ( FromReferenceNode ) GetChild(0);
			    String path = collectionNode.Path + "[]." + propertyName;

			    if (Log.IsDebugEnabled) 
                {
				    Log.Debug( "Creating join for many-to-many elements for " + path );
			    }

			    FromElementFactory factory = new FromElementFactory( fromElement.FromClause, fromElement, path );

			    // This will add the new from element to the origin.
			    FromElement elementJoin = factory.CreateElementJoin( queryableCollection );
			    FromElement = elementJoin;
		    }
	    }
Example #13
0
		public override void ResolveIndex(IASTNode parent)
		{
			// An ident node can represent an index expression if the ident
			// represents a naked property ref
			//      *Note: this makes the assumption (which is currently the case
			//      in the hql-sql grammar) that the ident is first resolved
			//      itself (addrExpr -> resolve()).  The other option, if that
			//      changes, is to call resolve from here; but it is
			//      currently un-needed overhead.
			if (!(IsResolved && _nakedPropertyRef)) 
			{
				throw new InvalidOperationException();
			}

			string propertyName = OriginalText;
			if (!DataType.IsCollectionType) 
			{
				throw new SemanticException("Collection expected; [" + propertyName + "] does not refer to a collection property");
			}

			// TODO : most of below was taken verbatim from DotNode; should either delegate this logic or super-type it
			CollectionType type = (CollectionType) DataType;
			string role = type.Role;
			IQueryableCollection queryableCollection = SessionFactoryHelper.RequireQueryableCollection(role);

			string columnTableAlias = FromElement.TableAlias;

			FromElementFactory factory = new FromElementFactory(
				  	Walker.CurrentFromClause,
					FromElement,
					propertyName,
					null,
					FromElement.ToColumns(columnTableAlias, propertyName, false),
					true
			);

			FromElement elem = factory.CreateCollection(queryableCollection, role, JoinType.InnerJoin, false, true);
			FromElement = elem;
			Walker.AddQuerySpaces(queryableCollection.CollectionSpaces);	// Always add the collection's query spaces.
		}