/*
* 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.accumulo;
import com.facebook.presto.testing.MaterializedResult;
import com.facebook.presto.tests.AbstractTestDistributedQueries;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import org.intellij.lang.annotations.Language;
import org.testng.annotations.Test;
import static com.facebook.presto.accumulo.AccumuloQueryRunner.createAccumuloQueryRunner;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertTrue;
/**
* Accumulo requires a unique identifier for the rows.
* Any row that has a duplicate row ID is effectively an update,
* overwriting existing values of the row with whatever the new values are.
* For the lineitem and partsupp tables, there is no unique identifier,
* so a generated UUID is used in order to prevent overwriting rows of data.
* This is the same for any test cases that were creating tables with duplicate rows,
* so some test cases are overriden from the base class and slightly modified to add an additional UUID column.
*/
public class TestAccumuloDistributedQueries
extends AbstractTestDistributedQueries
{
public TestAccumuloDistributedQueries()
throws Exception
{
super(() -> createAccumuloQueryRunner(ImmutableMap.of()));
}
@Override
public void testAddColumn()
{
// Adding columns via SQL are not supported until adding columns with comments are supported
}
@Override
public void testCreateTableAsSelect()
{
// This test is overridden due to Function "UUID" not found errors
// Some test cases from the base class are removed
assertUpdate("CREATE TABLE test_create_table_as_if_not_exists (a bigint, b double)");
assertTrue(getQueryRunner().tableExists(getSession(), "test_create_table_as_if_not_exists"));
assertTableColumnNames("test_create_table_as_if_not_exists", "a", "b");
assertUpdate("CREATE TABLE IF NOT EXISTS test_create_table_as_if_not_exists AS SELECT UUID() AS uuid, orderkey, discount FROM lineitem", 0);
assertTrue(getQueryRunner().tableExists(getSession(), "test_create_table_as_if_not_exists"));
assertTableColumnNames("test_create_table_as_if_not_exists", "a", "b");
assertUpdate("DROP TABLE test_create_table_as_if_not_exists");
assertFalse(getQueryRunner().tableExists(getSession(), "test_create_table_as_if_not_exists"));
this.assertCreateTableAsSelect(
"test_group",
"SELECT orderstatus, sum(totalprice) x FROM orders GROUP BY orderstatus",
"SELECT count(DISTINCT orderstatus) FROM orders");
this.assertCreateTableAsSelect(
"test_with_data",
"SELECT * FROM orders WITH DATA",
"SELECT * FROM orders",
"SELECT count(*) FROM orders");
this.assertCreateTableAsSelect(
"test_with_no_data",
"SELECT * FROM orders WITH NO DATA",
"SELECT * FROM orders LIMIT 0",
"SELECT 0");
}
@Override
public void testDelete()
{
// Deletes are not supported by the connector
}
@Override
public void testInsert()
{
@Language("SQL") String query = "SELECT UUID() AS uuid, orderdate, orderkey FROM orders";
assertUpdate("CREATE TABLE test_insert AS " + query + " WITH NO DATA", 0);
assertQuery("SELECT count(*) FROM test_insert", "SELECT 0");
assertUpdate("INSERT INTO test_insert " + query, "SELECT count(*) FROM orders");
assertQuery("SELECT orderdate, orderkey FROM test_insert", "SELECT orderdate, orderkey FROM orders");
// Override because base class error: Cannot insert null row ID
assertUpdate("INSERT INTO test_insert (uuid, orderkey) VALUES ('000000', -1)", 1);
assertUpdate("INSERT INTO test_insert (uuid, orderdate) VALUES ('000001', DATE '2001-01-01')", 1);
assertUpdate("INSERT INTO test_insert (uuid, orderkey, orderdate) VALUES ('000002', -2, DATE '2001-01-02')", 1);
assertUpdate("INSERT INTO test_insert (uuid, orderdate, orderkey) VALUES ('000003', DATE '2001-01-03', -3)", 1);
assertQuery("SELECT orderdate, orderkey FROM test_insert",
"SELECT orderdate, orderkey FROM orders"
+ " UNION ALL SELECT null, -1"
+ " UNION ALL SELECT DATE '2001-01-01', null"
+ " UNION ALL SELECT DATE '2001-01-02', -2"
+ " UNION ALL SELECT DATE '2001-01-03', -3");
// UNION query produces columns in the opposite order
// of how they are declared in the table schema
assertUpdate(
"INSERT INTO test_insert (uuid, orderkey, orderdate) " +
"SELECT UUID() AS uuid, orderkey, orderdate FROM orders " +
"UNION ALL " +
"SELECT UUID() AS uuid, orderkey, orderdate FROM orders",
"SELECT 2 * count(*) FROM orders");
assertUpdate("DROP TABLE test_insert");
}
@Test
public void testInsertDuplicateRows()
{
// This test case tests the Accumulo connectors override capabilities
// When a row is inserted into a table where a row with the same row ID already exists,
// the cells of the existing row are overwritten with the new values
try {
assertUpdate("CREATE TABLE test_insert_duplicate AS SELECT 1 a, 2 b, '3' c", 1);
assertQuery("SELECT a, b, c FROM test_insert_duplicate", "SELECT 1, 2, '3'");
assertUpdate("INSERT INTO test_insert_duplicate (a, c) VALUES (1, '4')", 1);
assertUpdate("INSERT INTO test_insert_duplicate (a, b) VALUES (1, 3)", 1);
assertQuery("SELECT a, b, c FROM test_insert_duplicate", "SELECT 1, 3, '4'");
}
finally {
assertUpdate("DROP TABLE test_insert_duplicate");
}
}
@Override
public void testBuildFilteredLeftJoin()
{
// Override because of extra UUID column in lineitem table, cannot SELECT *
assertQuery("SELECT "
+ "lineitem.orderkey, partkey, suppkey, linenumber, quantity, "
+ "extendedprice, discount, tax, returnflag, linestatus, "
+ "shipdate, commitdate, receiptdate, shipinstruct, shipmode, lineitem.comment "
+ "FROM lineitem LEFT JOIN (SELECT * FROM orders WHERE orderkey % 2 = 0) a ON lineitem.orderkey = a.orderkey");
}
@Override
@Test
public void testJoinWithAlias()
{
// Override because of extra UUID column in lineitem table, cannot SELECT *
// Cannot munge test to pass due to aliased data set 'x' containing duplicate orderkey and comment columns
}
@Override
public void testProbeFilteredLeftJoin()
{
// Override because of extra UUID column in lineitem table, cannot SELECT *
assertQuery("SELECT "
+ "a.orderkey, partkey, suppkey, linenumber, quantity, "
+ "extendedprice, discount, tax, returnflag, linestatus, "
+ "shipdate, commitdate, receiptdate, shipinstruct, shipmode, a.comment "
+ "FROM (SELECT * FROM lineitem WHERE orderkey % 2 = 0) a LEFT JOIN orders ON a.orderkey = orders.orderkey");
}
@Override
@Test
public void testJoinWithDuplicateRelations()
{
// Override because of extra UUID column in lineitem table, cannot SELECT *
// Cannot munge test to pass due to aliased data sets 'x' containing duplicate orderkey and comment columns
}
@Override
public void testLeftJoinWithEmptyInnerTable()
{
// Override because of extra UUID column in lineitem table, cannot SELECT *
// Use orderkey = rand() to create an empty relation
assertQuery("SELECT a.orderkey, partkey, suppkey, linenumber, quantity, "
+ "extendedprice, discount, tax, returnflag, linestatus, "
+ "shipdate, commitdate, receiptdate, shipinstruct, shipmode, a.comment " +
"FROM lineitem a LEFT JOIN(SELECT * FROM orders WHERE orderkey = rand())b ON a.orderkey = b.orderkey");
assertQuery("SELECT a.orderkey, partkey, suppkey, linenumber, quantity, "
+ "extendedprice, discount, tax, returnflag, linestatus, "
+ "shipdate, commitdate, receiptdate, shipinstruct, shipmode, a.comment " +
"FROM lineitem a LEFT JOIN (SELECT * FROM orders WHERE orderkey = rand()) b ON a.orderkey > b.orderkey");
assertQuery("SELECT a.orderkey, partkey, suppkey, linenumber, quantity, "
+ "extendedprice, discount, tax, returnflag, linestatus, "
+ "shipdate, commitdate, receiptdate, shipinstruct, shipmode, a.comment " +
" FROM lineitem a LEFT JOIN (SELECT * FROM orders WHERE orderkey = rand()) b ON 1 = 1");
assertQuery("SELECT a.orderkey, partkey, suppkey, linenumber, quantity, "
+ "extendedprice, discount, tax, returnflag, linestatus, "
+ "shipdate, commitdate, receiptdate, shipinstruct, shipmode, a.comment " +
"FROM lineitem a LEFT JOIN (SELECT * FROM orders WHERE orderkey = rand()) b ON b.orderkey > 1");
assertQuery("SELECT a.orderkey, partkey, suppkey, linenumber, quantity, "
+ "extendedprice, discount, tax, returnflag, linestatus, "
+ "shipdate, commitdate, receiptdate, shipinstruct, shipmode, a.comment " +
"FROM lineitem a LEFT JOIN (SELECT * FROM orders WHERE orderkey = rand()) b ON b.orderkey > b.totalprice");
}
@Override
public void testScalarSubquery()
{
// Override because of extra UUID column in lineitem table, cannot SELECT *
// nested
assertQuery("SELECT (SELECT (SELECT (SELECT 1)))");
// aggregation
assertQuery("SELECT "
+ "orderkey, partkey, suppkey, linenumber, quantity, "
+ "extendedprice, discount, tax, returnflag, linestatus, "
+ "shipdate, commitdate, receiptdate, shipinstruct, shipmode, comment "
+ "FROM lineitem WHERE orderkey = \n"
+ "(SELECT max(orderkey) FROM orders)");
// no output
assertQuery("SELECT "
+ "orderkey, partkey, suppkey, linenumber, quantity, "
+ "extendedprice, discount, tax, returnflag, linestatus, "
+ "shipdate, commitdate, receiptdate, shipinstruct, shipmode, comment "
+ "FROM lineitem WHERE orderkey = \n"
+ "(SELECT orderkey FROM orders WHERE 0=1)");
// no output matching with null test
assertQuery("SELECT "
+ "orderkey, partkey, suppkey, linenumber, quantity, "
+ "extendedprice, discount, tax, returnflag, linestatus, "
+ "shipdate, commitdate, receiptdate, shipinstruct, shipmode, comment "
+ "FROM lineitem WHERE \n"
+ "(SELECT orderkey FROM orders WHERE 0=1) "
+ "is null");
assertQuery("SELECT "
+ "orderkey, partkey, suppkey, linenumber, quantity, "
+ "extendedprice, discount, tax, returnflag, linestatus, "
+ "shipdate, commitdate, receiptdate, shipinstruct, shipmode, comment "
+ "FROM lineitem WHERE \n"
+ "(SELECT orderkey FROM orders WHERE 0=1) "
+ "is not null");
// subquery results and in in-predicate
assertQuery("SELECT (SELECT 1) IN (1, 2, 3)");
assertQuery("SELECT (SELECT 1) IN ( 2, 3)");
// multiple subqueries
assertQuery("SELECT (SELECT 1) = (SELECT 3)");
assertQuery("SELECT (SELECT 1) < (SELECT 3)");
assertQuery("SELECT COUNT(*) FROM lineitem WHERE " +
"(SELECT min(orderkey) FROM orders)" +
"<" +
"(SELECT max(orderkey) FROM orders)");
// distinct
assertQuery("SELECT DISTINCT orderkey FROM lineitem " +
"WHERE orderkey BETWEEN" +
" (SELECT avg(orderkey) FROM orders) - 10 " +
" AND" +
" (SELECT avg(orderkey) FROM orders) + 10");
// subqueries with joins
for (String joinType : ImmutableList.of("INNER", "LEFT OUTER")) {
assertQuery("SELECT l.orderkey, COUNT(*) " +
"FROM lineitem l " + joinType + " JOIN orders o ON l.orderkey = o.orderkey " +
"WHERE l.orderkey BETWEEN" +
" (SELECT avg(orderkey) FROM orders) - 10 " +
" AND" +
" (SELECT avg(orderkey) FROM orders) + 10 " +
"GROUP BY l.orderkey");
}
// subqueries with ORDER BY
assertQuery("SELECT orderkey, totalprice FROM orders ORDER BY (SELECT 2)");
// subquery returns multiple rows
String multipleRowsErrorMsg = "Scalar sub-query has returned multiple rows";
assertQueryFails("SELECT "
+ "orderkey, partkey, suppkey, linenumber, quantity, "
+ "extendedprice, discount, tax, returnflag, linestatus, "
+ "shipdate, commitdate, receiptdate, shipinstruct, shipmode, comment "
+ "FROM lineitem WHERE orderkey = (\n"
+ "SELECT orderkey FROM orders ORDER BY totalprice)",
multipleRowsErrorMsg);
assertQueryFails("SELECT orderkey, totalprice FROM orders ORDER BY (VALUES 1, 2)",
multipleRowsErrorMsg);
// exposes a bug in optimize hash generation because EnforceSingleNode does not
// support more than one column from the underlying query
assertQuery("SELECT custkey, (SELECT DISTINCT custkey FROM orders ORDER BY custkey LIMIT 1) FROM orders");
}
@Override
public void testShowColumns()
{
// Override base class because table descriptions for Accumulo connector include comments
MaterializedResult actual = computeActual("SHOW COLUMNS FROM orders");
assertEquals(actual.getMaterializedRows().get(0).getField(0), "orderkey");
assertEquals(actual.getMaterializedRows().get(0).getField(1), "bigint");
assertEquals(actual.getMaterializedRows().get(1).getField(0), "custkey");
assertEquals(actual.getMaterializedRows().get(1).getField(1), "bigint");
assertEquals(actual.getMaterializedRows().get(2).getField(0), "orderstatus");
assertEquals(actual.getMaterializedRows().get(2).getField(1), "varchar(1)");
assertEquals(actual.getMaterializedRows().get(3).getField(0), "totalprice");
assertEquals(actual.getMaterializedRows().get(3).getField(1), "double");
assertEquals(actual.getMaterializedRows().get(4).getField(0), "orderdate");
assertEquals(actual.getMaterializedRows().get(4).getField(1), "date");
assertEquals(actual.getMaterializedRows().get(5).getField(0), "orderpriority");
assertEquals(actual.getMaterializedRows().get(5).getField(1), "varchar(15)");
assertEquals(actual.getMaterializedRows().get(6).getField(0), "clerk");
assertEquals(actual.getMaterializedRows().get(6).getField(1), "varchar(15)");
assertEquals(actual.getMaterializedRows().get(7).getField(0), "shippriority");
assertEquals(actual.getMaterializedRows().get(7).getField(1), "integer");
assertEquals(actual.getMaterializedRows().get(8).getField(0), "comment");
assertEquals(actual.getMaterializedRows().get(8).getField(1), "varchar(79)");
}
@Test
public void testMultiInBelowCardinality()
{
assertQuery("SELECT COUNT(*) FROM partsupp WHERE partkey = 1", "SELECT 4");
assertQuery("SELECT COUNT(*) FROM partsupp WHERE partkey = 2", "SELECT 4");
assertQuery("SELECT COUNT(*) FROM partsupp WHERE partkey IN (1, 2)", "SELECT 8");
}
@Test
public void testSelectNullValue()
{
try {
assertUpdate("CREATE TABLE test_select_null_value AS SELECT 1 a, 2 b, CAST(NULL AS BIGINT) c", 1);
assertQuery("SELECT * FROM test_select_null_value", "SELECT 1, 2, NULL");
assertQuery("SELECT a, c FROM test_select_null_value", "SELECT 1, NULL");
}
finally {
assertUpdate("DROP TABLE test_select_null_value");
}
}
@Test
public void testCreateTableEmptyColumns()
{
try {
assertUpdate("CREATE TABLE test_create_table_empty_columns WITH (column_mapping = 'a:a:a,b::b,c:c:,d::', index_columns='a,b,c,d') AS SELECT 1 id, 2 a, 3 b, 4 c, 5 d", 1);
assertQuery("SELECT * FROM test_create_table_empty_columns", "SELECT 1, 2, 3, 4, 5");
assertQuery("SELECT * FROM test_create_table_empty_columns WHERE a = 2", "SELECT 1, 2, 3, 4, 5");
assertQuery("SELECT * FROM test_create_table_empty_columns WHERE b = 3", "SELECT 1, 2, 3, 4, 5");
assertQuery("SELECT * FROM test_create_table_empty_columns WHERE c = 4", "SELECT 1, 2, 3, 4, 5");
assertQuery("SELECT * FROM test_create_table_empty_columns WHERE d = 5", "SELECT 1, 2, 3, 4, 5");
}
finally {
assertUpdate("DROP TABLE test_create_table_empty_columns");
}
}
@Override
public void testDescribeOutput()
{
// this connector uses a non-canonical type for varchar columns in tpch
}
@Override
public void testDescribeOutputNamedAndUnnamed()
{
// this connector uses a non-canonical type for varchar columns in tpch
}
}