From cc8aaab9add0a8a9f9078f908b1d69777f567df4 Mon Sep 17 00:00:00 2001 From: Andrea Boriero Date: Thu, 21 May 2020 12:58:47 +0100 Subject: [PATCH] Fix multilineextractor erorr message when statements have no terminal chars --- .../script/MultiLineSqlScriptExtracter.java | 23 ++++++++++++ ...ntsWithoutTerminalCharsImportFileTest.java | 36 +++++++++---------- .../statements-without-terminal-chars.sql | 2 +- 3 files changed, 42 insertions(+), 19 deletions(-) diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/script/MultiLineSqlScriptExtracter.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/script/MultiLineSqlScriptExtracter.java index 3fda852e18..2ba0a41663 100644 --- a/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/script/MultiLineSqlScriptExtracter.java +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/script/MultiLineSqlScriptExtracter.java @@ -17,10 +17,13 @@ import org.hibernate.tool.schema.spi.SqlScriptCommandExtractor; import org.hibernate.tool.schema.spi.SqlScriptException; import org.antlr.v4.runtime.BailErrorStrategy; +import org.antlr.v4.runtime.BaseErrorListener; import org.antlr.v4.runtime.CharStreams; import org.antlr.v4.runtime.CommonTokenStream; import org.antlr.v4.runtime.ConsoleErrorListener; import org.antlr.v4.runtime.DefaultErrorStrategy; +import org.antlr.v4.runtime.RecognitionException; +import org.antlr.v4.runtime.Recognizer; import org.antlr.v4.runtime.atn.PredictionMode; import org.antlr.v4.runtime.misc.ParseCancellationException; @@ -44,6 +47,9 @@ public class MultiLineSqlScriptExtracter implements SqlScriptCommandExtractor { return visitor.visitScript( scriptParseTree ); } catch (Exception e) { + if ( e instanceof SqlScriptException ) { + throw (SqlScriptException) e; + } throw new SqlScriptException( "Error during sql-script parsing.", e ); } } @@ -62,6 +68,7 @@ public class MultiLineSqlScriptExtracter implements SqlScriptCommandExtractor { parser.getInterpreter().setPredictionMode( PredictionMode.SLL ); parser.removeErrorListeners(); parser.setErrorHandler( new BailErrorStrategy() ); + parser.addErrorListener( new VerboseListener() ); try { return parser.script(); @@ -79,4 +86,20 @@ public class MultiLineSqlScriptExtracter implements SqlScriptCommandExtractor { return parser.script(); } } + + public static class VerboseListener extends BaseErrorListener { + @Override + public void syntaxError( + Recognizer recognizer, + Object offendingSymbol, + int line, + int charPositionInLine, + String msg, + RecognitionException e) { + if ( msg.contains( "missing STMT_END" ) ) { + throw new SqlScriptException( "Import script Sql statements must terminate with a ';' char" ); + } + super.syntaxError( recognizer, offendingSymbol, line, charPositionInLine, msg, e ); + } + } } diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/tool/schema/scripts/StatementsWithoutTerminalCharsImportFileTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/tool/schema/scripts/StatementsWithoutTerminalCharsImportFileTest.java index 80fdf993c5..64dab3fc15 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/tool/schema/scripts/StatementsWithoutTerminalCharsImportFileTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/tool/schema/scripts/StatementsWithoutTerminalCharsImportFileTest.java @@ -23,13 +23,14 @@ import org.hibernate.tool.schema.SourceType; import org.hibernate.tool.schema.TargetType; import org.hibernate.tool.schema.internal.ExceptionHandlerLoggedImpl; import org.hibernate.tool.schema.internal.SchemaCreatorImpl; -import org.hibernate.tool.schema.internal.script.SingleLineSqlScriptExtractor; +import org.hibernate.tool.schema.internal.script.MultiLineSqlScriptExtracter; import org.hibernate.tool.schema.spi.ExceptionHandler; import org.hibernate.tool.schema.spi.ExecutionOptions; import org.hibernate.tool.schema.spi.SchemaCreator; import org.hibernate.tool.schema.spi.ScriptSourceInput; import org.hibernate.tool.schema.spi.ScriptTargetOutput; import org.hibernate.tool.schema.spi.SourceDescriptor; +import org.hibernate.tool.schema.spi.SqlScriptException; import org.hibernate.tool.schema.spi.TargetDescriptor; import org.hibernate.testing.RequiresDialect; @@ -41,8 +42,10 @@ import org.junit.After; import org.junit.Before; import org.junit.Test; +import static org.hamcrest.CoreMatchers.endsWith; import static org.hamcrest.CoreMatchers.instanceOf; import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.Assert.fail; /** * @author Andrea Boriero @@ -55,16 +58,7 @@ import static org.hamcrest.MatcherAssert.assertThat; public class StatementsWithoutTerminalCharsImportFileTest extends BaseUnitTestCase implements ExecutionOptions { private StandardServiceRegistry ssr; - // NOTE regarding `HBM2DDL_IMPORT_FILES_SQL_EXTRACTOR` setting: - // the original test tried to use the "no terminal chars" sql script along with the multi-line parser - // and expected the fact that the lines did not end with a `;` to throw a `SqlScriptException`. - // - // but I don't think its reasonable to expect this situation to lead to a "SqlScriptException": - // 1. The default is the single-line version, so the multi-line one is an explicit override. - // 2. The script does not comply with the format expected by the explicit multi-line parser. - // - // the script is perfectly valid in terms of being a multi-line script, although it is invalid when - // interpreted that way + private static final String EXPECTED_ERROR_MESSAGE = "Import script Sql statements must terminate with a ';' char"; @Before public void setUp() { @@ -80,7 +74,7 @@ public class StatementsWithoutTerminalCharsImportFileTest extends BaseUnitTestCa // specify anything as single-line is the default .applySetting( Environment.HBM2DDL_IMPORT_FILES_SQL_EXTRACTOR, - SingleLineSqlScriptExtractor.INSTANCE + MultiLineSqlScriptExtracter.INSTANCE ) .build(); } @@ -89,12 +83,18 @@ public class StatementsWithoutTerminalCharsImportFileTest extends BaseUnitTestCa public void testImportFile() { final SchemaCreator schemaCreator = new SchemaCreatorImpl( ssr ); - schemaCreator.doCreation( - buildMappings( ssr ), - this, - SourceDescriptorImpl.INSTANCE, - TargetDescriptorImpl.INSTANCE - ); + try { + schemaCreator.doCreation( + buildMappings( ssr ), + this, + SourceDescriptorImpl.INSTANCE, + TargetDescriptorImpl.INSTANCE + ); + fail( "SqlScriptParserException expected" ); + } + catch (SqlScriptException e) { + assertThat( e.getMessage(), endsWith( EXPECTED_ERROR_MESSAGE ) ); + } } @After diff --git a/hibernate-core/src/test/resources/org/hibernate/orm/test/tool/schema/scripts/statements-without-terminal-chars.sql b/hibernate-core/src/test/resources/org/hibernate/orm/test/tool/schema/scripts/statements-without-terminal-chars.sql index 11e3e82ad4..2f4539ec4a 100644 --- a/hibernate-core/src/test/resources/org/hibernate/orm/test/tool/schema/scripts/statements-without-terminal-chars.sql +++ b/hibernate-core/src/test/resources/org/hibernate/orm/test/tool/schema/scripts/statements-without-terminal-chars.sql @@ -1,3 +1,3 @@ CREATE TABLE test_data ( id NUMBER NOT NULL PRIMARY KEY, text VARCHAR2(100) ) -INSERT INTO test_data(id, text) VALUES (1, `sample`) +INSERT INTO test_data(id, text) VALUES (1, 'sample') DELETE FROM test_data \ No newline at end of file