private static IASTNode MakeIdent(IASTNode source, string text) { var ident = source.DupNode(); ident.Type = HqlSqlWalker.IDENT; ident.Text = text; return ident; }
private static void AddImpliedFromToFromNode(IASTNode fromClause, string collectionRole, ISessionFactoryImplementor factory) { SessionFactoryHelperExtensions _sessionFactoryHelper = new SessionFactoryHelperExtensions(factory); IQueryableCollection persister = _sessionFactoryHelper.GetCollectionPersister(collectionRole); IType collectionElementType = persister.ElementType; if (!collectionElementType.IsEntityType) { throw new QueryException("collection of values in filter: this"); } string collectionElementEntityName = persister.ElementPersister.EntityName; ITreeAdaptor adaptor = new ASTTreeAdaptor(); IASTNode fromElement = (IASTNode)adaptor.Create(HqlParser.FILTER_ENTITY, collectionElementEntityName); IASTNode alias = (IASTNode)adaptor.Create(HqlParser.ALIAS, "this"); fromClause.AddChild(fromElement); fromClause.AddChild(alias); // Show the modified AST. if (log.IsDebugEnabled) { log.Debug("AddImpliedFormToFromNode() : Filter - Added 'this' as a from element..."); } }
public void Visit(IASTNode node) { if (predicate == null || predicate(node)) { collectedNodes.Add(node); } }
/// <summary> /// Insert a new node into both the Tree and the Node Array. Add DOWN and UP nodes if needed. /// </summary> /// <param name="parent">The parent node</param> /// <param name="child">The child node</param> public void InsertChild(IASTNode parent, IASTNode child) { if (child.ChildCount > 0) { throw new InvalidOperationException("Currently do not support adding nodes with children"); } int parentIndex = nodes.IndexOf(parent); int numberOfChildNodes = NumberOfChildNodes(parentIndex); int insertPoint; if (numberOfChildNodes == 0) { insertPoint = parentIndex + 1; // We want to insert immediately after the parent nodes.Insert(insertPoint, down); insertPoint++; // We've just added a new node } else { insertPoint = parentIndex + numberOfChildNodes; } parent.AddChild(child); nodes.Insert(insertPoint, child); insertPoint++; if (numberOfChildNodes == 0) { nodes.Insert(insertPoint, up); } }
public void Visit(IASTNode node) { if (node.Type == HqlSqlWalker.FROM) { _nodes.AddRange(node.Where(child => child.Type == HqlSqlWalker.RANGE).Select(range => range.GetChild(0))); } }
protected SqlString GenerateIdInsertSelect(IQueryable persister, string tableAlias, IASTNode whereClause) { var select = new SqlSelectBuilder(Factory); SelectFragment selectFragment = new SelectFragment(Factory.Dialect) .AddColumns(tableAlias, persister.IdentifierColumnNames, persister.IdentifierColumnNames); select.SetSelectClause(selectFragment.ToFragmentString().Substring(2)); string rootTableName = persister.TableName; SqlString fromJoinFragment = persister.FromJoinFragment(tableAlias, true, false); SqlString whereJoinFragment = persister.WhereJoinFragment(tableAlias, true, false); select.SetFromClause(rootTableName + ' ' + tableAlias + fromJoinFragment); if (whereJoinFragment == null) { whereJoinFragment = SqlString.Empty; } else { whereJoinFragment = whereJoinFragment.Trim(); if (whereJoinFragment.StartsWithCaseInsensitive("and ")) { whereJoinFragment = whereJoinFragment.Substring(4); } } SqlString userWhereClause = SqlString.Empty; if (whereClause.ChildCount != 0) { // If a where clause was specified in the update/delete query, use it to limit the // returned ids here... try { var nodes = new CommonTreeNodeStream(whereClause); var gen = new SqlGenerator(Factory, nodes); gen.whereClause(); userWhereClause = gen.GetSQL().Substring(7); } catch (RecognitionException e) { throw new HibernateException("Unable to generate id select for DML operation", e); } if (whereJoinFragment.Length > 0) { whereJoinFragment.Append(" and "); } } select.SetWhereClause(whereJoinFragment + userWhereClause); var insert = new InsertSelect(); if (Factory.Settings.IsCommentsEnabled) { insert.SetComment("insert-select for " + persister.EntityName + " ids"); } insert.SetTableName(persister.TemporaryIdTableName); insert.SetSelect(select); return insert.ToSqlString(); }
protected HqlTreeNode(int type, string text, IASTFactory factory, IEnumerable<HqlTreeNode> children) { Factory = factory; _node = factory.CreateNode(type, text); _children = new List<HqlTreeNode>(); AddChildren(children); }
/// <summary> /// Returns the 'list' representation with some brackets around it for debugging. /// </summary> /// <param name="n">The tree.</param> /// <returns>The list representation of the tree.</returns> public static string GetDebugstring(IASTNode n) { StringBuilder buf = new StringBuilder(); buf.Append("[ "); buf.Append((n == null) ? "{null}" : n.ToStringTree()); buf.Append(" ]"); return buf.ToString(); }
public virtual void ReplaceBy(IASTNode node) { if (Parent != null) { throw new ApplicationException("Couldn't find a parent node to delegate"); } Parent.ReplaceChild(this, node); }
protected HqlTreeNode(int type, string text, IASTFactory factory, params HqlTreeNode[] children) { _node = factory.CreateNode(type, text); _children = new List<HqlTreeNode>(); foreach (var child in children) { _children.Add(child); _node.AddChild(child.AstNode); } }
private void AddImplementorsToMap(IASTNode querySource, string className, string[] implementors) { if (implementors.Length == 1 && implementors[0] == className) { // No need to change things return; } _map.Add(querySource, implementors.Select(implementor => MakeIdent(querySource, implementor)).ToArray()); }
public Dictionary<IASTNode, IASTNode[]> Process(IASTNode tree) { foreach (var querySource in new QuerySourceDetector(tree).LocateQuerySources()) { var className = GetClassName(querySource); string[] implementors = _sfi.GetImplementors(className); AddImplementorsToMap(querySource, className, implementors); } return _map; }
/// <summary> /// Traverse the AST tree depth first. Note that the AST passed in is not visited itself. Visitation starts /// with its children. /// </summary> /// <param name="ast">ast</param> public void TraverseDepthFirst(IASTNode ast) { if (ast == null) { throw new ArgumentNullException("ast"); } for (int i = 0; i < ast.ChildCount; i++) { VisitDepthFirst(ast.GetChild(i)); } }
public Dictionary<IASTNode, IASTNode[]> Process(IASTNode tree) { foreach (var querySource in new QuerySourceDetector(tree).LocateQuerySources()) { var className = GetClassName(querySource); var classType = _sessionFactoryHelper.GetImportedClass(className); AddImplementorsToMap(querySource, classType == null ? className : classType.FullName); } return _map; }
private static string GetClassName(IASTNode querySource) { switch (querySource.Type) { case HqlSqlWalker.IDENT: return querySource.Text; case HqlSqlWalker.DOT: return BuildPath(querySource); } // TODO throw new NotSupportedException(); }
/// <summary> /// Creates a new AST-based query translator. /// </summary> /// <param name="queryIdentifier">The query-identifier (used in stats collection)</param> /// <param name="parsedQuery">The hql query to translate</param> /// <param name="enabledFilters">Currently enabled filters</param> /// <param name="factory">The session factory constructing this translator instance.</param> public QueryTranslatorImpl( string queryIdentifier, IASTNode parsedQuery, IDictionary<string, IFilter> enabledFilters, ISessionFactoryImplementor factory) { _queryIdentifier = queryIdentifier; _stageOneAst = parsedQuery; _compiled = false; _shallowQuery = false; _enabledFilters = enabledFilters; _factory = factory; }
private IEnumerable<IASTNode> DuplicateTree() { var replacements = CrossJoinDictionaryArrays.PerformCrossJoin(_nodeMapping); var dups = new IASTNode[replacements.Count()]; for (var i = 0; i < replacements.Count(); i++) { dups[i] = DuplicateTree(_ast, replacements[i]); } return dups; }
private void VisitDepthFirst(IASTNode ast) { if (ast == null) { return; } _visitor.Visit(ast); for (int i = 0; i < ast.ChildCount; i++) { VisitDepthFirst(ast.GetChild(i)); } }
/// <summary> /// Handles HQL AST transformation for collection filters (which are created with <see cref="ISession.CreateFilter"/>). /// /// Adds FROM elements to implicit FROM clause. /// E.g., /// <code> /// ( query ( SELECT_FROM {filter-implied FROM} ) ( where ( = X 10 ) ) ) /// </code> /// gets converted to /// <code> /// ( query ( SELECT_FROM ( FROM NHibernate.DomainModel.Many this ) ) ( where ( = X 10 ) ) ) /// </code> /// </summary> /// <param name="ast">The root node of HQL query</param> /// <param name="collectionRole">Collection that is being filtered</param> /// <param name="factory">Session factory</param> internal static void AddImpliedFromToQuery(IASTNode ast, string collectionRole, ISessionFactoryImplementor factory) { if (ast.Type != HqlParser.QUERY) { var msg = string.Format(CultureInfo.InvariantCulture, "invalid query type for collection filtering: expected {0}, got {1}", HqlParser.tokenNames[HqlParser.QUERY], HqlParser.tokenNames[ast.Type]); throw new QueryException(msg); } var selectFromClause = ast.Where(x => x.Type == HqlParser.SELECT_FROM).Single(); var fromClause = selectFromClause.Where(x => x.Type == HqlParser.FROM).Single(); fromClause.Text = "FROM"; // Just for prettier debug output AddImpliedFromToFromNode(fromClause, collectionRole, factory); }
private static void BuildPath(IASTNode node, StringBuilder sb) { if (node.Type == HqlSqlWalker.DOT) { BuildPath(node.GetChild(0), sb); sb.Append('.'); sb.Append(node.GetChild(1).Text); } else { sb.Append(node.Text); } }
public void RecursiveResolve(int level, bool impliedAtRoot, string classAlias, IASTNode parent) { IASTNode lhs = GetFirstChild(); int nextLevel = level + 1; if ( lhs != null ) { FromReferenceNode n = ( FromReferenceNode ) lhs; n.RecursiveResolve( nextLevel, impliedAtRoot, null, this ); } ResolveFirstChild(); bool impliedJoin = !(level == RootLevel && !impliedAtRoot); Resolve( true, impliedJoin, classAlias, parent ); }
private static void Check(IASTNode check, IASTNode first, IASTNode second) { if (typeof(IExpectedTypeAwareNode).IsAssignableFrom(check.GetType())) { IType expectedType = null; if (typeof(SqlNode).IsAssignableFrom(first.GetType())) { expectedType = ((SqlNode)first).DataType; } if (expectedType == null && typeof(SqlNode).IsAssignableFrom(second.GetType())) { expectedType = ((SqlNode)second).DataType; } ((IExpectedTypeAwareNode)check).ExpectedType = expectedType; } }
/// <summary> /// Determine if a given node (test) is contained anywhere in the subtree /// of another given node (fixture). /// </summary> /// <param name="fixture">The node against which to be checked for children.</param> /// <param name="test">The node to be tested as being a subtree child of the parent.</param> /// <returns>True if child is contained in the parent's collection of children.</returns> public static bool IsSubtreeChild(IASTNode fixture, IASTNode test) { for (int i = 0; i < fixture.ChildCount; i++) { IASTNode n = fixture.GetChild(i); if (n == test) { return true; } if (n.ChildCount > 0 && IsSubtreeChild(n, test)) { return true; } } return false; }
private static IASTNode DuplicateTree(IASTNode ast, IDictionary<IASTNode, IASTNode> nodeMapping) { IASTNode candidate; if (nodeMapping.TryGetValue(ast, out candidate)) { return candidate; } var dup = ast.DupNode(); foreach (var child in ast) { dup.AddChild(DuplicateTree(child, nodeMapping)); } return dup; }
private static void GetPathText(StringBuilder buf, IASTNode n) { IASTNode firstChild = n.GetChild(0); // If the node has a first child, recurse into the first child. if (firstChild != null) { GetPathText(buf, firstChild); } // Append the text of the current node. buf.Append(n.Text); // If there is a second child (RHS), recurse into that child. if (firstChild != null && n.ChildCount > 1) { GetPathText(buf, n.GetChild(1)); } }
public IASTNode Translate(ISessionFactory sessionFactory) { //if (_astNode == null) { var requiredHqlParameters = new List<NamedParameterDescriptor>(); // TODO - can we cache any of this? var queryModel = NhRelinqQueryParser.Parse(_expression); ExpressionToHqlTranslationResults = QueryModelVisitor.GenerateHqlQuery(queryModel, _constantToParameterMap, requiredHqlParameters); ParameterDescriptors = requiredHqlParameters.AsReadOnly(); _astNode = ExpressionToHqlTranslationResults.Statement.AstNode; } return _astNode; }
public override void ResolveIndex(IASTNode parent) { // An ident node can represent an index expression if the ident // represents a naked property ref // *Note: this makes the assumption (which is currently the case // in the hql-sql grammar) that the ident is first resolved // itself (addrExpr -> resolve()). The other option, if that // changes, is to call resolve from here; but it is // currently un-needed overhead. if (!(IsResolved && _nakedPropertyRef)) { throw new InvalidOperationException(); } string propertyName = OriginalText; if (!DataType.IsCollectionType) { throw new SemanticException("Collection expected; [" + propertyName + "] does not refer to a collection property"); } // TODO : most of below was taken verbatim from DotNode; should either delegate this logic or super-type it CollectionType type = (CollectionType) DataType; string role = type.Role; IQueryableCollection queryableCollection = SessionFactoryHelper.RequireQueryableCollection(role); string columnTableAlias = FromElement.TableAlias; FromElementFactory factory = new FromElementFactory( Walker.CurrentFromClause, FromElement, propertyName, null, FromElement.ToColumns(columnTableAlias, propertyName, false), true ); FromElement elem = factory.CreateCollection(queryableCollection, role, JoinType.InnerJoin, false, true); FromElement = elem; Walker.AddQuerySpaces(queryableCollection.CollectionSpaces); // Always add the collection's query spaces. }
private static void Check(IASTNode check, IASTNode first, IASTNode second) { var expectedTypeAwareNode = check as IExpectedTypeAwareNode; if (expectedTypeAwareNode != null) { IType expectedType = null; var firstNode = first as SqlNode; if (firstNode != null) { expectedType = firstNode.DataType; } if (expectedType == null) { var secondNode = second as SqlNode; if (secondNode != null) { expectedType = secondNode.DataType; } } expectedTypeAwareNode.ExpectedType = expectedType; } }
/// <summary> /// Generates the scalar column AST nodes for a given array of SQL columns /// </summary> public static void GenerateScalarColumns(IASTFactory factory, IASTNode node, string[] sqlColumns, int i) { if (sqlColumns.Length == 1) { GenerateSingleScalarColumn(factory, node, i); } else { node.Text = sqlColumns[0]; // Use the DOT node to emit the first column name. // Create the column names, folled by the column aliases. for (int j = 0; j < sqlColumns.Length; j++) { if (j > 0) { node = node.AddSibling(factory.CreateNode(HqlSqlWalker.SQL_TOKEN, sqlColumns[j])); } node = node.AddSibling(factory.CreateNode(HqlSqlWalker.SELECT_COLUMNS, " as " + NameGenerator.ScalarName(i, j))); } } }
static IQueryTranslator[] CreateQueryTranslators(IASTNode ast, string queryIdentifier, string collectionRole, bool shallow, IDictionary<string, IFilter> filters, ISessionFactoryImplementor factory) { var polymorphicParsers = AstPolymorphicProcessor.Process(ast, factory); var translators = polymorphicParsers .Select(hql => new QueryTranslatorImpl(queryIdentifier, hql, filters, factory)) .ToArray(); foreach (var translator in translators) { if (collectionRole == null) { translator.Compile(factory.Settings.QuerySubstitutions, shallow); } else { translator.Compile(collectionRole, factory.Settings.QuerySubstitutions, shallow); } } return translators; }
void ProcessBool(IASTNode constant) { _literalProcessor.ProcessBoolean(constant); // Use the delegate. }
void CreateFromJoinElement( IASTNode path, IASTNode alias, int joinType, IASTNode fetchNode, IASTNode propertyFetch, IASTNode with) { bool fetch = fetchNode != null; if (fetch && IsSubQuery) { throw new QueryException("fetch not allowed in subquery from-elements"); } // The path AST should be a DotNode, and it should have been evaluated already. if (path.Type != DOT) { throw new SemanticException("Path expected for join!"); } DotNode dot = ( DotNode )path; //JoinType hibernateJoinType = JoinProcessor.ToHibernateJoinType( joinType ); JoinType hibernateJoinType = _impliedJoinType; dot.JoinType = hibernateJoinType; // Tell the dot node about the join type. dot.Fetch = fetch; // Generate an explicit join for the root dot node. The implied joins will be collected and passed up // to the root dot node. dot.Resolve(true, false, alias == null ? null : alias.Text); FromElement fromElement; if (dot.DataType != null && dot.DataType.IsComponentType) { var factory = new FromElementFactory(CurrentFromClause, dot.GetLhs().FromElement, dot.PropertyPath, alias == null ? null : alias.Text, null, false); fromElement = factory.CreateComponentJoin((ComponentType)dot.DataType); } else { fromElement = dot.GetImpliedJoin(); if (fromElement == null) { throw new InvalidPathException("Invalid join: " + dot.Path); } fromElement.SetAllPropertyFetch(propertyFetch != null); if (with != null) { if (fetch) { throw new SemanticException("with-clause not allowed on fetched associations; use filters"); } HandleWithFragment(fromElement, with); } } if (log.IsDebugEnabled) { log.Debug("createFromJoinElement() : " + _printer.ShowAsString(fromElement, "-- join tree --")); } }
public void RecursiveResolve(int level, bool impliedAtRoot, string classAlias, IASTNode parent) { IASTNode lhs = GetFirstChild(); int nextLevel = level + 1; if (lhs != null) { FromReferenceNode n = ( FromReferenceNode )lhs; n.RecursiveResolve(nextLevel, impliedAtRoot, null, this); } ResolveFirstChild(); bool impliedJoin = !(level == RootLevel && !impliedAtRoot); Resolve(true, impliedJoin, classAlias, parent); }
public static IList <IASTNode> CollectChildren(IASTNode root, FilterPredicate predicate) { return(new CollectingNodeVisitor(predicate).Collect(root)); }
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 [{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); } }
private static bool IsParam(IASTNode node) { return(node.Type == HqlSqlWalker.PARAM || node.Type == HqlSqlWalker.NAMED_PARAM); }
public override void Resolve(bool generateJoin, bool implicitJoin, string classAlias, IASTNode parent) { if (!IsResolved) { if (Walker.CurrentFromClause.IsFromElementAlias(Text)) { if (ResolveAsAlias()) { IsResolved = true; // We represent a from-clause alias } } else if (parent != null && parent.Type == HqlSqlWalker.DOT) { DotNode dot = (DotNode)parent; if (parent.GetFirstChild() == this) { if (ResolveAsNakedComponentPropertyRefLhs(dot)) { // we are the LHS of the DOT representing a naked comp-prop-ref IsResolved = true; } } else { if (ResolveAsNakedComponentPropertyRefRhs(dot)) { // we are the RHS of the DOT representing a naked comp-prop-ref IsResolved = true; } } } else { int result = ResolveAsNakedPropertyRef(); if (result == PropertyRef) { // we represent a naked (simple) prop-ref IsResolved = true; } else if (result == ComponentRef) { // EARLY EXIT!!! return so the resolve call explicitly coming from DotNode can // resolve this... return; } } // if we are still not resolved, we might represent a constant. // needed to add this here because the allowance of // naked-prop-refs in the grammar collides with the // definition of literals/constants ("nondeterminism"). // TODO: cleanup the grammar so that "processConstants" is always just handled from here if (!IsResolved) { try { Walker.LiteralProcessor.ProcessConstant(this, false); } catch (Exception) { // just ignore it for now, it'll get resolved later... } } } }
public override T VisitDefault(IASTNode node) => d;
static void SetAlias(IASTNode selectExpr, IASTNode ident) { ((ISelectExpression)selectExpr).Alias = ident.Text; }
void PostProcessUpdate(IASTNode update) { var updateStatement = (UpdateStatement)update; PostProcessDML(updateStatement); }
void PostProcessDelete(IASTNode delete) { PostProcessDML((DeleteStatement)delete); }
private static String ExtractAppliedAlias(IASTNode dotNode) { return(dotNode.Text.Substring(0, dotNode.Text.IndexOf('.'))); }
static void ProcessIndex(IASTNode indexOp) { IndexNode indexNode = (IndexNode)indexOp; indexNode.Resolve(true, true); }
protected void AddFunction(ASTNodeList newNodes, string functionName, IASTNode functionParameter) { AddFunction(newNodes, functionName, new List <IASTNode> { functionParameter }); }
static void PrepareLogicOperator(IASTNode operatorNode) { (( IOperatorNode )operatorNode).Initialize(); }
private void UseSelectClause(IASTNode select) { _selectClause = (SelectClause)select; _selectClause.InitializeExplicitSelectClause(_currentFromClause); }
public HqlSqlGenerator(IStatement ast, ISessionFactoryImplementor sfi) { _ast = (IASTNode)ast; _sfi = sfi; }
static void ProcessConstructor(IASTNode constructor) { ConstructorNode constructorNode = (ConstructorNode)constructor; constructorNode.Prepare(); }
public AssignmentSpecification(IASTNode eq, IQueryable persister) { if (eq.Type != HqlSqlWalker.EQ) { throw new QueryException("assignment in set-clause not associated with equals"); } _eq = eq; _factory = persister.Factory; // Needed to bump this up to DotNode, because that is the only thing which currently // knows about the property-ref path in the correct format; it is either this, or // recurse over the DotNodes constructing the property path just like DotNode does // internally DotNode lhs; try { lhs = (DotNode)eq.GetFirstChild(); } catch (InvalidCastException e) { throw new QueryException( string.Format("Left side of assigment should be a case sensitive property or a field (depending on mapping); found '{0}'", eq.GetFirstChild()), e); } var rhs = (SqlNode)lhs.NextSibling; ValidateLhs(lhs); string propertyPath = lhs.PropertyPath; var temp = new HashedSet <string>(); // yuck! var usep = persister as UnionSubclassEntityPersister; if (usep != null) { temp.AddAll(persister.ConstraintOrderedTableNameClosure); } else { temp.Add(persister.GetSubclassTableName(persister.GetSubclassPropertyTableNumber(propertyPath))); } _tableNames = new ImmutableSet <string>(temp); if (rhs == null) { _hqlParameters = new IParameterSpecification[0]; } else if (IsParam(rhs)) { _hqlParameters = new[] { ((ParameterNode)rhs).HqlParameterSpecification }; } else { var parameterList = ASTUtil.CollectChildren(rhs, IsParam); _hqlParameters = new IParameterSpecification[parameterList.Count]; int i = 0; foreach (ParameterNode parameterNode in parameterList) { _hqlParameters[i++] = parameterNode.HqlParameterSpecification; } } }
void CreateFromJoinElement( IASTNode path, IASTNode alias, int joinType, IASTNode fetchNode, IASTNode propertyFetch, IASTNode with) { bool fetch = fetchNode != null; if (fetch && IsSubQuery) { throw new QueryException("fetch not allowed in subquery from-elements"); } // the incoming "path" can be either: // 1) an implicit join path (join p.address.city) // 2) an entity-join (join com.acme.User) // // so make the proper interpretation here... var entityJoinReferencedPersister = ResolveEntityJoinReferencedPersister(path); if (entityJoinReferencedPersister != null) { var entityJoin = CreateEntityJoin(entityJoinReferencedPersister, alias, joinType, with); ((FromReferenceNode)path).FromElement = entityJoin; SetPropertyFetch(entityJoin, propertyFetch, alias); return; } // The path AST should be a DotNode, and it should have been evaluated already. if (path.Type != DOT) { throw new SemanticException("Path expected for join!"); } DotNode dot = ( DotNode )path; //JoinType hibernateJoinType = JoinProcessor.ToHibernateJoinType( joinType ); JoinType hibernateJoinType = _impliedJoinType; dot.JoinType = hibernateJoinType; // Tell the dot node about the join type. dot.Fetch = fetch; // Generate an explicit join for the root dot node. The implied joins will be collected and passed up // to the root dot node. dot.Resolve(true, false, alias == null ? null : alias.Text); FromElement fromElement; if (dot.DataType != null && dot.DataType.IsComponentType) { var factory = new FromElementFactory(CurrentFromClause, dot.GetLhs().FromElement, dot.PropertyPath, alias == null ? null : alias.Text, null, false); fromElement = factory.CreateComponentJoin((ComponentType)dot.DataType); } else { fromElement = dot.GetImpliedJoin(); if (fromElement == null) { throw new InvalidPathException("Invalid join: " + dot.Path); } SetPropertyFetch(fromElement, propertyFetch, alias); if (with != null) { if (fetch) { throw new SemanticException("with-clause not allowed on fetched associations; use filters"); } HandleWithFragment(fromElement, with); } if (fromElement.Parent == null) { fromElement.FromClause.AddChild(fromElement); } } if (log.IsDebugEnabled()) { log.Debug("createFromJoinElement() : {0}", _printer.ShowAsString(fromElement, "-- join tree --")); } }
protected SqlString GenerateIdInsertSelect(IQueryable persister, string tableAlias, IASTNode whereClause) { var select = new SqlSelectBuilder(Factory); SelectFragment selectFragment = new SelectFragment(Factory.Dialect) .AddColumns(tableAlias, persister.IdentifierColumnNames, persister.IdentifierColumnNames); select.SetSelectClause(selectFragment.ToFragmentString().Substring(2)); string rootTableName = persister.TableName; SqlString fromJoinFragment = persister.FromJoinFragment(tableAlias, true, false); select.SetFromClause(rootTableName + " " + tableAlias + fromJoinFragment); var whereJoinFragment = GetWhereJoinFragment(persister, tableAlias); SqlString userWhereClause = SqlString.Empty; if (whereClause.ChildCount != 0) { // If a where clause was specified in the update/delete query, use it to limit the // returned ids here... try { var nodes = new CommonTreeNodeStream(whereClause); var gen = new SqlGenerator(Factory, nodes); gen.whereClause(); userWhereClause = gen.GetSQL().Substring(7); } catch (RecognitionException e) { throw new HibernateException("Unable to generate id select for DML operation", e); } if (whereJoinFragment.Length > 0) { whereJoinFragment = whereJoinFragment.Append(" and "); } } select.SetWhereClause(whereJoinFragment + userWhereClause); var insert = new InsertSelect(); if (Factory.Settings.IsCommentsEnabled) { insert.SetComment("insert-select for " + persister.EntityName + " ids"); } insert.SetTableName(persister.TemporaryIdTableName); insert.SetSelect(select); return(insert.ToSqlString()); }
static void SetPropertyFetch(FromElement fromElement, IASTNode propertyFetch, IASTNode alias) { if (propertyFetch == null) { return; } if (propertyFetch.ChildCount == 0) { fromElement.SetAllPropertyFetch(true); } else { var propertyPaths = new string[propertyFetch.ChildCount / 2]; for (var i = 1; i < propertyFetch.ChildCount; i = i + 2) { string propertyPath; var child = propertyFetch.GetChild(i); // o.PropName if (child is DotNode dotNode) { dotNode.JoinType = JoinType.None; dotNode.PropertyPath = GetPropertyPath(dotNode, alias); propertyPath = dotNode.PropertyPath; } else if (child is IdentNode identNode) { propertyPath = identNode.OriginalText; } else { throw new InvalidOperationException($"Unable to determine property path for AST node: {child.ToStringTree()}"); } propertyPaths[(i - 1) / 2] = propertyPath; } fromElement.FetchLazyProperties = propertyPaths; } }
public static void MakeSiblingOfParent(IASTNode parent, IASTNode child) { parent.RemoveChild(child); parent.AddSibling(child); }
static void PrepareArithmeticOperator(IASTNode op) { ((IOperatorNode)op).Initialize(); }
void ProcessNumericLiteral(IASTNode literal) { _literalProcessor.ProcessNumericLiteral((SqlNode)literal); }
static void ProcessFunction(IASTNode functionCall, bool inSelect) { MethodNode methodNode = (MethodNode)functionCall; methodNode.Resolve(inSelect); }
void PostProcessInsert(IASTNode insert) { var insertStatement = (InsertStatement)insert; insertStatement.Validate(); SelectClause selectClause = insertStatement.SelectClause; var persister = insertStatement.IntoClause.Queryable; if (!insertStatement.IntoClause.IsExplicitIdInsertion) { // We need to generate ids as part of this bulk insert. // // Note that this is only supported for sequence-style generators and // post-insert-style generators; basically, only in-db generators IIdentifierGenerator generator = persister.IdentifierGenerator; if (!SupportsIdGenWithBulkInsertion(generator)) { throw new QueryException("can only generate ids as part of bulk insert with either sequence or post-insert style generators"); } IASTNode idSelectExprNode = null; var seqGenerator = generator as SequenceGenerator; if (seqGenerator != null) { string seqName = seqGenerator.GeneratorKey(); string nextval = SessionFactoryHelper.Factory.Dialect.GetSelectSequenceNextValString(seqName); idSelectExprNode = ASTFactory.CreateNode(SQL_TOKEN, nextval); } else { //Don't need this, because we should never ever be selecting no columns in an insert ... select... //and because it causes a bug on DB2 /*String idInsertString = sessionFactoryHelper.getFactory().getDialect().getIdentityInsertString(); * if ( idInsertString != null ) { * idSelectExprNode = getASTFactory().create( HqlSqlTokenTypes.SQL_TOKEN, idInsertString ); * }*/ } if (idSelectExprNode != null) { selectClause.InsertChild(0, idSelectExprNode); insertStatement.IntoClause.PrependIdColumnSpec(); } } bool includeVersionProperty = persister.IsVersioned && !insertStatement.IntoClause.IsExplicitVersionInsertion && persister.VersionPropertyInsertable; if (includeVersionProperty) { // We need to seed the version value as part of this bulk insert IVersionType versionType = persister.VersionType; IASTNode versionValueNode; if (SessionFactoryHelper.Factory.Dialect.SupportsParametersInInsertSelect) { versionValueNode = ASTFactory.CreateNode(PARAM, "?"); IParameterSpecification paramSpec = new VersionTypeSeedParameterSpecification(versionType); ((ParameterNode)versionValueNode).HqlParameterSpecification = paramSpec; _parameters.Insert(0, paramSpec); } else { if (IsIntegral(versionType)) { try { object seedValue = versionType.Seed(null); versionValueNode = ASTFactory.CreateNode(SQL_TOKEN, seedValue.ToString()); } catch (Exception t) { throw new QueryException("could not determine seed value for version on bulk insert [" + versionType + "]", t); } } else if (IsDatabaseGeneratedTimestamp(versionType)) { var functionName = IsUtcDatabaseGeneratedTimestamp(versionType) ? SessionFactoryHelper.Factory.Dialect.CurrentUtcTimestampSQLFunctionName : SessionFactoryHelper.Factory.Dialect.CurrentTimestampSQLFunctionName; versionValueNode = ASTFactory.CreateNode(SQL_TOKEN, functionName); } else { throw new QueryException("cannot handle version type [" + versionType + "] on bulk inserts with dialects not supporting parameters in insert-select statements"); } } selectClause.InsertChild(0, versionValueNode); insertStatement.IntoClause.PrependVersionColumnSpec(); } if (insertStatement.IntoClause.IsDiscriminated) { string sqlValue = insertStatement.IntoClause.Queryable.DiscriminatorSQLValue; IASTNode discrimValue = ASTFactory.CreateNode(SQL_TOKEN, sqlValue); insertStatement.SelectClause.AddChild(discrimValue); } }
public abstract void Resolve(bool generateJoin, bool implicitJoin, string classAlias, IASTNode parent);
public abstract void ResolveIndex(IASTNode parent);
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(); } }