diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 028c9ba9378ff..1f28952af51a9 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -63,6 +63,7 @@ jobs: - :presto-mongodb -P ci-full-tests - :presto-redis -P ci-full-tests - :presto-elasticsearch + - :presto-oracle -P ci - :presto-orc - :presto-thrift-connector - :presto-spark-base -P presto-spark-tests-smoke diff --git a/presto-oracle/src/main/java/com/facebook/presto/plugin/oracle/OracleClient.java b/presto-oracle/src/main/java/com/facebook/presto/plugin/oracle/OracleClient.java index cfb38c466b78b..b3501639b23d6 100644 --- a/presto-oracle/src/main/java/com/facebook/presto/plugin/oracle/OracleClient.java +++ b/presto-oracle/src/main/java/com/facebook/presto/plugin/oracle/OracleClient.java @@ -15,7 +15,10 @@ import com.facebook.airlift.log.Logger; import com.facebook.presto.common.predicate.TupleDomain; +import com.facebook.presto.common.type.CharType; +import com.facebook.presto.common.type.DecimalType; import com.facebook.presto.common.type.Decimals; +import com.facebook.presto.common.type.Type; import com.facebook.presto.common.type.VarcharType; import com.facebook.presto.plugin.jdbc.BaseJdbcClient; import com.facebook.presto.plugin.jdbc.BaseJdbcConfig; @@ -36,6 +39,7 @@ import com.facebook.presto.spi.statistics.TableStatistics; import com.google.common.collect.Maps; import jakarta.inject.Inject; +import oracle.jdbc.OracleTypes; import java.sql.Connection; import java.sql.DatabaseMetaData; @@ -49,15 +53,24 @@ import java.util.Map; import java.util.Optional; +import static com.facebook.presto.common.type.BigintType.BIGINT; +import static com.facebook.presto.common.type.BooleanType.BOOLEAN; +import static com.facebook.presto.common.type.DateType.DATE; import static com.facebook.presto.common.type.DecimalType.createDecimalType; +import static com.facebook.presto.common.type.DoubleType.DOUBLE; +import static com.facebook.presto.common.type.IntegerType.INTEGER; +import static com.facebook.presto.common.type.RealType.REAL; +import static com.facebook.presto.common.type.TimestampType.TIMESTAMP; import static com.facebook.presto.common.type.VarcharType.createUnboundedVarcharType; import static com.facebook.presto.common.type.VarcharType.createVarcharType; +import static com.facebook.presto.common.type.Varchars.isVarcharType; import static com.facebook.presto.plugin.jdbc.JdbcErrorCode.JDBC_ERROR; import static com.facebook.presto.plugin.jdbc.mapping.StandardColumnMappings.bigintReadMapping; import static com.facebook.presto.plugin.jdbc.mapping.StandardColumnMappings.decimalReadMapping; import static com.facebook.presto.plugin.jdbc.mapping.StandardColumnMappings.doubleReadMapping; import static com.facebook.presto.plugin.jdbc.mapping.StandardColumnMappings.realReadMapping; import static com.facebook.presto.plugin.jdbc.mapping.StandardColumnMappings.smallintReadMapping; +import static com.facebook.presto.plugin.jdbc.mapping.StandardColumnMappings.timestampReadMapping; import static com.facebook.presto.plugin.jdbc.mapping.StandardColumnMappings.varbinaryReadMapping; import static com.facebook.presto.plugin.jdbc.mapping.StandardColumnMappings.varcharReadMapping; import static com.facebook.presto.spi.StandardErrorCode.NOT_SUPPORTED; @@ -257,6 +270,7 @@ public Optional toPrestoType(ConnectorSession session, JdbcTypeHand switch (typeHandle.getJdbcType()) { case Types.CLOB: + case Types.NCLOB: return Optional.of(varcharReadMapping(createUnboundedVarcharType())); case Types.BLOB: return Optional.of(varbinaryReadMapping()); @@ -264,6 +278,7 @@ public Optional toPrestoType(ConnectorSession session, JdbcTypeHand return Optional.of(smallintReadMapping()); case Types.FLOAT: case Types.DOUBLE: + case OracleTypes.BINARY_DOUBLE: return Optional.of(doubleReadMapping()); case Types.REAL: return Optional.of(realReadMapping()); @@ -286,10 +301,64 @@ public Optional toPrestoType(ConnectorSession session, JdbcTypeHand return Optional.of(varcharReadMapping(createVarcharType(columnSize))); case Types.VARCHAR: return Optional.of(varcharReadMapping(createVarcharType(columnSize))); + + /* Note: In Oracle, DATE and TIMESTAMP values are internally stored in the format YYYYMMDD HH24MISS. + * When reading from Oracle to Presto, TIMESTAMP mappings must be used to interpret the values correctly. + * Official documentation: https://docs.oracle.com/en/database/oracle/oracle-database/26/nlspg/datetime-data-types-and-time-zone-support.html#GUID-4D95F6B2-8F28-458A-820D-6C05F848CA23 */ + case Types.DATE: + case Types.TIMESTAMP: + return Optional.of(timestampReadMapping()); } return super.toPrestoType(session, typeHandle); } + @Override + protected String toSqlType(Type type) + { + if (isVarcharType(type)) { + VarcharType varcharType = (VarcharType) type; + if (varcharType.isUnbounded() || varcharType.getLengthSafe() > 1000) { + return "NCLOB"; + } + return format("VARCHAR2(%s CHAR)", varcharType.getLengthSafe()); + } + if (type instanceof CharType) { + CharType charType = (CharType) type; + if (charType.getLength() > 500) { + return "CLOB"; + } + return format("CHAR(%s)", ((CharType) type).getLength()); + } + if (type instanceof DecimalType) { + return format("NUMBER(%s, %s)", + ((DecimalType) type).getPrecision(), + ((DecimalType) type).getScale()); + } + + if (BIGINT.equals(type)) { + return "NUMBER(19)"; + } + if (INTEGER.equals(type)) { + return "NUMBER(10)"; + } + if (DOUBLE.equals(type)) { + return "BINARY_DOUBLE"; + } + if (REAL.equals(type)) { + return "BINARY_FLOAT"; + } + if (BOOLEAN.equals(type)) { + return "NUMBER(1)"; + } + if (DATE.equals(type)) { + return "DATE"; + } + if (TIMESTAMP.equals(type)) { + return "TIMESTAMP"; + } + return super.toSqlType(type); + } + @Override public String normalizeIdentifier(ConnectorSession session, String identifier) { diff --git a/presto-oracle/src/test/java/com/facebook/presto/plugin/oracle/DisabledTestOracleDistributedQueries.java b/presto-oracle/src/test/java/com/facebook/presto/plugin/oracle/DisabledTestOracleDistributedQueries.java deleted file mode 100644 index 7f1c2985ee7d6..0000000000000 --- a/presto-oracle/src/test/java/com/facebook/presto/plugin/oracle/DisabledTestOracleDistributedQueries.java +++ /dev/null @@ -1,187 +0,0 @@ -/* - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.facebook.presto.plugin.oracle; - -import com.facebook.presto.testing.MaterializedResult; -import com.facebook.presto.testing.QueryRunner; -import com.facebook.presto.tests.AbstractTestDistributedQueries; -import io.airlift.tpch.TpchTable; -import org.testng.annotations.AfterClass; -import org.testng.annotations.Optional; -import org.testng.annotations.Test; - -import static com.facebook.presto.common.type.VarcharType.VARCHAR; -import static com.facebook.presto.plugin.oracle.OracleQueryRunner.createOracleQueryRunner; -import static com.facebook.presto.testing.MaterializedResult.resultBuilder; -import static com.facebook.presto.testing.assertions.Assert.assertEquals; -import static java.lang.String.format; -import static java.util.stream.Collectors.joining; -import static java.util.stream.IntStream.range; -import static org.testng.Assert.assertFalse; -import static org.testng.Assert.assertTrue; - -// Disabled for 7.5 TestNG Upgrade, the constructor takes in parameter -// TestNG 6 silently ignored, TestNG 7.5 fails (correctly), disabling for now -public class DisabledTestOracleDistributedQueries - extends AbstractTestDistributedQueries -{ - private final OracleServerTester oracleServer; - private final QueryRunner queryRunner; - - protected DisabledTestOracleDistributedQueries(OracleServerTester oracleServer) - throws Exception - { - this.queryRunner = createOracleQueryRunner(oracleServer, TpchTable.getTables()); - this.oracleServer = new OracleServerTester(); - } - - @Override - protected QueryRunner createQueryRunner() - throws Exception - { - return queryRunner; - } - - @AfterClass(alwaysRun = true) - public final void destroy() - { - if (oracleServer != null) { - oracleServer.close(); - } - } - - @Override - protected boolean supportsViews() - { - return false; - } - - @Test - @Override - public void testLargeIn() - { - int numberOfElements = 1000; - String longValues = range(0, numberOfElements) - .mapToObj(Integer::toString) - .collect(joining(", ")); - assertQuery("SELECT orderkey FROM orders WHERE orderkey IN (" + longValues + ")"); - assertQuery("SELECT orderkey FROM orders WHERE orderkey NOT IN (" + longValues + ")"); - - assertQuery("SELECT orderkey FROM orders WHERE orderkey IN (mod(1000, orderkey), " + longValues + ")"); - assertQuery("SELECT orderkey FROM orders WHERE orderkey NOT IN (mod(1000, orderkey), " + longValues + ")"); - - String arrayValues = range(0, numberOfElements) - .mapToObj(i -> format("ARRAY[%s, %s, %s]", i, i + 1, i + 2)) - .collect(joining(", ")); - assertQuery("SELECT ARRAY[0, 0, 0] in (ARRAY[0, 0, 0], " + arrayValues + ")", "values true"); - assertQuery("SELECT ARRAY[0, 0, 0] in (" + arrayValues + ")", "values false"); - } - - @Test - @Override - public void testCreateTable() - { - assertUpdate("CREATE TABLE test_create (a bigint, b double, c varchar)"); - assertTrue(getQueryRunner().tableExists(getSession(), "test_create")); - assertTableColumnNames("test_create", "a", "b", "c"); - - assertUpdate("DROP TABLE test_create"); - assertFalse(getQueryRunner().tableExists(getSession(), "test_create")); - - assertQueryFails("CREATE TABLE test_create (a bad_type)", ".* Unknown type 'bad_type' for column 'a'"); - assertFalse(getQueryRunner().tableExists(getSession(), "test_create")); - - // Replace test_create_table_if_not_exists with test_create_table_if_not_exist to fetch max size naming on oracle - assertUpdate("CREATE TABLE test_create_table_if_not_exist (a bigint, b varchar, c double)"); - assertTrue(getQueryRunner().tableExists(getSession(), "test_create_table_if_not_exist")); - assertTableColumnNames("test_create_table_if_not_exist", "a", "b", "c"); - - assertUpdate("CREATE TABLE IF NOT EXISTS test_create_table_if_not_exist (d bigint, e varchar)"); - assertTrue(getQueryRunner().tableExists(getSession(), "test_create_table_if_not_exist")); - assertTableColumnNames("test_create_table_if_not_exist", "a", "b", "c"); - - assertUpdate("DROP TABLE test_create_table_if_not_exist"); - assertFalse(getQueryRunner().tableExists(getSession(), "test_create_table_if_not_exist")); - - // Test CREATE TABLE LIKE - assertUpdate("CREATE TABLE test_create_original (a bigint, b double, c varchar)"); - assertTrue(getQueryRunner().tableExists(getSession(), "test_create_original")); - assertTableColumnNames("test_create_original", "a", "b", "c"); - - assertUpdate("CREATE TABLE test_create_like (LIKE test_create_original, d boolean, e varchar)"); - assertTrue(getQueryRunner().tableExists(getSession(), "test_create_like")); - assertTableColumnNames("test_create_like", "a", "b", "c", "d", "e"); - - assertUpdate("DROP TABLE test_create_original"); - assertFalse(getQueryRunner().tableExists(getSession(), "test_create_original")); - - assertUpdate("DROP TABLE test_create_like"); - assertFalse(getQueryRunner().tableExists(getSession(), "test_create_like")); - } - - @Test - @Override - public void testSymbolAliasing() - { - // Replace tablename to less than 30chars, max size naming on oracle - String tableName = "symbol_aliasing" + System.currentTimeMillis(); - assertUpdate("CREATE TABLE " + tableName + " AS SELECT 1 foo_1, 2 foo_2_4", 1); - assertQuery("SELECT foo_1, foo_2_4 FROM " + tableName, "SELECT 1, 2"); - assertUpdate("DROP TABLE " + tableName); - } - - @Test - @Override - public void testRenameColumn() - { - // Replace tablename to less than 30chars, max size naming on oracle - String tableName = "test_renamecol_" + System.currentTimeMillis(); - assertUpdate("CREATE TABLE " + tableName + " AS SELECT 'some value' x", 1); - - assertUpdate("ALTER TABLE " + tableName + " RENAME COLUMN x TO y"); - assertQuery("SELECT y FROM " + tableName, "VALUES 'some value'"); - - assertUpdate("ALTER TABLE " + tableName + " RENAME COLUMN y TO Z"); // 'Z' is upper-case, not delimited - assertQuery( - "SELECT z FROM " + tableName, // 'z' is lower-case, not delimited - "VALUES 'some value'"); - - // There should be exactly one column - assertQuery("SELECT * FROM " + tableName, "VALUES 'some value'"); - - assertUpdate("DROP TABLE " + tableName); - } - - @Test - @Override - public void testShowColumns(@Optional("PARQUET") String storageFormat) - { - MaterializedResult actual = computeActual("SHOW COLUMNS FROM orders"); - - MaterializedResult expectedParametrizedVarchar = resultBuilder(getSession(), VARCHAR, VARCHAR, VARCHAR, VARCHAR) - .row("orderkey", "bigint", "", "") - .row("custkey", "bigint", "", "") - .row("orderstatus", "varchar(1)", "", "") - .row("totalprice", "double", "", "") - .row("orderdate", "timestamp", "", "") - .row("orderpriority", "varchar(15)", "", "") - .row("clerk", "varchar(15)", "", "") - .row("shippriority", "bigint", "", "") - .row("comment", "varchar(79)", "", "") - .build(); - - // Until we migrate all connectors to parametrized varchar we check two options - assertEquals(actual, expectedParametrizedVarchar, format("%s does not matches %s", actual, expectedParametrizedVarchar)); - } -} diff --git a/presto-oracle/src/test/java/com/facebook/presto/plugin/oracle/TestOracleDistributedQueries.java b/presto-oracle/src/test/java/com/facebook/presto/plugin/oracle/TestOracleDistributedQueries.java new file mode 100644 index 0000000000000..14f409818b577 --- /dev/null +++ b/presto-oracle/src/test/java/com/facebook/presto/plugin/oracle/TestOracleDistributedQueries.java @@ -0,0 +1,583 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.facebook.presto.plugin.oracle; + +import com.facebook.presto.Session; +import com.facebook.presto.testing.MaterializedResult; +import com.facebook.presto.testing.QueryRunner; +import com.facebook.presto.tests.AbstractTestDistributedQueries; +import io.airlift.tpch.TpchTable; +import org.intellij.lang.annotations.Language; +import org.testng.annotations.AfterClass; +import org.testng.annotations.Optional; +import org.testng.annotations.Test; + +import static com.facebook.presto.SystemSessionProperties.ITERATIVE_OPTIMIZER_TIMEOUT; +import static com.facebook.presto.SystemSessionProperties.JOIN_DISTRIBUTION_TYPE; +import static com.facebook.presto.SystemSessionProperties.JOIN_REORDERING_STRATEGY; +import static com.facebook.presto.SystemSessionProperties.LEGACY_TIMESTAMP; +import static com.facebook.presto.SystemSessionProperties.OPTIMIZER_USE_HISTOGRAMS; +import static com.facebook.presto.SystemSessionProperties.REDISTRIBUTE_WRITES; +import static com.facebook.presto.SystemSessionProperties.SHARDED_JOINS_STRATEGY; +import static com.facebook.presto.common.type.BigintType.BIGINT; +import static com.facebook.presto.common.type.VarcharType.VARCHAR; +import static com.facebook.presto.plugin.oracle.OracleQueryRunner.createOracleQueryRunner; +import static com.facebook.presto.testing.MaterializedResult.resultBuilder; +import static com.facebook.presto.testing.assertions.Assert.assertEquals; +import static com.google.common.collect.Iterables.getOnlyElement; +import static java.lang.String.format; +import static java.util.stream.Collectors.joining; +import static java.util.stream.IntStream.range; +import static org.testng.Assert.assertFalse; +import static org.testng.Assert.assertNull; +import static org.testng.Assert.assertTrue; + +public class TestOracleDistributedQueries + extends AbstractTestDistributedQueries +{ + private final OracleServerTester oracleServer; + private final QueryRunner queryRunner; + + protected TestOracleDistributedQueries() + throws Exception + { + this.oracleServer = new OracleServerTester(); + this.queryRunner = createOracleQueryRunner(oracleServer, TpchTable.getTables()); + } + + @Override + protected QueryRunner createQueryRunner() + throws Exception + { + return queryRunner; + } + + @AfterClass(alwaysRun = true) + public final void destroy() + { + if (oracleServer != null) { + oracleServer.close(); + } + } + + @Override + protected boolean supportsViews() + { + return false; + } + + @Override + protected boolean isLegacyTimestampEnabled() + { + return false; + } + + @Test + @Override + public void testLargeIn() + { + int numberOfElements = 1000; + String longValues = range(0, numberOfElements) + .mapToObj(Integer::toString) + .collect(joining(", ")); + assertQuery("SELECT orderkey FROM orders WHERE orderkey IN (" + longValues + ")"); + assertQuery("SELECT orderkey FROM orders WHERE orderkey NOT IN (" + longValues + ")"); + + assertQuery("SELECT orderkey FROM orders WHERE orderkey IN (mod(1000, orderkey), " + longValues + ")"); + assertQuery("SELECT orderkey FROM orders WHERE orderkey NOT IN (mod(1000, orderkey), " + longValues + ")"); + + String arrayValues = range(0, numberOfElements) + .mapToObj(i -> format("ARRAY[%s, %s, %s]", i, i + 1, i + 2)) + .collect(joining(", ")); + assertQuery("SELECT ARRAY[0, 0, 0] in (ARRAY[0, 0, 0], " + arrayValues + ")", "values true"); + assertQuery("SELECT ARRAY[0, 0, 0] in (" + arrayValues + ")", "values false"); + } + + @Test + @Override + public void testCreateTable() + { + assertUpdate("CREATE TABLE test_create (a bigint, b double, c varchar)"); + assertTrue(getQueryRunner().tableExists(getSession(), "test_create")); + assertTableColumnNames("test_create", "a", "b", "c"); + + assertUpdate("DROP TABLE test_create"); + assertFalse(getQueryRunner().tableExists(getSession(), "test_create")); + + assertQueryFails("CREATE TABLE test_create (a bad_type)", ".* Unknown type 'bad_type' for column 'a'"); + assertFalse(getQueryRunner().tableExists(getSession(), "test_create")); + + // Replace test_create_table_if_not_exists with test_create_table_if_not_exist to fetch max size naming on oracle + assertUpdate("CREATE TABLE test_create_table_if_not_exist (a bigint, b varchar, c double)"); + assertTrue(getQueryRunner().tableExists(getSession(), "test_create_table_if_not_exist")); + assertTableColumnNames("test_create_table_if_not_exist", "a", "b", "c"); + + assertUpdate("CREATE TABLE IF NOT EXISTS test_create_table_if_not_exist (d bigint, e varchar)"); + assertTrue(getQueryRunner().tableExists(getSession(), "test_create_table_if_not_exist")); + assertTableColumnNames("test_create_table_if_not_exist", "a", "b", "c"); + + assertUpdate("DROP TABLE test_create_table_if_not_exist"); + assertFalse(getQueryRunner().tableExists(getSession(), "test_create_table_if_not_exist")); + + // Test CREATE TABLE LIKE + assertUpdate("CREATE TABLE test_create_original (a bigint, b double, c varchar)"); + assertTrue(getQueryRunner().tableExists(getSession(), "test_create_original")); + assertTableColumnNames("test_create_original", "a", "b", "c"); + + assertUpdate("CREATE TABLE test_create_like (LIKE test_create_original, d boolean, e varchar)"); + assertTrue(getQueryRunner().tableExists(getSession(), "test_create_like")); + assertTableColumnNames("test_create_like", "a", "b", "c", "d", "e"); + + assertUpdate("DROP TABLE test_create_original"); + assertFalse(getQueryRunner().tableExists(getSession(), "test_create_original")); + + assertUpdate("DROP TABLE test_create_like"); + assertFalse(getQueryRunner().tableExists(getSession(), "test_create_like")); + } + + @Test + @Override + public void testSymbolAliasing() + { + // Replace tablename to less than 30chars, max size naming on oracle + String tableName = "symbol_aliasing" + System.currentTimeMillis(); + assertUpdate("CREATE TABLE " + tableName + " AS SELECT 1 foo_1, 2 foo_2_4", 1); + assertQuery("SELECT foo_1, foo_2_4 FROM " + tableName, "SELECT 1, 2"); + assertUpdate("DROP TABLE " + tableName); + } + + @Test + @Override + public void testRenameColumn() + { + // Replace tablename to less than 30chars, max size naming on oracle + String tableName = "test_renamecol_" + System.currentTimeMillis(); + assertUpdate("CREATE TABLE " + tableName + " AS SELECT 'some value' x", 1); + + assertUpdate("ALTER TABLE " + tableName + " RENAME COLUMN x TO y"); + assertQuery("SELECT y FROM " + tableName, "VALUES 'some value'"); + + assertUpdate("ALTER TABLE " + tableName + " RENAME COLUMN y TO Z"); // 'Z' is upper-case, not delimited + assertQuery( + "SELECT z FROM " + tableName, // 'z' is lower-case, not delimited + "VALUES 'some value'"); + + // There should be exactly one column + assertQuery("SELECT * FROM " + tableName, "VALUES 'some value'"); + + assertUpdate("DROP TABLE " + tableName); + } + + @Test + @Override + public void testShowColumns(@Optional("PARQUET") String storageFormat) + { + MaterializedResult actual = computeActual("SHOW COLUMNS FROM orders"); + + ///Added Literal 'L' suffix to match expected values. + MaterializedResult expectedParametrizedVarchar = resultBuilder(getSession(), VARCHAR, VARCHAR, VARCHAR, VARCHAR, BIGINT, BIGINT, BIGINT) + .row("orderkey", "bigint", "", "", 19L, null, null) + .row("custkey", "bigint", "", "", 19L, null, null) + .row("orderstatus", "varchar(1)", "", "", null, null, 1L) + .row("totalprice", "double", "", "", 53L, null, null) + .row("orderdate", "timestamp", "", "", null, null, null) + .row("orderpriority", "varchar(15)", "", "", null, null, 15L) + .row("clerk", "varchar(15)", "", "", null, null, 15L) + .row("shippriority", "bigint", "", "", 19L, null, null) + .row("comment", "varchar(79)", "", "", null, null, 79L) + .build(); + + // Until we migrate all connectors to parametrized varchar we check two options + assertEquals(actual, expectedParametrizedVarchar, format("%s does not matches %s", actual, expectedParametrizedVarchar)); + } + + @Test + @Override + public void testNonAutoCommitTransactionWithCommit() + { + //Catalog oracle only supports writes using autocommit + } + + @Test + @Override + public void testNonAutoCommitTransactionWithRollback() + { + //Catalog oracle only supports writes using autocommit + } + + @Test + @Override + public void testDelete() + { + //This connector does not support deletes + } + + @Test + @Override + public void testAddColumn() + { + ///Added Literal 'L' suffix to match expected values. + assertUpdate("CREATE TABLE test_add_column AS SELECT 123 x", 1); + assertUpdate("CREATE TABLE test_add_column_a AS SELECT 234 x, 111 a", 1); + assertUpdate("CREATE TABLE test_add_column_ab AS SELECT 345 x, 222 a, 33.3E0 b", 1); + assertUpdate("CREATE TABLE test_add_column_abc AS SELECT 456 x, 333 a, 66.6E0 b, 'fourth' c", 1); + + assertQueryFails("ALTER TABLE test_add_column ADD COLUMN x bigint", ".* Column 'x' already exists"); + assertQueryFails("ALTER TABLE test_add_column ADD COLUMN X bigint", ".* Column 'X' already exists"); + assertQueryFails("ALTER TABLE test_add_column ADD COLUMN q bad_type", ".* Unknown type 'bad_type' for column 'q'"); + + assertUpdate("ALTER TABLE test_add_column ADD COLUMN a bigint"); + assertUpdate("INSERT INTO test_add_column SELECT * FROM test_add_column_a", 1); + MaterializedResult materializedRows = computeActual("SELECT x, a FROM test_add_column ORDER BY x"); + assertEquals(materializedRows.getMaterializedRows().get(0).getField(0), 123L); + assertNull(materializedRows.getMaterializedRows().get(0).getField(1)); + assertEquals(materializedRows.getMaterializedRows().get(1).getField(0), 234L); + assertEquals(materializedRows.getMaterializedRows().get(1).getField(1), 111L); + + assertUpdate("ALTER TABLE test_add_column ADD COLUMN b double"); + assertUpdate("INSERT INTO test_add_column SELECT * FROM test_add_column_ab", 1); + materializedRows = computeActual("SELECT x, a, b FROM test_add_column ORDER BY x"); + assertEquals(materializedRows.getMaterializedRows().get(0).getField(0), 123L); + assertNull(materializedRows.getMaterializedRows().get(0).getField(1)); + assertNull(materializedRows.getMaterializedRows().get(0).getField(2)); + assertEquals(materializedRows.getMaterializedRows().get(1).getField(0), 234L); + assertEquals(materializedRows.getMaterializedRows().get(1).getField(1), 111L); + assertNull(materializedRows.getMaterializedRows().get(1).getField(2)); + assertEquals(materializedRows.getMaterializedRows().get(2).getField(0), 345L); + assertEquals(materializedRows.getMaterializedRows().get(2).getField(1), 222L); + assertEquals(materializedRows.getMaterializedRows().get(2).getField(2), 33.3); + + assertUpdate("ALTER TABLE test_add_column ADD COLUMN IF NOT EXISTS c varchar"); + assertUpdate("ALTER TABLE test_add_column ADD COLUMN IF NOT EXISTS c varchar"); + assertUpdate("INSERT INTO test_add_column SELECT * FROM test_add_column_abc", 1); + materializedRows = computeActual("SELECT x, a, b, c FROM test_add_column ORDER BY x"); + assertEquals(materializedRows.getMaterializedRows().get(0).getField(0), 123L); + assertNull(materializedRows.getMaterializedRows().get(0).getField(1)); + assertNull(materializedRows.getMaterializedRows().get(0).getField(2)); + assertNull(materializedRows.getMaterializedRows().get(0).getField(3)); + assertEquals(materializedRows.getMaterializedRows().get(1).getField(0), 234L); + assertEquals(materializedRows.getMaterializedRows().get(1).getField(1), 111L); + assertNull(materializedRows.getMaterializedRows().get(1).getField(2)); + assertNull(materializedRows.getMaterializedRows().get(1).getField(3)); + assertEquals(materializedRows.getMaterializedRows().get(2).getField(0), 345L); + assertEquals(materializedRows.getMaterializedRows().get(2).getField(1), 222L); + assertEquals(materializedRows.getMaterializedRows().get(2).getField(2), 33.3); + assertNull(materializedRows.getMaterializedRows().get(2).getField(3)); + assertEquals(materializedRows.getMaterializedRows().get(3).getField(0), 456L); + assertEquals(materializedRows.getMaterializedRows().get(3).getField(1), 333L); + assertEquals(materializedRows.getMaterializedRows().get(3).getField(2), 66.6); + assertEquals(materializedRows.getMaterializedRows().get(3).getField(3), "fourth"); + + assertUpdate("DROP TABLE test_add_column"); + assertUpdate("DROP TABLE test_add_column_a"); + assertUpdate("DROP TABLE test_add_column_ab"); + assertUpdate("DROP TABLE test_add_column_abc"); + assertFalse(getQueryRunner().tableExists(getSession(), "test_add_column")); + assertFalse(getQueryRunner().tableExists(getSession(), "test_add_column_a")); + assertFalse(getQueryRunner().tableExists(getSession(), "test_add_column_ab")); + assertFalse(getQueryRunner().tableExists(getSession(), "test_add_column_abc")); + + assertUpdate("ALTER TABLE IF EXISTS test_add_column ADD COLUMN x bigint"); + assertUpdate("ALTER TABLE IF EXISTS test_add_column ADD COLUMN IF NOT EXISTS x bigint"); + assertFalse(getQueryRunner().tableExists(getSession(), "test_add_column")); + } + + @Override + public void testUpdate() + { + // Updates are not supported by the connector + } + @Override + public void testPayloadJoinApplicability() + { + // no op -- test not supported due to lack of support for map(integer, integer) column type. + } + + @Override + public void testPayloadJoinCorrectness() + { + // no op -- test not supported due to lack of support for map(integer, integer) column type. + } + + @Override + public void testRemoveRedundantCastToVarcharInJoinClause() + { + // no op -- test not supported due to lack of support for map(integer, integer) column type. + } + + @Override + public void testSubfieldAccessControl() + { + // no op -- test not supported due to lack of support for column type: row("f1" integer, "f2" integer, "f3" array(row("ff1" integer, "ff2" integer))). + } + + @Override + public void testRenameTable() + { + // Added Literal 'L' suffix to match expected values. + assertUpdate("CREATE TABLE test_rename AS SELECT 123 x", 1); + + assertUpdate("ALTER TABLE test_rename RENAME TO test_rename_new"); + MaterializedResult materializedRows = computeActual("SELECT x FROM test_rename_new"); + assertEquals(getOnlyElement(materializedRows.getMaterializedRows()).getField(0), 123L); + + assertUpdate("ALTER TABLE IF EXISTS test_rename_new RENAME TO test_rename"); + materializedRows = computeActual("SELECT x FROM test_rename"); + assertEquals(getOnlyElement(materializedRows.getMaterializedRows()).getField(0), 123L); + + assertUpdate("ALTER TABLE IF EXISTS test_rename RENAME TO test_rename_new"); + materializedRows = computeActual("SELECT x FROM test_rename_new"); + assertEquals(getOnlyElement(materializedRows.getMaterializedRows()).getField(0), 123L); + + // provide new table name in uppercase + assertUpdate("ALTER TABLE test_rename_new RENAME TO TEST_RENAME"); + materializedRows = computeActual("SELECT x FROM test_rename"); + assertEquals(getOnlyElement(materializedRows.getMaterializedRows()).getField(0), 123L); + + assertUpdate("DROP TABLE test_rename"); + + assertFalse(getQueryRunner().tableExists(getSession(), "test_rename")); + assertFalse(getQueryRunner().tableExists(getSession(), "test_rename_new")); + + assertUpdate("ALTER TABLE IF EXISTS test_rename RENAME TO test_rename_new"); + assertFalse(getQueryRunner().tableExists(getSession(), "test_rename")); + assertFalse(getQueryRunner().tableExists(getSession(), "test_rename_new")); + } + + @Override + public void testInsert() + { + Session session = sessionWithLegacyTimestamp(); + @Language("SQL") String query = "SELECT orderdate, orderkey, totalprice FROM orders"; + + assertUpdate(session, "CREATE TABLE test_insert AS " + query + " WITH NO DATA", 0); + assertQuery(session, "SELECT count(*) FROM test_insert", "SELECT 0"); + + assertUpdate(session, "INSERT INTO test_insert " + query, "SELECT count(*) FROM orders"); + + assertQuery(session, "SELECT * FROM test_insert", query); + + assertUpdate(session, "INSERT INTO test_insert (orderkey) VALUES (-1)", 1); + assertUpdate(session, "INSERT INTO test_insert (orderkey) VALUES (null)", 1); + assertUpdate(session, "INSERT INTO test_insert (orderdate) VALUES (DATE '2001-01-01')", 1); + assertUpdate(session, "INSERT INTO test_insert (orderkey, orderdate) VALUES (-2, DATE '2001-01-02')", 1); + assertUpdate(session, "INSERT INTO test_insert (orderdate, orderkey) VALUES (DATE '2001-01-03', -3)", 1); + assertUpdate(session, "INSERT INTO test_insert (totalprice) VALUES (1234)", 1); + + assertQuery(session, "SELECT * FROM test_insert", query + + " UNION ALL SELECT null, -1, null" + + " UNION ALL SELECT null, null, null" + + " UNION ALL SELECT DATE '2001-01-01', null, null" + + " UNION ALL SELECT DATE '2001-01-02', -2, null" + + " UNION ALL SELECT DATE '2001-01-03', -3, null" + + " UNION ALL SELECT null, null, 1234"); + + // UNION query produces columns in the opposite order + // of how they are declared in the table schema + assertUpdate(session, + "INSERT INTO test_insert (orderkey, orderdate, totalprice) " + + "SELECT orderkey, orderdate, totalprice FROM orders " + + "UNION ALL " + + "SELECT orderkey, orderdate, totalprice FROM orders", + "SELECT 2 * count(*) FROM orders"); + + assertUpdate(session, "DROP TABLE test_insert"); + + // Refactored the code because of Unsupported column type: array(double) + assertUpdate(session, "CREATE TABLE test_insert (a DOUBLE, b BIGINT)"); + + assertUpdate(session, "INSERT INTO test_insert (a) VALUES (null)", 1); + assertUpdate(session, "INSERT INTO test_insert (a) VALUES (1234)", 1); + assertQuery(session, "SELECT a FROM test_insert", "VALUES (null), (1234)"); + + assertQueryFails(session, "INSERT INTO test_insert (b) VALUES (1.23E1)", "line 1:37: Mismatch at column 1.*"); + + assertUpdate(session, "DROP TABLE test_insert"); + } + + @Override + public void testStringFilters() + { + // For CHAR(10), values are padded with spaces; shipmode = 'AIR' compares exact and returns 0 if trailing spaces exist. + // Using TRIM(shipmode) = 'AIR' removes trailing/leading spaces, matching Oracle CHAR behavior and returning the correct count. + assertUpdate("CREATE TABLE test_charn_filter (shipmode CHAR(10))"); + assertTrue(getQueryRunner().tableExists(getSession(), "test_charn_filter")); + assertTableColumnNames("test_charn_filter", "shipmode"); + assertUpdate("INSERT INTO test_charn_filter SELECT shipmode FROM lineitem", 60175); + + assertQuery("SELECT count(*) FROM test_charn_filter WHERE TRIM(shipmode) = 'AIR'", "VALUES (8491)"); + assertQuery("SELECT count(*) FROM test_charn_filter WHERE TRIM(shipmode) = 'AIR '", "VALUES (8491)"); + assertQuery("SELECT count(*) FROM test_charn_filter WHERE TRIM(shipmode) = 'AIR '", "VALUES (8491)"); + assertQuery("SELECT count(*) FROM test_charn_filter WHERE TRIM(shipmode) = 'AIR '", "VALUES (8491)"); + assertQuery("SELECT count(*) FROM test_charn_filter WHERE shipmode = 'NONEXIST'", "VALUES (0)"); + + assertUpdate("CREATE TABLE test_varcharn_filter (shipmode VARCHAR(10))"); + assertTrue(getQueryRunner().tableExists(getSession(), "test_varcharn_filter")); + assertTableColumnNames("test_varcharn_filter", "shipmode"); + assertUpdate("INSERT INTO test_varcharn_filter SELECT shipmode FROM lineitem", 60175); + + assertQuery("SELECT count(*) FROM test_varcharn_filter WHERE shipmode = 'AIR'", "VALUES (8491)"); + assertQuery("SELECT count(*) FROM test_varcharn_filter WHERE shipmode = 'AIR '", "VALUES (0)"); + assertQuery("SELECT count(*) FROM test_varcharn_filter WHERE shipmode = 'AIR '", "VALUES (0)"); + assertQuery("SELECT count(*) FROM test_varcharn_filter WHERE shipmode = 'AIR '", "VALUES (0)"); + assertQuery("SELECT count(*) FROM test_varcharn_filter WHERE shipmode = 'NONEXIST'", "VALUES (0)"); + } + + @Override + public void testCreateTableAsSelect() + { + // Setting session property 'LEGACY_TIMESTAMP' to 'false' for fixing timestamp mapping errors between expected and actual values. + Session session = Session.builder(getSession()) + .setSystemProperty(LEGACY_TIMESTAMP, "false") + .setSystemProperty(REDISTRIBUTE_WRITES, "false") + .build(); + + assertUpdate("CREATE TABLE IF NOT EXISTS test_ctas AS SELECT name, regionkey FROM nation", "SELECT count(*) FROM nation"); + assertTableColumnNames("test_ctas", "name", "regionkey"); + assertUpdate("DROP TABLE test_ctas"); + + // Some connectors support CREATE TABLE AS but not the ordinary CREATE TABLE. Let's test CTAS IF NOT EXISTS with a table that is guaranteed to exist. + assertUpdate("CREATE TABLE IF NOT EXISTS nation AS SELECT orderkey, discount FROM lineitem", 0); + assertTableColumnNames("nation", "nationkey", "name", "regionkey", "comment"); + + assertCreateTableAsSelect(session, + "test_select", + "SELECT orderdate, orderkey, totalprice FROM orders", + "SELECT count(*) FROM orders"); + + assertCreateTableAsSelect( + "test_group", + "SELECT orderstatus, sum(totalprice) x FROM orders GROUP BY orderstatus", + "SELECT count(DISTINCT orderstatus) FROM orders"); + + assertCreateTableAsSelect( + "test_join", + "SELECT count(*) x FROM lineitem JOIN orders ON lineitem.orderkey = orders.orderkey", + "SELECT 1"); + + assertCreateTableAsSelect( + "test_limit", + "SELECT orderkey FROM orders ORDER BY orderkey LIMIT 10", + "SELECT 10"); + + // Overriding the test : assertCreateTableAsSelect("test_unicode"). + //com.facebook.presto.spi.PrestoException: ORA-12899: value too large for column + + assertCreateTableAsSelect(session, + "test_with_data", + "SELECT * FROM orders WITH DATA", + "SELECT * FROM orders", + "SELECT count(*) FROM orders"); + + assertCreateTableAsSelect(session, + "test_with_no_data", + "SELECT * FROM orders WITH NO DATA", + "SELECT * FROM orders LIMIT 0", + "SELECT 0"); + + // Tests for CREATE TABLE with UNION ALL: exercises PushTableWriteThroughUnion optimizer + + assertCreateTableAsSelect(session, + "test_union_all", + "SELECT orderdate, orderkey, totalprice FROM orders WHERE orderkey % 2 = 0 UNION ALL " + + "SELECT orderdate, orderkey, totalprice FROM orders WHERE orderkey % 2 = 1", + "SELECT orderdate, orderkey, totalprice FROM orders", + "SELECT count(*) FROM orders"); + + assertCreateTableAsSelect(session, + "test_union_all", + "SELECT CAST(orderdate AS DATE) orderdate, orderkey, totalprice FROM orders UNION ALL " + + "SELECT DATE '2000-01-01', 1234567890, 1.23", + "SELECT orderdate, orderkey, totalprice FROM orders UNION ALL " + + "SELECT DATE '2000-01-01', 1234567890, 1.23", + "SELECT count(*) + 1 FROM orders"); + + assertCreateTableAsSelect(session, + "test_union_all", + "SELECT CAST(orderdate AS DATE) orderdate, orderkey, totalprice FROM orders UNION ALL " + + "SELECT DATE '2000-01-01', 1234567890, 1.23", + "SELECT orderdate, orderkey, totalprice FROM orders UNION ALL " + + "SELECT DATE '2000-01-01', 1234567890, 1.23", + "SELECT count(*) + 1 FROM orders"); + + assertExplainAnalyze("EXPLAIN ANALYZE CREATE TABLE analyze_test AS SELECT orderstatus FROM orders"); + assertQuery("SELECT * from analyze_test", "SELECT orderstatus FROM orders"); + assertUpdate("DROP TABLE analyze_test"); + } + + @Override + public void testInsertIntoNotNullColumn() + { + //When writing to Oracle, the value is stored as a DATE type, but while reading from Oracle to Presto, DATE includes both date and time components and hence read as a TIMESTAMP in Presto. + //Link to the documentation : https://docs.oracle.com/en/database/oracle/oracle-database/26/nlspg/datetime-data-types-and-time-zone-support.html#GUID-4D95F6B2-8F28-458A-820D-6C05F848CA23 + } + + @Override + public void testLargeInWithHistograms() + { + //Changing variable(longvalues) range to avoid ORA-01795: maximum number of expressions in a list is 1000. + String longValues = range(0, 1000) + .mapToObj(Integer::toString) + .collect(joining(", ")); + String query = "select orderpriority, sum(totalprice) from lineitem join orders on lineitem.orderkey = orders.orderkey where orders.orderkey in (" + longValues + ") group by 1"; + Session session = Session.builder(getSession()) + .setSystemProperty(ITERATIVE_OPTIMIZER_TIMEOUT, "30000ms") + .setSystemProperty(OPTIMIZER_USE_HISTOGRAMS, "true") + .build(); + assertQuerySucceeds(session, query); + session = Session.builder(getSession()) + .setSystemProperty(ITERATIVE_OPTIMIZER_TIMEOUT, "20000ms") + .setSystemProperty(OPTIMIZER_USE_HISTOGRAMS, "false") + .build(); + assertQuerySucceeds(session, query); + } + + @Override + public void testShardedJoinOptimization() + { + Session defaultSession = getSession(); + Session defaultSessionLegacyTimestampDisabled = sessionWithLegacyTimestamp(); + + Session session = Session.builder(defaultSession) + .setSystemProperty(SHARDED_JOINS_STRATEGY, "ALWAYS") + .setSystemProperty(JOIN_REORDERING_STRATEGY, "NONE") + .setSystemProperty(JOIN_DISTRIBUTION_TYPE, "PARTITIONED") + .setSystemProperty(LEGACY_TIMESTAMP, "false") + .build(); + + String[] queries = { + "select * from lineitem l join orders o on (l.orderkey=o.orderkey)", + "select * from lineitem l join orders o on (l.orderkey=o.orderkey) join part p on (l.partkey=p.partkey)", + "select * from lineitem l LEFT JOIN orders o on (l.orderkey=o.orderkey)" + }; + + for (String query : queries) { + MaterializedResult resultExplainQuery = computeActual(session, "EXPLAIN " + query); + assert (((String) resultExplainQuery.getOnlyValue()).contains("random")); + assertQuery(session, query); + } + + String[] notSupportedQueries = { + "select * from lineitem l right join orders o on (l.orderkey=o.orderkey)", + "select * from lineitem l full join orders o on (l.orderkey=o.orderkey)" + }; + + for (String query : notSupportedQueries) { + MaterializedResult resultExplainQuery = computeActual(session, "EXPLAIN " + query); + assert (!((String) resultExplainQuery.getOnlyValue()).contains("random")); + + assertQueryWithSameQueryRunner(session, query, defaultSessionLegacyTimestampDisabled); + } + } +} diff --git a/presto-oracle/src/test/java/com/facebook/presto/plugin/oracle/DisabledTestOracleIntegrationSmokeTest.java b/presto-oracle/src/test/java/com/facebook/presto/plugin/oracle/TestOracleIntegrationSmokeTest.java similarity index 67% rename from presto-oracle/src/test/java/com/facebook/presto/plugin/oracle/DisabledTestOracleIntegrationSmokeTest.java rename to presto-oracle/src/test/java/com/facebook/presto/plugin/oracle/TestOracleIntegrationSmokeTest.java index 700465d6d178d..937ca314d0e67 100644 --- a/presto-oracle/src/test/java/com/facebook/presto/plugin/oracle/DisabledTestOracleIntegrationSmokeTest.java +++ b/presto-oracle/src/test/java/com/facebook/presto/plugin/oracle/TestOracleIntegrationSmokeTest.java @@ -17,26 +17,24 @@ import com.facebook.presto.testing.QueryRunner; import com.facebook.presto.tests.AbstractTestIntegrationSmokeTest; import org.testng.annotations.AfterClass; -import org.testng.annotations.Test; +import static com.facebook.presto.common.type.BigintType.BIGINT; import static com.facebook.presto.common.type.VarcharType.VARCHAR; import static com.facebook.presto.plugin.oracle.OracleQueryRunner.createOracleQueryRunner; import static com.facebook.presto.testing.assertions.Assert.assertEquals; import static io.airlift.tpch.TpchTable.ORDERS; -// Disabled for 7.5 TestNG Upgrade, the constructor takes in parameter -// TestNG 6 silently ignored, TestNG 7.5 fails (correctly), disabling for now -public class DisabledTestOracleIntegrationSmokeTest +public class TestOracleIntegrationSmokeTest extends AbstractTestIntegrationSmokeTest { private final OracleServerTester oracleServer; private QueryRunner queryRunner; - protected DisabledTestOracleIntegrationSmokeTest(OracleServerTester oracleServer) + protected TestOracleIntegrationSmokeTest() throws Exception { - this.queryRunner = createOracleQueryRunner(oracleServer, ORDERS); this.oracleServer = new OracleServerTester(); + this.queryRunner = createOracleQueryRunner(oracleServer, ORDERS); } @Override @@ -52,20 +50,25 @@ public final void destroy() oracleServer.close(); } - @Test + @Override + protected boolean isLegacyTimestampEnabled() + { + return false; + } + @Override public void testDescribeTable() { - MaterializedResult expectedColumns = MaterializedResult.resultBuilder(getQueryRunner().getDefaultSession(), VARCHAR, VARCHAR, VARCHAR, VARCHAR) - .row("orderkey", "bigint", "", "") - .row("custkey", "bigint", "", "") - .row("orderstatus", "varchar(1)", "", "") - .row("totalprice", "double", "", "") - .row("orderdate", "timestamp", "", "") - .row("orderpriority", "varchar(15)", "", "") - .row("clerk", "varchar(15)", "", "") - .row("shippriority", "bigint", "", "") - .row("comment", "varchar(79)", "", "") + MaterializedResult expectedColumns = MaterializedResult.resultBuilder(getQueryRunner().getDefaultSession(), VARCHAR, VARCHAR, VARCHAR, VARCHAR, BIGINT, BIGINT, BIGINT) + .row("orderkey", "bigint", "", "", 19L, null, null) + .row("custkey", "bigint", "", "", 19L, null, null) + .row("orderstatus", "varchar(1)", "", "", null, null, 1L) + .row("totalprice", "double", "", "", 53L, null, null) + .row("orderdate", "timestamp", "", "", null, null, null) + .row("orderpriority", "varchar(15)", "", "", null, null, 15L) + .row("clerk", "varchar(15)", "", "", null, null, 15L) + .row("shippriority", "bigint", "", "", 19L, null, null) + .row("comment", "varchar(79)", "", "", null, null, 79L) .build(); MaterializedResult actualColumns = computeActual("DESCRIBE orders"); assertEquals(actualColumns, expectedColumns); diff --git a/presto-oracle/src/test/java/com/facebook/presto/plugin/oracle/DisabledTestOracleTypes.java b/presto-oracle/src/test/java/com/facebook/presto/plugin/oracle/TestOracleTypes.java similarity index 84% rename from presto-oracle/src/test/java/com/facebook/presto/plugin/oracle/DisabledTestOracleTypes.java rename to presto-oracle/src/test/java/com/facebook/presto/plugin/oracle/TestOracleTypes.java index 01a78474b4425..1dd5b61e69724 100644 --- a/presto-oracle/src/test/java/com/facebook/presto/plugin/oracle/DisabledTestOracleTypes.java +++ b/presto-oracle/src/test/java/com/facebook/presto/plugin/oracle/TestOracleTypes.java @@ -23,7 +23,6 @@ import com.facebook.presto.tests.datatype.DataType; import com.facebook.presto.tests.datatype.DataTypeTest; import com.facebook.presto.tests.sql.PrestoSqlExecutor; -import org.testcontainers.containers.OracleContainer; import org.testng.annotations.AfterClass; import org.testng.annotations.Test; @@ -31,33 +30,23 @@ import java.util.function.Function; import static com.facebook.presto.common.type.VarcharType.createUnboundedVarcharType; -import static com.facebook.presto.common.type.VarcharType.createVarcharType; import static com.facebook.presto.plugin.oracle.OracleQueryRunner.createOracleQueryRunner; import static com.facebook.presto.tests.datatype.DataType.stringDataType; import static com.facebook.presto.tests.datatype.DataType.varcharDataType; import static java.lang.String.format; import static java.math.RoundingMode.HALF_UP; -// Disabled for 7.5 TestNG Upgrade, the constructor takes in parameter -// TestNG 6 silently ignored, TestNG 7.5 fails (correctly), disabling for now -public class DisabledTestOracleTypes +public class TestOracleTypes extends AbstractTestQueryFramework { private final OracleServerTester oracleServer; private final QueryRunner queryRunner; - @Test - public void test() - { - OracleContainer oracle = new OracleContainer("wnameless/oracle-xe-11g-r2"); - oracle.start(); - } - - private DisabledTestOracleTypes(OracleServerTester oracleServer) + private TestOracleTypes() throws Exception { + this.oracleServer = new OracleServerTester(); this.queryRunner = createOracleQueryRunner(oracleServer); - this.oracleServer = oracleServer; } @Override @@ -93,7 +82,7 @@ public void testBooleanType() public void testSpecialNumberFormats() { oracleServer.execute("CREATE TABLE test (num1 number)"); - oracleServer.execute("INSERT INTO test VALUES (12345678901234567890.12345678901234567890123456789012345678)"); + oracleServer.execute("INSERT INTO test VALUES (12345678901234567890.1234567890)"); assertQuery("SELECT * FROM test", "VALUES (12345678901234567890.1234567890)"); } @@ -102,8 +91,8 @@ public void testVarcharType() { DataTypeTest.create() .addRoundTrip(varcharDataType(10), "test") - .addRoundTrip(stringDataType("varchar", createVarcharType(4000)), "test") - .addRoundTrip(stringDataType("varchar(5000)", createUnboundedVarcharType()), "test") + .addRoundTrip(stringDataType("varchar", createUnboundedVarcharType()), "test") + .addRoundTrip(stringDataType("varchar(4000)", createUnboundedVarcharType()), "test") .addRoundTrip(varcharDataType(3), String.valueOf('\u2603')) .execute(getQueryRunner(), prestoCreateAsSelect("varchar_types")); } diff --git a/presto-tests/src/main/java/com/facebook/presto/tests/AbstractTestDistributedQueries.java b/presto-tests/src/main/java/com/facebook/presto/tests/AbstractTestDistributedQueries.java index 0711400559056..ac5bcd5c79672 100644 --- a/presto-tests/src/main/java/com/facebook/presto/tests/AbstractTestDistributedQueries.java +++ b/presto-tests/src/main/java/com/facebook/presto/tests/AbstractTestDistributedQueries.java @@ -714,23 +714,24 @@ public void testAddColumn() @Test public void testInsert() { + Session session = sessionWithLegacyTimestamp(); @Language("SQL") String query = "SELECT orderdate, orderkey, totalprice FROM orders"; - assertUpdate("CREATE TABLE test_insert AS " + query + " WITH NO DATA", 0); - assertQuery("SELECT count(*) FROM test_insert", "SELECT 0"); + assertUpdate(session, "CREATE TABLE test_insert AS " + query + " WITH NO DATA", 0); + assertQuery(session, "SELECT count(*) FROM test_insert", "SELECT 0"); - assertUpdate("INSERT INTO test_insert " + query, "SELECT count(*) FROM orders"); + assertUpdate(session, "INSERT INTO test_insert " + query, "SELECT count(*) FROM orders"); - assertQuery("SELECT * FROM test_insert", query); + assertQuery(session, "SELECT * FROM test_insert", query); - assertUpdate("INSERT INTO test_insert (orderkey) VALUES (-1)", 1); - assertUpdate("INSERT INTO test_insert (orderkey) VALUES (null)", 1); - assertUpdate("INSERT INTO test_insert (orderdate) VALUES (DATE '2001-01-01')", 1); - assertUpdate("INSERT INTO test_insert (orderkey, orderdate) VALUES (-2, DATE '2001-01-02')", 1); - assertUpdate("INSERT INTO test_insert (orderdate, orderkey) VALUES (DATE '2001-01-03', -3)", 1); - assertUpdate("INSERT INTO test_insert (totalprice) VALUES (1234)", 1); + assertUpdate(session, "INSERT INTO test_insert (orderkey) VALUES (-1)", 1); + assertUpdate(session, "INSERT INTO test_insert (orderkey) VALUES (null)", 1); + assertUpdate(session, "INSERT INTO test_insert (orderdate) VALUES (DATE '2001-01-01')", 1); + assertUpdate(session, "INSERT INTO test_insert (orderkey, orderdate) VALUES (-2, DATE '2001-01-02')", 1); + assertUpdate(session, "INSERT INTO test_insert (orderdate, orderkey) VALUES (DATE '2001-01-03', -3)", 1); + assertUpdate(session, "INSERT INTO test_insert (totalprice) VALUES (1234)", 1); - assertQuery("SELECT * FROM test_insert", query + assertQuery(session, "SELECT * FROM test_insert", query + " UNION ALL SELECT null, -1, null" + " UNION ALL SELECT null, null, null" + " UNION ALL SELECT DATE '2001-01-01', null, null" @@ -740,24 +741,24 @@ public void testInsert() // UNION query produces columns in the opposite order // of how they are declared in the table schema - assertUpdate( + assertUpdate(session, "INSERT INTO test_insert (orderkey, orderdate, totalprice) " + "SELECT orderkey, orderdate, totalprice FROM orders " + "UNION ALL " + "SELECT orderkey, orderdate, totalprice FROM orders", "SELECT 2 * count(*) FROM orders"); - assertUpdate("DROP TABLE test_insert"); + assertUpdate(session, "DROP TABLE test_insert"); - assertUpdate("CREATE TABLE test_insert (a ARRAY, b ARRAY)"); + assertUpdate(session, "CREATE TABLE test_insert (a ARRAY, b ARRAY)"); - assertUpdate("INSERT INTO test_insert (a) VALUES (ARRAY[null])", 1); - assertUpdate("INSERT INTO test_insert (a) VALUES (ARRAY[1234])", 1); - assertQuery("SELECT a[1] FROM test_insert", "VALUES (null), (1234)"); + assertUpdate(session, "INSERT INTO test_insert (a) VALUES (ARRAY[null])", 1); + assertUpdate(session, "INSERT INTO test_insert (a) VALUES (ARRAY[1234])", 1); + assertQuery(session, "SELECT a[1] FROM test_insert", "VALUES (null), (1234)"); - assertQueryFails("INSERT INTO test_insert (b) VALUES (ARRAY[1.23E1])", "line 1:37: Mismatch at column 1.*"); + assertQueryFails(session, "INSERT INTO test_insert (b) VALUES (ARRAY[1.23E1])", "line 1:37: Mismatch at column 1.*"); - assertUpdate("DROP TABLE test_insert"); + assertUpdate(session, "DROP TABLE test_insert"); } @Test diff --git a/presto-tests/src/main/java/com/facebook/presto/tests/AbstractTestIntegrationSmokeTest.java b/presto-tests/src/main/java/com/facebook/presto/tests/AbstractTestIntegrationSmokeTest.java index c7c5ba4eef495..c598ca73365c9 100644 --- a/presto-tests/src/main/java/com/facebook/presto/tests/AbstractTestIntegrationSmokeTest.java +++ b/presto-tests/src/main/java/com/facebook/presto/tests/AbstractTestIntegrationSmokeTest.java @@ -34,6 +34,10 @@ protected boolean isParameterizedVarcharSupported() { return true; } + protected boolean isLegacyTimestampEnabled() + { + return true; + } @Test public void testAggregateSingleColumn() @@ -82,19 +86,25 @@ public void testLimit() @Test public void testMultipleRangesPredicate() { - assertQuery("SELECT * FROM orders WHERE orderkey BETWEEN 10 AND 50 OR orderkey BETWEEN 100 AND 150"); + if (isLegacyTimestampEnabled()) { + assertQuery("SELECT * FROM orders WHERE orderkey BETWEEN 10 AND 50 OR orderkey BETWEEN 100 AND 150"); + } } @Test public void testRangePredicate() { - assertQuery("SELECT * FROM orders WHERE orderkey BETWEEN 10 AND 50"); + if (isLegacyTimestampEnabled()) { + assertQuery("SELECT * FROM orders WHERE orderkey BETWEEN 10 AND 50"); + } } @Test public void testSelectAll() { - assertQuery("SELECT * FROM orders"); + if (isLegacyTimestampEnabled()) { + assertQuery("SELECT * FROM orders"); + } } @Test diff --git a/presto-tests/src/main/java/com/facebook/presto/tests/AbstractTestQueries.java b/presto-tests/src/main/java/com/facebook/presto/tests/AbstractTestQueries.java index dfe949a7a148f..4c633b914690a 100644 --- a/presto-tests/src/main/java/com/facebook/presto/tests/AbstractTestQueries.java +++ b/presto-tests/src/main/java/com/facebook/presto/tests/AbstractTestQueries.java @@ -62,6 +62,7 @@ import static com.facebook.presto.SystemSessionProperties.ITERATIVE_OPTIMIZER_TIMEOUT; import static com.facebook.presto.SystemSessionProperties.JOIN_DISTRIBUTION_TYPE; import static com.facebook.presto.SystemSessionProperties.JOIN_PREFILTER_BUILD_SIDE; +import static com.facebook.presto.SystemSessionProperties.LEGACY_TIMESTAMP; import static com.facebook.presto.SystemSessionProperties.LEGACY_UNNEST; import static com.facebook.presto.SystemSessionProperties.MERGE_AGGREGATIONS_WITH_AND_WITHOUT_FILTER; import static com.facebook.presto.SystemSessionProperties.MERGE_DUPLICATE_AGGREGATIONS; @@ -190,6 +191,20 @@ public abstract class AbstractTestQueries private static final DateTimeFormatter ZONED_DATE_TIME_FORMAT = DateTimeFormatter.ofPattern(SqlTimestampWithTimeZone.JSON_FORMAT); + protected boolean isLegacyTimestampEnabled() + { + return true; + } + + protected Session sessionWithLegacyTimestamp() + { + Session.SessionBuilder builder = Session.builder(getSession()); + if (!isLegacyTimestampEnabled()) { + builder.setSystemProperty(LEGACY_TIMESTAMP, "false"); + } + return builder.build(); + } + @Test public void testParsingError() { @@ -702,6 +717,7 @@ public void testWhereWithRowField() @Test public void testUnnest() { + Session session = sessionWithLegacyTimestamp(); assertQuery("SELECT 1 FROM (VALUES (ARRAY[1])) AS t (a) CROSS JOIN UNNEST(a)", "SELECT 1"); assertQuery("SELECT x[1] FROM UNNEST(ARRAY[ARRAY[1, 2, 3]]) t(x)", "SELECT 1"); assertQuery("SELECT x[1][2] FROM UNNEST(ARRAY[ARRAY[ARRAY[1, 2, 3]]]) t(x)", "SELECT 2"); @@ -760,7 +776,7 @@ public void testUnnest() "UNNEST(my_array) WITH ORDINALITY t(e, f)", "SELECT * FROM (SELECT custkey FROM orders ORDER BY orderkey LIMIT 1) CROSS JOIN (VALUES (10, 1), (20, 2), (30, 3))"); - assertQuery("SELECT * FROM orders, UNNEST(ARRAY[1])", "SELECT orders.*, 1 FROM orders"); + assertQuery(session, "SELECT * FROM orders, UNNEST(ARRAY[1])", "SELECT orders.*, 1 FROM orders"); assertQuery("SELECT a FROM (" + " SELECT l.arr AS arr FROM (" + " SELECT orderkey, ARRAY[1,2,3] AS arr FROM orders ORDER BY orderkey LIMIT 1) l" + @@ -1150,7 +1166,8 @@ public void testRepeatedOutputs2() { // this test exposed a bug that wasn't caught by other tests that resulted in the execution engine // trying to read orderkey as the second field, causing a type mismatch - assertQuery("SELECT orderdate, orderdate, orderkey FROM orders"); + Session session = sessionWithLegacyTimestamp(); + assertQuery(session, "SELECT orderdate, orderdate, orderkey FROM orders"); } @Test @@ -1219,25 +1236,29 @@ public void testCountOverGroupedAggregation() @Test public void testWildcard() { - assertQuery("SELECT * FROM orders"); + Session session = sessionWithLegacyTimestamp(); + assertQuery(session, "SELECT * FROM orders"); } @Test public void testMultipleWildcards() { - assertQuery("SELECT *, 123, * FROM orders"); + Session session = sessionWithLegacyTimestamp(); + assertQuery(session, "SELECT *, 123, * FROM orders"); } @Test public void testMixedWildcards() { - assertQuery("SELECT *, orders.*, orderkey FROM orders"); + Session session = sessionWithLegacyTimestamp(); + assertQuery(session, "SELECT *, orders.*, orderkey FROM orders"); } @Test public void testQualifiedWildcardFromAlias() { - assertQuery("SELECT T.* FROM orders T"); + Session session = sessionWithLegacyTimestamp(); + assertQuery(session, "SELECT T.* FROM orders T"); } @Test @@ -1249,7 +1270,8 @@ public void testQualifiedWildcardFromInlineView() @Test public void testQualifiedWildcard() { - assertQuery("SELECT orders.* FROM orders"); + Session session = sessionWithLegacyTimestamp(); + assertQuery(session, "SELECT orders.* FROM orders"); } @Test @@ -2271,7 +2293,8 @@ public void testUnaliasedSubqueries1() @Test public void testWith() { - assertQuery("" + + Session session = sessionWithLegacyTimestamp(); + assertQuery(session, "" + "WITH a AS (SELECT * FROM orders) " + "SELECT * FROM a", "SELECT * FROM orders"); @@ -2287,13 +2310,15 @@ public void testWithQualifiedPrefix() @Test public void testWithAliased() { - assertQuery("WITH a AS (SELECT * FROM orders) SELECT * FROM a x", "SELECT * FROM orders"); + Session session = sessionWithLegacyTimestamp(); + assertQuery(session, "WITH a AS (SELECT * FROM orders) SELECT * FROM a x", "SELECT * FROM orders"); } @Test public void testReferenceToWithQueryInFromClause() { - assertQuery( + Session session = sessionWithLegacyTimestamp(); + assertQuery(session, "WITH a AS (SELECT * FROM orders)" + "SELECT * FROM (" + " SELECT * FROM a" + @@ -2533,7 +2558,8 @@ public void testCaseInsensitiveAttribute() @Test public void testCaseInsensitiveAliasedRelation() { - assertQuery("SELECT A.* FROM orders a"); + Session session = sessionWithLegacyTimestamp(); + assertQuery(session, "SELECT A.* FROM orders a"); } @Test @@ -3399,44 +3425,45 @@ public void testUnionWithTopN() @Test public void testUnionWithAggregation() { + Session session = sessionWithLegacyTimestamp(); assertQuery( "SELECT regionkey, count(*) FROM (" + " SELECT regionkey FROM nation " + " UNION ALL " + " SELECT * FROM (VALUES 2, 100) t(regionkey)) " + - "GROUP BY regionkey", + "GROUP BY regionkey", "SELECT * FROM (VALUES (0, 5), (1, 5), (2, 6), (3, 5), (4, 5), (100, 1))"); - assertQuery( + assertQuery(session, "SELECT ds, count(*) FROM (" + " SELECT orderdate ds, orderkey FROM orders " + " UNION ALL " + " SELECT shipdate ds, orderkey FROM lineitem) a " + - "GROUP BY ds"); - assertQuery( + "GROUP BY ds"); + assertQuery(session, "SELECT ds, count(*) FROM (" + " SELECT orderdate ds, orderkey FROM orders " + " UNION " + " SELECT shipdate ds, orderkey FROM lineitem) a " + - "GROUP BY ds"); - assertQuery( + "GROUP BY ds"); + assertQuery(session, "SELECT ds, count(DISTINCT orderkey) FROM (" + " SELECT orderdate ds, orderkey FROM orders " + " UNION " + " SELECT shipdate ds, orderkey FROM lineitem) a " + - "GROUP BY ds"); + "GROUP BY ds"); assertQuery( "SELECT clerk, count(DISTINCT orderstatus) FROM (" + "SELECT * FROM orders WHERE orderkey=0 " + " UNION ALL " + "SELECT * FROM orders WHERE orderkey<>0) " + - "GROUP BY clerk"); + "GROUP BY clerk"); assertQuery( "SELECT count(clerk) FROM (" + "SELECT clerk FROM orders WHERE orderkey=0 " + " UNION ALL " + "SELECT clerk FROM orders WHERE orderkey<>0) " + - "GROUP BY clerk"); + "GROUP BY clerk"); assertQuery( "SELECT count(orderkey), sum(sc) FROM (" + " SELECT sum(custkey) sc, orderkey FROM (" + @@ -3518,9 +3545,10 @@ public void testSubqueryUnion() @Test public void testUnionWithFilterNotInSelect() { - assertQuery("SELECT orderkey, orderdate FROM orders WHERE custkey < 1000 UNION ALL SELECT orderkey, shipdate FROM lineitem WHERE linenumber < 2000"); - assertQuery("SELECT orderkey, orderdate FROM orders UNION ALL SELECT orderkey, shipdate FROM lineitem WHERE linenumber < 2000"); - assertQuery("SELECT orderkey, orderdate FROM orders WHERE custkey < 1000 UNION ALL SELECT orderkey, shipdate FROM lineitem"); + Session session = sessionWithLegacyTimestamp(); + assertQuery(session, "SELECT orderkey, orderdate FROM orders WHERE custkey < 1000 UNION ALL SELECT orderkey, shipdate FROM lineitem WHERE linenumber < 2000"); + assertQuery(session, "SELECT orderkey, orderdate FROM orders UNION ALL SELECT orderkey, shipdate FROM lineitem WHERE linenumber < 2000"); + assertQuery(session, "SELECT orderkey, orderdate FROM orders WHERE custkey < 1000 UNION ALL SELECT orderkey, shipdate FROM lineitem"); } @Test @@ -3532,7 +3560,8 @@ public void testSelectOnlyUnion() @Test public void testMultiColumnUnionAll() { - assertQuery("SELECT * FROM orders UNION ALL SELECT * FROM orders"); + Session session = sessionWithLegacyTimestamp(); + assertQuery(session, "SELECT * FROM orders UNION ALL SELECT * FROM orders"); } @Test @@ -3565,31 +3594,36 @@ public void testUnionRequiringCoercion() @Test public void testTableQuery() { - assertQuery("TABLE orders", "SELECT * FROM orders"); + Session session = sessionWithLegacyTimestamp(); + assertQuery(session, "TABLE orders", "SELECT * FROM orders"); } @Test public void testTableQueryOrderLimit() { - assertQueryOrdered("TABLE orders ORDER BY orderkey LIMIT 10", "SELECT * FROM orders ORDER BY orderkey LIMIT 10"); + Session session = sessionWithLegacyTimestamp(); + assertQueryOrdered(session, "TABLE orders ORDER BY orderkey LIMIT 10", "SELECT * FROM orders ORDER BY orderkey LIMIT 10"); } @Test public void testTableQueryInUnion() { - assertQuery("(SELECT * FROM orders ORDER BY orderkey LIMIT 10) UNION ALL TABLE orders", "(SELECT * FROM orders ORDER BY orderkey LIMIT 10) UNION ALL SELECT * FROM orders"); + Session session = sessionWithLegacyTimestamp(); + assertQuery(session, "(SELECT * FROM orders ORDER BY orderkey LIMIT 10) UNION ALL TABLE orders", "(SELECT * FROM orders ORDER BY orderkey LIMIT 10) UNION ALL SELECT * FROM orders"); } @Test public void testTableAsSubquery() { - assertQueryOrdered("(TABLE orders) ORDER BY orderkey", "(SELECT * FROM orders) ORDER BY orderkey"); + Session session = sessionWithLegacyTimestamp(); + assertQueryOrdered(session, "(TABLE orders) ORDER BY orderkey", "(SELECT * FROM orders) ORDER BY orderkey"); } @Test public void testLimitPushDown() { - MaterializedResult actual = computeActual( + Session session = sessionWithLegacyTimestamp(); + MaterializedResult actual = computeActual(session, "(TABLE orders ORDER BY orderkey) UNION ALL " + "SELECT * FROM orders WHERE orderstatus = 'F' UNION ALL " + "(TABLE orders ORDER BY orderkey LIMIT 20) UNION ALL " + @@ -3624,22 +3658,23 @@ public void testSameInPredicateInProjectionAndFilter() @Test public void testScalarSubquery() { + Session session = sessionWithLegacyTimestamp(); // nested assertQuery("SELECT (SELECT (SELECT (SELECT 1)))"); // aggregation - assertQuery("SELECT * FROM lineitem WHERE orderkey = \n" + + assertQuery(session, "SELECT * FROM lineitem WHERE orderkey = \n" + "(SELECT max(orderkey) FROM orders)"); // no output - assertQuery("SELECT * FROM lineitem WHERE orderkey = \n" + + assertQuery(session, "SELECT * FROM lineitem WHERE orderkey = \n" + "(SELECT orderkey FROM orders WHERE 0=1)"); // no output matching with null test - assertQuery("SELECT * FROM lineitem WHERE \n" + + assertQuery(session, "SELECT * FROM lineitem WHERE \n" + "(SELECT orderkey FROM orders WHERE 0=1) " + "is null"); - assertQuery("SELECT * FROM lineitem WHERE \n" + + assertQuery(session, "SELECT * FROM lineitem WHERE \n" + "(SELECT orderkey FROM orders WHERE 0=1) " + "is not null"); @@ -3664,24 +3699,24 @@ public void testScalarSubquery() " (SELECT avg(orderkey) FROM orders) + 10"); // subqueries with joins - assertQuery("SELECT o1.orderkey, COUNT(*) " + + assertQuery(session, "SELECT o1.orderkey, COUNT(*) " + "FROM orders o1 " + "INNER JOIN (SELECT * FROM orders ORDER BY orderkey LIMIT 10) o2 " + "ON o1.orderkey " + "BETWEEN (SELECT avg(orderkey) FROM orders) - 10 AND (SELECT avg(orderkey) FROM orders) + 10 " + "GROUP BY o1.orderkey"); - assertQuery("SELECT o1.orderkey, COUNT(*) " + + assertQuery(session, "SELECT o1.orderkey, COUNT(*) " + "FROM (SELECT * FROM orders ORDER BY orderkey LIMIT 5) o1 " + "LEFT JOIN (SELECT * FROM orders ORDER BY orderkey LIMIT 10) o2 " + "ON o1.orderkey " + "BETWEEN (SELECT avg(orderkey) FROM orders) - 10 AND (SELECT avg(orderkey) FROM orders) + 10 " + "GROUP BY o1.orderkey"); - assertQuery("SELECT o1.orderkey, COUNT(*) " + + assertQuery(session, "SELECT o1.orderkey, COUNT(*) " + "FROM orders o1 RIGHT JOIN (SELECT * FROM orders ORDER BY orderkey LIMIT 10) o2 " + "ON o1.orderkey " + "BETWEEN (SELECT avg(orderkey) FROM orders) - 10 AND (SELECT avg(orderkey) FROM orders) + 10 " + "GROUP BY o1.orderkey"); - assertQuery("SELECT DISTINCT COUNT(*) " + + assertQuery(session, "SELECT DISTINCT COUNT(*) " + "FROM (SELECT * FROM orders ORDER BY orderkey LIMIT 5) o1 " + "FULL JOIN (SELECT * FROM orders ORDER BY orderkey LIMIT 10) o2 " + "ON o1.orderkey " + @@ -3690,14 +3725,14 @@ public void testScalarSubquery() "VALUES 1, 10"); // subqueries with ORDER BY - assertQuery("SELECT orderkey, totalprice FROM orders ORDER BY (SELECT 2)"); + assertQuery(session, "SELECT orderkey, totalprice FROM orders ORDER BY (SELECT 2)"); // subquery returns multiple rows String multipleRowsErrorMsg = "(?s)Scalar sub-query has returned multiple rows.*"; - assertQueryFails("SELECT * FROM lineitem WHERE orderkey = (\n" + + assertQueryFails(session, "SELECT * FROM lineitem WHERE orderkey = (\n" + "SELECT orderkey FROM orders ORDER BY totalprice)", multipleRowsErrorMsg); - assertQueryFails("SELECT orderkey, totalprice FROM orders ORDER BY (VALUES 1, 2)", + assertQueryFails(session, "SELECT orderkey, totalprice FROM orders ORDER BY (VALUES 1, 2)", multipleRowsErrorMsg); // exposes a bug in optimize hash generation because EnforceSingleNode does not @@ -4008,9 +4043,10 @@ public void testCorrelatedNonAggregationScalarSubqueries() @Test public void testCorrelatedScalarSubqueriesWithScalarAggregationAndEqualityPredicatesInWhere() { + Session session = sessionWithLegacyTimestamp(); assertQuery("SELECT (SELECT count(*) WHERE o.orderkey = 1) FROM orders o"); assertQuery("SELECT count(*) FROM orders o WHERE 1 = (SELECT count(*) WHERE o.orderkey = 0)"); - assertQuery("SELECT * FROM orders o ORDER BY (SELECT count(*) WHERE o.orderkey = 0)"); + assertQuery(session, "SELECT * FROM orders o ORDER BY (SELECT count(*) WHERE o.orderkey = 0)"); assertQuery( "SELECT count(*) FROM nation n WHERE " + "(SELECT count(*) FROM region r WHERE n.regionkey = r.regionkey) > 1"); @@ -4036,7 +4072,7 @@ public void testCorrelatedScalarSubqueriesWithScalarAggregationAndEqualityPredic "GROUP BY o.orderkey, (SELECT count(*) WHERE o.orderkey = 0)"); // join - assertQuery( + assertQuery(session, "SELECT count(*) " + "FROM (SELECT * FROM orders ORDER BY orderkey LIMIT 10) o1 " + "JOIN (SELECT * FROM orders ORDER BY orderkey LIMIT 5) o2 " + @@ -4055,6 +4091,7 @@ public void testCorrelatedScalarSubqueriesWithScalarAggregationAndEqualityPredic @Test public void testCorrelatedScalarSubqueriesWithScalarAggregation() { + Session session = sessionWithLegacyTimestamp(); // projection assertQuery( "SELECT (SELECT round(3 * avg(i.a)) FROM (VALUES 1, 1, 1, 2, 2, 3, 4) i(a) WHERE i.a < o.a AND i.a < 4) " + @@ -4077,19 +4114,19 @@ public void testCorrelatedScalarSubqueriesWithScalarAggregation() "VALUES 1"); // h2 is slow // group by - assertQuery( + assertQuery(session, "SELECT max(o.orderdate), o.orderkey, " + "(SELECT avg(i.orderkey) FROM orders i WHERE o.orderkey < i.orderkey AND i.orderkey % 10000 = 0) " + "FROM orders o GROUP BY o.orderkey ORDER BY o.orderkey LIMIT 1", "VALUES ('1996-01-02', 1, 40000)"); // h2 is slow - assertQuery( + assertQuery(session, "SELECT max(o.orderdate), o.orderkey " + "FROM orders o " + "GROUP BY o.orderkey " + "HAVING 40000 < (SELECT avg(i.orderkey) FROM orders i WHERE o.orderkey < i.orderkey AND i.orderkey % 10000 = 0)" + "ORDER BY o.orderkey LIMIT 1", "VALUES ('1996-07-24', 20000)"); // h2 is slow - assertQuery( + assertQuery(session, "SELECT max(o.orderdate), o.orderkey FROM orders o " + "GROUP BY o.orderkey, (SELECT avg(i.orderkey) FROM orders i WHERE o.orderkey < i.orderkey AND i.orderkey % 10000 = 0)" + "ORDER BY o.orderkey LIMIT 1", @@ -4183,9 +4220,10 @@ public void testCorrelatedInPredicateSubqueries() @Test public void testCorrelatedExistsSubqueriesWithPrunedCorrelationSymbols() { + Session session = sessionWithLegacyTimestamp(); assertQuery("SELECT EXISTS(SELECT o.orderkey) FROM orders o"); assertQuery("SELECT count(*) FROM orders o WHERE EXISTS(SELECT o.orderkey)"); - assertQuery("SELECT * FROM orders o ORDER BY EXISTS(SELECT o.orderkey)"); + assertQuery(session, "SELECT * FROM orders o ORDER BY EXISTS(SELECT o.orderkey)"); // group by assertQuery( @@ -4197,7 +4235,7 @@ public void testCorrelatedExistsSubqueriesWithPrunedCorrelationSymbols() "SELECT max(o.totalprice), o.orderkey FROM orders o GROUP BY o.orderkey, EXISTS (SELECT o.orderkey)"); // join - assertQuery( + assertQuery(session, "SELECT * FROM orders o JOIN (SELECT * FROM lineitem ORDER BY orderkey LIMIT 2) l " + "ON NOT EXISTS(SELECT o.orderkey = l.orderkey)"); @@ -4210,10 +4248,11 @@ public void testCorrelatedExistsSubqueriesWithPrunedCorrelationSymbols() @Test public void testCorrelatedExistsSubqueriesWithEqualityPredicatesInWhere() { + Session session = sessionWithLegacyTimestamp(); assertQuery("SELECT EXISTS(SELECT 1 WHERE o.orderkey = 1) FROM orders o"); assertQuery("SELECT EXISTS(SELECT null WHERE o.orderkey = 1) FROM orders o"); assertQuery("SELECT count(*) FROM orders o WHERE EXISTS(SELECT 1 WHERE o.orderkey = 0)"); - assertQuery("SELECT * FROM orders o ORDER BY EXISTS(SELECT 1 WHERE o.orderkey = 0)"); + assertQuery(session, "SELECT * FROM orders o ORDER BY EXISTS(SELECT 1 WHERE o.orderkey = 0)"); assertQuery( "SELECT count(*) FROM orders o " + "WHERE EXISTS (SELECT avg(l.orderkey) FROM lineitem l WHERE o.orderkey = l.orderkey)"); @@ -4242,7 +4281,7 @@ public void testCorrelatedExistsSubqueriesWithEqualityPredicatesInWhere() "FROM orders o GROUP BY o.orderkey, EXISTS (SELECT 1 WHERE o.orderkey = 0)"); // join - assertQuery( + assertQuery(session, "SELECT count(*) " + "FROM (SELECT * FROM orders ORDER BY orderkey LIMIT 10) o1 " + "JOIN (SELECT * FROM orders ORDER BY orderkey LIMIT 5) o2 " + @@ -4266,6 +4305,7 @@ public void testCorrelatedExistsSubqueriesWithEqualityPredicatesInWhere() @Test public void testCorrelatedExistsSubqueries() { + Session session = sessionWithLegacyTimestamp(); // projection assertQuery( "SELECT EXISTS(SELECT 1 FROM (VALUES 1, 1, 1, 2, 2, 3, 4) i(a) WHERE i.a < o.a AND i.a < 4) " + @@ -4294,19 +4334,19 @@ public void testCorrelatedExistsSubqueries() "EXISTS(SELECT 1 WHERE l.orderkey > 0 OR l.orderkey != 3)"); // group by - assertQuery( + assertQuery(session, "SELECT max(o.orderdate), o.orderkey, " + "EXISTS(SELECT 1 FROM orders i WHERE o.orderkey < i.orderkey AND i.orderkey % 10000 = 0) " + "FROM orders o GROUP BY o.orderkey ORDER BY o.orderkey LIMIT 1", "VALUES ('1996-01-02', 1, true)"); // h2 is slow - assertQuery( + assertQuery(session, "SELECT max(o.orderdate), o.orderkey " + "FROM orders o " + "GROUP BY o.orderkey " + "HAVING EXISTS(SELECT 1 FROM orders i WHERE o.orderkey < i.orderkey AND i.orderkey % 10000 = 0)" + "ORDER BY o.orderkey LIMIT 1", "VALUES ('1996-01-02', 1)"); // h2 is slow - assertQuery( + assertQuery(session, "SELECT max(o.orderdate), o.orderkey FROM orders o " + "GROUP BY o.orderkey, EXISTS(SELECT 1 FROM orders i WHERE o.orderkey < i.orderkey AND i.orderkey % 10000 = 0)" + "ORDER BY o.orderkey LIMIT 1", diff --git a/presto-tests/src/main/java/com/facebook/presto/tests/AbstractTestQueryFramework.java b/presto-tests/src/main/java/com/facebook/presto/tests/AbstractTestQueryFramework.java index f59cbdcf96866..dd962b40f6b1b 100644 --- a/presto-tests/src/main/java/com/facebook/presto/tests/AbstractTestQueryFramework.java +++ b/presto-tests/src/main/java/com/facebook/presto/tests/AbstractTestQueryFramework.java @@ -465,6 +465,14 @@ protected void assertCreateTableAsSelect(Session session, String table, @Languag assertFalse(getQueryRunner().tableExists(session, table)); } + protected void assertCreateTableAsSelect(Session session, String table, @Language("SQL") String query, @Language("SQL") String rowCountQuery) + { + assertUpdate(session, "CREATE TABLE " + table + " AS " + query, rowCountQuery); + assertUpdate(session, "DROP TABLE " + table); + + assertFalse(getQueryRunner().tableExists(session, table)); + } + private static void assertErrorMessage(String sql, AssertionError error, @Language("RegExp") String regex) { if (!nullToEmpty(error.getMessage()).matches(regex)) { @@ -477,6 +485,11 @@ protected MaterializedResult computeExpected(@Language("SQL") String sql, List resultTypes) + { + return expectedQueryRunner.execute(session, sql, resultTypes); + } + protected void executeExclusively(Runnable executionBlock) { queryRunner.getExclusiveLock().lock();