Throw ParsingException on tokenization or parsing error for HQL instead of just logging to console and fix test issues

This commit is contained in:
Christian Beikov 2021-01-13 18:19:35 +01:00
parent e5c40e3af7
commit 0196911c8d
6 changed files with 54 additions and 24 deletions

View File

@ -6,21 +6,29 @@
*/
package org.hibernate.query.hql.internal;
import java.util.BitSet;
import org.hibernate.QueryException;
import org.hibernate.grammars.hql.HqlLexer;
import org.hibernate.grammars.hql.HqlParser;
import org.hibernate.query.hql.HqlLogging;
import org.hibernate.query.sqm.InterpretationException;
import org.hibernate.query.hql.HqlTranslator;
import org.hibernate.query.sqm.ParsingException;
import org.hibernate.query.sqm.internal.SqmTreePrinter;
import org.hibernate.query.sqm.spi.SqmCreationContext;
import org.hibernate.query.hql.spi.SqmCreationOptions;
import org.hibernate.query.sqm.tree.SqmStatement;
import org.antlr.v4.runtime.ANTLRErrorListener;
import org.antlr.v4.runtime.BailErrorStrategy;
import org.antlr.v4.runtime.ConsoleErrorListener;
import org.antlr.v4.runtime.DefaultErrorStrategy;
import org.antlr.v4.runtime.Parser;
import org.antlr.v4.runtime.RecognitionException;
import org.antlr.v4.runtime.Recognizer;
import org.antlr.v4.runtime.atn.ATNConfigSet;
import org.antlr.v4.runtime.atn.PredictionMode;
import org.antlr.v4.runtime.dfa.DFA;
import org.antlr.v4.runtime.misc.ParseCancellationException;
/**
@ -29,6 +37,27 @@ import org.antlr.v4.runtime.misc.ParseCancellationException;
* @author Steve Ebersole
*/
public class StandardHqlTranslator implements HqlTranslator {
protected static final ANTLRErrorListener ERR_LISTENER = new ANTLRErrorListener() {
@Override
public void syntaxError(Recognizer<?, ?> recognizer, Object offendingSymbol, int line, int charPositionInLine, String msg, RecognitionException e) {
throw new ParsingException( "line " + line + ":" + charPositionInLine + " " + msg);
}
@Override
public void reportAmbiguity(Parser recognizer, DFA dfa, int startIndex, int stopIndex, boolean exact, BitSet ambigAlts, ATNConfigSet configs) {
}
@Override
public void reportAttemptingFullContext(Parser recognizer, DFA dfa, int startIndex, int stopIndex, BitSet conflictingAlts, ATNConfigSet configs) {
}
@Override
public void reportContextSensitivity(Parser recognizer, DFA dfa, int startIndex, int stopIndex, int prediction, ATNConfigSet configs) {
}
};
private final SqmCreationContext sqmCreationContext;
private final SqmCreationOptions sqmCreationOptions;
@ -75,8 +104,10 @@ public class StandardHqlTranslator implements HqlTranslator {
final HqlParser hqlParser = HqlParseTreeBuilder.INSTANCE.buildHqlParser( hql, hqlLexer );
// try to use SLL(k)-based parsing first - its faster
hqlLexer.addErrorListener( ERR_LISTENER );
hqlParser.getInterpreter().setPredictionMode( PredictionMode.SLL );
hqlParser.removeErrorListeners();
hqlParser.addErrorListener( ERR_LISTENER );
hqlParser.setErrorHandler( new BailErrorStrategy() );
try {
@ -89,7 +120,6 @@ public class StandardHqlTranslator implements HqlTranslator {
// fall back to LL(k)-based parsing
hqlParser.getInterpreter().setPredictionMode( PredictionMode.LL );
hqlParser.addErrorListener( ConsoleErrorListener.INSTANCE );
hqlParser.setErrorHandler( new DefaultErrorStrategy() );
return hqlParser.statement();

View File

@ -58,7 +58,7 @@ public class SimpleDynamicHbmTests {
session -> {
session.createQuery( "from SimpleDynamicEntity" ).list();
session.createQuery( "select e from SimpleDynamicEntity e" ).list();
session.createQuery( "select e from SimpleDynamicEntity e.name = 'abc'" ).list();
session.createQuery( "select e from SimpleDynamicEntity e where e.name = 'abc'" ).list();
}
);
}

View File

@ -316,10 +316,10 @@ public class FunctionTests extends SessionFactoryBasedFunctionalTest {
.list();
session.createQuery("select trim(both ' ' from e.theString) from EntityOfBasics e")
.list();
assertThat( session.createQuery("select trim(leading from ' hello'").getSingleResult(), is("hello") );
assertThat( session.createQuery("select trim(trailing from 'hello '").getSingleResult(), is("hello") );
assertThat( session.createQuery("select trim(both from ' hello '").getSingleResult(), is("hello") );
assertThat( session.createQuery("select trim(both '-' from '---hello---'").getSingleResult(), is("hello") );
assertThat( session.createQuery("select trim(leading from ' hello')").getSingleResult(), is("hello") );
assertThat( session.createQuery("select trim(trailing from 'hello ')").getSingleResult(), is("hello") );
assertThat( session.createQuery("select trim(both from ' hello ')").getSingleResult(), is("hello") );
assertThat( session.createQuery("select trim(both '-' from '---hello---')").getSingleResult(), is("hello") );
}
);
}

View File

@ -40,7 +40,7 @@ public class LiteralTests {
byte[] bytes3 = (byte[]) session.createQuery( "select {0xDE, 0xAD, 0xBE, 0xEF}" ).getSingleResult();
assertThat( BINARY.toString(bytes3), is("deadbeef") );
byte[] bytes4 = (byte[]) session.createQuery( "select {0xde, 0xad, 0xbe, 0xef}'" ).getSingleResult();
byte[] bytes4 = (byte[]) session.createQuery( "select {0xde, 0xad, 0xbe, 0xef}" ).getSingleResult();
assertThat( BINARY.toString(bytes4), is("deadbeef") );
}
);
@ -141,13 +141,13 @@ public class LiteralTests {
.list();
// session.createQuery( "from EntityOfBasics e1 where e1.theTimestamp = {ts '2018-01-01T12:30:00+05'}" )
// .list();
// session.createQuery( "from EntityOfBasics e1 where e1.theTimestamp = offset datetime '2018-01-01 12:30:00+05:00'" )
// session.createQuery( "from EntityOfBasics e1 where e1.theTimestamp = datetime '2018-01-01 12:30:00+05:00'" )
// .list();
// session.createQuery( "from EntityOfBasics e1 where e1.theTimestamp = offset datetime '2018-01-01 12:30:00+05'" )
// session.createQuery( "from EntityOfBasics e1 where e1.theTimestamp = datetime '2018-01-01 12:30:00+05'" )
// .list();
session.createQuery( "from EntityOfBasics e1 where e1.theTimestamp = offset datetime 2018-01-01 12:30:00+05:00" )
session.createQuery( "from EntityOfBasics e1 where e1.theTimestamp = datetime 2018-01-01 12:30:00+05:00" )
.list();
session.createQuery( "from EntityOfBasics e1 where e1.theTimestamp = offset datetime 2018-01-01 12:30:00+05" )
session.createQuery( "from EntityOfBasics e1 where e1.theTimestamp = datetime 2018-01-01 12:30:00+05" )
.list();
session.createQuery( "from EntityOfBasics e1 where e1.theTimestamp = {ts '2018-01-01T12:30:00 GMT'}" )

View File

@ -36,16 +36,16 @@ public class PagingTests {
@Test
public void testPagingByParameter(SessionFactoryScope scope) {
interpretSelect( "select o from SimpleEntity o offset :param", scope.getSessionFactory() );
interpretSelect( "select o from SimpleEntity o limit :param", scope.getSessionFactory() );
interpretSelect( "select o from SimpleEntity o limit :param offset :param", scope.getSessionFactory() );
interpretSelect( "select o from SimpleEntity o order by o.id offset :param", scope.getSessionFactory() );
interpretSelect( "select o from SimpleEntity o order by o.id limit :param", scope.getSessionFactory() );
interpretSelect( "select o from SimpleEntity o order by o.id limit :param offset :param", scope.getSessionFactory() );
}
@Test
public void testPagingByConstant(SessionFactoryScope scope) {
interpretSelect( "select o from SimpleEntity o offset 1", scope.getSessionFactory() );
interpretSelect( "select o from SimpleEntity o limit 1", scope.getSessionFactory() );
interpretSelect( "select o from SimpleEntity o limit 1 offset 1", scope.getSessionFactory() );
interpretSelect( "select o from SimpleEntity o order by o.id offset 1", scope.getSessionFactory() );
interpretSelect( "select o from SimpleEntity o order by o.id limit 1", scope.getSessionFactory() );
interpretSelect( "select o from SimpleEntity o order by o.id limit 1 offset 1", scope.getSessionFactory() );
}
@Test

View File

@ -90,10 +90,10 @@ public class StandardFunctionTests {
session.createQuery( "select local_datetime() from EntityOfBasics" ).list();
session.createQuery( "select e from EntityOfBasics e where e.theTimestamp = local_datetime" ).list();
session.createQuery( "select e from EntityOfBasics e where e.theTimestamp = local_datetime()()" ).list();
session.createQuery( "select e from EntityOfBasics e where e.theTimestamp = local_datetime()" ).list();
session.createQuery( "select e from EntityOfBasics e where local_datetime between e.theTimestamp and e.theTimestamp" ).list();
session.createQuery( "select e from EntityOfBasics e where local_datetime() between e.theTimestamp and e.theTimestamp" ).list();
session.createQuery( "select e from EntityOfBasics e where local_datetime()() between e.theTimestamp and e.theTimestamp" ).list();
}
);
}
@ -106,10 +106,10 @@ public class StandardFunctionTests {
session.createQuery( "select local_date() from EntityOfBasics" ).list();
session.createQuery( "select e from EntityOfBasics e where e.theTimestamp = local_date" ).list();
session.createQuery( "select e from EntityOfBasics e where e.theTimestamp = local_date()()" ).list();
session.createQuery( "select e from EntityOfBasics e where e.theTimestamp = local_date()" ).list();
session.createQuery( "select e from EntityOfBasics e where local_date between e.theTimestamp and e.theTimestamp" ).list();
session.createQuery( "select e from EntityOfBasics e where local_date() between e.theTimestamp and e.theTimestamp" ).list();
session.createQuery( "select e from EntityOfBasics e where local_date()() between e.theTimestamp and e.theTimestamp" ).list();
assertThat(
session.createQuery( "select local_date" ).getSingleResult(),
@ -127,10 +127,10 @@ public class StandardFunctionTests {
session.createQuery( "select local_time() from EntityOfBasics" ).list();
session.createQuery( "select e from EntityOfBasics e where e.theLocalTime = local_time" ).list();
session.createQuery( "select e from EntityOfBasics e where e.theLocalTime = local_time()()" ).list();
session.createQuery( "select e from EntityOfBasics e where e.theLocalTime = local_time()" ).list();
session.createQuery( "select e from EntityOfBasics e where local_time between e.theLocalTime and e.theLocalTime" ).list();
session.createQuery( "select e from EntityOfBasics e where local_time() between e.theLocalTime and e.theLocalTime" ).list();
session.createQuery( "select e from EntityOfBasics e where local_time()() between e.theLocalTime and e.theLocalTime" ).list();
assertThat(
session.createQuery( "select local_time" ).getSingleResult(),