Retain newlines between command parts in sql script parsing as spaces like in Hibernate 5. Also, improve the parsing efficiency by not defining rules and thus creating contexts for every token type
This commit is contained in:
parent
181ac6e0ff
commit
c79e9effe9
|
@ -15,53 +15,38 @@ LINE_COMMENT
|
|||
;
|
||||
|
||||
MULTILINE_COMMENT
|
||||
: '/*' .*? '*/' -> skip
|
||||
: '/*'
|
||||
(
|
||||
{ getInputStream().LA(2)!='/' }? '*'
|
||||
| '\r' '\n'
|
||||
| '\r'
|
||||
| '\n'
|
||||
| ~('*'|'\n'|'\r')
|
||||
)*
|
||||
'*/' -> skip
|
||||
;
|
||||
|
||||
CHAR
|
||||
: ~( ';' | '\n' | '\r' | ' ' | '\t')
|
||||
;
|
||||
|
||||
SPACE
|
||||
: ' '
|
||||
;
|
||||
|
||||
TAB
|
||||
: '\t'
|
||||
;
|
||||
|
||||
NEWLINE
|
||||
: ('\r'? '\n' | '\r') -> skip
|
||||
: ('\r'? '\n' | '\r')
|
||||
;
|
||||
|
||||
STMT_END
|
||||
: ';' ( '\t' | ' ' | '\r' | '\n' )*
|
||||
;
|
||||
|
||||
NOT_STMT_END
|
||||
: ~[;]
|
||||
;
|
||||
DELIMITER:
|
||||
';'
|
||||
;
|
||||
|
||||
QUOTED_TEXT
|
||||
: '`' .*? '`'
|
||||
;
|
||||
|
||||
//WORD
|
||||
// : ~[;]
|
||||
// ;
|
||||
//
|
||||
//QUOTED_TEXT
|
||||
// : '\'' ( ESCAPE_SEQUENCE | ~('\\'|'\'') )* '\''
|
||||
// ;
|
||||
//
|
||||
//fragment
|
||||
//ESCAPE_SEQUENCE
|
||||
// : '\\' ('b'|'t'|'n'|'f'|'r'|'\\"'|'\''|'\\')
|
||||
// | UNICODE_ESCAPE
|
||||
// | OCTAL_ESCAPE
|
||||
// ;
|
||||
//
|
||||
//fragment
|
||||
//OCTAL_ESCAPE
|
||||
// : '\\' ('0'..'3') ('0'..'7') ('0'..'7')
|
||||
// | '\\' ('0'..'7') ('0'..'7')
|
||||
// | '\\' ('0'..'7')
|
||||
// ;
|
||||
//
|
||||
//fragment
|
||||
//UNICODE_ESCAPE
|
||||
// : '\\' 'u' HEX_DIGIT HEX_DIGIT HEX_DIGIT HEX_DIGIT
|
||||
// ;
|
||||
//
|
||||
//fragment
|
||||
//HEX_DIGIT
|
||||
// : ('0'..'9'|'a'..'f'|'A'..'F')
|
||||
// ;
|
||||
: '`' ( ~('`') )*? '`'
|
||||
| '\'' ( ('\'''\'') | ~('\'') )*? '\''
|
||||
;
|
|
@ -15,27 +15,18 @@ package org.hibernate.grammars.importsql;
|
|||
}
|
||||
|
||||
script
|
||||
: commandBlock+ EOF
|
||||
: (NEWLINE | SPACE | TAB)* ( commandBlock (NEWLINE | SPACE | TAB)* )+ EOF
|
||||
;
|
||||
|
||||
commandBlock
|
||||
: command STMT_END
|
||||
: command DELIMITER
|
||||
;
|
||||
|
||||
command
|
||||
: commandPart*
|
||||
;
|
||||
|
||||
commandPart
|
||||
: notStmtEnd
|
||||
| quotedText
|
||||
;
|
||||
|
||||
notStmtEnd
|
||||
: NOT_STMT_END+
|
||||
;
|
||||
|
||||
quotedText
|
||||
: QUOTED_TEXT
|
||||
: ( CHAR | QUOTED_TEXT ) // The first part must be a non-whitespace
|
||||
(
|
||||
( CHAR | QUOTED_TEXT | SPACE | TAB ) // Following chars may include spaces
|
||||
NEWLINE* // And also newlines in betweeen
|
||||
)*
|
||||
;
|
||||
|
||||
|
|
|
@ -96,7 +96,7 @@ public class MultiLineSqlScriptExtracter implements SqlScriptCommandExtractor {
|
|||
int charPositionInLine,
|
||||
String msg,
|
||||
RecognitionException e) {
|
||||
if ( msg.contains( "missing STMT_END" ) ) {
|
||||
if ( msg.contains( "missing ';'" ) ) {
|
||||
throw new SqlScriptException( "Import script Sql statements must terminate with a ';' char" );
|
||||
}
|
||||
super.syntaxError( recognizer, offendingSymbol, line, charPositionInLine, msg, e );
|
||||
|
|
|
@ -7,14 +7,20 @@
|
|||
package org.hibernate.tool.schema.internal.script;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.grammars.importsql.SqlScriptLexer;
|
||||
import org.hibernate.grammars.importsql.SqlScriptParser;
|
||||
import org.hibernate.grammars.importsql.SqlScriptParserBaseVisitor;
|
||||
|
||||
import org.antlr.v4.runtime.tree.ParseTree;
|
||||
import org.antlr.v4.runtime.tree.TerminalNode;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
* @author Christian Beikov
|
||||
*/
|
||||
public class SqlScriptVisitor extends SqlScriptParserBaseVisitor<Object> {
|
||||
private final Dialect dialect;
|
||||
|
@ -24,48 +30,42 @@ public class SqlScriptVisitor extends SqlScriptParserBaseVisitor<Object> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public ArrayList<String> visitScript(SqlScriptParser.ScriptContext ctx) {
|
||||
final ArrayList<String> commands = new ArrayList<>();
|
||||
|
||||
for ( int i = 0; i < ctx.commandBlock().size(); i++ ) {
|
||||
commands.add( visitCommandBlock( ctx.commandBlock().get( i ) ) );
|
||||
public List<String> visitScript(SqlScriptParser.ScriptContext ctx) {
|
||||
final List<ParseTree> children = ctx.children;
|
||||
if ( children == null ) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
final ArrayList<String> commands = new ArrayList<>( children.size() );
|
||||
final StringBuilder commandBuffer = new StringBuilder();
|
||||
for ( int i = 0; i < children.size(); i++ ) {
|
||||
final ParseTree parseTree = children.get( i );
|
||||
if ( parseTree instanceof SqlScriptParser.CommandBlockContext ) {
|
||||
commandBuffer.setLength( 0 );
|
||||
final SqlScriptParser.CommandBlockContext blockContext = (SqlScriptParser.CommandBlockContext) parseTree;
|
||||
final List<ParseTree> terminalNodes = blockContext.command().children;
|
||||
for ( int j = 0; j < terminalNodes.size(); j++ ) {
|
||||
final TerminalNode terminalNode = (TerminalNode) terminalNodes.get( j );
|
||||
switch ( terminalNode.getSymbol().getType() ) {
|
||||
case SqlScriptLexer.CHAR:
|
||||
case SqlScriptLexer.SPACE:
|
||||
case SqlScriptLexer.TAB:
|
||||
commandBuffer.append( terminalNode.getText() );
|
||||
break;
|
||||
case SqlScriptLexer.QUOTED_TEXT:
|
||||
commandBuffer.append( dialect.quote( terminalNode.getText() ) );
|
||||
break;
|
||||
case SqlScriptLexer.NEWLINE:
|
||||
commandBuffer.append( ' ' );
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException( "Unsupported token: " + terminalNode );
|
||||
}
|
||||
}
|
||||
commands.add( commandBuffer.toString() );
|
||||
}
|
||||
}
|
||||
|
||||
return commands;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String visitCommandBlock(SqlScriptParser.CommandBlockContext ctx) {
|
||||
return visitCommand( ctx.command() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String visitCommand(SqlScriptParser.CommandContext ctx) {
|
||||
final List<SqlScriptParser.CommandPartContext> commandParts = ctx.commandPart();
|
||||
|
||||
final StringBuilder commandBuffer = new StringBuilder();
|
||||
String separator = "";
|
||||
|
||||
for ( int i = 0; i < commandParts.size(); i++ ) {
|
||||
commandBuffer.append( separator );
|
||||
|
||||
final SqlScriptParser.CommandPartContext commandPart = commandParts.get( i );
|
||||
|
||||
if ( commandPart.notStmtEnd() != null ) {
|
||||
commandBuffer.append( commandPart.notStmtEnd().getText() );
|
||||
}
|
||||
else if ( commandPart.quotedText() != null ) {
|
||||
commandBuffer.append( visitQuotedText( commandPart.quotedText() ) );
|
||||
}
|
||||
|
||||
separator = " ";
|
||||
}
|
||||
|
||||
return commandBuffer.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visitQuotedText(SqlScriptParser.QuotedTextContext ctx) {
|
||||
return dialect.quote( ctx.QUOTED_TEXT().getText() );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -119,6 +119,14 @@ public class SchemaManagementToolCoordinator {
|
|||
exceptionHandler
|
||||
);
|
||||
|
||||
if ( scriptActionMap != null ) {
|
||||
scriptActionMap.forEach(
|
||||
(action, contributors) -> {
|
||||
performScriptAction( action, metadata, tool, serviceRegistry, executionOptions );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
if ( databaseActionMap != null ) {
|
||||
databaseActionMap.forEach(
|
||||
(action, contributors) -> {
|
||||
|
@ -149,14 +157,6 @@ public class SchemaManagementToolCoordinator {
|
|||
}
|
||||
);
|
||||
}
|
||||
|
||||
if ( scriptActionMap != null ) {
|
||||
scriptActionMap.forEach(
|
||||
(action, contributors) -> {
|
||||
performScriptAction( action, metadata, tool, serviceRegistry, executionOptions );
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public static ExecutionOptions buildExecutionOptions(
|
||||
|
|
Loading…
Reference in New Issue