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);
            }
        }
Beispiel #2
0
		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));
			}
		}
		/// <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));
			}
		}
Beispiel #4
0
        public IASTNode ProcessEqualityExpression(object o)
        {
            IASTNode x = o as IASTNode;

            if (x == null)
            {
                log.Warn("processEqualityExpression() : No expression to process!");
                return(null);
            }

            int type = x.Type;

            if (type == EQ || type == NE)
            {
                bool negated = type == NE;

                if (x.ChildCount == 2)
                {
                    IASTNode a = x.GetChild(0);
                    IASTNode b = x.GetChild(1);
                    // (EQ NULL b) => (IS_NULL b)
                    if (a.Type == NULL && b.Type != NULL)
                    {
                        return(CreateIsNullParent(b, negated));
                    }
                    // (EQ a NULL) => (IS_NULL a)
                    if (b.Type == NULL && a.Type != NULL)
                    {
                        return(CreateIsNullParent(a, negated));
                    }
                    if (b.Type == EMPTY)
                    {
                        return(ProcessIsEmpty(a, negated));
                    }
                }
            }

            return(x);
        }
        private void CreateSelectClauseFromFromClause(IASTNode qn)
        {
            // TODO - check this.  Not *exactly* the same logic as the Java original
            qn.InsertChild(0, (IASTNode)adaptor.Create(SELECT_CLAUSE, "{derived select clause}"));

            _selectClause = ( SelectClause )qn.GetChild(0);
            _selectClause.InitializeDerivedSelectClause(_currentFromClause);

            if (log.IsDebugEnabled())
            {
                log.Debug("Derived SELECT clause created.");
            }
        }
Beispiel #6
0
        private void VisitDepthFirst(IASTNode ast)
        {
            if (ast == null)
            {
                return;
            }

            _visitor.Visit(ast);

            for (int i = 0; i < ast.ChildCount; i++)
            {
                VisitDepthFirst(ast.GetChild(i));
            }
        }
		private void VisitDepthFirst(IASTNode ast)
		{
			if (ast == null)
			{
				return;
			}

			_visitor.Visit(ast);

			for (int i = 0; i < ast.ChildCount; i++)
			{
				VisitDepthFirst(ast.GetChild(i));
			}
		}
Beispiel #8
0
		/// <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;
		}
Beispiel #9
0
        private static string[] ExtractMutationTexts(IASTNode operand, int count)
        {
            if (operand is ParameterNode)
            {
                string[] rtn = new string[count];
                for (int i = 0; i < count; i++)
                {
                    rtn[i] = "?";
                }
                return(rtn);
            }
            else if (operand.Type == HqlSqlWalker.VECTOR_EXPR)
            {
                string[] rtn = new string[operand.ChildCount];

                for (int x = 0; x < operand.ChildCount; x++)
                {
                    rtn[x++] = operand.GetChild(x).Text;
                }
                return(rtn);
            }
            else if (operand is SqlNode)
            {
                string nodeText = operand.Text;

                if (nodeText.StartsWith("("))
                {
                    nodeText = nodeText.Substring(1);
                }
                if (nodeText.EndsWith(")"))
                {
                    nodeText = nodeText.Substring(0, nodeText.Length - 1);
                }
                String[] splits = StringHelper.Split(", ", nodeText);

                if (count != splits.Length)
                {
                    throw new HibernateException("SqlNode's text did not reference expected number of columns");
                }
                return(splits);
            }
            else
            {
                throw new HibernateException("dont know how to extract row value elements from node : " + operand);
            }
        }
Beispiel #10
0
        /// <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);
        }
Beispiel #11
0
        public virtual void Resolve(bool inSelect)
        {
            // Get the function name node.
            IASTNode name = GetChild(0);

            InitializeMethodNode(name, inSelect);
            IASTNode exprList = name.NextSibling;

            // If the expression list has exactly one expression, and the type of the expression is a collection
            // then this might be a collection function, such as index(c) or size(c).
            if ((exprList != null && exprList.ChildCount == 1) && IsCollectionPropertyMethod)
            {
                CollectionProperty(exprList.GetChild(0), name);
            }
            else
            {
                DialectFunction(exprList);
            }
        }
        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;
            }
        }
        private static string[] ExtractMutationTexts(IASTNode operand, int count)
        {
            if (operand is ParameterNode)
            {
                return(Enumerable.Repeat("?", count).ToArray());
            }
            if (operand is SqlNode)
            {
                string nodeText = operand.Text;

                if (nodeText.StartsWith("("))
                {
                    nodeText = nodeText.Substring(1);
                }
                if (nodeText.EndsWith(")"))
                {
                    nodeText = nodeText.Substring(0, nodeText.Length - 1);
                }
                string[] splits = nodeText.Split(new[] { ", " }, StringSplitOptions.None);

                if (count != splits.Length)
                {
                    throw new HibernateException("SqlNode's text did not reference expected number of columns");
                }
                return(splits);
            }
            if (operand.Type == HqlSqlWalker.VECTOR_EXPR)
            {
                var rtn = new string[operand.ChildCount];

                for (int x = 0; x < operand.ChildCount; x++)
                {
                    rtn[x] = operand.GetChild(x).Text;
                }
                return(rtn);
            }
            throw new HibernateException("dont know how to extract row value elements from node : " + operand);
        }
        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;

            if (lhsNode != null)
            {
                IType    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;
                }
            }
        }
        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() : {0}", _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, e);
            }
        }
Beispiel #16
0
		private void CreateSelectClauseFromFromClause(IASTNode qn)
		{
			// TODO - check this.  Not *exactly* the same logic as the Java original
			qn.InsertChild(0, (IASTNode)adaptor.Create(SELECT_CLAUSE, "{derived select clause}"));

			_selectClause = ( SelectClause ) qn.GetChild(0);
			_selectClause.InitializeDerivedSelectClause( _currentFromClause );

			if ( log.IsDebugEnabled ) 
			{
				log.Debug( "Derived SELECT clause created." );
			}
		}
Beispiel #17
0
        public IASTNode NegateNode(IASTNode node)
        {
            // TODO - copy code from HqlParser.java
            switch (node.Type)
            {
            case OR:
                node.Type = AND;
                node.Text = "{and}";
                NegateNode(node.GetChild(0));
                NegateNode(node.GetChild(1));
                return(node);

            case AND:
                node.Type = OR;
                node.Text = "{or}";
                NegateNode(node.GetChild(0));
                NegateNode(node.GetChild(1));
                return(node);

            case EQ:
                node.Type = NE;
                node.Text = "{not}" + node.Text;
                return(node);                           // (NOT (EQ a b) ) => (NE a b)

            case NE:
                node.Type = EQ;
                node.Text = "{not}" + node.Text;
                return(node);                           // (NOT (NE a b) ) => (EQ a b)

            case GT:
                node.Type = LE;
                node.Text = "{not}" + node.Text;
                return(node);                           // (NOT (GT a b) ) => (LE a b)

            case LT:
                node.Type = GE;
                node.Text = "{not}" + node.Text;
                return(node);                           // (NOT (LT a b) ) => (GE a b)

            case GE:
                node.Type = LT;
                node.Text = "{not}" + node.Text;
                return(node);                           // (NOT (GE a b) ) => (LT a b)

            case LE:
                node.Type = GT;
                node.Text = "{not}" + node.Text;
                return(node);                           // (NOT (LE a b) ) => (GT a b)

            case LIKE:
                node.Type = NOT_LIKE;
                node.Text = "{not}" + node.Text;
                return(node);                           // (NOT (LIKE a b) ) => (NOT_LIKE a b)

            case NOT_LIKE:
                node.Type = LIKE;
                node.Text = "{not}" + node.Text;
                return(node);                           // (NOT (NOT_LIKE a b) ) => (LIKE a b)

            case IN:
                node.Type = NOT_IN;
                node.Text = "{not}" + node.Text;
                return(node);

            case NOT_IN:
                node.Type = IN;
                node.Text = "{not}" + node.Text;
                return(node);

            case IS_NULL:
                node.Type = IS_NOT_NULL;
                node.Text = "{not}" + node.Text;
                return(node);                           // (NOT (IS_NULL a b) ) => (IS_NOT_NULL a b)

            case IS_NOT_NULL:
                node.Type = IS_NULL;
                node.Text = "{not}" + node.Text;
                return(node);                           // (NOT (IS_NOT_NULL a b) ) => (IS_NULL a b)

            case BETWEEN:
                node.Type = NOT_BETWEEN;
                node.Text = "{not}" + node.Text;
                return(node);                           // (NOT (BETWEEN a b) ) => (NOT_BETWEEN a b)

            case NOT_BETWEEN:
                node.Type = BETWEEN;
                node.Text = "{not}" + node.Text;
                return(node);                           // (NOT (NOT_BETWEEN a b) ) => (BETWEEN a b)

            /* This can never happen because this rule will always eliminate the child NOT.
             *                      case NOT:
             *                              return x.getFirstChild();			// (NOT (NOT x) ) => (x)
             */
            default:
                IASTNode not = (IASTNode)TreeAdaptor.Create(NOT, "not");
                not.AddChild(node);
                return(not);
            }
        }
		private void DialectFunction(IASTNode exprList)
		{
			_function = SessionFactoryHelper.FindSQLFunction(_methodName);

			if (_function != null)
			{
			    IASTNode child = null;

                if (exprList != null)
                {
                    child = _methodName == "iif" ? exprList.GetChild(1) : exprList.GetChild(0);
                }

                DataType = SessionFactoryHelper.FindFunctionReturnType(_methodName, child);
			}
			//TODO:
			/*else {
				methodName = (String) getWalker().getTokenReplacements().get( methodName );
			}*/
		}
Beispiel #19
0
		/// <summary>
		/// Finds the first node of the specified type in the chain of children.
		/// </summary>
		/// <param name="parent">The parent</param>
		/// <param name="type">The type to find.</param>
		/// <returns>The first node of the specified type, or null if not found.</returns>
		public static IASTNode FindTypeInChildren(IASTNode parent, int type)
		{
			for (int i = 0; i < parent.ChildCount; i++)
			{
				var child = parent.GetChild(i);
				if (child.Type == type)
				{
					return child;
				}
			}
			return null;
		}
Beispiel #20
0
		public IASTNode ProcessMemberOf(IToken n, IASTNode p, IASTNode root)
		{
			ASTFactory factory = new ASTFactory(adaptor);

			return factory.CreateNode(n == null ? IN : NOT_IN,
			                          n == null ? "in" : "not in",
			                          root.IsNil && root.ChildCount == 1 ? root.GetChild(0) : root,
			                          factory.CreateNode(IN_LIST, "inList",
			                                             CreateSubquery(p)));
		}
Beispiel #21
0
        /**
         * Mutate the subtree relating to a row-value-constructor to instead use
         * a series of ANDed predicates.  This allows multi-column type comparisons
         * and explicit row-value-constructor syntax even on databases which do
         * not support row-value-constructor.
         * <p/>
         * For example, here we'd mutate "... where (col1, col2) = ('val1', 'val2) ..." to
         * "... where col1 = 'val1' and col2 = 'val2' ..."
         *
         * @param valueElements The number of elements in the row value constructor list.
         */
        private void MutateRowValueConstructorSyntax(int valueElements)
        {
            // mutation depends on the types of nodes invloved...
            int    comparisonType = Type;
            string comparisonText = Text;

            Type = HqlSqlWalker.AND;
            Text = "AND";

            String[] lhsElementTexts = ExtractMutationTexts(LeftHandOperand, valueElements);
            String[] rhsElementTexts = ExtractMutationTexts(RightHandOperand, valueElements);

            IParameterSpecification lhsEmbeddedCompositeParameterSpecification =
                LeftHandOperand == null || (!(LeftHandOperand is ParameterNode))
                                                        ? null
                                                        : (( ParameterNode )LeftHandOperand).HqlParameterSpecification;

            IParameterSpecification rhsEmbeddedCompositeParameterSpecification =
                RightHandOperand == null || (!(RightHandOperand is ParameterNode))
                                                        ? null
                                                        : (( ParameterNode )RightHandOperand).HqlParameterSpecification;

            IASTNode container = this;

            for (int i = valueElements - 1; i > 0; i--)
            {
                if (i == 1)
                {
                    container.ClearChildren();

                    container.AddChildren(
                        ASTFactory.CreateNode(
                            comparisonType, comparisonText,
                            ASTFactory.CreateNode(HqlSqlWalker.SQL_TOKEN, lhsElementTexts[0]),
                            ASTFactory.CreateNode(HqlSqlWalker.SQL_TOKEN, rhsElementTexts[0])
                            ),
                        ASTFactory.CreateNode(
                            comparisonType, comparisonText,
                            ASTFactory.CreateNode(HqlSqlWalker.SQL_TOKEN, lhsElementTexts[1]),
                            ASTFactory.CreateNode(HqlSqlWalker.SQL_TOKEN, rhsElementTexts[1])
                            ));

                    // "pass along" our initial embedded parameter node(s) to the first generated
                    // sql fragment so that it can be handled later for parameter binding...
                    SqlFragment fragment = ( SqlFragment )container.GetChild(0).GetChild(0);
                    if (lhsEmbeddedCompositeParameterSpecification != null)
                    {
                        fragment.AddEmbeddedParameter(lhsEmbeddedCompositeParameterSpecification);
                    }
                    if (rhsEmbeddedCompositeParameterSpecification != null)
                    {
                        fragment.AddEmbeddedParameter(rhsEmbeddedCompositeParameterSpecification);
                    }
                }
                else
                {
                    container.ClearChildren();
                    container.AddChildren(
                        ASTFactory.CreateNode(HqlSqlWalker.AND, "AND"),
                        ASTFactory.CreateNode(
                            comparisonType, comparisonText,
                            ASTFactory.CreateNode(HqlSqlWalker.SQL_TOKEN, lhsElementTexts[i]),
                            ASTFactory.CreateNode(HqlSqlWalker.SQL_TOKEN, rhsElementTexts[i])
                            ));

                    container = container.GetChild(0);
                }
            }
        }
		public void Visit(IASTNode node)
		{
			if ((node.Type == HqlSqlWalker.PARAM) || (node.Type == HqlSqlWalker.COLON))
			{
				string name = node.GetChild(0).Text;

				if (_parameterNames.Contains(name))
				{
					_nodes.Add(node);
				}
			}
		}
		/// <summary>
		/// Finds the first node of the specified type in the chain of children.
		/// </summary>
		/// <param name="parent">The parent</param>
		/// <param name="type">The type to find.</param>
		/// <returns>The first node of the specified type, or null if not found.</returns>
		public static IASTNode FindTypeInChildren(IASTNode parent, int type)
		{
			for (int i = 0; i < parent.ChildCount; i++)
			{
				if (parent.GetChild(i).Type == type)
				{
					return parent.GetChild(i);
				}
			}
			return null;
		}
Beispiel #24
0
        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() : {0}", _printer.ShowAsString(hqlSqlWithNode, "-- with clause --"));
                }
                WithClauseVisitor visitor   = new WithClauseVisitor(fromElement);
                NodeTraverser     traverser = new NodeTraverser(visitor);
                traverser.TraverseDepthFirst(hqlSqlWithNode);
                SqlGenerator sql = new SqlGenerator(_sessionFactoryHelper.Factory, new CommonTreeNodeStream(adaptor, hqlSqlWithNode.GetChild(0)));

                sql.whereExpr();

                fromElement.WithClauseFragment = new SqlString("(", sql.GetSQL(), ")");
            }
            catch (SemanticException)
            {
                throw;
            }
            catch (InvalidWithClauseException)
            {
                throw;
            }
            catch (Exception e)
            {
                throw new SemanticException(e.Message, e);
            }
        }
Beispiel #25
0
		public IASTNode NegateNode(IASTNode node)
		{
			// TODO - copy code from HqlParser.java
			switch (node.Type)
			{
				case OR:
					node.Type = AND;
					node.Text = "{and}";
					NegateNode(node.GetChild(0));
					NegateNode(node.GetChild(1));
					return node;
				case AND:
					node.Type = OR;
					node.Text = "{or}";
					NegateNode(node.GetChild(0));
					NegateNode(node.GetChild(1));
					return node;
				case EQ:
					node.Type = NE;
					node.Text = "{not}" + node.Text;
					return node;	// (NOT (EQ a b) ) => (NE a b)
				case NE:
					node.Type = EQ;
					node.Text = "{not}" + node.Text;
					return node;	// (NOT (NE a b) ) => (EQ a b)
				case GT:
					node.Type = LE;
					node.Text = "{not}" + node.Text;
					return node;	// (NOT (GT a b) ) => (LE a b)
				case LT:
					node.Type = GE;
					node.Text = "{not}" + node.Text;
					return node;	// (NOT (LT a b) ) => (GE a b)
				case GE:
					node.Type = LT;
					node.Text = "{not}" + node.Text;
					return node;	// (NOT (GE a b) ) => (LT a b)
				case LE:
					node.Type = GT;
					node.Text = "{not}" + node.Text;
					return node;	// (NOT (LE a b) ) => (GT a b)
				case LIKE:
					node.Type = NOT_LIKE;
					node.Text = "{not}" + node.Text;
					return node;	// (NOT (LIKE a b) ) => (NOT_LIKE a b)
				case NOT_LIKE:
					node.Type = LIKE;
					node.Text = "{not}" + node.Text;
					return node;	// (NOT (NOT_LIKE a b) ) => (LIKE a b)
				case IN:
					node.Type = NOT_IN;
					node.Text = "{not}" + node.Text;
					return node;
				case NOT_IN:
					node.Type = IN;
					node.Text = "{not}" + node.Text;
					return node;
				case IS_NULL:
					node.Type = IS_NOT_NULL;
					node.Text = "{not}" + node.Text;
					return node;	// (NOT (IS_NULL a b) ) => (IS_NOT_NULL a b)
				case IS_NOT_NULL:
					node.Type = IS_NULL;
					node.Text = "{not}" + node.Text;
					return node;	// (NOT (IS_NOT_NULL a b) ) => (IS_NULL a b)
				case BETWEEN:
					node.Type = NOT_BETWEEN;
					node.Text = "{not}" + node.Text;
					return node;	// (NOT (BETWEEN a b) ) => (NOT_BETWEEN a b)
				case NOT_BETWEEN:
					node.Type = BETWEEN;
					node.Text = "{not}" + node.Text;
					return node;	// (NOT (NOT_BETWEEN a b) ) => (BETWEEN a b)
				/* This can never happen because this rule will always eliminate the child NOT.
							case NOT:
								return x.getFirstChild();			// (NOT (NOT x) ) => (x)
				*/
				default:
					IASTNode not = (IASTNode) TreeAdaptor.Create(NOT, "not");
					not.AddChild(node);
					return not;
			}
		}
		private static string[] ExtractMutationTexts(IASTNode operand, int count) 
		{
			if ( operand is ParameterNode ) 
			{
				string[] rtn = new string[count];
				for ( int i = 0; i < count; i++ ) 
				{
					rtn[i] = "?";
				}
				return rtn;
			}
			else if ( operand.Type == HqlSqlWalker.VECTOR_EXPR ) 
			{
				string[] rtn = new string[operand.ChildCount];

				for (int x = 0; x < operand.ChildCount; x++)
				{
					rtn[ x++ ] = operand.GetChild(x).Text;
					
				}
				return rtn;
			}
			else if ( operand is SqlNode ) 
			{
				string nodeText = operand.Text;

				if ( nodeText.StartsWith( "(" ) ) 
				{
					nodeText = nodeText.Substring( 1 );
				}
				if ( nodeText.EndsWith( ")" ) ) 
				{
					nodeText = nodeText.Substring( 0, nodeText.Length - 1 );
				}
				String[] splits = StringHelper.Split( ", ", nodeText );

				if ( count != splits.Length ) 
				{
					throw new HibernateException( "SqlNode's text did not reference expected number of columns" );
				}
				return splits;
			}
			else
			{
				throw new HibernateException( "dont know how to extract row value elements from node : " + operand );
			}
		}
        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 static string[] ExtractMutationTexts(IASTNode operand, int count) 
		{
			if ( operand is ParameterNode ) 
			{
				return Enumerable.Repeat("?", count).ToArray();
			}
			if (operand is SqlNode)
			{
				string nodeText = operand.Text;

				if (nodeText.StartsWith("("))
				{
					nodeText = nodeText.Substring(1);
				}
				if (nodeText.EndsWith(")"))
				{
					nodeText = nodeText.Substring(0, nodeText.Length - 1);
				}
				string[] splits = nodeText.Split(new[] { ", " }, StringSplitOptions.None);

				if (count != splits.Length)
				{
					throw new HibernateException("SqlNode's text did not reference expected number of columns");
				}
				return splits;
			}
			if (operand.Type == HqlSqlWalker.VECTOR_EXPR) 
			{
				var rtn = new string[operand.ChildCount];

				for (int x = 0; x < operand.ChildCount; x++)
				{
					rtn[ x ] = operand.GetChild(x).Text;
				}
				return rtn;
			}
			throw new HibernateException( "dont know how to extract row value elements from node : " + operand );
		}