public void ProcessJoins(QueryNode query) 
		{
			FromClause fromClause = query.FromClause;

			IList<IASTNode> fromElements;
			if ( DotNode.UseThetaStyleImplicitJoins ) 
			{
				// for regression testing against output from the old parser...
				// found it easiest to simply reorder the FromElements here into ascending order
				// in terms of injecting them into the resulting sql ast in orders relative to those
				// expected by the old parser; this is definitely another of those "only needed
				// for regression purposes".  The SyntheticAndFactory, then, simply injects them as it
				// encounters them.
				fromElements = new List<IASTNode>();
				IList<IASTNode> t = fromClause.GetFromElements();

				for (int i = t.Count - 1; i >= 0; i--)
				{
					fromElements.Add(t[i]);
				}
			}
			else 
			{
				fromElements = fromClause.GetFromElements();
			}

			// Iterate through the alias,JoinSequence pairs and generate SQL token nodes.
			foreach (FromElement fromElement in fromElements)
			{
				JoinSequence join = fromElement.JoinSequence;

				join.SetSelector(new JoinSequenceSelector(_walker, fromClause, fromElement));

				AddJoinNodes( query, join, fromElement );
			}
		}
		public void AddWhereFragment(
				JoinFragment joinFragment,
				SqlString whereFragment,
				QueryNode query,
				FromElement fromElement,
				HqlSqlWalker hqlSqlWalker)
		{
			if (whereFragment == null)
			{
				return;
			}

			if (!fromElement.UseWhereFragment && !joinFragment.HasThetaJoins)
			{
				return;
			}

			whereFragment = whereFragment.Trim();
			if (StringHelper.IsEmpty(whereFragment.ToString()))
			{
				return;
			}

			// Forcefully remove leading ands from where fragments; the grammar will
			// handle adding them
			if (whereFragment.StartsWithCaseInsensitive("and"))
			{
				whereFragment = whereFragment.Substring(4);
			}

			log.Debug("Using unprocessed WHERE-fragment [" + whereFragment +"]");

			SqlFragment fragment = (SqlFragment) Create(HqlSqlWalker.SQL_TOKEN, whereFragment.ToString());

			fragment.SetJoinFragment(joinFragment);
			fragment.FromElement = fromElement;

			if (fromElement.IndexCollectionSelectorParamSpec != null)
			{
				fragment.AddEmbeddedParameter(fromElement.IndexCollectionSelectorParamSpec);
				fromElement.IndexCollectionSelectorParamSpec = null;
			}

			if (hqlSqlWalker.IsFilter())
			{
				//if (whereFragment.IndexOfCaseInsensitive("?") >= 0)
                if (whereFragment.ToString().IndexOf("?") >= 0)
                {
					IType collectionFilterKeyType = hqlSqlWalker.SessionFactoryHelper
							.RequireQueryableCollection(hqlSqlWalker.CollectionFilterRole)
							.KeyType;
					CollectionFilterKeyParameterSpecification paramSpec = new CollectionFilterKeyParameterSpecification(
							hqlSqlWalker.CollectionFilterRole,
							collectionFilterKeyType,
							0
					);
					fragment.AddEmbeddedParameter(paramSpec);
				}
			}

			JoinProcessor.ProcessDynamicFilterParameters(
					whereFragment,
					fragment,
					hqlSqlWalker
			);

			log.Debug("Using processed WHERE-fragment [" + fragment.Text + "]");

			// Filter conditions need to be inserted before the HQL where condition and the
			// theta join node.  This is because org.hibernate.loader.Loader binds the filter parameters first,
			// then it binds all the HQL query parameters, see org.hibernate.loader.Loader.processFilterParameters().
			if (fragment.FromElement.IsFilter || fragment.HasFilterCondition)
			{
				if (_filters == null)
				{
					// Find or create the WHERE clause
					IASTNode where = (IASTNode) query.WhereClause;
					// Create a new FILTERS node as a parent of all filters
					_filters = Create(HqlSqlWalker.FILTERS, "{filter conditions}");
					// Put the FILTERS node before the HQL condition and theta joins
					where.InsertChild(0, _filters);
				}

				// add the current fragment to the FILTERS node
				_filters.AddChild(fragment);
			}
			else
			{
				if (_thetaJoins == null)
				{
					// Find or create the WHERE clause
					IASTNode where = (IASTNode) query.WhereClause;

					// Create a new THETA_JOINS node as a parent of all filters
					_thetaJoins = Create(HqlSqlWalker.THETA_JOINS, "{theta joins}");

					// Put the THETA_JOINS node before the HQL condition, after the filters.
					if (_filters == null)
					{
						where.InsertChild(0, _thetaJoins);
					}
					else
					{
                        _filters.AddSibling(_thetaJoins);
					}
				}

				// add the current fragment to the THETA_JOINS node
				_thetaJoins.AddChild(fragment);
			}
		}
		public override object Create(IToken payload)
		{
			if (payload == null)
			{
				return base.Create(payload);
			}

			object ret;

			switch (payload.Type)
			{
				case HqlSqlWalker.SELECT:
				case HqlSqlWalker.QUERY:
					ret = new QueryNode(payload);
					break;
				case HqlSqlWalker.UPDATE:
					ret = new UpdateStatement(payload);
					break;
				case HqlSqlWalker.DELETE:
					ret = new DeleteStatement(payload);
					break;
				case HqlSqlWalker.INSERT:
					ret = new InsertStatement(payload);
					break;
				case HqlSqlWalker.INTO:
					ret = new IntoClause(payload);
					break;
				case HqlSqlWalker.FROM:
					ret = new FromClause(payload);
					break;
				case HqlSqlWalker.FROM_FRAGMENT:
					ret = new FromElement(payload);
					break;
				case HqlSqlWalker.IMPLIED_FROM:
					ret = new ImpliedFromElement(payload);
					break;
				case HqlSqlWalker.DOT:
					ret = new DotNode(payload);
					break;
				case HqlSqlWalker.INDEX_OP:
					ret = new IndexNode(payload);
					break;
					// Alias references and identifiers use the same node class.
				case HqlSqlWalker.ALIAS_REF:
				case HqlSqlWalker.IDENT:
					ret = new IdentNode(payload);
					break;
				case HqlSqlWalker.SQL_TOKEN:
					ret = new SqlFragment(payload);
					break;
				case HqlSqlWalker.METHOD_CALL:
					ret = new MethodNode(payload);
					break;
				case HqlSqlWalker.ELEMENTS:
				case HqlSqlWalker.INDICES:
					ret = new CollectionFunction(payload);
					break;
				case HqlSqlWalker.SELECT_CLAUSE:
					ret = new SelectClause(payload);
					break;
				case HqlSqlWalker.SELECT_EXPR:
					ret = new SelectExpressionImpl(payload);
					break;
				case HqlSqlWalker.AGGREGATE:
					ret = new AggregateNode(payload);
					break;
				case HqlSqlWalker.COUNT:
					ret = new CountNode(payload);
					break;
				case HqlSqlWalker.CONSTRUCTOR:
					ret = new ConstructorNode(payload);
					break;
				case HqlSqlWalker.NUM_INT:
				case HqlSqlWalker.NUM_FLOAT:
				case HqlSqlWalker.NUM_LONG:
				case HqlSqlWalker.NUM_DOUBLE:
                case HqlSqlWalker.NUM_DECIMAL:
                case HqlSqlWalker.QUOTED_String:
					ret = new LiteralNode(payload);
					break;
				case HqlSqlWalker.TRUE:
				case HqlSqlWalker.FALSE:
					ret = new BooleanLiteralNode(payload);
					break;
				case HqlSqlWalker.JAVA_CONSTANT:
					ret = new JavaConstantNode(payload);
					break;
				case HqlSqlWalker.ORDER:
					ret = new OrderByClause(payload);
					break;
				case HqlSqlWalker.PLUS:
				case HqlSqlWalker.MINUS:
				case HqlSqlWalker.STAR:
				case HqlSqlWalker.DIV:
				case HqlSqlWalker.BAND:
				case HqlSqlWalker.BOR:
				case HqlSqlWalker.BXOR:
					ret = new BinaryArithmeticOperatorNode(payload);
					break;
				case HqlSqlWalker.UNARY_MINUS:
				case HqlSqlWalker.UNARY_PLUS:
				case HqlSqlWalker.BNOT:
					ret = new UnaryArithmeticNode(payload);
					break;
				case HqlSqlWalker.CASE2:
					ret = new Case2Node(payload);
					break;
				case HqlSqlWalker.CASE:
					ret = new CaseNode(payload);
					break;
				case HqlSqlWalker.PARAM:
				case HqlSqlWalker.NAMED_PARAM:
					ret = new ParameterNode(payload);
					break;
				case HqlSqlWalker.EQ:
				case HqlSqlWalker.NE:
				case HqlSqlWalker.LT:
				case HqlSqlWalker.GT:
				case HqlSqlWalker.LE:
				case HqlSqlWalker.GE:
				case HqlSqlWalker.LIKE:
				case HqlSqlWalker.NOT_LIKE:
					ret = new BinaryLogicOperatorNode(payload);
					break;
				case HqlSqlWalker.IN:
				case HqlSqlWalker.NOT_IN:
					ret = new InLogicOperatorNode(payload);
					break;
				case HqlSqlWalker.BETWEEN:
				case HqlSqlWalker.NOT_BETWEEN:
					ret = new BetweenOperatorNode(payload);
					break;
				case HqlSqlWalker.IS_NULL:
					ret = new IsNullLogicOperatorNode(payload);
					break;
				case HqlSqlWalker.IS_NOT_NULL:
					ret = new IsNotNullLogicOperatorNode(payload);
					break;
				case HqlSqlWalker.EXISTS:
					ret = new UnaryLogicOperatorNode(payload);
					break;
				default:
					ret = new SqlNode(payload);
					break;
			}

			Initialise(ret);
			return ret;
		}
		private void AddJoinNodes(QueryNode query, JoinSequence join, FromElement fromElement) 
		{
			JoinFragment joinFragment = join.ToJoinFragment(
					_walker.EnabledFilters,
					fromElement.UseFromFragment || fromElement.IsDereferencedBySuperclassOrSubclassProperty,
					fromElement.WithClauseFragment,
					fromElement.WithClauseJoinAlias
			);

			SqlString frag = joinFragment.ToFromFragmentString;
			SqlString whereFrag = joinFragment.ToWhereFragmentString;

			// If the from element represents a JOIN_FRAGMENT and it is
			// a theta-style join, convert its type from JOIN_FRAGMENT
			// to FROM_FRAGMENT
			if ( fromElement.Type == HqlSqlWalker.JOIN_FRAGMENT &&
					( join.IsThetaStyle || SqlStringHelper.IsNotEmpty( whereFrag ) ) ) 
			{
				fromElement.Type = HqlSqlWalker.FROM_FRAGMENT;
				fromElement.JoinSequence.SetUseThetaStyle( true ); // this is used during SqlGenerator processing
			}

			// If there is a FROM fragment and the FROM element is an explicit, then add the from part.
			if ( fromElement.UseFromFragment /*&& StringHelper.isNotEmpty( frag )*/ ) 
			{
				SqlString fromFragment = ProcessFromFragment( frag, join ).Trim();
				if ( log.IsDebugEnabled ) 
				{
					log.Debug( "Using FROM fragment [" + fromFragment + "]" );
				}

				ProcessDynamicFilterParameters(fromFragment,fromElement,_walker);
			}

			_syntheticAndFactory.AddWhereFragment( 
					joinFragment,
					whereFrag,
					query,
					fromElement,
					_walker
			);
		}
        public override object Create(IToken payload)
        {
            if (payload == null)
            {
                return(base.Create(payload));
            }

            object ret;

            switch (payload.Type)
            {
            case HqlSqlWalker.SELECT:
            case HqlSqlWalker.QUERY:
                ret = new QueryNode(payload);
                break;

            case HqlSqlWalker.UPDATE:
                ret = new UpdateStatement(payload);
                break;

            case HqlSqlWalker.DELETE:
                ret = new DeleteStatement(payload);
                break;

            case HqlSqlWalker.INSERT:
                ret = new InsertStatement(payload);
                break;

            case HqlSqlWalker.INTO:
                ret = new IntoClause(payload);
                break;

            case HqlSqlWalker.FROM:
                ret = new FromClause(payload);
                break;

            case HqlSqlWalker.FROM_FRAGMENT:
                ret = new FromElement(payload);
                break;

            case HqlSqlWalker.IMPLIED_FROM:
                ret = new ImpliedFromElement(payload);
                break;

            case HqlSqlWalker.DOT:
                ret = new DotNode(payload);
                break;

            case HqlSqlWalker.INDEX_OP:
                ret = new IndexNode(payload);
                break;

            // Alias references and identifiers use the same node class.
            case HqlSqlWalker.ALIAS_REF:
            case HqlSqlWalker.IDENT:
                ret = new IdentNode(payload);
                break;

            case HqlSqlWalker.SQL_TOKEN:
                ret = new SqlFragment(payload);
                break;

            case HqlSqlWalker.METHOD_CALL:
                ret = new MethodNode(payload);
                break;

            case HqlSqlWalker.ELEMENTS:
            case HqlSqlWalker.INDICES:
                ret = new CollectionFunction(payload);
                break;

            case HqlSqlWalker.SELECT_CLAUSE:
                ret = new SelectClause(payload);
                break;

            case HqlSqlWalker.SELECT_EXPR:
                ret = new SelectExpressionImpl(payload);
                break;

            case HqlSqlWalker.AGGREGATE:
                ret = new AggregateNode(payload);
                break;

            case HqlSqlWalker.COUNT:
                ret = new CountNode(payload);
                break;

            case HqlSqlWalker.CONSTRUCTOR:
                ret = new ConstructorNode(payload);
                break;

            case HqlSqlWalker.NUM_INT:
            case HqlSqlWalker.NUM_FLOAT:
            case HqlSqlWalker.NUM_LONG:
            case HqlSqlWalker.NUM_DOUBLE:
            case HqlSqlWalker.QUOTED_String:
                ret = new LiteralNode(payload);
                break;

            case HqlSqlWalker.TRUE:
            case HqlSqlWalker.FALSE:
                ret = new BooleanLiteralNode(payload);
                break;

            case HqlSqlWalker.JAVA_CONSTANT:
                ret = new JavaConstantNode(payload);
                break;

            case HqlSqlWalker.ORDER:
                ret = new OrderByClause(payload);
                break;

            case HqlSqlWalker.PLUS:
            case HqlSqlWalker.MINUS:
            case HqlSqlWalker.STAR:
            case HqlSqlWalker.DIV:
            case HqlSqlWalker.BAND:
            case HqlSqlWalker.BOR:
            case HqlSqlWalker.BXOR:
                ret = new BinaryArithmeticOperatorNode(payload);
                break;

            case HqlSqlWalker.UNARY_MINUS:
            case HqlSqlWalker.UNARY_PLUS:
            case HqlSqlWalker.BNOT:
                ret = new UnaryArithmeticNode(payload);
                break;

            case HqlSqlWalker.CASE2:
                ret = new Case2Node(payload);
                break;

            case HqlSqlWalker.CASE:
                ret = new CaseNode(payload);
                break;

            case HqlSqlWalker.PARAM:
            case HqlSqlWalker.NAMED_PARAM:
                ret = new ParameterNode(payload);
                break;

            case HqlSqlWalker.EQ:
            case HqlSqlWalker.NE:
            case HqlSqlWalker.LT:
            case HqlSqlWalker.GT:
            case HqlSqlWalker.LE:
            case HqlSqlWalker.GE:
            case HqlSqlWalker.LIKE:
            case HqlSqlWalker.NOT_LIKE:
                ret = new BinaryLogicOperatorNode(payload);
                break;

            case HqlSqlWalker.IN:
            case HqlSqlWalker.NOT_IN:
                ret = new InLogicOperatorNode(payload);
                break;

            case HqlSqlWalker.BETWEEN:
            case HqlSqlWalker.NOT_BETWEEN:
                ret = new BetweenOperatorNode(payload);
                break;

            case HqlSqlWalker.IS_NULL:
                ret = new IsNullLogicOperatorNode(payload);
                break;

            case HqlSqlWalker.IS_NOT_NULL:
                ret = new IsNotNullLogicOperatorNode(payload);
                break;

            case HqlSqlWalker.EXISTS:
                ret = new UnaryLogicOperatorNode(payload);
                break;

            default:
                ret = new SqlNode(payload);
                break;
            }

            Initialise(ret);
            return(ret);
        }