Skip to content

Commit

Permalink
Refactor BaseJdbcConnectorTest native-query tests
Browse files Browse the repository at this point in the history
Make testNativeQuery* conditional based on whether connector supports
native-query passthrough table functions. This removes a lot of
duplication and also makes it easier to verify correct behaviour without
overriding tests.
  • Loading branch information
hashhar committed Apr 11, 2023
1 parent 2449f9d commit daa6bba
Show file tree
Hide file tree
Showing 5 changed files with 35 additions and 318 deletions.
Expand Up @@ -94,6 +94,7 @@
import static io.trino.testing.TestingConnectorBehavior.SUPPORTS_JOIN_PUSHDOWN_WITH_VARCHAR_INEQUALITY;
import static io.trino.testing.TestingConnectorBehavior.SUPPORTS_LIMIT_PUSHDOWN;
import static io.trino.testing.TestingConnectorBehavior.SUPPORTS_MERGE;
import static io.trino.testing.TestingConnectorBehavior.SUPPORTS_NATIVE_QUERY;
import static io.trino.testing.TestingConnectorBehavior.SUPPORTS_PREDICATE_ARITHMETIC_EXPRESSION_PUSHDOWN;
import static io.trino.testing.TestingConnectorBehavior.SUPPORTS_PREDICATE_EXPRESSION_PUSHDOWN_WITH_LIKE;
import static io.trino.testing.TestingConnectorBehavior.SUPPORTS_PREDICATE_PUSHDOWN;
Expand Down Expand Up @@ -1699,15 +1700,29 @@ public static Object[][] batchSizeAndTotalNumberOfRowsToInsertDataProvider()
};
}

@Test
public void verifySupportsNativeQueryDeclaration()
{
if (hasBehavior(SUPPORTS_NATIVE_QUERY)) {
// Covered by testNativeQuerySelectFromNation
return;
}
assertQueryFails(
format("SELECT * FROM TABLE(system.query(query => 'SELECT name FROM %s.nation WHERE nationkey = 0'))", getSession().getSchema().orElseThrow()),
"line 1:21: Table function system.query not registered");
}

@Test
public void testNativeQuerySimple()
{
skipTestUnless(hasBehavior(SUPPORTS_NATIVE_QUERY));
assertQuery("SELECT * FROM TABLE(system.query(query => 'SELECT 1'))", "VALUES 1");
}

@Test
public void testNativeQueryParameters()
{
skipTestUnless(hasBehavior(SUPPORTS_NATIVE_QUERY));
Session session = Session.builder(getSession())
.addPreparedStatement("my_query_simple", "SELECT * FROM TABLE(system.query(query => ?))")
.addPreparedStatement("my_query", "SELECT * FROM TABLE(system.query(query => format('SELECT %s FROM %s', ?, ?)))")
Expand All @@ -1719,6 +1734,7 @@ public void testNativeQueryParameters()
@Test
public void testNativeQuerySelectFromNation()
{
skipTestUnless(hasBehavior(SUPPORTS_NATIVE_QUERY));
assertQuery(
format("SELECT * FROM TABLE(system.query(query => 'SELECT name FROM %s.nation WHERE nationkey = 0'))", getSession().getSchema().orElseThrow()),
"VALUES 'ALGERIA'");
Expand All @@ -1727,6 +1743,7 @@ public void testNativeQuerySelectFromNation()
@Test
public void testNativeQuerySelectFromTestTable()
{
skipTestUnless(hasBehavior(SUPPORTS_NATIVE_QUERY));
try (TestTable testTable = simpleTable()) {
assertQuery(
format("SELECT * FROM TABLE(system.query(query => 'SELECT * FROM %s'))", testTable.getName()),
Expand All @@ -1737,6 +1754,7 @@ public void testNativeQuerySelectFromTestTable()
@Test
public void testNativeQueryColumnAlias()
{
skipTestUnless(hasBehavior(SUPPORTS_NATIVE_QUERY));
// The output column type may differ per connector. Skipping the check because it's unrelated to the test purpose.
assertThat(query(format("SELECT region_name FROM TABLE(system.query(query => 'SELECT name AS region_name FROM %s.region WHERE regionkey = 0'))", getSession().getSchema().orElseThrow())))
.skippingTypesCheck()
Expand All @@ -1746,6 +1764,7 @@ public void testNativeQueryColumnAlias()
@Test
public void testNativeQueryColumnAliasNotFound()
{
skipTestUnless(hasBehavior(SUPPORTS_NATIVE_QUERY));
assertQueryFails(
format("SELECT name FROM TABLE(system.query(query => 'SELECT name AS region_name FROM %s.region'))", getSession().getSchema().orElseThrow()),
".* Column 'name' cannot be resolved");
Expand All @@ -1757,6 +1776,7 @@ public void testNativeQueryColumnAliasNotFound()
@Test
public void testNativeQuerySelectUnsupportedType()
{
skipTestUnless(hasBehavior(SUPPORTS_NATIVE_QUERY));
try (TestTable testTable = createTableWithUnsupportedColumn()) {
String unqualifiedTableName = testTable.getName().replaceAll("^\\w+\\.", "");
// Check that column 'two' is not supported.
Expand All @@ -1770,6 +1790,7 @@ public void testNativeQuerySelectUnsupportedType()
@Test
public void testNativeQueryCreateStatement()
{
skipTestUnless(hasBehavior(SUPPORTS_NATIVE_QUERY));
assertFalse(getQueryRunner().tableExists(getSession(), "numbers"));
assertThatThrownBy(() -> query("SELECT * FROM TABLE(system.query(query => 'CREATE TABLE numbers(n INTEGER)'))"))
.hasMessageContaining("Query not supported: ResultSetMetaData not available for query: CREATE TABLE numbers(n INTEGER)");
Expand All @@ -1779,6 +1800,7 @@ public void testNativeQueryCreateStatement()
@Test
public void testNativeQueryInsertStatementTableDoesNotExist()
{
skipTestUnless(hasBehavior(SUPPORTS_NATIVE_QUERY));
assertFalse(getQueryRunner().tableExists(getSession(), "non_existent_table"));
assertThatThrownBy(() -> query("SELECT * FROM TABLE(system.query(query => 'INSERT INTO non_existent_table VALUES (1)'))"))
.hasMessageContaining("Failed to get table handle for prepared query");
Expand All @@ -1787,6 +1809,7 @@ public void testNativeQueryInsertStatementTableDoesNotExist()
@Test
public void testNativeQueryInsertStatementTableExists()
{
skipTestUnless(hasBehavior(SUPPORTS_NATIVE_QUERY));
try (TestTable testTable = simpleTable()) {
assertThatThrownBy(() -> query(format("SELECT * FROM TABLE(system.query(query => 'INSERT INTO %s VALUES (3)'))", testTable.getName())))
.hasMessageContaining(format("Query not supported: ResultSetMetaData not available for query: INSERT INTO %s VALUES (3)", testTable.getName()));
Expand All @@ -1797,6 +1820,7 @@ public void testNativeQueryInsertStatementTableExists()
@Test
public void testNativeQueryIncorrectSyntax()
{
skipTestUnless(hasBehavior(SUPPORTS_NATIVE_QUERY));
assertThatThrownBy(() -> query("SELECT * FROM TABLE(system.query(query => 'some wrong syntax'))"))
.hasMessageContaining("Failed to get table handle for prepared query");
}
Expand Down
Expand Up @@ -15,7 +15,6 @@

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import io.trino.Session;
import io.trino.plugin.jdbc.BaseJdbcConnectorTest;
import io.trino.sql.planner.plan.AggregationNode;
import io.trino.testing.MaterializedResult;
Expand Down Expand Up @@ -81,6 +80,9 @@ protected boolean hasBehavior(TestingConnectorBehavior connectorBehavior)
case SUPPORTS_NEGATIVE_DATE:
return false;

case SUPPORTS_NATIVE_QUERY:
return false;

default:
return super.hasBehavior(connectorBehavior);
}
Expand Down Expand Up @@ -660,115 +662,6 @@ public void testCharTrailingSpace()
throw new SkipException("Implement test for ClickHouse");
}

@Override
public void testNativeQuerySimple()
{
// table function disabled for ClickHouse, because it doesn't provide ResultSetMetaData, so the result relation type cannot be determined
assertQueryFails("SELECT * FROM TABLE(system.query(query => 'SELECT 1'))", "line 1:21: Table function system.query not registered");
}

@Override
public void testNativeQueryParameters()
{
// table function disabled for ClickHouse, because it doesn't provide ResultSetMetaData, so the result relation type cannot be determined
Session session = Session.builder(getSession())
.addPreparedStatement("my_query_simple", "SELECT * FROM TABLE(system.query(query => ?))")
.addPreparedStatement("my_query", "SELECT * FROM TABLE(system.query(query => format('SELECT %s FROM %s', ?, ?)))")
.build();
assertQueryFails(session, "EXECUTE my_query_simple USING 'SELECT 1 a'", "line 1:21: Table function system.query not registered");
assertQueryFails(session, "EXECUTE my_query USING 'a', '(SELECT 2 a) t'", "line 1:21: Table function system.query not registered");
}

@Override
public void testNativeQuerySelectFromNation()
{
// table function disabled for ClickHouse, because it doesn't provide ResultSetMetaData, so the result relation type cannot be determined
assertQueryFails(
format("SELECT * FROM TABLE(system.query(query => 'SELECT name FROM %s.nation WHERE nationkey = 0'))", getSession().getSchema().orElseThrow()),
"line 1:21: Table function system.query not registered");
}

@Override
public void testNativeQuerySelectFromTestTable()
{
// table function disabled for ClickHouse, because it doesn't provide ResultSetMetaData, so the result relation type cannot be determined
try (TestTable testTable = simpleTable()) {
assertQueryFails(
format("SELECT * FROM TABLE(system.query(query => 'SELECT * FROM %s'))", testTable.getName()),
"line 1:21: Table function system.query not registered");
}
}

@Override
public void testNativeQueryColumnAlias()
{
// table function disabled for ClickHouse, because it doesn't provide ResultSetMetaData, so the result relation type cannot be determined
assertQueryFails(
"SELECT * FROM TABLE(system.query(query => 'SELECT name AS region_name FROM tpch.region WHERE regionkey = 0'))",
".* Table function system.query not registered");
}

@Override
public void testNativeQueryColumnAliasNotFound()
{
// table function disabled for ClickHouse, because it doesn't provide ResultSetMetaData, so the result relation type cannot be determined
assertQueryFails(
"SELECT name FROM TABLE(system.query(query => 'SELECT name AS region_name FROM tpch.region'))",
".* Table function system.query not registered");
}

@Override
public void testNativeQuerySelectUnsupportedType()
{
// table function disabled for ClickHouse, because it doesn't provide ResultSetMetaData, so the result relation type cannot be determined
try (TestTable testTable = createTableWithUnsupportedColumn()) {
String unqualifiedTableName = testTable.getName().replaceAll("^\\w+\\.", "");
// Check that column 'two' is not supported.
assertQuery("SELECT column_name FROM information_schema.columns WHERE table_name = '" + unqualifiedTableName + "'", "VALUES 'one', 'three'");
assertUpdate("INSERT INTO " + testTable.getName() + " (one, three) VALUES (123, 'test')", 1);
assertThatThrownBy(() -> query(format("SELECT * FROM TABLE(system.query(query => 'SELECT * FROM %s'))", testTable.getName())))
.hasMessage("line 1:21: Table function system.query not registered");
}
}

@Override
public void testNativeQueryCreateStatement()
{
// table function disabled for ClickHouse, because it doesn't provide ResultSetMetaData, so the result relation type cannot be determined
assertFalse(getQueryRunner().tableExists(getSession(), "numbers"));
assertThatThrownBy(() -> query("SELECT * FROM TABLE(system.query(query => 'CREATE TABLE numbers(n INTEGER)'))"))
.hasMessage("line 1:21: Table function system.query not registered");
assertFalse(getQueryRunner().tableExists(getSession(), "numbers"));
}

@Override
public void testNativeQueryInsertStatementTableDoesNotExist()
{
// table function disabled for ClickHouse, because it doesn't provide ResultSetMetaData, so the result relation type cannot be determined
assertFalse(getQueryRunner().tableExists(getSession(), "non_existent_table"));
assertThatThrownBy(() -> query("SELECT * FROM TABLE(system.query(query => 'INSERT INTO non_existent_table VALUES (1)'))"))
.hasMessage("line 1:21: Table function system.query not registered");
}

@Override
public void testNativeQueryInsertStatementTableExists()
{
// table function disabled for ClickHouse, because it doesn't provide ResultSetMetaData, so the result relation type cannot be determined
try (TestTable testTable = simpleTable()) {
assertThatThrownBy(() -> query(format("SELECT * FROM TABLE(system.query(query => 'INSERT INTO %s VALUES (3)'))", testTable.getName())))
.hasMessage("line 1:21: Table function system.query not registered");
assertQuery("SELECT * FROM " + testTable.getName(), "VALUES 1, 2");
}
}

@Override
public void testNativeQueryIncorrectSyntax()
{
// table function disabled for ClickHouse, because it doesn't provide ResultSetMetaData, so the result relation type cannot be determined
assertThatThrownBy(() -> query("SELECT * FROM TABLE(system.query(query => 'some wrong syntax'))"))
.hasMessage("line 1:21: Table function system.query not registered");
}

@Override
protected TestTable simpleTable()
{
Expand Down

0 comments on commit daa6bba

Please sign in to comment.