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); }
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); } }
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); } }
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); } }