Beispiel #1
0
        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);
 }
Beispiel #3
0
        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;
            }
        }
Beispiel #4
0
        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;
				}
			}
		}
Beispiel #10
0
        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 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);
        }