private void InitializeColumns() { IASTNode propertySpec = GetFirstChild(); var ts = new List <IType>(); VisitPropertySpecNodes(propertySpec.GetFirstChild(), ts); _types = ts.ToArray(); _columnSpec = _columnSpec.Substring(0, _columnSpec.Length - 2); }
private static bool TryGetParameterName(IASTNode node, out string result) { if (node.Type != HqlSqlWalker.COLON) { result = null; return(false); } result = node.GetFirstChild().Text; return(true); }
void PrepareVersioned(IASTNode updateNode, IASTNode versioned) { var updateStatement = (UpdateStatement)updateNode; FromClause fromClause = updateStatement.FromClause; if (versioned != null) { // Make sure that the persister is versioned IQueryable persister = fromClause.GetFromElement().Queryable; if (!persister.IsVersioned) { throw new SemanticException("increment option specified for update of non-versioned entity"); } IVersionType versionType = persister.VersionType; if (versionType is IUserVersionType) { throw new SemanticException("user-defined version types not supported for increment option"); } IASTNode eq = ASTFactory.CreateNode(EQ, "="); IASTNode versionPropertyNode = GenerateVersionPropertyNode(persister); eq.SetFirstChild(versionPropertyNode); IASTNode versionIncrementNode; if (typeof(DateTime).IsAssignableFrom(versionType.ReturnedClass)) { versionIncrementNode = ASTFactory.CreateNode(PARAM, "?"); IParameterSpecification paramSpec = new VersionTypeSeedParameterSpecification(versionType); ((ParameterNode)versionIncrementNode).HqlParameterSpecification = paramSpec; Parameters.Insert(0, paramSpec); } else { // Not possible to simply re-use the versionPropertyNode here as it causes // OOM errors due to circularity :( versionIncrementNode = ASTFactory.CreateNode(PLUS, "+"); versionIncrementNode.SetFirstChild(GenerateVersionPropertyNode(persister)); versionIncrementNode.AddChild(ASTFactory.CreateNode(IDENT, "1")); } eq.AddChild(versionIncrementNode); EvaluateAssignment(eq, persister, 0); IASTNode setClause = updateStatement.SetClause; IASTNode currentFirstSetElement = setClause.GetFirstChild(); setClause.SetFirstChild(eq); eq.NextSibling = currentFirstSetElement; } }
private void VisitPropertySpecNodes(IASTNode propertyNode, ICollection <IType> types) { if (propertyNode == null) { return; } // TODO : we really need to be able to deal with component paths here also; // this is difficult because the hql-sql grammar expects all those node types // to be FromReferenceNodes. One potential fix here would be to convert the // IntoClause to just use a FromClause/FromElement combo (as a child of the // InsertStatement) and move all this logic into the InsertStatement. That's // probably the easiest approach (read: least amount of changes to the grammar // and code), but just doesn't feel right as then an insert would contain // 2 from-clauses string name = propertyNode.Text; if (IsSuperclassProperty(name)) { throw new QueryException("INSERT statements cannot refer to superclass/joined properties [" + name + "]"); } if (name == _persister.IdentifierPropertyName) { _explicitIdInsertion = true; } if (_persister.IsVersioned) { if (name == _persister.PropertyNames[_persister.VersionProperty]) { _explicitVersionInsertion = true; } } string[] columnNames = _persister.ToColumns(name); RenderColumns(columnNames); types.Add(_persister.ToType(name)); // visit width-first, then depth VisitPropertySpecNodes(propertyNode.NextSibling, types); VisitPropertySpecNodes(propertyNode.GetFirstChild(), types); }
private void ExtractOrders(IASTNode node) { if (this.rootClassMetadata == null) { throw new NotSupportedException("Ordering of sharded scalar HQL queries is not supported"); } var child = node.GetFirstChild(); while (child != null) { var propertyPath = ASTUtil.GetPathText(child); var aliasLength = propertyPath.IndexOf('.'); if (aliasLength >= 0) { propertyPath = propertyPath.Substring(aliasLength + 1); } var isDescending = false; child = child.NextSibling; if (child != null) { isDescending = child.Type == HqlSqlWalker.DESCENDING; if (isDescending || child.Type == HqlSqlWalker.ASCENDING) { child = child.NextSibling; } } this.exitOperationBuilder.Orders.Add( new SortOrder( o => propertyPath == this.rootClassMetadata.IdentifierPropertyName ? this.rootClassMetadata.GetIdentifier(o) : this.rootClassMetadata.GetPropertyValue(o, propertyPath), isDescending)); } }
public override void Initialize() { IASTNode lhs = LeftHandOperand; if (lhs == null) { throw new SemanticException("left-hand operand of in operator was null"); } IASTNode inList = InList; if (inList == null) { throw new SemanticException("right-hand operand of in operator was null"); } // for expected parameter type injection, we expect that the lhs represents // some form of property ref and that the children of the in-list represent // one-or-more params. var lhsNode = lhs as SqlNode; IType lhsType = null; if (lhsNode != null) { lhsType = lhsNode.DataType; IASTNode inListChild = inList.GetChild(0); while (inListChild != null) { var expectedTypeAwareNode = inListChild as IExpectedTypeAwareNode; if (expectedTypeAwareNode != null) { expectedTypeAwareNode.ExpectedType = lhsType; } inListChild = inListChild.NextSibling; } } var sessionFactory = SessionFactoryHelper.Factory; if (sessionFactory.Dialect.SupportsRowValueConstructorSyntaxInInList) { return; } lhsType = lhsType ?? ExtractDataType(lhs); if (lhsType == null) { return; } var rhsNode = inList.GetFirstChild(); if (rhsNode == null || !IsNodeAcceptable(rhsNode)) { return; } var lhsColumnSpan = lhsType.GetColumnSpan(sessionFactory); var rhsColumnSpan = rhsNode.Type == HqlSqlWalker.VECTOR_EXPR ? rhsNode.ChildCount : ExtractDataType(rhsNode)?.GetColumnSpan(sessionFactory) ?? 0; if (lhsColumnSpan > 1 && rhsColumnSpan > 1) { MutateRowValueConstructorSyntaxInInListSyntax(lhs, lhsColumnSpan, rhsNode, rhsColumnSpan); } }
private void VisitPropertySpecNodes(IASTNode propertyNode, ICollection<IType> types) { if (propertyNode == null) { return; } // TODO : we really need to be able to deal with component paths here also; // this is difficult because the hql-sql grammar expects all those node types // to be FromReferenceNodes. One potential fix here would be to convert the // IntoClause to just use a FromClause/FromElement combo (as a child of the // InsertStatement) and move all this logic into the InsertStatement. That's // probably the easiest approach (read: least amount of changes to the grammar // and code), but just doesn't feel right as then an insert would contain // 2 from-clauses string name = propertyNode.Text; if (IsSuperclassProperty(name)) { throw new QueryException("INSERT statements cannot refer to superclass/joined properties [" + name + "]"); } if (name == _persister.IdentifierPropertyName) { _explicitIdInsertion = true; } if (_persister.IsVersioned) { if (name == _persister.PropertyNames[_persister.VersionProperty]) { _explicitVersionInsertion = true; } } string[] columnNames = _persister.ToColumns(name); RenderColumns(columnNames); types.Add(_persister.ToType(name)); // visit width-first, then depth VisitPropertySpecNodes(propertyNode.NextSibling, types); VisitPropertySpecNodes(propertyNode.GetFirstChild(), types); }
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; } } }
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; } } }
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... } } } }
private bool CanCopy(IASTNode node, out Action <IASTNode> copyTransformer) { copyTransformer = null; IASTNode child; switch (node.Type) { case HqlSqlWalker.SKIP: child = node.GetFirstChild(); if (TryGetParameterName(child, out var skipParameterName)) { this.exitOperationBuilder.FirstResult = (int)namedParameters[skipParameterName].Item1; } else if (TryGetInt32(child, out var firstResult)) { this.exitOperationBuilder.FirstResult = firstResult; } return(false); case HqlSqlWalker.TAKE: child = node.GetFirstChild(); if (TryGetParameterName(child, out var takeParameterName)) { this.exitOperationBuilder.MaxResults = (int)namedParameters[takeParameterName].Item1; } else if (TryGetInt32(child, out var maxResults)) { this.exitOperationBuilder.MaxResults = maxResults; } return(false); case HqlSqlWalker.ORDER: ExtractOrders(node); return(true); case HqlSqlWalker.AGGREGATE: if ("avg".Equals(node.Text, StringComparison.OrdinalIgnoreCase)) { goto case HqlSqlWalker.AVG; } if ("min".Equals(node.Text, StringComparison.OrdinalIgnoreCase)) { goto case HqlSqlWalker.MIN; } else if ("max".Equals(node.Text, StringComparison.OrdinalIgnoreCase)) { goto case HqlSqlWalker.MAX; } throw new NotSupportedException(string.Format( CultureInfo.InvariantCulture, "HQL aggregate function '{0}' is currently not supported across shards.", node.Text)); case HqlSqlWalker.AVG: ThrowIfAggregationInComplexSelectList(node); this.exitOperationBuilder.Aggregation = c => AggregationUtil.Average(c, GetFieldSelector(0), GetFieldSelector(1)); copyTransformer = TransformUnshardedAverageNode; return(true); case HqlSqlWalker.COUNT: ThrowIfAggregationInComplexSelectList(node); this.exitOperationBuilder.Aggregation = c => AggregationUtil.SumInt64(c, o => o); return(true); case HqlSqlWalker.MIN: ThrowIfAggregationInComplexSelectList(node); this.exitOperationBuilder.Aggregation = c => AggregationUtil.Min(c, o => o); return(true); case HqlSqlWalker.MAX: ThrowIfAggregationInComplexSelectList(node); this.exitOperationBuilder.Aggregation = c => AggregationUtil.Max(c, o => o); return(true); case HqlSqlWalker.SUM: ThrowIfAggregationInComplexSelectList(node); this.exitOperationBuilder.Aggregation = c => AggregationUtil.Sum(c, o => o); return(true); } return(true); }