From: Sébastien Lesaint Date: Wed, 14 Sep 2016 09:05:09 +0000 (+0200) Subject: SONAR-8025 strengthen name checks in CreateTableBuilder X-Git-Tag: 6.1-RC1~38 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=d3f9558099de1943dc52ddae312d357193cdf6c1;p=sonarqube.git SONAR-8025 strengthen name checks in CreateTableBuilder --- diff --git a/sonar-db/src/main/java/org/sonar/db/version/CreateTableBuilder.java b/sonar-db/src/main/java/org/sonar/db/version/CreateTableBuilder.java index 2a23ccb2653..462da8dd3d7 100644 --- a/sonar-db/src/main/java/org/sonar/db/version/CreateTableBuilder.java +++ b/sonar-db/src/main/java/org/sonar/db/version/CreateTableBuilder.java @@ -19,6 +19,7 @@ */ package org.sonar.db.version; +import com.google.common.base.CharMatcher; import com.google.common.collect.HashMultimap; import com.google.common.collect.Multimap; import java.util.ArrayList; @@ -37,12 +38,21 @@ import org.sonar.db.dialect.MySql; import org.sonar.db.dialect.Oracle; import org.sonar.db.dialect.PostgreSql; +import static com.google.common.base.CharMatcher.anyOf; +import static com.google.common.base.CharMatcher.inRange; import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkState; import static java.util.Objects.requireNonNull; import static java.util.stream.Stream.of; public class CreateTableBuilder { + private static final int TABLE_NAME_MAX_SIZE = 25; + private static final int CONSTRAINT_NAME_MAX_SIZE = 30; + private static final CharMatcher DIGIT_CHAR_MATCHER = inRange('0', '9'); + private static final CharMatcher LOWER_CASE_ASCII_LETTERS_CHAR_MATCHER = inRange('a', 'z'); + private static final CharMatcher UNDERSCORE_CHAR_MATCHER = anyOf("_"); + private final Dialect dialect; private final String tableName; private final List columnDefs = new ArrayList<>(); @@ -53,7 +63,7 @@ public class CreateTableBuilder { public CreateTableBuilder(Dialect dialect, String tableName) { this.dialect = requireNonNull(dialect, "dialect can't be null"); - this.tableName = requireNonNull(tableName, "table name can't be null").toLowerCase(Locale.ENGLISH); + this.tableName = checkDbIdentifier(tableName, "Table name", TABLE_NAME_MAX_SIZE); } public List build() { @@ -122,10 +132,24 @@ public class CreateTableBuilder { } public CreateTableBuilder withPkConstraintName(String pkConstraintName) { - this.pkConstraintName = requireNonNull(pkConstraintName, "primary key constraint name can't be null"); + this.pkConstraintName = checkDbIdentifier(pkConstraintName, "Primary key constraint name", CONSTRAINT_NAME_MAX_SIZE); return this; } + private static String checkDbIdentifier(String identifier, String identifierDesc, int maxSize) { + String res = checkNotNull(identifier, "%s can't be null", identifierDesc); + checkArgument( + identifier.length() <= maxSize, + "%s length can't be more than %s", identifierDesc, maxSize); + checkArgument( + LOWER_CASE_ASCII_LETTERS_CHAR_MATCHER.or(DIGIT_CHAR_MATCHER).or(anyOf("_")).matchesAllOf(identifier), + "%s must be lower case and contain only alphanumeric chars or '_', got '%s'", identifierDesc, identifier); + checkArgument( + DIGIT_CHAR_MATCHER.or(UNDERSCORE_CHAR_MATCHER).matchesNoneOf(identifier.subSequence(0, 1)), + "%s must not start by a number or '_', got '%s'", identifierDesc, identifier); + return res; + } + private String createTableStatement() { StringBuilder res = new StringBuilder("CREATE TABLE "); res.append(tableName); diff --git a/sonar-db/src/test/java/org/sonar/db/version/CreateTableBuilderTest.java b/sonar-db/src/test/java/org/sonar/db/version/CreateTableBuilderTest.java index 5fd45810c0d..655c608a67b 100644 --- a/sonar-db/src/test/java/org/sonar/db/version/CreateTableBuilderTest.java +++ b/sonar-db/src/test/java/org/sonar/db/version/CreateTableBuilderTest.java @@ -19,11 +19,15 @@ */ package org.sonar.db.version; +import com.tngtech.java.junit.dataprovider.DataProvider; +import com.tngtech.java.junit.dataprovider.DataProviderRunner; +import com.tngtech.java.junit.dataprovider.UseDataProvider; import java.util.Arrays; import java.util.List; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; import org.sonar.db.dialect.Dialect; import org.sonar.db.dialect.H2; import org.sonar.db.dialect.MsSql; @@ -43,6 +47,7 @@ import static org.sonar.db.version.DecimalColumnDef.newDecimalColumnDefBuilder; import static org.sonar.db.version.IntegerColumnDef.newIntegerColumnDefBuilder; import static org.sonar.db.version.VarcharColumnDef.newVarcharColumnDefBuilder; +@RunWith(DataProviderRunner.class) public class CreateTableBuilderTest { private static final H2 H2 = new H2(); private static final Oracle ORACLE = new Oracle(); @@ -68,11 +73,77 @@ public class CreateTableBuilderTest { @Test public void constructor_fails_with_NPE_if_tablename_is_null() { expectedException.expect(NullPointerException.class); - expectedException.expectMessage("table name can't be null"); + expectedException.expectMessage("Table name can't be null"); new CreateTableBuilder(mock(Dialect.class), null); } + @Test + public void constructor_throws_IAE_if_table_name_is_not_lowercase() { + expectedException.expect(IllegalArgumentException.class); + expectedException.expectMessage("Table name must be lower case and contain only alphanumeric chars or '_', got 'Tooo"); + + new CreateTableBuilder(mock(Dialect.class), "Tooo"); + } + + @Test + public void constructor_throws_IAE_if_table_name_is_26_chars_long() { + expectedException.expect(IllegalArgumentException.class); + expectedException.expectMessage("Table name length can't be more than 25"); + + new CreateTableBuilder(mock(Dialect.class), "abcdefghijklmnopqrstuvwxyz"); + } + + @Test + public void constructor_does_not_fail_if_table_name_is_25_chars_long() { + new CreateTableBuilder(mock(Dialect.class), "abcdefghijklmnopqrstuvwxy"); + } + + @Test + public void constructor_does_not_fail_if_table_name_contains_ascii_letters() { + new CreateTableBuilder(mock(Dialect.class), "abcdefghijklmnopqrstuvwxy"); + new CreateTableBuilder(mock(Dialect.class), "z"); + } + + @Test + public void constructor_throws_IAE_if_table_name_starts_with_underscore() { + expectedException.expect(IllegalArgumentException.class); + expectedException.expectMessage("Table name must not start by a number or '_', got '_a'"); + + new CreateTableBuilder(mock(Dialect.class), "_a"); + } + + @Test + @UseDataProvider("digitCharsDataProvider") + public void constructor_throws_IAE_if_table_name_starts_with_number(char number) { + expectedException.expect(IllegalArgumentException.class); + expectedException.expectMessage("Table name must not start by a number or '_', got '" + number + "a'"); + + new CreateTableBuilder(mock(Dialect.class), number + "a"); + } + + @DataProvider + public static Object[][] digitCharsDataProvider() { + return new Object[][]{ + {'0'}, + {'1'}, + {'2'}, + {'3'}, + {'4'}, + {'5'}, + {'6'}, + {'7'}, + {'8'}, + {'9'}, + }; + } + + @Test + public void constructor_does_not_fail_if_table_name_contains_underscore_or_numbers() { + new CreateTableBuilder(mock(Dialect.class), "a1234567890"); + new CreateTableBuilder(mock(Dialect.class), "a_"); + } + @Test public void build_throws_ISE_if_no_column_has_been_set() { expectedException.expect(IllegalStateException.class); @@ -118,176 +189,218 @@ public class CreateTableBuilderTest { @Test public void addPkColumn_throws_IAE_when_AUTO_INCREMENT_flag_is_provided_with_def_other_than_Integer_and_BigInteger() { ColumnDef[] columnDefs = { - newBooleanColumnDefBuilder().setColumnName("id").build(), - newClobColumnDefBuilder().setColumnName("id").build(), - newDecimalColumnDefBuilder().setColumnName("id").build(), - new TinyIntColumnDef.Builder().setColumnName("id").build(), - newVarcharColumnDefBuilder().setColumnName("id").setLimit(40).build(), - newBlobColumnDefBuilder().setColumnName("id").build() + newBooleanColumnDefBuilder().setColumnName("id").build(), + newClobColumnDefBuilder().setColumnName("id").build(), + newDecimalColumnDefBuilder().setColumnName("id").build(), + new TinyIntColumnDef.Builder().setColumnName("id").build(), + newVarcharColumnDefBuilder().setColumnName("id").setLimit(40).build(), + newBlobColumnDefBuilder().setColumnName("id").build() }; Arrays.stream(columnDefs) - .forEach(columnDef -> { - try { - underTest.addPkColumn(columnDef, AUTO_INCREMENT); - fail("A IllegalArgumentException should have been raised"); - } catch (IllegalArgumentException e) { - assertThat(e).hasMessage("Auto increment column must either be BigInteger or Integer"); - } - }); + .forEach(columnDef -> { + try { + underTest.addPkColumn(columnDef, AUTO_INCREMENT); + fail("A IllegalArgumentException should have been raised"); + } catch (IllegalArgumentException e) { + assertThat(e).hasMessage("Auto increment column must either be BigInteger or Integer"); + } + }); } @Test public void addPkColumn_throws_IAE_when_AUTO_INCREMENT_flag_is_provided_and_column_is_nullable() { ColumnDef[] columnDefs = { - newIntegerColumnDefBuilder().setColumnName("id").build(), - newBigIntegerColumnDefBuilder().setColumnName("id").build() + newIntegerColumnDefBuilder().setColumnName("id").build(), + newBigIntegerColumnDefBuilder().setColumnName("id").build() }; Arrays.stream(columnDefs) - .forEach(columnDef -> { - try { - underTest.addPkColumn(columnDef, AUTO_INCREMENT); - fail("A IllegalArgumentException should have been raised"); - } catch (IllegalArgumentException e) { - assertThat(e).hasMessage("Auto increment column can't be nullable"); - } - }); + .forEach(columnDef -> { + try { + underTest.addPkColumn(columnDef, AUTO_INCREMENT); + fail("A IllegalArgumentException should have been raised"); + } catch (IllegalArgumentException e) { + assertThat(e).hasMessage("Auto increment column can't be nullable"); + } + }); } @Test public void build_sets_type_SERIAL_for_autoincrement_integer_pk_column_on_Postgresql() { List stmts = new CreateTableBuilder(POSTGRESQL, TABLE_NAME) - .addPkColumn(newIntegerColumnDefBuilder().setColumnName("id").setIsNullable(false).build(), AUTO_INCREMENT) - .build(); + .addPkColumn(newIntegerColumnDefBuilder().setColumnName("id").setIsNullable(false).build(), AUTO_INCREMENT) + .build(); assertThat(stmts).hasSize(1); assertThat(stmts.iterator().next()) - .isEqualTo( - "CREATE TABLE table_42 (id SERIAL NOT NULL, CONSTRAINT pk_table_42 PRIMARY KEY (id))"); + .isEqualTo( + "CREATE TABLE table_42 (id SERIAL NOT NULL, CONSTRAINT pk_table_42 PRIMARY KEY (id))"); } @Test public void build_sets_type_BIGSERIAL_for_autoincrement_biginteger_pk_column_on_Postgresql() { List stmts = new CreateTableBuilder(POSTGRESQL, TABLE_NAME) - .addPkColumn(newBigIntegerColumnDefBuilder().setColumnName("id").setIsNullable(false).build(), AUTO_INCREMENT) - .build(); + .addPkColumn(newBigIntegerColumnDefBuilder().setColumnName("id").setIsNullable(false).build(), AUTO_INCREMENT) + .build(); assertThat(stmts).hasSize(1); assertThat(stmts.iterator().next()) - .isEqualTo( - "CREATE TABLE table_42 (id BIGSERIAL NOT NULL, CONSTRAINT pk_table_42 PRIMARY KEY (id))"); + .isEqualTo( + "CREATE TABLE table_42 (id BIGSERIAL NOT NULL, CONSTRAINT pk_table_42 PRIMARY KEY (id))"); } @Test public void build_generates_a_create_trigger_statement_when_an_autoincrement_pk_column_is_specified_and_on_Oracle() { List stmts = new CreateTableBuilder(ORACLE, TABLE_NAME) - .addPkColumn(newIntegerColumnDefBuilder().setColumnName("id").setIsNullable(false).build(), AUTO_INCREMENT) - .build(); + .addPkColumn(newIntegerColumnDefBuilder().setColumnName("id").setIsNullable(false).build(), AUTO_INCREMENT) + .build(); assertThat(stmts).hasSize(3); assertThat(stmts.get(0)) - .isEqualTo("CREATE TABLE table_42 (id INTEGER NOT NULL, CONSTRAINT pk_table_42 PRIMARY KEY (id))"); + .isEqualTo("CREATE TABLE table_42 (id INTEGER NOT NULL, CONSTRAINT pk_table_42 PRIMARY KEY (id))"); assertThat(stmts.get(1)) - .isEqualTo("CREATE SEQUENCE table_42_seq START WITH 1 INCREMENT BY 1"); + .isEqualTo("CREATE SEQUENCE table_42_seq START WITH 1 INCREMENT BY 1"); assertThat(stmts.get(2)) - .isEqualTo("CREATE OR REPLACE TRIGGER table_42_idt" + - " BEFORE INSERT ON table_42" + - " FOR EACH ROW" + - " BEGIN" + - " IF :new.id IS null THEN" + - " SELECT table_42_seq.nextval INTO :new.id FROM dual;" + - " END IF;" + - " END;"); + .isEqualTo("CREATE OR REPLACE TRIGGER table_42_idt" + + " BEFORE INSERT ON table_42" + + " FOR EACH ROW" + + " BEGIN" + + " IF :new.id IS null THEN" + + " SELECT table_42_seq.nextval INTO :new.id FROM dual;" + + " END IF;" + + " END;"); } @Test public void build_adds_IDENTITY_clause_on_MsSql() { List stmts = new CreateTableBuilder(MS_SQL, TABLE_NAME) - .addPkColumn(newIntegerColumnDefBuilder().setColumnName("id").setIsNullable(false).build(), AUTO_INCREMENT) - .build(); + .addPkColumn(newIntegerColumnDefBuilder().setColumnName("id").setIsNullable(false).build(), AUTO_INCREMENT) + .build(); assertThat(stmts).hasSize(1); assertThat(stmts.iterator().next()) - .isEqualTo( - "CREATE TABLE table_42 (id INT NOT NULL IDENTITY (0,1), CONSTRAINT pk_table_42 PRIMARY KEY (id))"); + .isEqualTo( + "CREATE TABLE table_42 (id INT NOT NULL IDENTITY (0,1), CONSTRAINT pk_table_42 PRIMARY KEY (id))"); } @Test public void build_adds_AUTO_INCREMENT_clause_on_H2() { List stmts = new CreateTableBuilder(H2, TABLE_NAME) - .addPkColumn(newIntegerColumnDefBuilder().setColumnName("id").setIsNullable(false).build(), AUTO_INCREMENT) - .build(); + .addPkColumn(newIntegerColumnDefBuilder().setColumnName("id").setIsNullable(false).build(), AUTO_INCREMENT) + .build(); assertThat(stmts).hasSize(1); assertThat(stmts.iterator().next()) - .isEqualTo( - "CREATE TABLE table_42 (id INTEGER NOT NULL AUTO_INCREMENT (0,1), CONSTRAINT pk_table_42 PRIMARY KEY (id))"); + .isEqualTo( + "CREATE TABLE table_42 (id INTEGER NOT NULL AUTO_INCREMENT (0,1), CONSTRAINT pk_table_42 PRIMARY KEY (id))"); } @Test public void build_adds_AUTO_INCREMENT_clause_on_MySql() { List stmts = new CreateTableBuilder(MY_SQL, TABLE_NAME) - .addPkColumn(newIntegerColumnDefBuilder().setColumnName("id").setIsNullable(false).build(), AUTO_INCREMENT) - .build(); + .addPkColumn(newIntegerColumnDefBuilder().setColumnName("id").setIsNullable(false).build(), AUTO_INCREMENT) + .build(); assertThat(stmts).hasSize(1); assertThat(stmts.iterator().next()) - .isEqualTo( - "CREATE TABLE table_42 (id INTEGER NOT NULL AUTO_INCREMENT, CONSTRAINT pk_table_42 PRIMARY KEY (id))"); + .isEqualTo( + "CREATE TABLE table_42 (id INTEGER NOT NULL AUTO_INCREMENT, CONSTRAINT pk_table_42 PRIMARY KEY (id))"); } @Test - public void withPkConstraintName_throws_NPE_if_ColumnDef_is_null() { + public void withPkConstraintName_throws_NPE_if_name_is_null() { expectedException.expect(NullPointerException.class); - expectedException.expectMessage("primary key constraint name can't be null"); + expectedException.expectMessage("Primary key constraint name can't be null"); underTest.withPkConstraintName(null); } @Test - public void build_lowers_case_of_table_name() { - List stmts = new CreateTableBuilder(H2, "SOmE_TABLe_NamE") - .addColumn(newBooleanColumnDefBuilder().setColumnName("bool_col").build()) - .build(); - assertThat(stmts).hasSize(1); - assertThat(stmts.iterator().next()) - .startsWith("CREATE TABLE some_table_name (") - .endsWith(")"); + public void withPkConstraintName_throws_IAE_if_name_is_not_lowercase() { + expectedException.expect(IllegalArgumentException.class); + expectedException.expectMessage("Primary key constraint name must be lower case and contain only alphanumeric chars or '_', got 'Too'"); + + underTest.withPkConstraintName("Too"); + } + + @Test + public void withPkConstraintName_throws_IAE_if_name_is_more_than_30_char_long() { + expectedException.expect(IllegalArgumentException.class); + expectedException.expectMessage("Primary key constraint name length can't be more than 30"); + + underTest.withPkConstraintName("abcdefghijklmnopqrstuvwxyzabcdf"); + } + + @Test + public void withPkConstraintName_throws_IAE_if_name_starts_with_underscore() { + expectedException.expect(IllegalArgumentException.class); + expectedException.expectMessage("Primary key constraint name must not start by a number or '_', got '_a'"); + + underTest.withPkConstraintName("_a"); + } + + @Test + @UseDataProvider("digitCharsDataProvider") + public void withPkConstraintName_throws_IAE_if_name_starts_with_number(char number) { + expectedException.expect(IllegalArgumentException.class); + expectedException.expectMessage("Primary key constraint name must not start by a number or '_', got '" + number + "a'"); + + underTest.withPkConstraintName(number + "a"); + } + + @Test + public void withPkConstraintName_does_not_fail_if_name_is_30_char_long() { + underTest.withPkConstraintName("abcdefghijklmnopqrstuvwxyzabcd"); + } + + @Test + public void withPkConstraintName_does_not_fail_if_name_contains_ascii_letters() { + underTest.withPkConstraintName("abcdefghijklmnopqrstuvwxyz"); + } + + @Test + public void withPkConstraintName_does_not_fail_if_name_contains_underscore() { + underTest.withPkConstraintName("a_"); + } + + @Test + public void withPkConstraintName_does_not_fail_if_name_contains_numbers() { + underTest.withPkConstraintName("a0123456789"); } @Test public void build_adds_NULL_when_column_is_nullable_for_all_DBs() { Arrays.stream(ALL_DIALECTS) - .forEach(dialect -> { - List stmts = new CreateTableBuilder(dialect, TABLE_NAME) - .addColumn(newBigIntegerColumnDefBuilder().setColumnName("bg_col").build()) - .build(); - assertThat(stmts).hasSize(1); - - assertThat(stmts.iterator().next()) - .isEqualTo("CREATE TABLE " + TABLE_NAME + " (" + - "bg_col " + - bigIntSqlType(dialect) + " NULL" + - ")"); - }); + .forEach(dialect -> { + List stmts = new CreateTableBuilder(dialect, TABLE_NAME) + .addColumn(newBigIntegerColumnDefBuilder().setColumnName("bg_col").build()) + .build(); + assertThat(stmts).hasSize(1); + + assertThat(stmts.iterator().next()) + .isEqualTo("CREATE TABLE " + TABLE_NAME + " (" + + "bg_col " + + bigIntSqlType(dialect) + " NULL" + + ")"); + }); } @Test public void build_adds_NOT_NULL_when_column_is_not_nullable_for_all_DBs() { Arrays.stream(ALL_DIALECTS) - .forEach(dialect -> { - List stmts = new CreateTableBuilder(dialect, TABLE_NAME) - .addColumn(newBigIntegerColumnDefBuilder().setColumnName("bg_col").setIsNullable(false).build()) - .build(); - assertThat(stmts).hasSize(1); - - assertThat(stmts.iterator().next()) - .isEqualTo("CREATE TABLE " + TABLE_NAME + " (" + - "bg_col " + - bigIntSqlType(dialect) + - " NOT NULL" + - ")"); - }); + .forEach(dialect -> { + List stmts = new CreateTableBuilder(dialect, TABLE_NAME) + .addColumn(newBigIntegerColumnDefBuilder().setColumnName("bg_col").setIsNullable(false).build()) + .build(); + assertThat(stmts).hasSize(1); + + assertThat(stmts.iterator().next()) + .isEqualTo("CREATE TABLE " + TABLE_NAME + " (" + + "bg_col " + + bigIntSqlType(dialect) + + " NOT NULL" + + ")"); + }); } @Test public void build_of_single_column_table() { List stmts = new CreateTableBuilder(H2, TABLE_NAME) - .addColumn(newBooleanColumnDefBuilder().setColumnName("bool_col_1").build()) - .build(); + .addColumn(newBooleanColumnDefBuilder().setColumnName("bool_col_1").build()) + .build(); assertThat(stmts).hasSize(1); assertThat(stmts.iterator().next()).isEqualTo("CREATE TABLE table_42 (bool_col_1 BOOLEAN NULL)"); @@ -296,148 +409,148 @@ public class CreateTableBuilderTest { @Test public void build_table_with_pk() { List stmts = new CreateTableBuilder(H2, TABLE_NAME) - .addPkColumn(newBooleanColumnDefBuilder().setColumnName("bool_col").build()) - .addColumn(newVarcharColumnDefBuilder().setColumnName("varchar_col").setLimit(40).build()) - .build(); + .addPkColumn(newBooleanColumnDefBuilder().setColumnName("bool_col").build()) + .addColumn(newVarcharColumnDefBuilder().setColumnName("varchar_col").setLimit(40).build()) + .build(); assertThat(stmts).hasSize(1); assertThat(stmts.iterator().next()) - .isEqualTo("CREATE TABLE " + TABLE_NAME + " (" + - "bool_col BOOLEAN NULL," + - "varchar_col VARCHAR (40) NULL," + - " CONSTRAINT pk_" + TABLE_NAME + " PRIMARY KEY (bool_col)" + - ")"); + .isEqualTo("CREATE TABLE " + TABLE_NAME + " (" + + "bool_col BOOLEAN NULL," + + "varchar_col VARCHAR (40) NULL," + + " CONSTRAINT pk_" + TABLE_NAME + " PRIMARY KEY (bool_col)" + + ")"); } @Test public void build_adds_PRIMARY_KEY_constraint_on_single_column_with_name_computed_from_tablename() { Arrays.asList(ALL_DIALECTS) - .forEach(dialect -> { - List stmts = new CreateTableBuilder(dialect, TABLE_NAME) - .addPkColumn(newBigIntegerColumnDefBuilder().setColumnName("bg_col").setIsNullable(false).build()) - .build(); - assertThat(stmts).hasSize(1); - - assertThat(stmts.iterator().next()) - .isEqualTo("CREATE TABLE " + TABLE_NAME + " (" + - "bg_col " + bigIntSqlType(dialect) + " NOT NULL," + - " CONSTRAINT pk_" + TABLE_NAME + " PRIMARY KEY (bg_col)" + - ")"); - }); + .forEach(dialect -> { + List stmts = new CreateTableBuilder(dialect, TABLE_NAME) + .addPkColumn(newBigIntegerColumnDefBuilder().setColumnName("bg_col").setIsNullable(false).build()) + .build(); + assertThat(stmts).hasSize(1); + + assertThat(stmts.iterator().next()) + .isEqualTo("CREATE TABLE " + TABLE_NAME + " (" + + "bg_col " + bigIntSqlType(dialect) + " NOT NULL," + + " CONSTRAINT pk_" + TABLE_NAME + " PRIMARY KEY (bg_col)" + + ")"); + }); } @Test public void build_adds_PRIMARY_KEY_constraint_on_single_column_with_lower_case_of_specified_name() { Arrays.asList(ALL_DIALECTS) - .forEach(dialect -> { - List stmts = new CreateTableBuilder(dialect, TABLE_NAME) - .addPkColumn(newBigIntegerColumnDefBuilder().setColumnName("bg_col").setIsNullable(false).build()) - .withPkConstraintName("My_PK") - .build(); - assertThat(stmts).hasSize(1); - - assertThat(stmts.iterator().next()) - .isEqualTo("CREATE TABLE " + TABLE_NAME + " (" + - "bg_col " + - bigIntSqlType(dialect) + - " NOT NULL," + - " CONSTRAINT my_pk PRIMARY KEY (bg_col)" + - ")"); - }); + .forEach(dialect -> { + List stmts = new CreateTableBuilder(dialect, TABLE_NAME) + .addPkColumn(newBigIntegerColumnDefBuilder().setColumnName("bg_col").setIsNullable(false).build()) + .withPkConstraintName("my_pk") + .build(); + assertThat(stmts).hasSize(1); + + assertThat(stmts.iterator().next()) + .isEqualTo("CREATE TABLE " + TABLE_NAME + " (" + + "bg_col " + + bigIntSqlType(dialect) + + " NOT NULL," + + " CONSTRAINT my_pk PRIMARY KEY (bg_col)" + + ")"); + }); } @Test public void build_adds_PRIMARY_KEY_constraint_on_multiple_columns_with_name_computed_from_tablename() { Arrays.asList(ALL_DIALECTS) - .forEach(dialect -> { - List stmts = new CreateTableBuilder(dialect, TABLE_NAME) - .addPkColumn(newBigIntegerColumnDefBuilder().setColumnName("bg_col_1").setIsNullable(false).build()) - .addPkColumn(newBigIntegerColumnDefBuilder().setColumnName("bg_col_2").setIsNullable(false).build()) - .build(); - assertThat(stmts).hasSize(1); - - assertThat(stmts.iterator().next()) - .isEqualTo("CREATE TABLE " + TABLE_NAME + " (" + - "bg_col_1 " + bigIntSqlType(dialect) + " NOT NULL," + - "bg_col_2 " + bigIntSqlType(dialect) + " NOT NULL," + - " CONSTRAINT pk_" + TABLE_NAME + " PRIMARY KEY (bg_col_1,bg_col_2)" + - ")"); - }); + .forEach(dialect -> { + List stmts = new CreateTableBuilder(dialect, TABLE_NAME) + .addPkColumn(newBigIntegerColumnDefBuilder().setColumnName("bg_col_1").setIsNullable(false).build()) + .addPkColumn(newBigIntegerColumnDefBuilder().setColumnName("bg_col_2").setIsNullable(false).build()) + .build(); + assertThat(stmts).hasSize(1); + + assertThat(stmts.iterator().next()) + .isEqualTo("CREATE TABLE " + TABLE_NAME + " (" + + "bg_col_1 " + bigIntSqlType(dialect) + " NOT NULL," + + "bg_col_2 " + bigIntSqlType(dialect) + " NOT NULL," + + " CONSTRAINT pk_" + TABLE_NAME + " PRIMARY KEY (bg_col_1,bg_col_2)" + + ")"); + }); } @Test public void build_adds_PRIMARY_KEY_constraint_on_multiple_columns_with_lower_case_of_specified_name() { Arrays.asList(ALL_DIALECTS) - .forEach(dialect -> { - List stmts = new CreateTableBuilder(dialect, TABLE_NAME) - .addPkColumn(newBigIntegerColumnDefBuilder().setColumnName("bg_col_1").setIsNullable(false).build()) - .addPkColumn(newBigIntegerColumnDefBuilder().setColumnName("bg_col_2").setIsNullable(false).build()) - .withPkConstraintName("My_PK") - .build(); - assertThat(stmts).hasSize(1); - - assertThat(stmts.iterator().next()) - .isEqualTo("CREATE TABLE " + TABLE_NAME + " (" + - "bg_col_1 " + bigIntSqlType(dialect) + " NOT NULL," + - "bg_col_2 " + bigIntSqlType(dialect) + " NOT NULL," + - " CONSTRAINT my_pk PRIMARY KEY (bg_col_1,bg_col_2)" + - ")"); - }); + .forEach(dialect -> { + List stmts = new CreateTableBuilder(dialect, TABLE_NAME) + .addPkColumn(newBigIntegerColumnDefBuilder().setColumnName("bg_col_1").setIsNullable(false).build()) + .addPkColumn(newBigIntegerColumnDefBuilder().setColumnName("bg_col_2").setIsNullable(false).build()) + .withPkConstraintName("my_pk") + .build(); + assertThat(stmts).hasSize(1); + + assertThat(stmts.iterator().next()) + .isEqualTo("CREATE TABLE " + TABLE_NAME + " (" + + "bg_col_1 " + bigIntSqlType(dialect) + " NOT NULL," + + "bg_col_2 " + bigIntSqlType(dialect) + " NOT NULL," + + " CONSTRAINT my_pk PRIMARY KEY (bg_col_1,bg_col_2)" + + ")"); + }); } @Test public void builds_adds_LOB_storage_clause_on_Oracle_for_CLOB_column() { List stmts = new CreateTableBuilder(ORACLE, TABLE_NAME) - .addColumn(newClobColumnDefBuilder().setColumnName("clob_1").setIsNullable(false).build()) - .build(); + .addColumn(newClobColumnDefBuilder().setColumnName("clob_1").setIsNullable(false).build()) + .build(); assertThat(stmts).hasSize(1); assertThat(stmts.iterator().next()).isEqualTo( - "CREATE TABLE " + TABLE_NAME + " (" + - "clob_1 CLOB NOT NULL)" + - " LOB (clob_1) STORE AS SECUREFILE (RETENTION NONE NOCACHE NOLOGGING)"); + "CREATE TABLE " + TABLE_NAME + " (" + + "clob_1 CLOB NOT NULL)" + + " LOB (clob_1) STORE AS SECUREFILE (RETENTION NONE NOCACHE NOLOGGING)"); } @Test public void builds_adds_LOB_storage_clause_on_Oracle_for_BLOB_column() { List stmts = new CreateTableBuilder(ORACLE, TABLE_NAME) - .addColumn(newBlobColumnDefBuilder().setColumnName("blob_1").setIsNullable(false).build()) - .build(); + .addColumn(newBlobColumnDefBuilder().setColumnName("blob_1").setIsNullable(false).build()) + .build(); assertThat(stmts).hasSize(1); assertThat(stmts.iterator().next()).isEqualTo( - "CREATE TABLE " + TABLE_NAME + " (" + - "blob_1 BLOB NOT NULL)" + - " LOB (blob_1) STORE AS SECUREFILE (RETENTION NONE NOCACHE NOLOGGING)"); + "CREATE TABLE " + TABLE_NAME + " (" + + "blob_1 BLOB NOT NULL)" + + " LOB (blob_1) STORE AS SECUREFILE (RETENTION NONE NOCACHE NOLOGGING)"); } @Test public void build_does_not_add_LOB_storage_clause_for_CLOB_column_for_other_than_Oracle() { Arrays.stream(ALL_DIALECTS) - .filter(dialect -> dialect != ORACLE) - .forEach(dialect -> { - List stmts = new CreateTableBuilder(dialect, TABLE_NAME) - .addColumn(newClobColumnDefBuilder().setColumnName("clob_1").setIsNullable(false).build()) - .build(); - assertThat(stmts).hasSize(1); - - assertThat(stmts.iterator().next()).doesNotContain("STORE AS SECUREFILE"); - }); + .filter(dialect -> dialect != ORACLE) + .forEach(dialect -> { + List stmts = new CreateTableBuilder(dialect, TABLE_NAME) + .addColumn(newClobColumnDefBuilder().setColumnName("clob_1").setIsNullable(false).build()) + .build(); + assertThat(stmts).hasSize(1); + + assertThat(stmts.iterator().next()).doesNotContain("STORE AS SECUREFILE"); + }); } @Test public void build_does_not_add_LOB_storage_clause_for_BLOB_column_for_other_than_Oracle() { Arrays.stream(ALL_DIALECTS) - .filter(dialect -> dialect != ORACLE) - .forEach(dialect -> { - List stmts = new CreateTableBuilder(dialect, TABLE_NAME) - .addColumn(newBlobColumnDefBuilder().setColumnName("blob_1").setIsNullable(false).build()) - .build(); - assertThat(stmts).hasSize(1); - - assertThat(stmts.iterator().next()).doesNotContain("STORE AS SECUREFILE"); - }); + .filter(dialect -> dialect != ORACLE) + .forEach(dialect -> { + List stmts = new CreateTableBuilder(dialect, TABLE_NAME) + .addColumn(newBlobColumnDefBuilder().setColumnName("blob_1").setIsNullable(false).build()) + .build(); + assertThat(stmts).hasSize(1); + + assertThat(stmts.iterator().next()).doesNotContain("STORE AS SECUREFILE"); + }); } private static String bigIntSqlType(Dialect dialect) {