public void AddWhereFragment(
            JoinFragment joinFragment,
            SqlString whereFragment,
            QueryNode query,
            FromElement fromElement,
            HqlSqlWalker hqlSqlWalker)
        {
            IRestrictableStatement rs = query;

            AddWhereFragment(joinFragment, whereFragment, rs, fromElement, hqlSqlWalker);
        }
        private void PostProcessDML(IRestrictableStatement statement)
        {
            statement.FromClause.Resolve();

            var        fromElement = statement.FromClause.GetFromElementsTyped()[0];
            IQueryable persister   = fromElement.Queryable;

            // Make #@%$^#^&# sure no alias is applied to the table name
            fromElement.Text = persister.TableName;

            // Use the same logic as query does in order to support session filters
            var joinProcessor = new JoinProcessor(this);

            joinProcessor.ProcessJoins(statement);
        }
Example #3
0
        private void PostProcessDML(IRestrictableStatement statement)
        {
            statement.FromClause.Resolve();

            var        fromElement = (FromElement)statement.FromClause.GetFromElements()[0];
            IQueryable persister   = fromElement.Queryable;

            // Make #@%$^#^&# sure no alias is applied to the table name
            fromElement.Text = persister.TableName;

            // append any filter fragments; the EMPTY_MAP is used under the assumption that
            // currently enabled filters should not affect this process
            if (persister.DiscriminatorType != null)
            {
                new SyntheticAndFactory(this)
                .AddDiscriminatorWhereFragment(statement, persister, CollectionHelper.EmptyDictionary <string, IFilter>(), fromElement.TableAlias);
            }
        }
        private void AddJoinNodes(IRestrictableStatement query, JoinSequence join, FromElement fromElement, bool supportRootAlias)
        {
            JoinFragment joinFragment = join.ToJoinFragment(
                _walker.EnabledFilters,
                fromElement.UseFromFragment || fromElement.IsDereferencedBySuperclassOrSubclassProperty,
                fromElement.WithClauseFragment,
                fromElement.WithClauseJoinAlias,
                supportRootAlias ? join.RootAlias : string.Empty
                );

            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 [{0}]", fromFragment);
                }

                ProcessDynamicFilterParameters(fromFragment, fromElement, _walker);
            }

            _syntheticAndFactory.AddWhereFragment(
                joinFragment,
                whereFrag,
                query,
                fromElement,
                _walker
                );
        }
        public void ProcessJoins(IRestrictableStatement query)
        {
            FromClause fromClause       = query.FromClause;
            var        supportRootAlias = !(query is DeleteStatement || query is UpdateStatement);

            IList <FromElement> fromElements;

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

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

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

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

                // the delete and update statements created here will never be executed when IsMultiTable is true,
                // only the where clause will be used by MultiTableUpdateExecutor/MultiTableDeleteExecutor. In that case
                // we have to use the alias from the persister.
                AddJoinNodes(query, join, fromElement, supportRootAlias || fromElement.Queryable.IsMultiTable);
            }
        }
Example #6
0
        public virtual void AddDiscriminatorWhereFragment(IRestrictableStatement statement, IQueryable persister, IDictionary <string, IFilter> enabledFilters, string alias)
        {
            string whereFragment = persister.FilterFragment(alias, enabledFilters).Trim();

            if (string.Empty.Equals(whereFragment))
            {
                return;
            }
            if (whereFragment.StartsWith("and"))
            {
                whereFragment = whereFragment.Substring(4);
            }

            // Need to parse off the column qualifiers; this is assuming (which is true as of now)
            // that this is only used from update and delete HQL statement parsing
            whereFragment = StringHelper.Replace(whereFragment, persister.GenerateFilterConditionAlias(alias) + ".", "");

            // Note: this simply constructs a "raw" SQL_TOKEN representing the
            // where fragment and injects this into the tree.  This "works";
            // however it is probably not the best long-term solution.
            //
            // At some point we probably want to apply an additional grammar to
            // properly tokenize this where fragment into constituent parts
            // focused on the operators embedded within the fragment.
            IASTNode discrimNode = Create(HqlSqlWalker.SQL_TOKEN, whereFragment);

            if (statement.WhereClause.ChildCount == 0)
            {
                statement.WhereClause.SetFirstChild(discrimNode);
            }
            else
            {
                IASTNode and = Create(HqlSqlWalker.AND, "{and}");
                IASTNode currentFirstChild = statement.WhereClause.GetFirstChild();
                and.SetFirstChild(discrimNode);
                and.AddChild(currentFirstChild);
                statement.WhereClause.SetFirstChild(and);
            }
        }
        void ProcessQuery(IASTNode select, IASTNode query)
        {
            if (log.IsDebugEnabled())
            {
                log.Debug("processQuery() : {0}", query.ToStringTree());
            }

            try {
                QueryNode qn = ( QueryNode )query;

                // Was there an explicit select expression?
                bool explicitSelect = select != null && select.ChildCount > 0;

                if (!explicitSelect)
                {
                    // No explicit select expression; render the id and properties
                    // projection lists for every persister in the from clause into
                    // a single 'token node'.
                    //TODO: the only reason we need this stuff now is collection filters,
                    //      we should get rid of derived select clause completely!
                    CreateSelectClauseFromFromClause(qn);
                }
                else
                {
                    // Use the explicitly declared select expression; determine the
                    // return types indicated by each select token
                    UseSelectClause(select);
                }

                // After that, process the JOINs.
                // Invoke a delegate to do the work, as this is farily complex.
                JoinProcessor          joinProcessor = new JoinProcessor(this);
                IRestrictableStatement rs            = qn;
                joinProcessor.ProcessJoins(rs);

                // Attach any mapping-defined "ORDER BY" fragments
                foreach (FromElement fromElement in qn.FromClause.GetProjectionListTyped())
                {
                    if (fromElement.IsFetch && fromElement.QueryableCollection != null)
                    {
                        // Does the collection referenced by this FromElement
                        // specify an order-by attribute?  If so, attach it to
                        // the query's order-by
                        if (fromElement.QueryableCollection.HasOrdering)
                        {
                            string orderByFragment = fromElement
                                                     .QueryableCollection
                                                     .GetSQLOrderByString(fromElement.TableAlias);
                            qn.GetOrderByClause().AddOrderFragment(orderByFragment);
                        }
                        if (fromElement.QueryableCollection.HasManyToManyOrdering)
                        {
                            string orderByFragment = fromElement.QueryableCollection
                                                     .GetManyToManyOrderByString(fromElement.TableAlias);
                            qn.GetOrderByClause().AddOrderFragment(orderByFragment);
                        }
                    }
                }
            }
            finally
            {
                PopFromClause();
            }
        }
		public virtual void AddDiscriminatorWhereFragment(IRestrictableStatement statement, IQueryable persister, IDictionary<string, IFilter> enabledFilters, string alias)
		{
			string whereFragment = persister.FilterFragment(alias, enabledFilters).Trim();
			if (string.Empty.Equals(whereFragment))
			{
				return;
			}
			if (whereFragment.StartsWith("and"))
			{
				whereFragment = whereFragment.Substring(4);
			}

			// Need to parse off the column qualifiers; this is assuming (which is true as of now)
			// that this is only used from update and delete HQL statement parsing
			whereFragment = StringHelper.Replace(whereFragment, persister.GenerateFilterConditionAlias(alias) + ".", "");

			// Note: this simply constructs a "raw" SQL_TOKEN representing the
			// where fragment and injects this into the tree.  This "works";
			// however it is probably not the best long-term solution.
			//
			// At some point we probably want to apply an additional grammar to
			// properly tokenize this where fragment into constituent parts
			// focused on the operators embedded within the fragment.
			IASTNode discrimNode = Create(HqlSqlWalker.SQL_TOKEN, whereFragment);

			if (statement.WhereClause.ChildCount == 0)
			{
				statement.WhereClause.SetFirstChild(discrimNode);
			}
			else
			{
				IASTNode and = Create(HqlSqlWalker.AND, "{and}");
				IASTNode currentFirstChild = statement.WhereClause.GetFirstChild();
				and.SetFirstChild(discrimNode);
				and.AddChild(currentFirstChild);
				statement.WhereClause.SetFirstChild(and);
			}
		}
Example #9
0
		private void PostProcessDML(IRestrictableStatement statement)
		{
			statement.FromClause.Resolve();

			var fromElement = (FromElement)statement.FromClause.GetFromElements()[0];
			IQueryable persister = fromElement.Queryable;
			// Make #@%$^#^&# sure no alias is applied to the table name
			fromElement.Text = persister.TableName;

			// append any filter fragments; the EMPTY_MAP is used under the assumption that
			// currently enabled filters should not affect this process
			if (persister.DiscriminatorType != null)
			{
				new SyntheticAndFactory(this)
					.AddDiscriminatorWhereFragment(statement, persister, new CollectionHelper.EmptyMapClass<string, IFilter>(), fromElement.TableAlias);
			}
		}
        public void AddWhereFragment(
            JoinFragment joinFragment,
            SqlString whereFragment,
            IRestrictableStatement 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 [{0}]", 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.IndexOfOrdinal("?") >= 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 [{0}]", 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);
            }
        }
        public void ProcessJoins(QueryNode query)
        {
            IRestrictableStatement rs = query;

            ProcessJoins(rs);
        }
        public void ProcessJoins(IRestrictableStatement query)
        {
            FromClause          fromClause = query.FromClause;
            IList <FromElement> fromElements;

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

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

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

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

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

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

                JoinSequence join = fromElement.JoinSequence;

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

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