/// <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; }
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; }
public void AddJoinByPathMap(string path, FromElement destination) { if (Log.IsDebugEnabled) { Log.Debug("addJoinByPathMap() : " + path + " -> " + destination); } _fromElementsByPath.Add(path, destination); }
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 ); } }
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); } } }
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; }
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; }
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; }
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; }
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; }
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); }
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); } }
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. }
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 ); } }
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. }
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); } } }
public void AddDuplicateAlias(string alias, FromElement element) { if (alias != null) { _fromElementByClassAlias.Add(alias, element); } }
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); } }
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; }
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 ); }
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); }
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; }