diff --git a/morf-core/src/main/java/org/alfasoftware/morf/sql/AbstractSelectStatementBuilder.java b/morf-core/src/main/java/org/alfasoftware/morf/sql/AbstractSelectStatementBuilder.java index cf1cff5df..ef13ea93e 100644 --- a/morf-core/src/main/java/org/alfasoftware/morf/sql/AbstractSelectStatementBuilder.java +++ b/morf-core/src/main/java/org/alfasoftware/morf/sql/AbstractSelectStatementBuilder.java @@ -183,6 +183,11 @@ public T fields(AliasedFieldBuilder... fields) { return fields(Arrays.asList(fields)); } + public T withFields(Iterable fields) { + this.fields.clear(); + Iterables.addAll(this.fields, Builder.Helper.buildAll(fields)); + return castToChild(this); + } /** * Selects fields from a specific table: diff --git a/morf-h2/src/test/java/org/alfasoftware/morf/jdbc/h2/TestH2Dialect.java b/morf-h2/src/test/java/org/alfasoftware/morf/jdbc/h2/TestH2Dialect.java index 5b9470735..55374079c 100755 --- a/morf-h2/src/test/java/org/alfasoftware/morf/jdbc/h2/TestH2Dialect.java +++ b/morf-h2/src/test/java/org/alfasoftware/morf/jdbc/h2/TestH2Dialect.java @@ -1105,6 +1105,17 @@ protected List expectedAddTableFromStatements() { "INSERT INTO TESTSCHEMA.SomeTable SELECT someField, otherField FROM TESTSCHEMA.OtherTable" ); } + /** + * @see org.alfasoftware.morf.jdbc.AbstractSqlDialectTest#expectedAddTableFromStatementsNullValue() + */ + @Override + protected List expectedAddTableFromStatementsNullValue() { + return ImmutableList.of( + "CREATE TABLE TESTSCHEMA.SomeTable (someField VARCHAR(3) NOT NULL, otherField DECIMAL(3,0) NOT NULL, nullField VARCHAR(3) NOT NULL, CONSTRAINT SomeTable_PK PRIMARY KEY (someField))", + "CREATE INDEX SomeTable_1 ON TESTSCHEMA.SomeTable (otherField)", + "INSERT INTO TESTSCHEMA.SomeTable SELECT someField, otherField, null FROM TESTSCHEMA.OtherTable" + ); + } /** diff --git a/morf-mysql/src/test/java/org/alfasoftware/morf/jdbc/mysql/TestMySqlDialect.java b/morf-mysql/src/test/java/org/alfasoftware/morf/jdbc/mysql/TestMySqlDialect.java index b93a4f2e6..78e472b7e 100755 --- a/morf-mysql/src/test/java/org/alfasoftware/morf/jdbc/mysql/TestMySqlDialect.java +++ b/morf-mysql/src/test/java/org/alfasoftware/morf/jdbc/mysql/TestMySqlDialect.java @@ -1168,6 +1168,18 @@ protected List expectedAddTableFromStatements() { ); } + /** + * @see org.alfasoftware.morf.jdbc.AbstractSqlDialectTest#expectedAddTableFromStatementsNullValue() + */ + @Override + protected List expectedAddTableFromStatementsNullValue() { + return ImmutableList.of( + "CREATE TABLE `SomeTable` (`someField` VARCHAR(3) NOT NULL, `otherField` DECIMAL(3,0) NOT NULL, `nullField` VARCHAR(3) NOT NULL, CONSTRAINT `SomeTable_PK` PRIMARY KEY (`someField`)) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin", + "ALTER TABLE `SomeTable` ADD INDEX `SomeTable_1` (`otherField`)", + "INSERT INTO SomeTable SELECT someField, otherField, null FROM OtherTable" + ); + } + /** * We only support {@link SelectStatement#useImplicitJoinOrder()}, and only to a limited extent. diff --git a/morf-nuodb/src/test/java/org/alfasoftware/morf/jdbc/nuodb/TestNuoDBDialect.java b/morf-nuodb/src/test/java/org/alfasoftware/morf/jdbc/nuodb/TestNuoDBDialect.java index 7717cfe6a..7d215bd55 100755 --- a/morf-nuodb/src/test/java/org/alfasoftware/morf/jdbc/nuodb/TestNuoDBDialect.java +++ b/morf-nuodb/src/test/java/org/alfasoftware/morf/jdbc/nuodb/TestNuoDBDialect.java @@ -1402,6 +1402,19 @@ protected List expectedAddTableFromStatements() { ); } + /** + * @see org.alfasoftware.morf.jdbc.AbstractSqlDialectTest#expectedAddTableFromStatementsNullValue() + */ + @Override + protected List expectedAddTableFromStatementsNullValue() { + return ImmutableList.of( + "CREATE TABLE SCM.SomeTable (someField VARCHAR(3) NOT NULL, otherField DECIMAL(3,0) NOT NULL, nullField VARCHAR(3) NOT NULL, PRIMARY KEY (someField))", + "DROP INDEX IF EXISTS SCM.SomeTable_1", + "CREATE INDEX SomeTable_1 ON SCM.SomeTable (otherField)", + "INSERT INTO SCM.SomeTable SELECT someField, otherField, null FROM SCM.OtherTable" + ); + } + /** * @see org.alfasoftware.morf.jdbc.AbstractSqlDialectTest#expectedHints1(int) diff --git a/morf-oracle/src/main/java/org/alfasoftware/morf/jdbc/oracle/OracleDialect.java b/morf-oracle/src/main/java/org/alfasoftware/morf/jdbc/oracle/OracleDialect.java index b6e6938b6..e444ba7b3 100755 --- a/morf-oracle/src/main/java/org/alfasoftware/morf/jdbc/oracle/OracleDialect.java +++ b/morf-oracle/src/main/java/org/alfasoftware/morf/jdbc/oracle/OracleDialect.java @@ -63,6 +63,7 @@ import org.alfasoftware.morf.sql.element.ConcatenatedField; import org.alfasoftware.morf.sql.element.FieldReference; import org.alfasoftware.morf.sql.element.Function; +import org.alfasoftware.morf.sql.element.NullFieldLiteral; import org.alfasoftware.morf.sql.element.SqlParameter; import org.alfasoftware.morf.sql.element.TableReference; import org.apache.commons.lang3.StringUtils; @@ -96,6 +97,8 @@ class OracleDialect extends SqlDialect { */ public static final String NULLS_LAST = "NULLS LAST"; + private static final String CANNOT_CONVERT_NULL_STATEMENT_TO_SQL = "Cannot convert a null statement to SQL"; + /** * Database platforms may order nulls first or last. My SQL always orders nulls first, Oracle defaults to ordering nulls last. * Fortunately on Oracle it is possible to specify that nulls should be ordered first. @@ -1105,11 +1108,26 @@ public Collection renameTableStatements(Table fromTable, Table toTable) */ @Override public Collection addTableFromStatements(Table table, SelectStatement selectStatement) { + List fieldsToInclude = new ArrayList<>(); + + for(AliasedField field: selectStatement.getFields()) { + if (field instanceof NullFieldLiteral || field instanceof FieldReference) { + Column column = table.columns().get(selectStatement.getFields().indexOf(field)); + fieldsToInclude.add(new Cast( + field, + column.getType(), + column.getWidth(), + column.getScale()).as(column.getName())); + } else { + fieldsToInclude.add(field); + } + } + Builder result = ImmutableList.builder(); result.add(new StringBuilder() .append(createTableStatement(table, true)) .append(" AS ") - .append(convertStatementToSQL(selectStatement)) + .append(convertStatementToSQL(selectStatement.shallowCopy().withFields(fieldsToInclude).build())) .toString() ); result.add("ALTER TABLE " + schemaNamePrefix() + table.getName() + " NOPARALLEL LOGGING"); @@ -1123,7 +1141,6 @@ public Collection addTableFromStatements(Table table, SelectStatement se return result.build(); } - /** * Builds the remaining statements (triggers, sequences and comments). * diff --git a/morf-oracle/src/test/java/org/alfasoftware/morf/jdbc/oracle/TestOracleDialect.java b/morf-oracle/src/test/java/org/alfasoftware/morf/jdbc/oracle/TestOracleDialect.java index 3a924b457..ac69b82fa 100755 --- a/morf-oracle/src/test/java/org/alfasoftware/morf/jdbc/oracle/TestOracleDialect.java +++ b/morf-oracle/src/test/java/org/alfasoftware/morf/jdbc/oracle/TestOracleDialect.java @@ -16,7 +16,8 @@ package org.alfasoftware.morf.jdbc.oracle; import static org.alfasoftware.morf.jdbc.oracle.OracleDialect.NULLS_LAST; -import static org.alfasoftware.morf.sql.SqlUtils.parameter; +import static org.alfasoftware.morf.metadata.SchemaUtils.*; +import static org.alfasoftware.morf.sql.SqlUtils.*; import static org.alfasoftware.morf.sql.element.Direction.ASCENDING; import static org.hamcrest.Matchers.contains; import static org.junit.Assert.assertEquals; @@ -43,10 +44,13 @@ import org.alfasoftware.morf.jdbc.SqlScriptExecutor; import org.alfasoftware.morf.metadata.DataType; import org.alfasoftware.morf.metadata.SchemaUtils; +import org.alfasoftware.morf.metadata.Table; import org.alfasoftware.morf.sql.CustomHint; import org.alfasoftware.morf.sql.OracleCustomHint; +import org.alfasoftware.morf.sql.SelectStatement; import org.alfasoftware.morf.sql.element.Direction; import org.alfasoftware.morf.sql.element.SqlParameter; +import org.junit.Test; import org.mockito.ArgumentCaptor; import com.google.common.base.Strings; @@ -1452,7 +1456,7 @@ protected String expectedSelectLiteralWithWhereClauseString() { @Override public List expectedAddTableFromStatements() { return ImmutableList.of( - "CREATE TABLE TESTSCHEMA.SomeTable (someField NOT NULL, otherField NOT NULL, CONSTRAINT SomeTable_PK PRIMARY KEY (someField) USING INDEX (CREATE UNIQUE INDEX TESTSCHEMA.SomeTable_PK ON TESTSCHEMA.SomeTable (someField))) PARALLEL NOLOGGING AS SELECT someField, otherField FROM TESTSCHEMA.OtherTable", + "CREATE TABLE TESTSCHEMA.SomeTable (someField NOT NULL, otherField NOT NULL, CONSTRAINT SomeTable_PK PRIMARY KEY (someField) USING INDEX (CREATE UNIQUE INDEX TESTSCHEMA.SomeTable_PK ON TESTSCHEMA.SomeTable (someField))) PARALLEL NOLOGGING AS SELECT CAST(someField AS NVARCHAR2(3)) AS someField, CAST(otherField AS DECIMAL(3,0)) AS otherField FROM TESTSCHEMA.OtherTable", "ALTER TABLE TESTSCHEMA.SomeTable NOPARALLEL LOGGING", "ALTER INDEX TESTSCHEMA.SomeTable_PK NOPARALLEL LOGGING", "COMMENT ON TABLE TESTSCHEMA.SomeTable IS '"+OracleDialect.REAL_NAME_COMMENT_LABEL+":[SomeTable]'", @@ -1461,6 +1465,22 @@ public List expectedAddTableFromStatements() { ); } + /** + * @see org.alfasoftware.morf.jdbc.AbstractSqlDialectTest#expectedAddTableFromStatementsNullValue() + */ + @Override + public List expectedAddTableFromStatementsNullValue() { + return ImmutableList.of( + "CREATE TABLE TESTSCHEMA.SomeTable (someField NOT NULL, otherField NOT NULL, nullField NOT NULL, CONSTRAINT SomeTable_PK PRIMARY KEY (someField) USING INDEX (CREATE UNIQUE INDEX TESTSCHEMA.SomeTable_PK ON TESTSCHEMA.SomeTable (someField))) PARALLEL NOLOGGING AS SELECT CAST(someField AS NVARCHAR2(3)) AS someField, CAST(otherField AS DECIMAL(3,0)) AS otherField, CAST(null AS NVARCHAR2(3)) AS nullField FROM TESTSCHEMA.OtherTable", + "ALTER TABLE TESTSCHEMA.SomeTable NOPARALLEL LOGGING", + "ALTER INDEX TESTSCHEMA.SomeTable_PK NOPARALLEL LOGGING", + "COMMENT ON TABLE TESTSCHEMA.SomeTable IS 'REALNAME:[SomeTable]'", + "COMMENT ON COLUMN TESTSCHEMA.SomeTable.someField IS 'REALNAME:[someField]/TYPE:[STRING]'", + "COMMENT ON COLUMN TESTSCHEMA.SomeTable.otherField IS 'REALNAME:[otherField]/TYPE:[DECIMAL]'", + "COMMENT ON COLUMN TESTSCHEMA.SomeTable.nullField IS 'REALNAME:[nullField]/TYPE:[STRING]'" + ); + } + /** * @see org.alfasoftware.morf.jdbc.AbstractSqlDialectTest#expectedHints1(int) */ diff --git a/morf-oracle/src/test/java/org/alfasoftware/morf/jdbc/oracle/TestOracleDialectBespokeFunctionality.java b/morf-oracle/src/test/java/org/alfasoftware/morf/jdbc/oracle/TestOracleDialectBespokeFunctionality.java new file mode 100644 index 000000000..045a0b3cc --- /dev/null +++ b/morf-oracle/src/test/java/org/alfasoftware/morf/jdbc/oracle/TestOracleDialectBespokeFunctionality.java @@ -0,0 +1,188 @@ +package org.alfasoftware.morf.jdbc.oracle; + +import org.alfasoftware.morf.metadata.DataType; +import org.alfasoftware.morf.metadata.Table; +import org.alfasoftware.morf.sql.SelectStatement; +import org.junit.Test; + +import static org.alfasoftware.morf.metadata.SchemaUtils.*; +import static org.alfasoftware.morf.sql.SqlUtils.*; +import static org.junit.Assert.assertEquals; + +public class TestOracleDialectBespokeFunctionality { + + + + @Test + public void testConvertStatementToSQL() { + Table table = table("SomeTable") + .columns( + column("someField", DataType.STRING, 3).primaryKey(), + column("otherField", DataType.DECIMAL, 3), + column("nullField", DataType.STRING, 3) + ).indexes( + index("SomeTable_1").columns("otherField") + ); + + SelectStatement selectStatement = select(field("someField"), field("otherField"), nullLiteral()).from(tableRef("OtherTable")); + + OracleDialect oracleDialect = new OracleDialect("TEST"); + String result = oracleDialect.addTableFromStatements(table, selectStatement).toString(); + + String expectedResult = "[CREATE TABLE TEST.SomeTable (" + + "someField NOT NULL, " + + "otherField NOT NULL, " + + "nullField NOT NULL, " + + "CONSTRAINT SomeTable_PK PRIMARY KEY (someField) " + + "USING INDEX (CREATE UNIQUE INDEX TEST.SomeTable_PK ON TEST.SomeTable (someField))) " + + "PARALLEL NOLOGGING " + + "AS SELECT " + + "CAST(someField AS NVARCHAR2(3)) AS someField, " + + "CAST(otherField AS DECIMAL(3,0)) AS otherField, " + + "CAST(null AS NVARCHAR2(3)) AS nullField " + + "FROM TEST.OtherTable, " + + "ALTER TABLE TEST.SomeTable NOPARALLEL LOGGING, " + + "ALTER INDEX TEST.SomeTable_PK NOPARALLEL LOGGING, " + + "COMMENT ON TABLE TEST.SomeTable IS 'REALNAME:[SomeTable]', " + + "COMMENT ON COLUMN TEST.SomeTable.someField IS 'REALNAME:[someField]/TYPE:[STRING]', " + + "COMMENT ON COLUMN TEST.SomeTable.otherField IS 'REALNAME:[otherField]/TYPE:[DECIMAL]', " + + "COMMENT ON COLUMN TEST.SomeTable.nullField IS 'REALNAME:[nullField]/TYPE:[STRING]']"; + assertEquals(expectedResult, result); + } + + @Test + public void testDistinctStatement() { + OracleDialect oracleDialect = new OracleDialect("TEST"); + + Table table = table("SomeTable") + .columns( + column("someField", DataType.STRING, 3).primaryKey(), + column("otherField", DataType.DECIMAL, 3) + ).indexes( + index("SomeTable_1").columns("otherField") + ); + + SelectStatement selectStatement = select(field("someField"), field("otherField")).from(tableRef("OtherTable")); + SelectStatement distinctSelectStatement = selectStatement.shallowCopy().distinct().build(); + + String result = oracleDialect.addTableFromStatements(table, distinctSelectStatement).toString(); + + String expectedResult = "[CREATE TABLE TEST.SomeTable (" + + "someField NOT NULL, " + + "otherField NOT NULL, " + + "CONSTRAINT SomeTable_PK PRIMARY KEY (someField) " + + "USING INDEX (CREATE UNIQUE INDEX TEST.SomeTable_PK ON TEST.SomeTable (someField))) " + + "PARALLEL NOLOGGING " + + "AS SELECT DISTINCT " + + "CAST(someField AS NVARCHAR2(3)) AS someField, " + + "CAST(otherField AS DECIMAL(3,0)) AS otherField FROM TEST.OtherTable, " + + "ALTER TABLE TEST.SomeTable NOPARALLEL LOGGING, " + + "ALTER INDEX TEST.SomeTable_PK NOPARALLEL LOGGING, " + + "COMMENT ON TABLE TEST.SomeTable IS 'REALNAME:[SomeTable]', " + + "COMMENT ON COLUMN TEST.SomeTable.someField IS 'REALNAME:[someField]/TYPE:[STRING]', " + + "COMMENT ON COLUMN TEST.SomeTable.otherField IS 'REALNAME:[otherField]/TYPE:[DECIMAL]']"; + assertEquals(expectedResult, result); + } + + + @Test + public void testAllStatement() { + OracleDialect oracleDialect = new OracleDialect("TEST"); + + Table table = table("SomeTable") + .columns( + column("someField", DataType.STRING, 3).primaryKey(), + column("otherField", DataType.DECIMAL, 3) + ).indexes( + index("SomeTable_1").columns("otherField") + ); + + SelectStatement selectStatement = select().from(tableRef("OtherTable")); + SelectStatement distinctSelectStatement = selectStatement.shallowCopy().distinct().build(); + + String result = oracleDialect.addTableFromStatements(table, distinctSelectStatement).toString(); + + String expectedResult = "[CREATE TABLE TEST.SomeTable (" + + "someField NOT NULL, " + + "otherField NOT NULL, " + + "CONSTRAINT SomeTable_PK PRIMARY KEY (someField) " + + "USING INDEX (CREATE UNIQUE INDEX TEST.SomeTable_PK ON TEST.SomeTable (someField))) " + + "PARALLEL NOLOGGING " + + "AS SELECT DISTINCT * FROM TEST.OtherTable, " + + "ALTER TABLE TEST.SomeTable NOPARALLEL LOGGING, " + + "ALTER INDEX TEST.SomeTable_PK NOPARALLEL LOGGING, " + + "COMMENT ON TABLE TEST.SomeTable IS 'REALNAME:[SomeTable]', " + + "COMMENT ON COLUMN TEST.SomeTable.someField IS 'REALNAME:[someField]/TYPE:[STRING]', " + + "COMMENT ON COLUMN TEST.SomeTable.otherField IS 'REALNAME:[otherField]/TYPE:[DECIMAL]']"; + assertEquals(expectedResult, result); + } + + @Test + public void testUpdateStatement() { + OracleDialect oracleDialect = new OracleDialect("TEST"); + + Table table = table("SomeTable") + .columns( + column("someField", DataType.STRING, 3).primaryKey(), + column("otherField", DataType.DECIMAL, 3) + ).indexes( + index("SomeTable_1").columns("otherField") + ); + + SelectStatement selectStatement = select().from(tableRef("OtherTable")); + SelectStatement updateSelectStatement = selectStatement.shallowCopy().forUpdate().build(); + + String result = oracleDialect.addTableFromStatements(table, updateSelectStatement).toString(); + + String expectedResult = "[CREATE TABLE TEST.SomeTable (" + + "someField NOT NULL, " + + "otherField NOT NULL, " + + "CONSTRAINT SomeTable_PK PRIMARY KEY (someField) " + + "USING INDEX (CREATE UNIQUE INDEX TEST.SomeTable_PK ON TEST.SomeTable (someField))) " + + "PARALLEL NOLOGGING " + + "AS SELECT * FROM TEST.OtherTable " + + "FOR UPDATE, " + + "ALTER TABLE TEST.SomeTable NOPARALLEL LOGGING, " + + "ALTER INDEX TEST.SomeTable_PK NOPARALLEL LOGGING, " + + "COMMENT ON TABLE TEST.SomeTable IS 'REALNAME:[SomeTable]', " + + "COMMENT ON COLUMN TEST.SomeTable.someField IS 'REALNAME:[someField]/TYPE:[STRING]', " + + "COMMENT ON COLUMN TEST.SomeTable.otherField IS 'REALNAME:[otherField]/TYPE:[DECIMAL]']"; + assertEquals(expectedResult, result); + } + + @Test(expected = IllegalArgumentException.class) + public void testUpdateForDistinctStatement() { + OracleDialect oracleDialect = new OracleDialect("TEST"); + + Table table = table("SomeTable") + .columns( + column("someField", DataType.STRING, 3).primaryKey(), + column("otherField", DataType.DECIMAL, 3) + ).indexes( + index("SomeTable_1").columns("otherField") + ); + + SelectStatement selectStatement = select().from(tableRef("OtherTable")); + SelectStatement distinctSelectStatement = selectStatement.shallowCopy().forUpdate().distinct().build(); + + String result = oracleDialect.addTableFromStatements(table, distinctSelectStatement).toString(); + } + + @Test(expected = IllegalArgumentException.class) + public void testIllegalArgumentExeptionIsThrown() { + OracleDialect oracleDialect = new OracleDialect("TEST"); + + Table table = table("SomeTable") + .columns( + column("someField", DataType.STRING, 3).primaryKey(), + column("otherField", DataType.DECIMAL, 3), + column("nullField", DataType.STRING, 3) + ).indexes( + index("SomeTable_1").columns("otherField") + ); + + oracleDialect.convertStatementToSQL((SelectStatement) null); + } + + +} diff --git a/morf-postgresql/src/test/java/org/alfasoftware/morf/jdbc/postgresql/TestPostgreSQLDialect.java b/morf-postgresql/src/test/java/org/alfasoftware/morf/jdbc/postgresql/TestPostgreSQLDialect.java index e66e6d6d1..dd5d59a14 100644 --- a/morf-postgresql/src/test/java/org/alfasoftware/morf/jdbc/postgresql/TestPostgreSQLDialect.java +++ b/morf-postgresql/src/test/java/org/alfasoftware/morf/jdbc/postgresql/TestPostgreSQLDialect.java @@ -1181,6 +1181,23 @@ protected List expectedAddTableFromStatements() { ); } + /** + * @see org.alfasoftware.morf.jdbc.AbstractSqlDialectTest#expectedAddTableFromStatementsNullValue() + */ + @Override + protected List expectedAddTableFromStatementsNullValue() { + return ImmutableList.of( + "CREATE TABLE testschema.SomeTable (someField VARCHAR(3) COLLATE \"POSIX\" NOT NULL, otherField DECIMAL(3,0) NOT NULL, nullField VARCHAR(3) COLLATE \"POSIX\" NOT NULL, CONSTRAINT SomeTable_PK PRIMARY KEY(someField))", + "COMMENT ON TABLE testschema.SomeTable IS '"+PostgreSQLDialect.REAL_NAME_COMMENT_LABEL+":[SomeTable]'", + "COMMENT ON COLUMN testschema.SomeTable.someField IS '"+PostgreSQLDialect.REAL_NAME_COMMENT_LABEL+":[someField]/TYPE:[STRING]'", + "COMMENT ON COLUMN testschema.SomeTable.otherField IS '"+PostgreSQLDialect.REAL_NAME_COMMENT_LABEL+":[otherField]/TYPE:[DECIMAL]'", + "COMMENT ON COLUMN testschema.SomeTable.nullField IS 'REALNAME:[nullField]/TYPE:[STRING]'", + "CREATE INDEX SomeTable_1 ON testschema.SomeTable (otherField)", + "COMMENT ON INDEX SomeTable_1 IS '"+PostgreSQLDialect.REAL_NAME_COMMENT_LABEL+":[SomeTable_1]'", + "INSERT INTO testschema.SomeTable SELECT someField, otherField, null FROM testschema.OtherTable" + ); + } + /** * @see org.alfasoftware.morf.jdbc.AbstractSqlDialectTest#expectedHints1(int) diff --git a/morf-sqlserver/src/test/java/org/alfasoftware/morf/jdbc/sqlserver/TestSqlServerDialect.java b/morf-sqlserver/src/test/java/org/alfasoftware/morf/jdbc/sqlserver/TestSqlServerDialect.java index ad108868a..d732276ec 100755 --- a/morf-sqlserver/src/test/java/org/alfasoftware/morf/jdbc/sqlserver/TestSqlServerDialect.java +++ b/morf-sqlserver/src/test/java/org/alfasoftware/morf/jdbc/sqlserver/TestSqlServerDialect.java @@ -1235,6 +1235,18 @@ protected List expectedAddTableFromStatements() { ); } + /** + * @see org.alfasoftware.morf.jdbc.AbstractSqlDialectTest#expectedAddTableFromStatementsNullValue() + */ + @Override + protected List expectedAddTableFromStatementsNullValue() { + return ImmutableList.of( + "CREATE TABLE TESTSCHEMA.SomeTable ([someField] NVARCHAR(3) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL, [otherField] NUMERIC(3,0) NOT NULL, [nullField] NVARCHAR(3) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL, CONSTRAINT [SomeTable_PK] PRIMARY KEY ([someField]))", + "CREATE INDEX SomeTable_1 ON TESTSCHEMA.SomeTable ([otherField])", + "INSERT INTO TESTSCHEMA.SomeTable SELECT someField, otherField, null FROM TESTSCHEMA.OtherTable" + ); + } + /** * @see org.alfasoftware.morf.jdbc.AbstractSqlDialectTest#expectedHints1(int) diff --git a/morf-testsupport/src/main/java/org/alfasoftware/morf/jdbc/AbstractSqlDialectTest.java b/morf-testsupport/src/main/java/org/alfasoftware/morf/jdbc/AbstractSqlDialectTest.java index e155bcba1..6d2c1b18a 100755 --- a/morf-testsupport/src/main/java/org/alfasoftware/morf/jdbc/AbstractSqlDialectTest.java +++ b/morf-testsupport/src/main/java/org/alfasoftware/morf/jdbc/AbstractSqlDialectTest.java @@ -33,6 +33,7 @@ import static org.alfasoftware.morf.sql.SqlUtils.insert; import static org.alfasoftware.morf.sql.SqlUtils.literal; import static org.alfasoftware.morf.sql.SqlUtils.merge; +import static org.alfasoftware.morf.sql.SqlUtils.nullLiteral; import static org.alfasoftware.morf.sql.SqlUtils.parameter; import static org.alfasoftware.morf.sql.SqlUtils.select; import static org.alfasoftware.morf.sql.SqlUtils.selectDistinct; @@ -4218,6 +4219,24 @@ public void testAddTableFromStatements() { compareStatements(expectedAddTableFromStatements(), getTestDialect().addTableFromStatements(table, selectStatement)); } + @Test + @SuppressWarnings("unchecked") + public void testAddTableFromStatementsWithNullValue() { + + Table table = table("SomeTable") + .columns( + column("someField", DataType.STRING, 3).primaryKey(), + column("otherField", DataType.DECIMAL, 3), + column("nullField", DataType.STRING, 3) + ).indexes( + index("SomeTable_1").columns("otherField") + ); + + SelectStatement selectStatement = select(field("someField"), field("otherField"), nullLiteral()).from(tableRef("OtherTable")); + + compareStatements(expectedAddTableFromStatementsNullValue(), getTestDialect().addTableFromStatements(table, selectStatement)); + } + /** * On some databases our string literals need prefixing with N to be @@ -5127,6 +5146,7 @@ protected List expectedPreInsertStatementsNotInsertingUnderAutonumLimit( protected abstract List expectedAddTableFromStatements(); + protected abstract List expectedAddTableFromStatementsNullValue(); /** * @return The expected SQL for an insert to Test that inserts an empty string (i.e. NULL).