/// <summary>
		/// Creates entity from elements.
		/// </summary>
		/// <param name="fromClause"></param>
		/// <param name="origin"></param>
		/// <param name="path"></param>
		public FromElementFactory(FromClause fromClause, FromElement origin, string path)
		{
			_fromClause = fromClause;
			_origin = origin;
			_path = path;
			_collection = false;
		}
		/// <summary>
		/// Constructor form used to initialize <see cref="ComponentJoin"/>.
		/// </summary>
		/// <param name="fromClause">The FROM clause to which this element belongs.</param>
		/// <param name="origin">The origin (LHS) of this element.</param>
		/// <param name="alias">The alias applied to this element.</param>
		protected FromElement(FromClause fromClause,FromElement origin,string alias):this(origin._token)
		{
			_fromClause = fromClause;
			_origin = origin;
			_classAlias = alias;
			_tableAlias = origin.TableAlias;
			base.Initialize(fromClause.Walker);
		}
		public FromElementType(FromElement fromElement, IEntityPersister persister, EntityType entityType)
		{
			_fromElement = fromElement;
			_persister = persister;
			_entityType = entityType;

			var queryable = persister as IQueryable;
			if (queryable != null)
				fromElement.Text = queryable.TableName + " " + fromElement.TableAlias;
		}
Beispiel #4
0
		public FromElementType(FromElement fromElement, IEntityPersister persister, EntityType entityType)
		{
			_fromElement = fromElement;
			_persister = persister;
			_entityType = entityType;

			if (persister != null)
			{
				fromElement.Text = ((IQueryable)persister).TableName + " " + TableAlias;
			}
		}
		public ComponentJoin(FromClause fromClause, FromElement origin, string alias, string componentPath, ComponentType componentType)
			: base(fromClause, origin, alias)
		{
			this.componentPath = componentPath;
			this.componentType = componentType;
			componentProperty = StringHelper.Unqualify(componentPath);
			fromClause.AddJoinByPathMap(componentPath, this);
			InitializeComponentJoin(new ComponentFromElementType(this));

			string[] cols = origin.GetPropertyMapping("").ToColumns(TableAlias, componentProperty);
			columns = string.Join(", ", cols);
		}
		/// <summary>
		/// Creates collection from elements.
		/// </summary>
		/// <param name="fromClause"></param>
		/// <param name="origin"></param>
		/// <param name="path"></param>
		/// <param name="classAlias"></param>
		/// <param name="columns"></param>
		/// <param name="implied"></param>
		public FromElementFactory(
				FromClause fromClause,
				FromElement origin,
				string path,
				string classAlias,
				string[] columns,
				bool implied)
			: this(fromClause, origin, path)
		{
			_classAlias = classAlias;
			_columns = columns;
			_implied = implied;
			_collection = true;
		}
Beispiel #7
0
		public void AddJoinByPathMap(string path, FromElement destination)
		{
			if (Log.IsDebugEnabled)
			{
				Log.Debug("addJoinByPathMap() : " + path + " -> " + destination);
			}

			_fromElementsByPath.Add(path, destination);
		}
Beispiel #8
0
		public void SetOrigin(FromElement origin, bool manyToMany)
		{
			_origin = origin;
			origin.AddDestination(this);

			if (origin.FromClause == FromClause)
			{
				// TODO: Figure out a better way to get the FROM elements in a proper tree structure.
				// If this is not the destination of a many-to-many, add it as a child of the origin.
				if (manyToMany)
				{
					origin.AddSibling(this);
				}
				else
				{
					if (!Walker.IsInFrom && !Walker.IsInSelect)
					{
						FromClause.AddChild(this);
					}
					else
					{
						origin.AddChild(this);
					}
				}
			}
			else if (!Walker.IsInFrom)
			{
				// HHH-276 : implied joins in a subselect where clause - The destination needs to be added
				// to the destination's from clause.
				FromClause.AddChild(this);	// Not sure if this is will fix everything, but it works.
			}
			else
			{
				// Otherwise, the destination node was implied by the FROM clause and the FROM clause processor
				// will automatically add it in the right place.
			}
		}
		public void ResolveCollectionProperty(IASTNode expr)
		{
			String propertyName = CollectionProperties.GetNormalizedPropertyName( _methodName );

			if ( expr is FromReferenceNode ) 
			{
				FromReferenceNode collectionNode = ( FromReferenceNode ) expr;
				// If this is 'elements' then create a new FROM element.
				if ( CollectionPropertyNames.Elements == propertyName ) 
				{
					HandleElements( collectionNode, propertyName );
				}
				else {
					// Not elements(x)
					_fromElement = collectionNode.FromElement;
					DataType = _fromElement.GetPropertyType( propertyName, propertyName );
					_selectColumns = _fromElement.ToColumns( _fromElement.TableAlias, propertyName, _inSelect );
				}
				if ( collectionNode is DotNode ) 
				{
					PrepareAnyImplicitJoins( ( DotNode ) collectionNode );
				}
				if ( !_inSelect ) 
				{
					_fromElement.Text = "";
					_fromElement.UseWhereFragment = false;
				}

				PrepareSelectColumns( _selectColumns );
				Text = _selectColumns[0];
				Type = HqlSqlWalker.SQL_TOKEN;
			}
			else 
			{
				throw new SemanticException( 
						"Unexpected expression " + expr + 
						" found for collection function " + propertyName 
					);
			}
		}
Beispiel #10
0
		private static void RenderNonScalarProperties(ASTAppender appender, FromElement fromElement, int nonscalarSize, int k)
		{
			string text = fromElement.RenderPropertySelect(nonscalarSize, k);
			appender.Append(HqlSqlWalker.SQL_TOKEN, text, false);

			if (fromElement.QueryableCollection != null && fromElement.IsFetch)
			{
				text = fromElement.RenderCollectionSelectFragment(nonscalarSize, k);
				appender.Append(HqlSqlWalker.SQL_TOKEN, text, false);
			}

			// Look through the FromElement's children to find any collections of values that should be fetched...
			ASTIterator iter = new ASTIterator(fromElement);
			foreach (FromElement child in iter)
			{
				if (child.IsCollectionOfValuesOrComponents && child.IsFetch)
				{
					// Need a better way to define the suffixes here...
					text = child.RenderValueCollectionSelectFragment(nonscalarSize, nonscalarSize + k);
					appender.Append(HqlSqlWalker.SQL_TOKEN, text, false);
				}
			}
		}
Beispiel #11
0
		IASTNode GenerateSyntheticDotNodeForNonQualifiedPropertyRef(IASTNode property, FromElement fromElement)
		{
			IASTNode dot = (IASTNode) adaptor.Create(DOT, "{non-qualified-property-ref}");

			// TODO : better way?!?
			((DotNode)dot).PropertyPath = ((FromReferenceNode)property).Path;

			IdentNode syntheticAlias = (IdentNode)adaptor.Create(IDENT, "{synthetic-alias}");
			syntheticAlias.FromElement = fromElement;
			syntheticAlias.IsResolved = true;

			dot.SetFirstChild(syntheticAlias);
			dot.AddChild(property);

			return dot;
		}
Beispiel #12
0
		public WithClauseVisitor(FromElement fromElement) 
		{
			_joinFragment = fromElement;
		}
		public override object Create(IToken payload)
		{
			if (payload == null)
			{
				return base.Create(payload);
			}

			object ret;

			switch (payload.Type)
			{
				case HqlSqlWalker.SELECT:
				case HqlSqlWalker.QUERY:
					ret = new QueryNode(payload);
					break;
				case HqlSqlWalker.UPDATE:
					ret = new UpdateStatement(payload);
					break;
				case HqlSqlWalker.DELETE:
					ret = new DeleteStatement(payload);
					break;
				case HqlSqlWalker.INSERT:
					ret = new InsertStatement(payload);
					break;
				case HqlSqlWalker.INTO:
					ret = new IntoClause(payload);
					break;
				case HqlSqlWalker.FROM:
					ret = new FromClause(payload);
					break;
				case HqlSqlWalker.FROM_FRAGMENT:
					ret = new FromElement(payload);
					break;
				case HqlSqlWalker.IMPLIED_FROM:
					ret = new ImpliedFromElement(payload);
					break;
				case HqlSqlWalker.DOT:
					ret = new DotNode(payload);
					break;
				case HqlSqlWalker.INDEX_OP:
					ret = new IndexNode(payload);
					break;
					// Alias references and identifiers use the same node class.
				case HqlSqlWalker.ALIAS_REF:
				case HqlSqlWalker.IDENT:
					ret = new IdentNode(payload);
					break;
				case HqlSqlWalker.SQL_TOKEN:
					ret = new SqlFragment(payload);
					break;
				case HqlSqlWalker.METHOD_CALL:
					ret = new MethodNode(payload);
					break;
				case HqlSqlWalker.ELEMENTS:
				case HqlSqlWalker.INDICES:
					ret = new CollectionFunction(payload);
					break;
				case HqlSqlWalker.SELECT_CLAUSE:
					ret = new SelectClause(payload);
					break;
				case HqlSqlWalker.SELECT_EXPR:
					ret = new SelectExpressionImpl(payload);
					break;
				case HqlSqlWalker.AGGREGATE:
					ret = new AggregateNode(payload);
					break;
				case HqlSqlWalker.COUNT:
					ret = new CountNode(payload);
					break;
				case HqlSqlWalker.CONSTRUCTOR:
					ret = new ConstructorNode(payload);
					break;
				case HqlSqlWalker.NUM_INT:
				case HqlSqlWalker.NUM_FLOAT:
				case HqlSqlWalker.NUM_LONG:
				case HqlSqlWalker.NUM_DOUBLE:
                case HqlSqlWalker.NUM_DECIMAL:
                case HqlSqlWalker.QUOTED_String:
					ret = new LiteralNode(payload);
					break;
				case HqlSqlWalker.TRUE:
				case HqlSqlWalker.FALSE:
					ret = new BooleanLiteralNode(payload);
					break;
				case HqlSqlWalker.JAVA_CONSTANT:
					ret = new JavaConstantNode(payload);
					break;
				case HqlSqlWalker.ORDER:
					ret = new OrderByClause(payload);
					break;
				case HqlSqlWalker.PLUS:
				case HqlSqlWalker.MINUS:
				case HqlSqlWalker.STAR:
				case HqlSqlWalker.DIV:
				case HqlSqlWalker.BAND:
				case HqlSqlWalker.BOR:
				case HqlSqlWalker.BXOR:
					ret = new BinaryArithmeticOperatorNode(payload);
					break;
				case HqlSqlWalker.UNARY_MINUS:
				case HqlSqlWalker.UNARY_PLUS:
				case HqlSqlWalker.BNOT:
					ret = new UnaryArithmeticNode(payload);
					break;
				case HqlSqlWalker.CASE2:
					ret = new Case2Node(payload);
					break;
				case HqlSqlWalker.CASE:
					ret = new CaseNode(payload);
					break;
				case HqlSqlWalker.PARAM:
				case HqlSqlWalker.NAMED_PARAM:
					ret = new ParameterNode(payload);
					break;
				case HqlSqlWalker.EQ:
				case HqlSqlWalker.NE:
				case HqlSqlWalker.LT:
				case HqlSqlWalker.GT:
				case HqlSqlWalker.LE:
				case HqlSqlWalker.GE:
				case HqlSqlWalker.LIKE:
				case HqlSqlWalker.NOT_LIKE:
					ret = new BinaryLogicOperatorNode(payload);
					break;
				case HqlSqlWalker.IN:
				case HqlSqlWalker.NOT_IN:
					ret = new InLogicOperatorNode(payload);
					break;
				case HqlSqlWalker.BETWEEN:
				case HqlSqlWalker.NOT_BETWEEN:
					ret = new BetweenOperatorNode(payload);
					break;
				case HqlSqlWalker.IS_NULL:
					ret = new IsNullLogicOperatorNode(payload);
					break;
				case HqlSqlWalker.IS_NOT_NULL:
					ret = new IsNotNullLogicOperatorNode(payload);
					break;
				case HqlSqlWalker.EXISTS:
					ret = new UnaryLogicOperatorNode(payload);
					break;
				default:
					ret = new SqlNode(payload);
					break;
			}

			Initialise(ret);
			return ret;
		}
 protected FromElementType(FromElement fromElement)
 {
     _fromElement = fromElement;
 }
Beispiel #15
0
        private void DereferenceEntity(EntityType entityType, bool implicitJoin, string classAlias, bool generateJoin, IASTNode parent)
        {
            CheckForCorrelatedSubquery("dereferenceEntity");

            // three general cases we check here as to whether to render a physical SQL join:
            // 1) is our parent a DotNode as well?  If so, our property reference is
            //      being further de-referenced...
            // 2) is this a DML statement
            // 3) we were asked to generate any needed joins (generateJoins==true) *OR*
            //		we are currently processing a select or from clause
            // (an additional check is the REGRESSION_STYLE_JOIN_SUPPRESSION check solely intended for the test suite)
            //
            // The REGRESSION_STYLE_JOIN_SUPPRESSION is an additional check
            // intended solely for use within the test suite.  This forces the
            // implicit join resolution to behave more like the classic parser.
            // The underlying issue is that classic translator is simply wrong
            // about its decisions on whether or not to render an implicit join
            // into a physical SQL join in a lot of cases.  The piece it generally
            // tends to miss is that INNER joins effect the results by further
            // restricting the data set!  A particular manifestation of this is
            // the fact that the classic translator will skip the physical join
            // for ToOne implicit joins *if the query is shallow*; the result
            // being that Query.list() and Query.iterate() could return
            // different number of results!

            DotNode parentAsDotNode = null;
            string  property        = _propertyName;
            bool    joinIsNeeded;

            //For nullable entity comparisons we always need to add join (like not constrained one-to-one or not-found ignore associations)
            //NOTE: This fix is not fully correct. It doesn't work for comparisons with null (where e.OneToOneProp is null)
            // as by default implicit join is generated and to work propelry left join is required (see GH-2611)
            bool comparisonWithNullableEntity = false;

            if (IsDotNode(parent))
            {
                // our parent is another dot node, meaning we are being further dereferenced.
                // thus we need to generate a join unless the parent refers to the associated
                // entity's PK (because 'our' table would know the FK).
                parentAsDotNode = ( DotNode )parent;
                property        = parentAsDotNode._propertyName;
                joinIsNeeded    = generateJoin && ((Walker.IsSelectStatement && entityType.IsNullable) || !IsReferenceToPrimaryKey(parentAsDotNode._propertyName, entityType));
            }
            else if (!Walker.IsSelectStatement)
            {
                // in non-select queries, the only time we should need to join is if we are in a subquery from clause
                joinIsNeeded = Walker.CurrentStatementType == HqlSqlWalker.SELECT && Walker.IsInFrom;
            }
            else if (REGRESSION_STYLE_JOIN_SUPPRESSION)
            {
                // this is the regression style determination which matches the logic of the classic translator
                joinIsNeeded = generateJoin && (!Walker.IsInSelect || !Walker.IsShallowQuery);
            }
            else
            {
                comparisonWithNullableEntity = (Walker.IsComparativeExpressionClause && entityType.IsNullable);
                joinIsNeeded = generateJoin || (Walker.IsInSelect && !Walker.IsInCase) || (Walker.IsInFrom && !Walker.IsComparativeExpressionClause) ||
                               comparisonWithNullableEntity;
            }

            if (joinIsNeeded)
            {
                DereferenceEntityJoin(classAlias, entityType, implicitJoin, parent);
                if (comparisonWithNullableEntity)
                {
                    _columns = FromElement.GetIdentityColumns();
                }
            }
            else
            {
                DereferenceEntityIdentifier(property, parentAsDotNode);
            }
        }
		private void InitializeAndAddFromElement(FromElement element,
																						string className,
																						string classAlias,
																						IEntityPersister entityPersister,
																						EntityType type,
																						string tableAlias)
		{
			if (tableAlias == null)
			{
				AliasGenerator aliasGenerator = _fromClause.AliasGenerator;
				tableAlias = aliasGenerator.CreateName(entityPersister.EntityName);
			}
			element.InitializeEntity(_fromClause, className, entityPersister, type, classAlias, tableAlias);
		}
		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;
		}
Beispiel #18
0
 private void AddDestination(FromElement fromElement)
 {
     _destinations.Add(fromElement);
 }
		private FromElement CreateFromElementInSubselect(
				string path,
				string pathAlias,
				FromElement parentFromElement,
				string classAlias)
		{
			if (Log.IsDebugEnabled)
			{
				Log.Debug("createFromElementInSubselect() : path = " + path);
			}

			// Create an DotNode AST for the path and resolve it.
			FromElement fromElement = EvaluateFromElementPath(path, classAlias);
			IEntityPersister entityPersister = fromElement.EntityPersister;

			// If the first identifier in the path referrs to the class alias (not the class name), then this
			// is a correlated subselect.  If it's a correlated sub-select, use the existing table alias.  Otherwise
			// generate a new one.
			bool correlatedSubselect = pathAlias == parentFromElement.ClassAlias;
			
			string tableAlias = correlatedSubselect ? fromElement.TableAlias : null;

			// If the from element isn't in the same clause, create a new from element.
			if (fromElement.FromClause != _fromClause)
			{
				if (Log.IsDebugEnabled)
				{
					Log.Debug("createFromElementInSubselect() : creating a new FROM element...");
				}

				fromElement = CreateFromElement(entityPersister);

				InitializeAndAddFromElement(fromElement,
								path,
								classAlias,
								entityPersister,
								(EntityType)((IQueryable)entityPersister).Type,
								tableAlias
				);
			}
			if (Log.IsDebugEnabled)
			{
				Log.Debug("createFromElementInSubselect() : " + path + " -> " + fromElement);
			}

			return fromElement;
		}
		private static FromElement GetOrigin(FromElement fromElement)
		{
			var realOrigin = fromElement.RealOrigin;
			if (realOrigin != null)
				return realOrigin;

			// work around that crazy issue where the tree contains
			// "empty" FromElements (no text); afaict, this is caused
			// by FromElementFactory.createCollectionJoin()
			var origin = fromElement.Origin;
			if (origin == null)
				throw new QueryException("Unable to determine origin of join fetch [" + fromElement.GetDisplayText() + "]");

			return origin;
		}
Beispiel #21
0
		private void SetImpliedJoin(FromElement elem)
		{
			_impliedJoin = elem;
			if (GetFirstChild().Type == HqlSqlWalker.DOT)
			{
				DotNode dotLhs = (DotNode)GetFirstChild();
				if (dotLhs.GetImpliedJoin() != null)
				{
					_impliedJoin = dotLhs.GetImpliedJoin();
				}
			}
		}
			internal JoinSequenceSelector(HqlSqlWalker walker, FromClause fromClause, FromElement fromElement)
			{
				_walker = walker;
				_fromClause = fromClause;
				_fromElement = fromElement;
			}
Beispiel #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);
        }
Beispiel #24
0
		private void HandleWithFragment(FromElement fromElement, IASTNode hqlWithNode)
		{
			try
			{
				ITreeNodeStream old = input;
				input = new CommonTreeNodeStream(adaptor, hqlWithNode);

				IASTNode hqlSqlWithNode = (IASTNode) withClause().Tree;
				input = old;

				if (log.IsDebugEnabled)
				{
					log.Debug("handleWithFragment() : " + _printer.ShowAsString(hqlSqlWithNode, "-- with clause --"));
				}
				WithClauseVisitor visitor = new WithClauseVisitor(fromElement);
				NodeTraverser traverser = new NodeTraverser(visitor);
				traverser.TraverseDepthFirst(hqlSqlWithNode);
				FromElement referencedFromElement = visitor.GetReferencedFromElement();
				if (referencedFromElement != fromElement)
				{
					throw new InvalidWithClauseException(
						"with-clause expressions did not reference from-clause element to which the with-clause was associated");
				}
				SqlGenerator sql = new SqlGenerator(_sessionFactoryHelper.Factory, new CommonTreeNodeStream(adaptor, hqlSqlWithNode.GetChild(0)));

				sql.whereExpr();

				var withClauseFragment = new SqlString("(", sql.GetSQL(), ")");
				fromElement.SetWithClauseFragment(visitor.GetJoinAlias(), withClauseFragment);
			}
			catch (SemanticException)
			{
				throw;
			}
			catch (InvalidWithClauseException)
			{
				throw;
			}
			catch (Exception e)
			{
				throw new SemanticException(e.Message);
			}
		}
Beispiel #25
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
            var 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.
        }
Beispiel #26
0
		public void Visit(IASTNode node) 
		{
			// todo : currently expects that the individual with expressions apply to the same sql table join.
			//      This may not be the case for joined-subclass where the property values
			//      might be coming from different tables in the joined hierarchy.  At some
			//      point we should expand this to support that capability.  However, that has
			//      some difficulties:
			//          1) the biggest is how to handle ORs when the individual comparisons are
			//              linked to different sql joins.
			//          2) here we would need to track each comparison individually, along with
			//              the join alias to which it applies and then pass that information
			//              back to the FromElement so it can pass it along to the JoinSequence
			if ( node is DotNode ) 
			{
				DotNode dotNode = ( DotNode ) node;
				FromElement fromElement = dotNode.FromElement;
				if ( _referencedFromElement != null )
				{
					if ( fromElement != _referencedFromElement ) 
					{
						throw new HibernateException( "with-clause referenced two different from-clause elements" );
					}
				}
				else
				{
					_referencedFromElement = fromElement;
					_joinAlias = ExtractAppliedAlias( dotNode );

					// todo : temporary
					//      needed because currently persister is the one that
					//      creates and renders the join fragments for inheritence
					//      hierarchies...
					if ( _joinAlias != _referencedFromElement.TableAlias) 
					{
						throw new InvalidWithClauseException( "with clause can only reference columns in the driving table" );
					}
				}
			}
			else if ( node is ParameterNode ) 
			{
				ApplyParameterSpecification(((ParameterNode) node).HqlParameterSpecification);
			}
			else if ( node is IParameterContainer ) 
			{
				ApplyParameterSpecifications( ( IParameterContainer ) node );
			}
		}
Beispiel #27
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 ok to reuse only if in same from clause (are there any other cases when we should reject implied joins?).
            bool useFoundFromElement = found &&
                                       (elem.IsImplied && elem.FromClause == currentFromClause ||                                     // NH different behavior (NH-3002)
                                        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);

                var 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.
        }
Beispiel #28
0
		private void RenderNonScalarIdentifiers(FromElement fromElement, int nonscalarSize, int j, ISelectExpression expr, ASTAppender appender)
		{
			string text = fromElement.RenderIdentifierSelect(nonscalarSize, j);

			if (!fromElement.FromClause.IsSubQuery)
			{
				if (!_scalarSelect && !Walker.IsShallowQuery)
				{
					//TODO: is this a bit ugly?
					expr.Text = text;
				}
				else
				{
					appender.Append(HqlSqlWalker.SQL_TOKEN, text, false);
				}
			}
		}
Beispiel #29
0
		public void AddDuplicateAlias(string alias, FromElement element)
		{
			if (alias != null)
			{
				_fromElementByClassAlias.Add(alias, element);
			}
		}
Beispiel #30
0
		private void AddCollectionFromElement(FromElement fromElement)
		{
			if (fromElement.IsFetch)
			{
				if (fromElement.CollectionJoin || fromElement.QueryableCollection != null)
				{
					String suffix;
					if (_collectionFromElements == null)
					{
						_collectionFromElements = new List<FromElement>();
						suffix = VERSION2_SQL ? "__" : "0__";
					}
					else
					{
						suffix = _collectionFromElements.Count + "__";
					}
					_collectionFromElements.Add(fromElement);
					fromElement.CollectionSuffix = suffix;
				}
			}
		}
 public override void SetScalarColumnText(int i)
 {
     Text = FromElement.RenderScalarIdentifierSelect(i);
 }
		public void AddWhereFragment(
				JoinFragment joinFragment,
				SqlString whereFragment,
				QueryNode query,
				FromElement fromElement,
				HqlSqlWalker hqlSqlWalker)
		{
			if (whereFragment == null)
			{
				return;
			}

			if (!fromElement.UseWhereFragment && !joinFragment.HasThetaJoins)
			{
				return;
			}

			whereFragment = whereFragment.Trim();
			if (StringHelper.IsEmpty(whereFragment.ToString()))
			{
				return;
			}

			// Forcefully remove leading ands from where fragments; the grammar will
			// handle adding them
			if (whereFragment.StartsWithCaseInsensitive("and"))
			{
				whereFragment = whereFragment.Substring(4);
			}

			log.Debug("Using unprocessed WHERE-fragment [" + whereFragment +"]");

			SqlFragment fragment = (SqlFragment) Create(HqlSqlWalker.SQL_TOKEN, whereFragment.ToString());

			fragment.SetJoinFragment(joinFragment);
			fragment.FromElement = fromElement;

			if (fromElement.IndexCollectionSelectorParamSpec != null)
			{
				fragment.AddEmbeddedParameter(fromElement.IndexCollectionSelectorParamSpec);
				fromElement.IndexCollectionSelectorParamSpec = null;
			}

			if (hqlSqlWalker.IsFilter())
			{
				//if (whereFragment.IndexOfCaseInsensitive("?") >= 0)
                if (whereFragment.ToString().IndexOf("?") >= 0)
                {
					IType collectionFilterKeyType = hqlSqlWalker.SessionFactoryHelper
							.RequireQueryableCollection(hqlSqlWalker.CollectionFilterRole)
							.KeyType;
					CollectionFilterKeyParameterSpecification paramSpec = new CollectionFilterKeyParameterSpecification(
							hqlSqlWalker.CollectionFilterRole,
							collectionFilterKeyType,
							0
					);
					fragment.AddEmbeddedParameter(paramSpec);
				}
			}

			JoinProcessor.ProcessDynamicFilterParameters(
					whereFragment,
					fragment,
					hqlSqlWalker
			);

			log.Debug("Using processed WHERE-fragment [" + fragment.Text + "]");

			// Filter conditions need to be inserted before the HQL where condition and the
			// theta join node.  This is because org.hibernate.loader.Loader binds the filter parameters first,
			// then it binds all the HQL query parameters, see org.hibernate.loader.Loader.processFilterParameters().
			if (fragment.FromElement.IsFilter || fragment.HasFilterCondition)
			{
				if (_filters == null)
				{
					// Find or create the WHERE clause
					IASTNode where = (IASTNode) query.WhereClause;
					// Create a new FILTERS node as a parent of all filters
					_filters = Create(HqlSqlWalker.FILTERS, "{filter conditions}");
					// Put the FILTERS node before the HQL condition and theta joins
					where.InsertChild(0, _filters);
				}

				// add the current fragment to the FILTERS node
				_filters.AddChild(fragment);
			}
			else
			{
				if (_thetaJoins == null)
				{
					// Find or create the WHERE clause
					IASTNode where = (IASTNode) query.WhereClause;

					// Create a new THETA_JOINS node as a parent of all filters
					_thetaJoins = Create(HqlSqlWalker.THETA_JOINS, "{theta joins}");

					// Put the THETA_JOINS node before the HQL condition, after the filters.
					if (_filters == null)
					{
						where.InsertChild(0, _thetaJoins);
					}
					else
					{
                        _filters.AddSibling(_thetaJoins);
					}
				}

				// add the current fragment to the THETA_JOINS node
				_thetaJoins.AddChild(fragment);
			}
		}
Beispiel #33
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;
        }
Beispiel #34
0
		private void AddDestination(FromElement fromElement)
		{
			_destinations.Add(fromElement);
		}
		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 || SqlStringHelper.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
			);
		}
Beispiel #36
0
		public void AddCollectionJoinFromElementByPath(string path, FromElement destination)
		{
			if (Log.IsDebugEnabled)
			{
				Log.Debug("addCollectionJoinFromElementByPath() : " + path + " -> " + destination);
			}
			_collectionJoinFromElementsByPath.Add(path, destination);	// Add the new node to the map so that we don't create it twice.
		}
        public override object Create(IToken payload)
        {
            if (payload == null)
            {
                return(base.Create(payload));
            }

            object ret;

            switch (payload.Type)
            {
            case HqlSqlWalker.SELECT:
            case HqlSqlWalker.QUERY:
                ret = new QueryNode(payload);
                break;

            case HqlSqlWalker.UPDATE:
                ret = new UpdateStatement(payload);
                break;

            case HqlSqlWalker.DELETE:
                ret = new DeleteStatement(payload);
                break;

            case HqlSqlWalker.INSERT:
                ret = new InsertStatement(payload);
                break;

            case HqlSqlWalker.INTO:
                ret = new IntoClause(payload);
                break;

            case HqlSqlWalker.FROM:
                ret = new FromClause(payload);
                break;

            case HqlSqlWalker.FROM_FRAGMENT:
                ret = new FromElement(payload);
                break;

            case HqlSqlWalker.IMPLIED_FROM:
                ret = new ImpliedFromElement(payload);
                break;

            case HqlSqlWalker.DOT:
                ret = new DotNode(payload);
                break;

            case HqlSqlWalker.INDEX_OP:
                ret = new IndexNode(payload);
                break;

            // Alias references and identifiers use the same node class.
            case HqlSqlWalker.ALIAS_REF:
            case HqlSqlWalker.IDENT:
                ret = new IdentNode(payload);
                break;

            case HqlSqlWalker.SQL_TOKEN:
                ret = new SqlFragment(payload);
                break;

            case HqlSqlWalker.METHOD_CALL:
                ret = new MethodNode(payload);
                break;

            case HqlSqlWalker.ELEMENTS:
            case HqlSqlWalker.INDICES:
                ret = new CollectionFunction(payload);
                break;

            case HqlSqlWalker.SELECT_CLAUSE:
                ret = new SelectClause(payload);
                break;

            case HqlSqlWalker.SELECT_EXPR:
                ret = new SelectExpressionImpl(payload);
                break;

            case HqlSqlWalker.AGGREGATE:
                ret = new AggregateNode(payload);
                break;

            case HqlSqlWalker.COUNT:
                ret = new CountNode(payload);
                break;

            case HqlSqlWalker.CONSTRUCTOR:
                ret = new ConstructorNode(payload);
                break;

            case HqlSqlWalker.NUM_INT:
            case HqlSqlWalker.NUM_FLOAT:
            case HqlSqlWalker.NUM_LONG:
            case HqlSqlWalker.NUM_DOUBLE:
            case HqlSqlWalker.QUOTED_String:
                ret = new LiteralNode(payload);
                break;

            case HqlSqlWalker.TRUE:
            case HqlSqlWalker.FALSE:
                ret = new BooleanLiteralNode(payload);
                break;

            case HqlSqlWalker.JAVA_CONSTANT:
                ret = new JavaConstantNode(payload);
                break;

            case HqlSqlWalker.ORDER:
                ret = new OrderByClause(payload);
                break;

            case HqlSqlWalker.PLUS:
            case HqlSqlWalker.MINUS:
            case HqlSqlWalker.STAR:
            case HqlSqlWalker.DIV:
            case HqlSqlWalker.BAND:
            case HqlSqlWalker.BOR:
            case HqlSqlWalker.BXOR:
                ret = new BinaryArithmeticOperatorNode(payload);
                break;

            case HqlSqlWalker.UNARY_MINUS:
            case HqlSqlWalker.UNARY_PLUS:
            case HqlSqlWalker.BNOT:
                ret = new UnaryArithmeticNode(payload);
                break;

            case HqlSqlWalker.CASE2:
                ret = new Case2Node(payload);
                break;

            case HqlSqlWalker.CASE:
                ret = new CaseNode(payload);
                break;

            case HqlSqlWalker.PARAM:
            case HqlSqlWalker.NAMED_PARAM:
                ret = new ParameterNode(payload);
                break;

            case HqlSqlWalker.EQ:
            case HqlSqlWalker.NE:
            case HqlSqlWalker.LT:
            case HqlSqlWalker.GT:
            case HqlSqlWalker.LE:
            case HqlSqlWalker.GE:
            case HqlSqlWalker.LIKE:
            case HqlSqlWalker.NOT_LIKE:
                ret = new BinaryLogicOperatorNode(payload);
                break;

            case HqlSqlWalker.IN:
            case HqlSqlWalker.NOT_IN:
                ret = new InLogicOperatorNode(payload);
                break;

            case HqlSqlWalker.BETWEEN:
            case HqlSqlWalker.NOT_BETWEEN:
                ret = new BetweenOperatorNode(payload);
                break;

            case HqlSqlWalker.IS_NULL:
                ret = new IsNullLogicOperatorNode(payload);
                break;

            case HqlSqlWalker.IS_NOT_NULL:
                ret = new IsNotNullLogicOperatorNode(payload);
                break;

            case HqlSqlWalker.EXISTS:
                ret = new UnaryLogicOperatorNode(payload);
                break;

            default:
                ret = new SqlNode(payload);
                break;
            }

            Initialise(ret);
            return(ret);
        }
Beispiel #38
0
		public void RegisterFromElement(FromElement element)
		{
			_fromElements.Add(element);
			string classAlias = element.ClassAlias;
			if (classAlias != null)
			{
				// The HQL class alias refers to the class name.
				_fromElementByClassAlias.Add(classAlias, element);
			}
			// Associate the table alias with the element.
			string tableAlias = element.TableAlias;
			if (tableAlias != null)
			{
				_fromElementByTableAlias[tableAlias] = element;
			}
		}
		protected FromElementType(FromElement fromElement)
		{
			_fromElement = fromElement;
		}