diff --git a/pom.xml b/pom.xml index 44ab183..8ba9ca0 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ io.ebean ebean-migration - 11.17.2-SNAPSHOT + 11.18.1-SNAPSHOT org.avaje @@ -73,6 +73,13 @@ mvn install:install-file -Dfile=/some/path/to/ojdbc7.jar -DgroupId=oracle \ + + org.avaje.composite + logback + 1.1 + test + + io.ebean.test ebean-test-docker @@ -94,20 +101,6 @@ mvn install:install-file -Dfile=/some/path/to/ojdbc7.jar -DgroupId=oracle \ test - - org.slf4j - slf4j-simple - 1.7.25 - test - - - - ch.qos.logback - logback-classic - 1.2.3 - test - - diff --git a/src/main/java/io/ebean/migration/ddl/DdlParser.java b/src/main/java/io/ebean/migration/ddl/DdlParser.java index 0fb35aa..82d38bb 100644 --- a/src/main/java/io/ebean/migration/ddl/DdlParser.java +++ b/src/main/java/io/ebean/migration/ddl/DdlParser.java @@ -2,7 +2,7 @@ import java.io.BufferedReader; import java.io.IOException; -import java.io.StringReader; +import java.io.Reader; import java.util.ArrayList; import java.util.List; @@ -14,7 +14,7 @@ public class DdlParser { /** * Break up the sql in reader into a list of statements using the semi-colon and $$ delimiters; */ - public List parse(StringReader reader) { + public List parse(Reader reader) { try { BufferedReader br = new BufferedReader(reader); @@ -43,6 +43,9 @@ static class StatementsSeparator { private static final String EOL = "\n"; + private static final String GO = "GO"; + private static final String PROCEDURE = " PROCEDURE "; + ArrayList statements = new ArrayList<>(); boolean trimDelimiter; @@ -51,6 +54,7 @@ static class StatementsSeparator { StringBuilder sb = new StringBuilder(); + int lineCount; int quoteCount; void lineContainsDollars(String line) { @@ -74,11 +78,21 @@ void endOfStatement(String line) { sb.append(line); statements.add(sb.toString().trim()); quoteCount = 0; + lineCount = 0; + inDbProcedure = false; sb = new StringBuilder(); } + /** + * Process the next line of the script. + */ void nextLine(String line) { + if (line.trim().equals(GO)) { + endOfStatement(""); + return; + } + if (line.contains("$$")) { lineContainsDollars(line); return; @@ -94,6 +108,11 @@ void nextLine(String line) { return; } + if (lineCount == 0 && isStartDbProcedure(line)) { + inDbProcedure = true; + } + + lineCount++; quoteCount += countQuotes(line); if (hasOddQuotes()) { // must continue @@ -123,6 +142,13 @@ void nextLine(String line) { } } + /** + * Return true if the start of DB procedure is detected. + */ + private boolean isStartDbProcedure(String line) { + return line.length() > 26 && line.substring(0, 26).toUpperCase().contains(PROCEDURE); + } + /** * Return true if the count of quotes is odd. */ diff --git a/src/test/java/io/ebean/migration/MigrationRunner_platform_Test.java b/src/test/java/io/ebean/migration/MigrationRunner_platform_Test.java index a939c42..c0350d0 100644 --- a/src/test/java/io/ebean/migration/MigrationRunner_platform_Test.java +++ b/src/test/java/io/ebean/migration/MigrationRunner_platform_Test.java @@ -139,7 +139,7 @@ public void sqlServer_migration() throws SQLException { readQuery(connection, "select * from m3"); } - sqlServerContainer.stopRemove(); +// sqlServerContainer.stopRemove(); } @Test diff --git a/src/test/java/io/ebean/migration/ddl/DdlParserTest.java b/src/test/java/io/ebean/migration/ddl/DdlParserTest.java index 8e2d047..717422f 100644 --- a/src/test/java/io/ebean/migration/ddl/DdlParserTest.java +++ b/src/test/java/io/ebean/migration/ddl/DdlParserTest.java @@ -2,6 +2,8 @@ import org.testng.annotations.Test; +import java.io.FileNotFoundException; +import java.io.FileReader; import java.io.StringReader; import java.util.List; @@ -31,6 +33,31 @@ public void parse_functionWithInlineComments() { assertThat(stmts).containsExactly(plpgsql); } + @Test + public void parse_sqlserver_create_procs() throws FileNotFoundException { + + FileReader fr = new FileReader("src/test/resources/dbmig_sqlserver/I__create_procs.sql"); + final List statements = parser.parse(fr); + + assertThat(statements).hasSize(11); + assertThat(statements.get(0)).isEqualTo("if not exists (select name from sys.types where name = 'ebean_bigint_tvp')\n" + + "create type ebean_bigint_tvp as table (c1 bigint)"); + + assertThat(statements.get(6)).isEqualTo("if not exists (select name from sys.types where name = 'ebean_nvarchar_tvp')\n" + + "create type ebean_nvarchar_tvp as table (c1 nvarchar(max))"); + + assertThat(statements.get(8)).isEqualTo("CREATE OR ALTER PROCEDURE usp_ebean_drop_default_constraint @tableName nvarchar(255), @columnName nvarchar(255)\n" + + "AS SET NOCOUNT ON\n" + + "declare @tmp nvarchar(1000)\n" + + "BEGIN\n" + + " select @tmp = t1.name from sys.default_constraints t1\n" + + " join sys.columns t2 on t1.object_id = t2.default_object_id\n" + + " where t1.parent_object_id = OBJECT_ID(@tableName) and t2.name = @columnName;\n" + + "\n" + + " if @tmp is not null EXEC('alter table ' + @tableName +' drop constraint ' + @tmp);\n" + + "END"); + } + @Test public void parse_ignoresEmptyLines() { diff --git a/src/test/resources/dbmig_sqlserver/I__create_procs.sql b/src/test/resources/dbmig_sqlserver/I__create_procs.sql index 84e933e..aa2cfce 100644 --- a/src/test/resources/dbmig_sqlserver/I__create_procs.sql +++ b/src/test/resources/dbmig_sqlserver/I__create_procs.sql @@ -1,22 +1,46 @@ --- Initial script to create stored procedures etc for sqlserver platform - --- create table-value-parameters if not exists (select name from sys.types where name = 'ebean_bigint_tvp') -create type ebean_bigint_tvp as table (c1 bigint); +create type ebean_bigint_tvp as table +( + c1 bigint +) +GO if not exists (select name from sys.types where name = 'ebean_float_tvp') -create type ebean_float_tvp as table (c1 float); +create type ebean_float_tvp as table +( + c1 float +) +GO if not exists (select name from sys.types where name = 'ebean_bit_tvp') -create type ebean_bit_tvp as table (c1 bit); +create type ebean_bit_tvp as table +( + c1 bit +) +GO if not exists (select name from sys.types where name = 'ebean_date_tvp') -create type ebean_date_tvp as table (c1 date); +create type ebean_date_tvp as table +( + c1 date +) +GO if not exists (select name from sys.types where name = 'ebean_time_tvp') -create type ebean_time_tvp as table (c1 time); +create type ebean_time_tvp as table +( + c1 time +) +GO if not exists (select name from sys.types where name = 'ebean_uniqueidentifier_tvp') -create type ebean_uniqueidentifier_tvp as table (c1 uniqueidentifier); +create type ebean_uniqueidentifier_tvp as table +( + c1 uniqueidentifier +) +GO if not exists (select name from sys.types where name = 'ebean_nvarchar_tvp') -create type ebean_nvarchar_tvp as table (c1 nvarchar(max)); +create type ebean_nvarchar_tvp as table +( + c1 nvarchar(max) +) +GO -delimiter $$ -- -- PROCEDURE: usp_ebean_drop_indices TABLE, COLUMN -- deletes all indices referring to TABLE.COLUMN @@ -42,9 +66,8 @@ BEGIN CLOSE index_cursor; DEALLOCATE index_cursor; END -$$ +GO -delimiter $$ -- -- PROCEDURE: usp_ebean_drop_default_constraint TABLE, COLUMN -- deletes the default constraint, which has a random name @@ -59,9 +82,8 @@ BEGIN if @tmp is not null EXEC('alter table ' + @tableName +' drop constraint ' + @tmp); END -$$ +GO -delimiter $$ -- -- PROCEDURE: usp_ebean_drop_constraints TABLE, COLUMN -- deletes constraints and foreign keys refering to TABLE.COLUMN @@ -93,9 +115,8 @@ BEGIN CLOSE name_cursor; DEALLOCATE name_cursor; END -$$ +GO -delimiter $$ -- -- PROCEDURE: usp_ebean_drop_column TABLE, COLUMN -- deletes the column annd ensures that all indices and constraints are dropped first @@ -111,4 +132,4 @@ BEGIN set @sql = 'alter table ' + @tableName + ' drop column ' + @columnName; EXECUTE(@sql); END -$$ +GO