Skip to content
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 @@ -71,6 +71,9 @@ protected boolean hasBehavior(TestingConnectorBehavior connectorBehavior)
case SUPPORTS_TOPN_PUSHDOWN:
return false;

case SUPPORTS_CREATE_VIEW:
return true;

default:
return super.hasBehavior(connectorBehavior);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/*
* 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 io.trino.plugin.hive;

import io.trino.testing.BaseConnectorSmokeTest;
import io.trino.testing.QueryRunner;
import io.trino.testing.TestingConnectorBehavior;
import org.testng.annotations.Test;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;

// Redundant over TestHiveConnectorTest, but exists to exercise BaseConnectorSmokeTest
// Some features like views may be supported by Hive only.
public class TestHiveConnectorSmokeTest
extends BaseConnectorSmokeTest
{
@Override
protected QueryRunner createQueryRunner()
throws Exception
{
return HiveQueryRunner.builder()
.setInitialTables(REQUIRED_TPCH_TABLES)
.build();
}

@Override
protected boolean hasBehavior(TestingConnectorBehavior connectorBehavior)
{
switch (connectorBehavior) {
case SUPPORTS_TOPN_PUSHDOWN:
return false;

case SUPPORTS_CREATE_VIEW:
return true;

case SUPPORTS_DELETE:
return true;

default:
return super.hasBehavior(connectorBehavior);
}
}

@Override
public void testDelete()
{
assertThatThrownBy(super::testDelete)
.hasMessage("Deletes must match whole partitions for non-transactional tables");
}

@Test
@Override
public void testShowCreateTable()
{
assertThat((String) computeScalar("SHOW CREATE TABLE region"))
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: cast to string is not needed

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

indeed, but may help completion. i will keep for now, but we can remove as followup

.isEqualTo("" +
"CREATE TABLE hive.tpch.region (\n" +
" regionkey bigint,\n" +
" name varchar(25),\n" +
" comment varchar(152)\n" +
")\n" +
"WITH (\n" +
" format = 'ORC'\n" +
")");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,13 @@ protected boolean hasBehavior(TestingConnectorBehavior connectorBehavior)
switch (connectorBehavior) {
case SUPPORTS_TOPN_PUSHDOWN:
return false;

case SUPPORTS_CREATE_VIEW:
return true;

case SUPPORTS_DELETE:
return true;

default:
return super.hasBehavior(connectorBehavior);
}
Expand All @@ -211,7 +218,8 @@ protected boolean hasBehavior(TestingConnectorBehavior connectorBehavior)
@Override
public void testDelete()
{
throw new SkipException("Hive connector supports row-by-row delete only for ACID tables but these currently cannot be used with file metastore.");
assertThatThrownBy(super::testDelete)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: separete commit

.hasStackTraceContaining("Deletes must match whole partitions for non-transactional tables");
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,10 @@ protected boolean hasBehavior(TestingConnectorBehavior connectorBehavior)
case SUPPORTS_RENAME_TABLE:
case SUPPORTS_TOPN_PUSHDOWN:
return false;

case SUPPORTS_CREATE_MATERIALIZED_VIEW:
return true;

case SUPPORTS_DELETE:
return true;
default:
Expand All @@ -142,6 +146,7 @@ public void testDelete()
public void testRenameTable()
{
// Iceberg table rename is not supported in FileHiveMetastore
// TODO add a test with a different metastore, or block rename in IcebergMetadata
assertThatThrownBy(super::testRenameTable)
.hasStackTraceContaining("Rename not supported for Iceberg tables");
}
Expand Down Expand Up @@ -203,6 +208,46 @@ public void testShowCreateTable()
")");
}

@Override
protected void checkInformationSchemaTablesForPointedQueryForMaterializedView(String schemaName, String viewName)
{
// TODO The query should not fail, obviously. It should return the viewName, as information_schema.tables returns it when invoked without filters
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue link

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@raunaqmorarka is there an issue for fix Iceberg MV reporting?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BTW Do we have any roadmap issue for materialized views?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I already have a fix for iceberg information_schema.tables listing in 5fff606

assertThatThrownBy(() -> super.checkInformationSchemaTablesForPointedQueryForMaterializedView(schemaName, viewName))
.hasMessageContaining("Not an Iceberg table");
}

@Override
protected void checkShowColumnsForMaterializedView(String viewName)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

where are you overriding those?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@losipiuk in AbstractTestIcebergConnectorTest

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@losipiuk sorry, i think i misunderstood the question.

{
// TODO The query should not fail, obviously. It should return all the columns in the view
assertThatThrownBy(() -> super.checkShowColumnsForMaterializedView(viewName))
.hasMessageContaining("Not an Iceberg table");
}

@Override
protected void checkInformationSchemaColumnsForMaterializedView(String schemaName, String viewName)
{
// TODO The query should not fail, obviously. It should return columns for all tables, views, and materialized views
assertThatThrownBy(() -> super.checkInformationSchemaColumnsForMaterializedView(schemaName, viewName))
.hasMessageFindingMatch("(?s)Expecting.*to contain:.*, nationkey\\).*, name\\).*, regionkey\\).*, comment\\)");
}

@Override
protected void checkInformationSchemaColumnsForPointedQueryForMaterializedView(String schemaName, String viewName)
{
// TODO The query should not fail, obviously. It should return columns for the materialized view
assertThatThrownBy(() -> super.checkInformationSchemaColumnsForPointedQueryForMaterializedView(schemaName, viewName))
.hasMessageContaining("Not an Iceberg table");
}

@Override
protected void checkInformationSchemaViewsForMaterializedView(String schemaName, String viewName)
{
// TODO should probably return materialized view, as it's also a view -- to be double checked
assertThatThrownBy(() -> super.checkInformationSchemaViewsForMaterializedView(schemaName, viewName))
.hasMessageFindingMatch("(?s)Expecting.*to contain:.*\\Q[(" + viewName + ")]");
}

@Test
// This particular method may or may not be @Flaky. It is annotated since the problem is generic.
@Flaky(issue = "https://github.com/trinodb/trino/issues/5201", match = "Failed to read footer of file: HdfsInputFile")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
/*
* 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 io.trino.plugin.iceberg;

import com.google.common.collect.ImmutableMap;
import io.trino.testing.BaseConnectorSmokeTest;
import io.trino.testing.QueryRunner;
import io.trino.testing.TestingConnectorBehavior;
import org.apache.iceberg.FileFormat;
import org.testng.annotations.Test;

import static io.trino.plugin.iceberg.IcebergQueryRunner.createIcebergQueryRunner;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;

// Redundant over TestIcebergOrcConnectorTest, but exists to exercise BaseConnectorSmokeTest
// Some features like materialized views may be supported by Iceberg only.
public class TestIcebergConnectorSmokeTest
extends BaseConnectorSmokeTest
{
@Override
protected QueryRunner createQueryRunner()
throws Exception
{
return createIcebergQueryRunner(ImmutableMap.of(), FileFormat.ORC, REQUIRED_TPCH_TABLES);
}

@Override
protected boolean hasBehavior(TestingConnectorBehavior connectorBehavior)
{
switch (connectorBehavior) {
case SUPPORTS_COMMENT_ON_COLUMN:
case SUPPORTS_RENAME_TABLE:
case SUPPORTS_TOPN_PUSHDOWN:
return false;

case SUPPORTS_CREATE_MATERIALIZED_VIEW:
return true;

case SUPPORTS_DELETE:
return true;
default:
return super.hasBehavior(connectorBehavior);
}
}

@Test
@Override
public void testDelete()
{
// Deletes are covered AbstractTestIcebergConnectorTest
assertThatThrownBy(super::testDelete)
.hasStackTraceContaining("This connector only supports delete where one or more partitions are deleted entirely");
}

@Test
@Override
public void testRenameTable()
{
// Iceberg table rename is not supported in FileHiveMetastore
// TODO add a test with a different metastore, or block rename in IcebergMetadata
assertThatThrownBy(super::testRenameTable)
.hasStackTraceContaining("Rename not supported for Iceberg tables");
}

@Test
@Override
public void testShowCreateTable()
{
assertThat((String) computeScalar("SHOW CREATE TABLE region"))
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: cast to string is not needed

.isEqualTo("" +
"CREATE TABLE iceberg.tpch.region (\n" +
" regionkey bigint,\n" +
" name varchar,\n" +
" comment varchar\n" +
")\n" +
"WITH (\n" +
" format = 'ORC'\n" +
")");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ public void testViews()
}

@Test
public void testMaterializedView()
public void testPostgreSqlMaterializedView()
throws Exception
{
execute("CREATE MATERIALIZED VIEW test_mv as SELECT * FROM orders");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -731,7 +731,10 @@ public void testDropTableIfExists()
@Test
public void testView()
{
skipTestUnless(supportsViews());
if (!supportsViews()) {
assertQueryFails("CREATE VIEW nation_v AS SELECT * FROM nation", "This connector does not support creating views");
return;
}

@Language("SQL") String query = "SELECT orderkey, orderstatus, totalprice / 2 half FROM orders";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -352,7 +352,7 @@ public void testTableSampleWithFiltering()
@Test
public void testShowCreateTable()
{
assertThat((String) computeActual("SHOW CREATE TABLE orders").getOnlyValue())
assertThat((String) computeScalar("SHOW CREATE TABLE orders"))
// 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 bigint,\n" +
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,11 @@
import java.util.List;
import java.util.regex.Pattern;

import static io.trino.testing.TestingConnectorBehavior.SUPPORTS_CREATE_MATERIALIZED_VIEW;
import static io.trino.testing.TestingConnectorBehavior.SUPPORTS_CREATE_SCHEMA;
import static io.trino.testing.TestingConnectorBehavior.SUPPORTS_CREATE_TABLE;
import static io.trino.testing.TestingConnectorBehavior.SUPPORTS_CREATE_TABLE_WITH_DATA;
import static io.trino.testing.TestingConnectorBehavior.SUPPORTS_CREATE_VIEW;
import static io.trino.testing.TestingConnectorBehavior.SUPPORTS_DELETE;
import static io.trino.testing.TestingConnectorBehavior.SUPPORTS_INSERT;
import static io.trino.testing.TestingConnectorBehavior.SUPPORTS_RENAME_TABLE;
Expand Down Expand Up @@ -303,11 +305,11 @@ public void testSelectInformationSchemaColumns()
.matches("VALUES 'regionkey', 'name', 'comment'");
}

// SHOW CREATE TABLE exercises table properties and comments, which may be skipped during regular SELECT execution
@Test
public void testShowCreateTable()
{
// SHOW CREATE TABLE exercises table properties and comments, which may be skipped during regular SELECT execution
assertThat((String) computeActual("SHOW CREATE TABLE region").getOnlyValue())
assertThat((String) computeScalar("SHOW CREATE TABLE region"))
.matches(format(
"CREATE TABLE %s.%s.region \\(\n" +
" regionkey (bigint|decimal\\(19, 0\\)),\n" +
Expand All @@ -317,4 +319,62 @@ public void testShowCreateTable()
Pattern.quote(getSession().getCatalog().orElseThrow()),
Pattern.quote(getSession().getSchema().orElseThrow())));
}

@Test
public void testView()
{
if (!hasBehavior(SUPPORTS_CREATE_VIEW)) {
assertQueryFails("CREATE VIEW nation_v AS SELECT * FROM nation", "This connector does not support creating views");
return;
}

String catalogName = getSession().getCatalog().orElseThrow();
String schemaName = getSession().getSchema().orElseThrow();
String viewName = "test_view_" + randomTableSuffix();
assertUpdate("CREATE VIEW " + viewName + " AS SELECT * FROM nation");

assertThat(query("SELECT * FROM " + viewName))
.skippingTypesCheck()
.matches("SELECT * FROM nation");

assertThat(((String) computeScalar("SHOW CREATE VIEW " + viewName)))
.matches("(?s)" +
"CREATE VIEW \\Q" + catalogName + "." + schemaName + "." + viewName + "\\E" +
".* AS\n" +
"SELECT \\*\n" +
"FROM\n" +
" nation");

assertUpdate("DROP VIEW " + viewName);
}

@Test
public void testMaterializedView()
{
if (!hasBehavior(SUPPORTS_CREATE_MATERIALIZED_VIEW)) {
assertQueryFails("CREATE MATERIALIZED VIEW nation_mv AS SELECT * FROM nation", "This connector does not support creating materialized views");
return;
}

String catalogName = getSession().getCatalog().orElseThrow();
String schemaName = getSession().getSchema().orElseThrow();
String viewName = "test_materialized_view_" + randomTableSuffix();
assertUpdate("CREATE MATERIALIZED VIEW " + viewName + " AS SELECT * FROM nation");

// reading
Comment thread
findepi marked this conversation as resolved.
Outdated
assertThat(query("SELECT * FROM " + viewName))
.skippingTypesCheck()
.matches("SELECT * FROM nation");

// details
assertThat(((String) computeScalar("SHOW CREATE MATERIALIZED VIEW " + viewName)))
.matches("(?s)" +
"CREATE MATERIALIZED VIEW \\Q" + catalogName + "." + schemaName + "." + viewName + "\\E" +
".* AS\n" +
"SELECT \\*\n" +
"FROM\n" +
" nation");

assertUpdate("DROP MATERIALIZED VIEW " + viewName);
}
}
Loading