From: <fab...@us...> - 2009-04-30 17:54:12
|
Revision: 4217 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=4217&view=rev Author: fabiomaulo Date: 2009-04-30 17:54:10 +0000 (Thu, 30 Apr 2009) Log Message: ----------- continue work on executable HQL Modified Paths: -------------- trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/QueryTranslatorImpl.cs trunk/nhibernate/src/NHibernate/NHibernate.csproj Added Paths: ----------- trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/Exec/AbstractStatementExecutor.cs trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/Exec/BasicExecutor.cs Added: trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/Exec/AbstractStatementExecutor.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/Exec/AbstractStatementExecutor.cs (rev 0) +++ trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/Exec/AbstractStatementExecutor.cs 2009-04-30 17:54:10 UTC (rev 4217) @@ -0,0 +1,23 @@ +using NHibernate.Engine; +using NHibernate.SqlCommand; +using log4net; + +namespace NHibernate.Hql.Ast.ANTLR.Exec +{ + public abstract class AbstractStatementExecutor : IStatementExecutor + { + private readonly ILog log; + + protected AbstractStatementExecutor(HqlSqlWalker walker, ILog log) + { + Walker = walker; + this.log = log; + } + + protected HqlSqlWalker Walker { get; private set; } + + public abstract SqlString[] SqlStatements{get;} + + public abstract int Execute(QueryParameters parameters, ISessionImplementor session); + } +} \ No newline at end of file Added: trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/Exec/BasicExecutor.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/Exec/BasicExecutor.cs (rev 0) +++ trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/Exec/BasicExecutor.cs 2009-04-30 17:54:10 UTC (rev 4217) @@ -0,0 +1,94 @@ +using System; +using System.Collections.Generic; +using System.Data; +using System.Data.Common; +using Antlr.Runtime; +using log4net; +using NHibernate.Engine; +using NHibernate.Exceptions; +using NHibernate.Hql.Ast.ANTLR.Parameters; +using NHibernate.Persister.Entity; +using NHibernate.SqlCommand; + +namespace NHibernate.Hql.Ast.ANTLR.Exec +{ + public class BasicExecutor : AbstractStatementExecutor + { + private readonly IQueryable persister; + private static readonly ILog log = LogManager.GetLogger(typeof(QueryTranslatorImpl)); + private SqlString sql; + + public BasicExecutor(HqlSqlWalker walker, IQueryable persister) : base(walker, log) + { + this.persister = persister; + try + { + + //SqlGenerator gen = new SqlGenerator(Factory); + //gen.statement(walker.getAST()); + //sql = gen.GetSQL(); + //gen.ParseErrorHandler.ThrowQueryException(); + } + catch (RecognitionException e) + { + throw QuerySyntaxException.Convert(e); + } + } + + protected ISessionFactoryImplementor Factory + { + get + { + return Walker.SessionFactoryHelper.Factory; + } + } + + public override SqlString[] SqlStatements + { + get { return new[] {sql}; } + } + + public override int Execute(QueryParameters parameters, ISessionImplementor session) + { + //CoordinateSharedCacheCleanup(session); + + IDbCommand st = null; + RowSelection selection = parameters.RowSelection; + + try + { + try + { + //st = session.Batcher.PrepareCommand(CommandType.Text, sql, parameterTypes); + IEnumerator<IParameterSpecification> paramSpecifications = Walker.Parameters.GetEnumerator(); + int pos = 1; + while (paramSpecifications.MoveNext()) + { + var paramSpec = paramSpecifications.Current; + pos += paramSpec.Bind(st, parameters, session, pos); + } + if (selection != null) + { + if (selection.Timeout != RowSelection.NoValue) + { + st.CommandTimeout = selection.Timeout; + } + } + return session.Batcher.ExecuteNonQuery(st); + } + finally + { + if (st != null) + { + session.Batcher.CloseCommand(st, null); + } + } + } + catch (DbException sqle) + { + throw ADOExceptionHelper.Convert(session.Factory.SQLExceptionConverter, sqle, + "could not execute update query", sql); + } + } + } +} \ No newline at end of file Modified: trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/QueryTranslatorImpl.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/QueryTranslatorImpl.cs 2009-04-29 22:09:01 UTC (rev 4216) +++ trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/QueryTranslatorImpl.cs 2009-04-30 17:54:10 UTC (rev 4217) @@ -6,10 +6,12 @@ using Iesi.Collections.Generic; using log4net; using NHibernate.Engine; +using NHibernate.Hql.Ast.ANTLR.Exec; using NHibernate.Hql.Ast.ANTLR.Loader; using NHibernate.Hql.Ast.ANTLR.Parameters; using NHibernate.Hql.Ast.ANTLR.Tree; using NHibernate.Hql.Ast.ANTLR.Util; +using NHibernate.Persister.Entity; using NHibernate.SqlCommand; using NHibernate.Type; using NHibernate.Util; @@ -27,8 +29,10 @@ private IDictionary<string, IFilter> _enabledFilters; private readonly ISessionFactoryImplementor _factory; private QueryLoader _queryLoader; - private ParameterTranslationsImpl _paramTranslations; - + private IStatementExecutor statementExecutor; + private IStatement sqlAst; + private ParameterTranslationsImpl _paramTranslations; + private IDictionary<string, string> tokenReplacements; private HqlParseEngine _parser; private HqlSqlTranslator _translator; private HqlSqlGenerator _generator; @@ -202,7 +206,7 @@ public IStatement SqlAST { - get { return _translator.SqlStatement; } + get { return sqlAst; } } public IList<IParameterSpecification> CollectedParameterSpecifications @@ -322,27 +326,21 @@ return; } - if (replacements == null) - { - replacements = new Dictionary<string, string>(); - } + // Remember the parameters for the compilation. + tokenReplacements = replacements ?? new Dictionary<string, string>(1); _shallowQuery = shallow; try { // PHASE 1 : Parse the HQL into an AST. - if (_parser == null) - { - _parser = new HqlParseEngine(_hql, true, _factory); - _parser.Parse(); - } + HqlParseEngine parser = Parse(true); // PHASE 2 : Analyze the HQL AST, and produce an SQL AST. - _translator = new HqlSqlTranslator(_parser.Ast, _parser.Tokens, this, _factory, replacements, - collectionRole); - _translator.Translate(); - + HqlSqlWalker w = Analyze(parser, collectionRole); + + sqlAst = (IStatement)w.statement().Tree; + // at some point the generate phase needs to be moved out of here, // because a single object-level DML might spawn multiple SQL DML // command executions. @@ -356,16 +354,15 @@ if (_translator.SqlStatement.NeedsExecutor) { - throw new NotImplementedException(); // DML -// statementExecutor = buildAppropriateStatementExecutor( w ); + statementExecutor = BuildAppropriateStatementExecutor(w); } else { // PHASE 3 : Generate the SQL. - _generator = new HqlSqlGenerator(_translator.SqlStatement, _parser.Tokens, _factory); + _generator = new HqlSqlGenerator(_translator.SqlStatement, parser.Tokens, _factory); _generator.Generate(); - - _queryLoader = new QueryLoader( this, _factory, _translator.SqlStatement.Walker.SelectClause ); + + _queryLoader = new QueryLoader(this, _factory, w.SelectClause); } _compiled = true; @@ -389,6 +386,70 @@ _enabledFilters = null; //only needed during compilation phase... } + private IStatementExecutor BuildAppropriateStatementExecutor(HqlSqlWalker walker) + { + if (walker.StatementType == HqlSqlWalker.DELETE) + { + FromElement fromElement = walker.GetFinalFromClause().GetFromElement(); + IQueryable persister = fromElement.Queryable; + if (persister.IsMultiTable) + { + throw new NotSupportedException(); + //return new MultiTableDeleteExecutor(walker); + } + else + { + return new BasicExecutor(walker, persister); + } + } + else if (walker.StatementType == HqlSqlWalker.UPDATE) + { + FromElement fromElement = walker.GetFinalFromClause().GetFromElement(); + IQueryable persister = fromElement.Queryable; + if (persister.IsMultiTable) + { + // even here, if only properties mapped to the "base table" are referenced + // in the set and where clauses, this could be handled by the BasicDelegate. + // TODO : decide if it is better performance-wise to perform that check, or to simply use the MultiTableUpdateDelegate + throw new NotSupportedException(); + //return new MultiTableUpdateExecutor(walker); + } + else + { + return new BasicExecutor(walker, persister); + } + } + else if (walker.StatementType == HqlSqlWalker.INSERT) + { + //var statement = (IStatement)walker.statement().Tree; + + throw new QueryException("Unexpected statement type"); + } + else + { + throw new QueryException("Unexpected statement type"); + } + } + + private HqlSqlWalker Analyze(HqlParseEngine parser, string collectionRole) + { + _translator = new HqlSqlTranslator(parser.Ast, parser.Tokens, this, _factory, tokenReplacements, + collectionRole); + _translator.Translate(); + + return _translator.SqlStatement.Walker; + } + + private HqlParseEngine Parse(bool isFilter) + { + if (_parser == null) + { + _parser = new HqlParseEngine(_hql, isFilter, _factory); + _parser.Parse(); + } + return _parser; + } + private void ErrorIfDML() { if (_translator.SqlStatement.NeedsExecutor) Modified: trunk/nhibernate/src/NHibernate/NHibernate.csproj =================================================================== --- trunk/nhibernate/src/NHibernate/NHibernate.csproj 2009-04-29 22:09:01 UTC (rev 4216) +++ trunk/nhibernate/src/NHibernate/NHibernate.csproj 2009-04-30 17:54:10 UTC (rev 4217) @@ -480,6 +480,8 @@ <Compile Include="Hql\Ast\ANTLR\CollectionProperties.cs" /> <Compile Include="Hql\Ast\ANTLR\DetailedSemanticException.cs" /> <Compile Include="Hql\Ast\ANTLR\ErrorCounter.cs" /> + <Compile Include="Hql\Ast\ANTLR\Exec\AbstractStatementExecutor.cs" /> + <Compile Include="Hql\Ast\ANTLR\Exec\BasicExecutor.cs" /> <Compile Include="Hql\Ast\ANTLR\Exec\IStatementExecutor.cs" /> <Compile Include="Hql\Ast\ANTLR\Generated\HqlLexer.cs" /> <Compile Include="Hql\Ast\ANTLR\Generated\HqlParser.cs" /> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |