HHH-2403 - Improved import.sql
This commit is contained in:
parent
ebd24bbc87
commit
c6d616a8bf
|
@ -0,0 +1,83 @@
|
|||
header
|
||||
{
|
||||
package org.hibernate.hql.internal.antlr;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.LinkedList;
|
||||
}
|
||||
/**
|
||||
* Lexer and parser used to extract single statements from import SQL script. Supports single and multiple line
|
||||
* instructions/comments and quoted strings. Each statement should end with semicolon.
|
||||
*
|
||||
* @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com)
|
||||
*/
|
||||
class SqlStatementParser extends Parser;
|
||||
|
||||
options {
|
||||
buildAST = false;
|
||||
}
|
||||
|
||||
{
|
||||
/** List of all SQL statements. */
|
||||
private List<String> statementList = new LinkedList<String>();
|
||||
|
||||
/** Currently processing SQL statement. */
|
||||
private StringBuilder current = new StringBuilder();
|
||||
|
||||
protected void out(String stmt) {
|
||||
current.append( stmt );
|
||||
}
|
||||
|
||||
protected void out(Token token) {
|
||||
out( token.getText() );
|
||||
}
|
||||
|
||||
public List<String> getStatementList() {
|
||||
return statementList;
|
||||
}
|
||||
|
||||
protected void statementEnd() {
|
||||
statementList.add( current.toString().trim() );
|
||||
current = new StringBuilder();
|
||||
}
|
||||
}
|
||||
|
||||
script
|
||||
: ( statement )*
|
||||
;
|
||||
|
||||
statement
|
||||
: ( s:NOT_STMT_END { out( s ); } | q:QUOTED_STRING { out( q ); } )* STMT_END { statementEnd(); }
|
||||
;
|
||||
|
||||
class SqlStatementLexer extends Lexer;
|
||||
|
||||
options {
|
||||
k = 2;
|
||||
charVocabulary = '\u0000'..'\uFFFE';
|
||||
}
|
||||
|
||||
STMT_END
|
||||
: ';'
|
||||
;
|
||||
|
||||
NOT_STMT_END
|
||||
: ~( ';' )
|
||||
;
|
||||
|
||||
QUOTED_STRING
|
||||
: '\'' ( (ESCqs)=> ESCqs | ~'\'' )* '\''
|
||||
;
|
||||
|
||||
protected
|
||||
ESCqs
|
||||
: '\'' '\''
|
||||
;
|
||||
|
||||
LINE_COMMENT
|
||||
: ( "//" | "--" ) ( ~('\n'|'\r') )* { $setType(Token.SKIP); }
|
||||
;
|
||||
|
||||
MULTILINE_COMMENT
|
||||
: "/*" ( options {greedy=false;} : . )* "*/" { $setType(Token.SKIP); }
|
||||
;
|
|
@ -39,6 +39,7 @@ import java.util.ArrayList;
|
|||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.hibernate.internal.util.StringHelper;
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
|
@ -418,29 +419,19 @@ public class SchemaExport {
|
|||
|
||||
private void importScript(NamedReader namedReader, List<Exporter> exporters) throws Exception {
|
||||
BufferedReader reader = new BufferedReader( namedReader.getReader() );
|
||||
long lineNo = 0;
|
||||
for ( String sql = reader.readLine(); sql != null; sql = reader.readLine() ) {
|
||||
try {
|
||||
lineNo++;
|
||||
String trimmedSql = sql.trim();
|
||||
if ( trimmedSql.length() == 0 ||
|
||||
trimmedSql.startsWith( "--" ) ||
|
||||
trimmedSql.startsWith( "//" ) ||
|
||||
trimmedSql.startsWith( "/*" ) ) {
|
||||
continue;
|
||||
}
|
||||
if ( trimmedSql.endsWith(";") ) {
|
||||
trimmedSql = trimmedSql.substring(0, trimmedSql.length() - 1);
|
||||
}
|
||||
LOG.debugf( trimmedSql );
|
||||
for ( Exporter exporter: exporters ) {
|
||||
if ( exporter.acceptsImportScripts() ) {
|
||||
exporter.export( trimmedSql );
|
||||
List<String> statementList = new StatementExtractor().retrieveStatements( reader );
|
||||
for ( String statement : statementList ) {
|
||||
if ( !StringHelper.isEmpty( statement ) ) {
|
||||
try {
|
||||
for ( Exporter exporter : exporters ) {
|
||||
if ( exporter.acceptsImportScripts() ) {
|
||||
exporter.export( statement );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch ( Exception e ) {
|
||||
throw new ImportScriptException( "Error during import script execution at line " + lineNo, e );
|
||||
catch ( Exception e ) {
|
||||
throw new ImportScriptException( "Error during statement execution (file: '" + namedReader.getName() + "'): " + statement, e );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
package org.hibernate.tool.hbm2ddl;
|
||||
|
||||
import org.hibernate.hql.internal.antlr.SqlStatementLexer;
|
||||
import org.hibernate.hql.internal.antlr.SqlStatementParser;
|
||||
|
||||
import java.io.Reader;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Class responsible for extracting SQL statements from import script. Supports single and multiple line
|
||||
* instructions/comments and quoted strings.
|
||||
*
|
||||
* @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com)
|
||||
*/
|
||||
public class StatementExtractor {
|
||||
/**
|
||||
* @param reader Character stream reader of entire SQL script. Each statement should end with semicolon.
|
||||
* @return List of single SQL statements (each without semicolon at the end).
|
||||
*/
|
||||
List<String> retrieveStatements(final Reader reader) {
|
||||
final SqlStatementLexer lexer = new SqlStatementLexer( reader );
|
||||
final SqlStatementParser parser = new SqlStatementParser( lexer );
|
||||
try {
|
||||
parser.script(); // Parse script.
|
||||
}
|
||||
catch ( Exception e ) {
|
||||
throw new ImportScriptException( "Error during import script parsing.", e );
|
||||
}
|
||||
return parser.getStatementList();
|
||||
}
|
||||
}
|
|
@ -22,6 +22,7 @@
|
|||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.test.importfile;
|
||||
import java.math.BigInteger;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Test;
|
||||
|
@ -33,14 +34,16 @@ import org.hibernate.cfg.Environment;
|
|||
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNull;
|
||||
|
||||
/**
|
||||
* @author Emmanuel Bernard
|
||||
* @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com)
|
||||
*/
|
||||
public class ImportFileTest extends BaseCoreFunctionalTestCase {
|
||||
@Override
|
||||
public void configure(Configuration cfg) {
|
||||
cfg.setProperty( Environment.HBM2DDL_IMPORT_FILES, "/humans.sql,/dogs.sql" );
|
||||
cfg.setProperty( Environment.HBM2DDL_IMPORT_FILES, "/humans.sql,/dogs.sql,/multiline-stmt.sql" );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -52,7 +55,7 @@ public class ImportFileTest extends BaseCoreFunctionalTestCase {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testImportFile() throws Exception {
|
||||
public void testSingleLineImportFile() throws Exception {
|
||||
Session s = openSession( );
|
||||
final Transaction tx = s.beginTransaction();
|
||||
final List<?> humans = s.createQuery( "from " + Human.class.getName() ).list();
|
||||
|
@ -69,4 +72,22 @@ public class ImportFileTest extends BaseCoreFunctionalTestCase {
|
|||
tx.commit();
|
||||
s.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultipleLineImportFile() throws Exception {
|
||||
Session s = openSession();
|
||||
final Transaction tx = s.beginTransaction();
|
||||
|
||||
BigInteger count = (BigInteger) s.createSQLQuery( "SELECT COUNT(*) FROM test_data" ).uniqueResult();
|
||||
assertEquals( "incorrect row number", 3L, count.longValue() );
|
||||
|
||||
String multilineText = (String) s.createSQLQuery( "SELECT text FROM test_data WHERE id = 2" ).uniqueResult();
|
||||
assertEquals( "multiline string inserted incorrectly", "Multiline comment line 1\r\n-- line 2'\r\n/* line 3 */", multilineText );
|
||||
|
||||
String empty = (String) s.createSQLQuery( "SELECT text FROM test_data WHERE id = 3" ).uniqueResult();
|
||||
assertNull( "NULL value inserted incorrectly", empty );
|
||||
|
||||
tx.commit();
|
||||
s.close();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
INSERT INTO dog (id, master_fk) VALUES (1,1)
|
||||
INSERT INTO dog (id, master_fk) VALUES (2,2)
|
||||
INSERT INTO dog (id, master_fk) VALUES (3,3)
|
||||
INSERT INTO dog (id, master_fk) VALUES (1,1);
|
||||
INSERT INTO dog (id, master_fk) VALUES (2,2);
|
||||
INSERT INTO dog (id, master_fk) VALUES (3,3);
|
|
@ -1,3 +1,3 @@
|
|||
INSERT INTO human (id, fname, lname) VALUES (1,'Emmanuel','Bernard')
|
||||
INSERT INTO human (id, fname, lname) VALUES (2,'Gavin','King')
|
||||
INSERT INTO human (id, fname, lname) VALUES (3,'Max','Andersen')
|
||||
INSERT INTO human (id, fname, lname) VALUES (1,'Emmanuel','Bernard');
|
||||
INSERT INTO human (id, fname, lname) VALUES (2,'Gavin','King');
|
||||
INSERT INTO human (id, fname, lname) VALUES (3,'Max','Andersen');
|
|
@ -0,0 +1,31 @@
|
|||
-- Sample file used to test import feature of multiline SQL script (HHH-2403).
|
||||
-- Contains various SQL instructions with comments.
|
||||
|
||||
CREATE TABLE test_data (
|
||||
id NUMBER NOT NULL PRIMARY KEY -- primary key
|
||||
, text VARCHAR2(100) /* any other data */
|
||||
);
|
||||
|
||||
INSERT INTO test_data VALUES (1, 'sample');
|
||||
|
||||
DELETE
|
||||
FROM test_data;
|
||||
|
||||
/*
|
||||
* Data insertion...
|
||||
*/
|
||||
INSERT INTO test_data VALUES (2, 'Multiline comment line 1
|
||||
-- line 2''
|
||||
/* line 3 */');
|
||||
|
||||
/* Invalid insert: INSERT INTO test_data VALUES (1, NULL); */
|
||||
-- INSERT INTO test_data VALUES (1, NULL);
|
||||
|
||||
INSERT INTO test_data VALUES (3 /* 'third record' */, NULL /* value */); -- with NULL value
|
||||
|
||||
INSERT INTO test_data (id, text)
|
||||
VALUES
|
||||
(
|
||||
4 -- another record
|
||||
, NULL
|
||||
);
|
Loading…
Reference in New Issue