Fix multilineextractor erorr message when statements have no terminal chars

This commit is contained in:
Andrea Boriero 2020-05-21 12:58:47 +01:00
parent 88c653f6e3
commit cc8aaab9ad
3 changed files with 42 additions and 19 deletions

View File

@ -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 );
}
}
}

View File

@ -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

View File

@ -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