context: using System;
  using System.Collections.Generic;
  using Antlr.Runtime;
  using Antlr.Runtime.Tree;
  
  using NHibernate.Engine;
  using NHibernate.Hql.Ast.ANTLR.Tree;
  using NHibernate.Hql.Ast.ANTLR.Util;
  using NHibernate.Id;
  using NHibernate.Param;
  using NHibernate.Persister.Collection;
  using NHibernate.Persister.Entity;
  using NHibernate.SqlCommand;
  using NHibernate.Type;
  using NHibernate.UserTypes;
  using NHibernate.Util;
  
  namespace NHibernate.Hql.Ast.ANTLR
  {
  	public partial class HqlSqlWalker
  	{
  		private static readonly IInternalLogger log = LoggerProvider.LoggerFor(typeof(HqlSqlWalker));
  
  		// Fields
  		private readonly string _collectionFilterRole;
  		private readonly SessionFactoryHelperExtensions _sessionFactoryHelper;
  		private readonly QueryTranslatorImpl _qti;
  		private int _currentClauseType;
  		private int _level;
  		private bool _inSelect;
  		private bool _inFrom;
  		private bool _inFunctionCall;
  		private bool _inCase;
  		private int _statementType;
  		private int _currentStatementType;
  		private string _statementTypeName;
  		private int _positionalParameterCount;
  		private int _parameterCount;
  		private readonly NullableDictionary<string, object> _namedParameters = new NullableDictionary<string, object>();
  		private readonly List<IParameterSpecification> _parameters = new List<IParameterSpecification>();
  		private FromClause _currentFromClause;
  		private SelectClause _selectClause;
  		private readonly AliasGenerator _aliasGenerator = new AliasGenerator();
  		private readonly ASTPrinter _printer = new ASTPrinter();
  
  		//
  		//Maps each top-level result variable to its SelectExpression;
  		//(excludes result variables defined in subqueries)
  		//
  		private readonly IDictionary<String, ISelectExpression> selectExpressionsByResultVariable = new Dictionary<string, ISelectExpression>();
  
  		private readonly ISet<string> _querySpaces = new HashSet<string>();
  
  		private readonly LiteralProcessor _literalProcessor;
  
  		private readonly IDictionary<string, string> _tokenReplacements;
  
  		private JoinType _impliedJoinType;
  
  		private IParseErrorHandler _parseErrorHandler = new ErrorCounter();
  
  		private IASTFactory _nodeFactory;
  		private readonly List<AssignmentSpecification> assignmentSpecifications = new List<AssignmentSpecification>();
  		private int numberOfParametersInSetClause;
  
  		public HqlSqlWalker(QueryTranslatorImpl qti,
  					  ISessionFactoryImplementor sfi,
  					  ITreeNodeStream input, 
  					  IDictionary<string, string> tokenReplacements,
  					  string collectionRole)
  			: this(input)
  		{
  			_sessionFactoryHelper = new SessionFactoryHelperExtensions(sfi);
  			_qti = qti;
  			_literalProcessor = new LiteralProcessor(this);
  			_tokenReplacements = tokenReplacements;
  			_collectionFilterRole = collectionRole;
  		}
  
  		public override void ReportError(RecognitionException e)
  		{
  			_parseErrorHandler.ReportError(e);
  		}
  
  		/*
  		protected override void Mismatch(IIntStream input, int ttype, BitSet follow)
  		{
  		   throw new MismatchedTokenException(ttype, input);
  		}
  
  		public override object RecoverFromMismatchedSet(IIntStream input, RecognitionException e, BitSet follow)
  		{
  			throw e;
  		}
  		*/
  		public IList<AssignmentSpecification> AssignmentSpecifications
  		{
  			get { return assignmentSpecifications; }
  		}
  
  		public int NumberOfParametersInSetClause
  		{
  			get { return numberOfParametersInSetClause; }
  		}
  
  		public IParseErrorHandler ParseErrorHandler
  		{
  			get { return _parseErrorHandler; }
  			set { _parseErrorHandler = value; }
  		}
  
  		public AliasGenerator AliasGenerator
  		{
  			get { return _aliasGenerator; }
  		}
  
  		public ISet<string> QuerySpaces
  		{
  			get { return _querySpaces; }
  		}
  
  		public IDictionary<string, object> NamedParameters
  		{
  			get { return _namedParameters; }
  		}
  
  		internal SessionFactoryHelperExtensions SessionFactoryHelper
  		{
  			get { return _sessionFactoryHelper; }
  		}
  		
  		public int CurrentStatementType
  		{
  			get { return _currentStatementType; }
  		}
  
  		public JoinType ImpliedJoinType
  		{
  			get { return _impliedJoinType; }
  		}
  
  		public String[] ReturnAliases
  		{
  			get { return _selectClause.QueryReturnAliases; }
  		}
  
  		public IType[] ReturnTypes
  		{
  			get { return _selectClause.QueryReturnTypes; }	
  		}
  
  		public string CollectionFilterRole
  		{
  			get { return _collectionFilterRole; }	
  		}
  
  		public SelectClause SelectClause
  		{
  			get { return _selectClause; }
  		}
  
  		public IList<IParameterSpecification> Parameters
  		{
  			get { return _parameters; }
  		}
  
  		void BeforeStatement(string statementName, int statementType)
  		{
  			_inFunctionCall = false;
  			_level++;
  			if (_level == 1)
  			{
  				_statementTypeName = statementName;
  				_statementType = statementType;
  			}
  			_currentStatementType = statementType;
  			if (log.IsDebugEnabled)
  			{
  				log.Debug(statementName + " << begin [level=" + _level + ", statement=" + _statementTypeName + "]");
  			}
  		}
  
  		void BeforeStatementCompletion(string statementName)
  		{
  			if (log.IsDebugEnabled)
  			{
  				log.Debug(statementName + " : finishing up [level=" + _level + ", statement=" + _statementTypeName + "]");
  			}
  		}
  
  		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;
  				setClause.InsertChild(0, eq);
  			}
  		}
  
  		private IASTNode GenerateVersionPropertyNode(IQueryable persister)
  		{
  			string versionPropertyName = persister.PropertyNames[persister.VersionProperty];
  			var versionPropertyRef = ASTFactory.CreateNode(IDENT, versionPropertyName);
  			var versionPropertyNode = LookupNonQualifiedProperty(versionPropertyRef);
  			Resolve(versionPropertyNode);
  			return versionPropertyNode;
  		}
  
  		void PostProcessUpdate(IASTNode update)
  		{
  			var updateStatement = (UpdateStatement)update;
  			PostProcessDML(updateStatement);
  		}
  
  		void PostProcessDelete(IASTNode delete)
  		{
  			PostProcessDML((DeleteStatement)delete);
  		}
  
  		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)
  				{
  
gt: 					string seqName = seqGenerator.GeneratorKey();