Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rework Oracle tests to use BaseConnectorTest #7104

Merged
merged 1 commit into from
Mar 2, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,13 @@
*/
package io.trino.plugin.oracle;

import com.google.common.collect.ImmutableList;
import io.trino.Session;
import io.trino.execution.QueryInfo;
import io.trino.testing.AbstractTestDistributedQueries;
import io.trino.sql.planner.plan.AggregationNode;
import io.trino.sql.planner.plan.FilterNode;
import io.trino.sql.planner.plan.ProjectNode;
import io.trino.testing.BaseConnectorTest;
import io.trino.testing.MaterializedResult;
import io.trino.testing.ResultWithQueryId;
import io.trino.testing.sql.SqlExecutor;
Expand All @@ -24,15 +28,18 @@

import java.util.Optional;

import static io.trino.plugin.oracle.TestingOracleServer.TEST_USER;
import static io.trino.spi.type.VarcharType.VARCHAR;
import static io.trino.testing.MaterializedResult.resultBuilder;
import static io.trino.testing.assertions.Assert.assertEquals;
import static io.trino.testing.sql.TestTable.randomTableSuffix;
import static java.lang.String.format;
import static org.testng.Assert.assertEquals;
import static org.assertj.core.api.Assertions.assertThat;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertTrue;

public abstract class BaseTestOracleDistributedQueries
extends AbstractTestDistributedQueries
public abstract class BaseOracleConnectorTest
extends BaseConnectorTest
{
@Override
protected boolean supportsDelete()
Expand Down Expand Up @@ -90,7 +97,7 @@ protected Optional<DataMappingTestSetup> filterDataMappingSmokeTestData(DataMapp
protected TestTable createTableWithDefaultColumns()
{
return new TestTable(
createJdbcSqlExecutor(),
onOracle(),
"test_default_columns",
"(col_required decimal(20,0) NOT NULL," +
"col_nullable decimal(20,0)," +
Expand Down Expand Up @@ -288,5 +295,169 @@ protected Optional<String> filterColumnNameTestData(String columnName)
return Optional.empty();
}

protected abstract SqlExecutor createJdbcSqlExecutor();
@Test
@Override
public void testDescribeTable()
{
MaterializedResult expectedColumns = MaterializedResult.resultBuilder(getQueryRunner().getDefaultSession(), VARCHAR, VARCHAR, VARCHAR, VARCHAR)
.row("orderkey", "decimal(19,0)", "", "")
.row("custkey", "decimal(19,0)", "", "")
.row("orderstatus", "varchar(1)", "", "")
.row("totalprice", "double", "", "")
.row("orderdate", "timestamp(3)", "", "")
.row("orderpriority", "varchar(15)", "", "")
.row("clerk", "varchar(15)", "", "")
.row("shippriority", "decimal(10,0)", "", "")
.row("comment", "varchar(79)", "", "")
.build();
MaterializedResult actualColumns = computeActual("DESCRIBE orders");
assertEquals(actualColumns, expectedColumns);
}

@Test
@Override
public void testShowCreateTable()
{
assertThat((String) computeActual("SHOW CREATE TABLE orders").getOnlyValue())
// If the connector reports additional column properties, the expected value needs to be adjusted in the test subclass
.matches("CREATE TABLE \\w+\\.\\w+\\.orders \\Q(\n" +
" orderkey decimal(19, 0),\n" +
" custkey decimal(19, 0),\n" +
" orderstatus varchar(1),\n" +
" totalprice double,\n" +
" orderdate timestamp(3),\n" +
" orderpriority varchar(15),\n" +
" clerk varchar(15),\n" +
" shippriority decimal(10, 0),\n" +
" comment varchar(79)\n" +
")");
}

@Test
public void testDropTable()
{
String tableName = "test_drop" + randomTableSuffix();
assertUpdate(format("CREATE TABLE %s AS SELECT 1 test_drop", tableName), 1);
assertTrue(getQueryRunner().tableExists(getSession(), tableName));

assertUpdate("DROP TABLE " + tableName);
assertFalse(getQueryRunner().tableExists(getSession(), tableName));
}

@Test
public void testViews()
{
try (TestView view = new TestView(onOracle(), getUser() + ".test_view", "AS SELECT 'O' as status FROM dual")) {
assertQuery("SELECT status FROM " + view.getName(), "SELECT 'O'");
}
}

@Test
public void testSynonyms()
{
try (TestSynonym synonym = new TestSynonym(onOracle(), getUser() + ".test_synonym", "FOR ORDERS")) {
assertQueryFails("SELECT orderkey FROM " + synonym.getName(), "line 1:22: Table 'oracle.*' does not exist");
}
}

@Test
public void testPredicatePushdown()
{
// varchar equality
assertThat(query("SELECT regionkey, nationkey, name FROM nation WHERE name = 'ROMANIA'"))
.matches("VALUES (CAST(3 AS DECIMAL(19,0)), CAST(19 AS DECIMAL(19,0)), CAST('ROMANIA' AS varchar(25)))")
.isFullyPushedDown();

// varchar range
assertThat(query("SELECT regionkey, nationkey, name FROM nation WHERE name BETWEEN 'POLAND' AND 'RPA'"))
.matches("VALUES (CAST(3 AS DECIMAL(19,0)), CAST(19 AS DECIMAL(19,0)), CAST('ROMANIA' AS varchar(25)))")
.isFullyPushedDown();

// varchar different case
assertThat(query("SELECT regionkey, nationkey, name FROM nation WHERE name = 'romania'"))
.returnsEmptyResult()
.isFullyPushedDown();

// date equality
assertThat(query("SELECT orderkey FROM orders WHERE orderdate = DATE '1992-09-29'"))
.matches("VALUES CAST(1250 AS DECIMAL(19,0)), 34406, 38436, 57570")
.isFullyPushedDown();

// predicate over aggregation key (likely to be optimized before being pushed down into the connector)
assertThat(query("SELECT * FROM (SELECT regionkey, sum(nationkey) FROM nation GROUP BY regionkey) WHERE regionkey = 3"))
.matches("VALUES (CAST(3 AS decimal(19,0)), CAST(77 AS decimal(38,0)))")
.isNotFullyPushedDown(AggregationNode.class, ProjectNode.class);

// predicate over aggregation result
assertThat(query("SELECT regionkey, sum(nationkey) FROM nation GROUP BY regionkey HAVING sum(nationkey) = 77"))
.matches("VALUES (CAST(3 AS decimal(19,0)), CAST(77 AS decimal(38,0)))")
.isNotFullyPushedDown(AggregationNode.class, ProjectNode.class);
}

@Test
public void testPredicatePushdownForNumerics()
{
predicatePushdownTest("DECIMAL(9, 3)", "123.321", "<=", "124");
predicatePushdownTest("DECIMAL(9, 3)", "123.321", "<=", "123.321");
predicatePushdownTest("DECIMAL(9, 3)", "123.321", "=", "123.321");
predicatePushdownTest("DECIMAL(30, 10)", "123456789.987654321", "<=", "123456790");
predicatePushdownTest("DECIMAL(30, 10)", "123456789.987654321", "<=", "123456789.987654321");
predicatePushdownTest("DECIMAL(30, 10)", "123456789.987654321", "=", "123456789.987654321");
predicatePushdownTest("FLOAT(63)", "123456789.987654321", "<=", "CAST(123456789.99 AS REAL)");
predicatePushdownTest("FLOAT(63)", "123456789.987654321", "<=", "CAST(123456789.99 AS DOUBLE)");
predicatePushdownTest("FLOAT(126)", "123456789.987654321", "<=", "CAST(123456789.99 AS REAL)");
predicatePushdownTest("FLOAT(126)", "123456789.987654321", "<=", "CAST(123456789.99 AS DOUBLE)");
predicatePushdownTest("BINARY_FLOAT", "5.0f", "=", "CAST(5.0 AS REAL)");
predicatePushdownTest("BINARY_DOUBLE", "20.233", "=", "CAST(20.233 AS DOUBLE)");
predicatePushdownTest("NUMBER(5,3)", "5.0", "=", "CAST(5.0 AS DECIMAL(5,3))");
}

@Test
public void testPredicatePushdownForChars()
{
predicatePushdownTest("CHAR(1)", "'0'", "=", "'0'");
predicatePushdownTest("CHAR(1)", "'0'", "<=", "'0'");
predicatePushdownTest("CHAR(5)", "'0'", "=", "CHAR'0'");
predicatePushdownTest("CHAR(7)", "'my_char'", "=", "CAST('my_char' AS CHAR(7))");
predicatePushdownTest("NCHAR(7)", "'my_char'", "=", "CAST('my_char' AS CHAR(7))");
predicatePushdownTest("VARCHAR2(7)", "'my_char'", "=", "CAST('my_char' AS VARCHAR(7))");
predicatePushdownTest("NVARCHAR2(7)", "'my_char'", "=", "CAST('my_char' AS VARCHAR(7))");

try (TestTable table = new TestTable(
onOracle(),
getUser() + ".test_pdown_",
"(c_clob CLOB, c_nclob NCLOB)",
ImmutableList.of("'my_clob', 'my_nclob'"))) {
assertThat(query(format("SELECT c_clob FROM %s WHERE c_clob = cast('my_clob' as varchar)", table.getName()))).isNotFullyPushedDown(FilterNode.class);
assertThat(query(format("SELECT c_nclob FROM %s WHERE c_nclob = cast('my_nclob' as varchar)", table.getName()))).isNotFullyPushedDown(FilterNode.class);
}
}

@Test
public void testTooLargeDomainCompactionThreshold()
{
assertQueryFails(
Session.builder(getSession())
.setCatalogSessionProperty("oracle", "domain_compaction_threshold", "10000")
.build(),
"SELECT * from nation", "Domain compaction threshold \\(10000\\) cannot exceed 1000");
}

private void predicatePushdownTest(String oracleType, String oracleLiteral, String operator, String filterLiteral)
{
String tableName = "test_pdown_" + oracleType.replaceAll("[^a-zA-Z0-9]", "");
try (TestTable table = new TestTable(onOracle(), getUser() + "." + tableName, format("(c %s)", oracleType))) {
onOracle().execute(format("INSERT INTO %s VALUES (%s)", table.getName(), oracleLiteral));

assertThat(query(format("SELECT * FROM %s WHERE c %s %s", table.getName(), operator, filterLiteral)))
.isFullyPushedDown();
}
}

protected String getUser()
{
return TEST_USER;
}

protected abstract SqlExecutor onOracle();
}
Loading