Return-Path: X-Original-To: apmail-tajo-commits-archive@minotaur.apache.org Delivered-To: apmail-tajo-commits-archive@minotaur.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id C1A5110A2D for ; Fri, 18 Apr 2014 10:31:59 +0000 (UTC) Received: (qmail 67048 invoked by uid 500); 18 Apr 2014 10:31:40 -0000 Delivered-To: apmail-tajo-commits-archive@tajo.apache.org Received: (qmail 66801 invoked by uid 500); 18 Apr 2014 10:31:32 -0000 Mailing-List: contact commits-help@tajo.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@tajo.apache.org Delivered-To: mailing list commits@tajo.apache.org Received: (qmail 65948 invoked by uid 99); 18 Apr 2014 10:31:14 -0000 Received: from tyr.zones.apache.org (HELO tyr.zones.apache.org) (140.211.11.114) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 18 Apr 2014 10:31:14 +0000 Received: by tyr.zones.apache.org (Postfix, from userid 65534) id BCE9E98132D; Fri, 18 Apr 2014 10:31:13 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: hyunsik@apache.org To: commits@tajo.apache.org Date: Fri, 18 Apr 2014 10:31:21 -0000 Message-Id: <5be608bf959048eb9158d4d622c3b8da@git.apache.org> In-Reply-To: <3b4025c804b9465d9da1d6d5bd0fce12@git.apache.org> References: <3b4025c804b9465d9da1d6d5bd0fce12@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: [09/51] [partial] TAJO-752: Escalate sub modules in tajo-core into the top-level modules. (hyunsik) http://git-wip-us.apache.org/repos/asf/tajo/blob/026368be/tajo-core/src/test/java/org/apache/tajo/client/TestTajoClient.java ---------------------------------------------------------------------- diff --git a/tajo-core/src/test/java/org/apache/tajo/client/TestTajoClient.java b/tajo-core/src/test/java/org/apache/tajo/client/TestTajoClient.java new file mode 100644 index 0000000..49e6874 --- /dev/null +++ b/tajo-core/src/test/java/org/apache/tajo/client/TestTajoClient.java @@ -0,0 +1,666 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.tajo.client; + +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.google.common.collect.Sets; +import com.google.protobuf.ServiceException; +import com.sun.org.apache.commons.logging.Log; +import com.sun.org.apache.commons.logging.LogFactory; +import org.apache.hadoop.fs.FileSystem; +import org.apache.hadoop.fs.Path; +import org.apache.tajo.*; +import org.apache.tajo.catalog.CatalogUtil; +import org.apache.tajo.catalog.FunctionDesc; +import org.apache.tajo.catalog.TableDesc; +import org.apache.tajo.catalog.proto.CatalogProtos; +import org.apache.tajo.conf.TajoConf; +import org.apache.tajo.ipc.ClientProtos; +import org.apache.tajo.jdbc.TajoResultSet; +import org.apache.tajo.storage.StorageUtil; +import org.apache.tajo.util.CommonTestingUtil; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.experimental.categories.Category; + +import java.io.IOException; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.*; + +import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; + +@Category(IntegrationTest.class) +public class TestTajoClient { + private static TajoTestingCluster cluster; + private static TajoConf conf; + private static TajoClient client; + private static Path testDir; + + @BeforeClass + public static void setUp() throws Exception { + cluster = TpchTestBase.getInstance().getTestingCluster(); + conf = cluster.getConfiguration(); + client = new TajoClient(conf); + testDir = CommonTestingUtil.getTestDir(); + } + + @AfterClass + public static void tearDown() throws Exception { + client.close(); + } + + private static Path writeTmpTable(String tableName) throws IOException { + Path tablePath = StorageUtil.concatPath(testDir, tableName); + BackendTestingUtil.writeTmpTable(conf, tablePath); + return tablePath; + } + + @Test + public final void testCreateAndDropDatabases() throws ServiceException { + int currentNum = client.getAllDatabaseNames().size(); + + String prefix = CatalogUtil.normalizeIdentifier("testCreateDatabase_"); + for (int i = 0; i < 10; i++) { + // test allDatabaseNames + assertEquals(currentNum + i, client.getAllDatabaseNames().size()); + + // test existence + assertFalse(client.existDatabase(prefix + i)); + assertTrue(client.createDatabase(prefix + i)); + assertTrue(client.existDatabase(prefix + i)); + + // test allDatabaseNames + assertEquals(currentNum + i + 1, client.getAllDatabaseNames().size()); + assertTrue(client.getAllDatabaseNames().contains(prefix + i)); + } + + // test dropDatabase, existDatabase and getAllDatabaseNames() + for (int i = 0; i < 10; i++) { + assertTrue(client.existDatabase(prefix + i)); + assertTrue(client.getAllDatabaseNames().contains(prefix + i)); + assertTrue(client.dropDatabase(prefix + i)); + assertFalse(client.existDatabase(prefix + i)); + assertFalse(client.getAllDatabaseNames().contains(prefix + i)); + } + + assertEquals(currentNum, client.getAllDatabaseNames().size()); + } + + @Test + public final void testCurrentDatabase() throws IOException, ServiceException, InterruptedException { + int currentNum = client.getAllDatabaseNames().size(); + assertEquals(TajoConstants.DEFAULT_DATABASE_NAME, client.getCurrentDatabase()); + + String databaseName = CatalogUtil.normalizeIdentifier("testcurrentdatabase"); + assertTrue(client.createDatabase(databaseName)); + assertEquals(currentNum + 1, client.getAllDatabaseNames().size()); + assertEquals(TajoConstants.DEFAULT_DATABASE_NAME, client.getCurrentDatabase()); + assertTrue(client.selectDatabase(databaseName)); + assertEquals(databaseName, client.getCurrentDatabase()); + assertTrue(client.selectDatabase(TajoConstants.DEFAULT_DATABASE_NAME)); + assertTrue(client.dropDatabase(databaseName)); + + assertEquals(currentNum, client.getAllDatabaseNames().size()); + } + + @Test + public final void testSelectDatabaseToInvalidOne() throws IOException, ServiceException, InterruptedException { + int currentNum = client.getAllDatabaseNames().size(); + assertFalse(client.existDatabase("invaliddatabase")); + + try { + assertTrue(client.selectDatabase("invaliddatabase")); + assertFalse(true); + } catch (Throwable t) { + assertFalse(false); + } + + assertEquals(currentNum, client.getAllDatabaseNames().size()); + } + + @Test + public final void testDropCurrentDatabase() throws IOException, ServiceException, InterruptedException { + int currentNum = client.getAllDatabaseNames().size(); + String databaseName = CatalogUtil.normalizeIdentifier("testdropcurrentdatabase"); + assertTrue(client.createDatabase(databaseName)); + assertTrue(client.selectDatabase(databaseName)); + assertEquals(databaseName, client.getCurrentDatabase()); + + try { + client.dropDatabase(databaseName); + assertFalse(true); + } catch (Throwable t) { + assertFalse(false); + } + + assertTrue(client.selectDatabase(TajoConstants.DEFAULT_DATABASE_NAME)); + assertTrue(client.dropDatabase(databaseName)); + assertEquals(currentNum, client.getAllDatabaseNames().size()); + } + + @Test + public final void testSessionVariables() throws IOException, ServiceException, InterruptedException { + String prefixName = "key_"; + String prefixValue = "val_"; + for (int i = 0; i < 10; i++) { + String key = prefixName + i; + String val = prefixValue + i; + + assertEquals(i, client.getAllSessionVariables().size()); + assertFalse(client.getAllSessionVariables().containsKey(key)); + assertFalse(client.existSessionVariable(key)); + + Map map = Maps.newHashMap(); + map.put(key, val); + client.updateSessionVariables(map); + + assertEquals(i + 1, client.getAllSessionVariables().size()); + assertTrue(client.getAllSessionVariables().containsKey(key)); + assertTrue(client.existSessionVariable(key)); + } + + int totalSessionVarNum = client.getAllSessionVariables().size(); + + for (int i = 0; i < 10; i++) { + String key = prefixName + i; + + assertTrue(client.getAllSessionVariables().containsKey(key)); + assertTrue(client.existSessionVariable(key)); + + client.unsetSessionVariables(Lists.newArrayList(key)); + + assertFalse(client.getAllSessionVariables().containsKey(key)); + assertFalse(client.existSessionVariable(key)); + } + + assertEquals(totalSessionVarNum - 10, client.getAllSessionVariables().size()); + } + + @Test + public final void testKillQuery() throws IOException, ServiceException, InterruptedException { + ClientProtos.SubmitQueryResponse res = client.executeQuery("select sleep(1) from lineitem"); + Thread.sleep(1000); + QueryId queryId = new QueryId(res.getQueryId()); + client.killQuery(queryId); + assertEquals(TajoProtos.QueryState.QUERY_KILLED, client.getQueryStatus(queryId).getState()); + } + + @Test + public final void testUpdateQuery() throws IOException, ServiceException { + final String tableName = CatalogUtil.normalizeIdentifier("testUpdateQuery"); + Path tablePath = writeTmpTable(tableName); + + assertFalse(client.existTable(tableName)); + String sql = + "create external table " + tableName + " (deptname text, score integer) " + + "using csv location '" + tablePath + "'"; + client.updateQuery(sql); + assertTrue(client.existTable(tableName)); + client.dropTable(tableName); + assertFalse(client.existTable(tableName)); + } + + @Test + public final void testCreateAndDropExternalTable() + throws IOException, ServiceException, SQLException { + final String tableName = "testCreateAndDropExternalTable"; + Path tablePath = writeTmpTable(tableName); + LOG.error("Full path:" + tablePath.toUri().getRawPath()); + FileSystem fs = tablePath.getFileSystem(conf); + assertTrue(fs.exists(tablePath)); + + assertFalse(client.existTable(tableName)); + + client.createExternalTable(tableName, BackendTestingUtil.mockupSchema, tablePath, BackendTestingUtil.mockupMeta); + assertTrue(client.existTable(tableName)); + client.dropTable(tableName); + assertFalse(client.existTable(tableName)); + fs = tablePath.getFileSystem(conf); + assertTrue(fs.exists(tablePath)); + } + + @Test + public final void testCreateAndPurgeExternalTable() throws IOException, ServiceException, SQLException { + final String tableName = "testCreateAndPurgeExternalTable"; + Path tablePath = writeTmpTable(tableName); + LOG.error("Full path:" + tablePath.toUri().getRawPath()); + FileSystem fs = tablePath.getFileSystem(conf); + assertTrue(fs.exists(tablePath)); + + assertFalse(client.existTable(tableName)); + + client.createExternalTable(tableName, BackendTestingUtil.mockupSchema, tablePath, BackendTestingUtil.mockupMeta); + assertTrue(client.existTable(tableName)); + client.dropTable(tableName, true); + assertFalse(client.existTable(tableName)); + fs = tablePath.getFileSystem(conf); + assertFalse("Checking if table data exists", fs.exists(tablePath)); + } + + @Test + public final void testCreateAndDropExternalTableByExecuteQuery() throws IOException, ServiceException { + TajoConf conf = cluster.getConfiguration(); + final String tableName = CatalogUtil.normalizeIdentifier("testCreateAndDropExternalTableByExecuteQuery"); + + Path tablePath = writeTmpTable(tableName); + assertFalse(client.existTable(tableName)); + + String sql = "create external table " + tableName + " (deptname text, score int4) " + "using csv location '" + + tablePath + "'"; + + client.executeQueryAndGetResult(sql); + assertTrue(client.existTable(tableName)); + + client.updateQuery("drop table " + tableName); + assertFalse(client.existTable("tableName")); + FileSystem localFS = FileSystem.getLocal(conf); + assertTrue(localFS.exists(tablePath)); + } + + @Test + public final void testCreateAndPurgeExternalTableByExecuteQuery() throws IOException, ServiceException { + TajoConf conf = cluster.getConfiguration(); + final String tableName = CatalogUtil.normalizeIdentifier("testCreateAndPurgeExternalTableByExecuteQuery"); + + Path tablePath = writeTmpTable(tableName); + assertFalse(client.existTable(tableName)); + + String sql = "create external table " + tableName + " (deptname text, score int4) " + "using csv location '" + + tablePath + "'"; + + client.executeQueryAndGetResult(sql); + assertTrue(client.existTable(tableName)); + + client.updateQuery("drop table " + tableName + " purge"); + assertFalse(client.existTable(tableName)); + FileSystem localFS = FileSystem.getLocal(conf); + assertFalse(localFS.exists(tablePath)); + } + + @Test + public final void testCreateAndDropTableByExecuteQuery() throws IOException, ServiceException, SQLException { + TajoConf conf = cluster.getConfiguration(); + final String tableName = CatalogUtil.normalizeIdentifier("testCreateAndDropTableByExecuteQuery"); + + assertFalse(client.existTable(tableName)); + + String sql = "create table " + tableName + " (deptname text, score int4)"; + + client.updateQuery(sql); + assertTrue(client.existTable(tableName)); + + Path tablePath = client.getTableDesc(tableName).getPath(); + FileSystem hdfs = tablePath.getFileSystem(conf); + assertTrue(hdfs.exists(tablePath)); + + client.updateQuery("drop table " + tableName); + assertFalse(client.existTable(tableName)); + assertTrue(hdfs.exists(tablePath)); + } + + @Test + public final void testCreateAndPurgeTableByExecuteQuery() throws IOException, ServiceException, SQLException { + TajoConf conf = cluster.getConfiguration(); + final String tableName = CatalogUtil.normalizeIdentifier("testCreateAndPurgeTableByExecuteQuery"); + + assertFalse(client.existTable(tableName)); + + String sql = "create table " + tableName + " (deptname text, score int4)"; + + client.updateQuery(sql); + assertTrue(client.existTable(tableName)); + + Path tablePath = client.getTableDesc(tableName).getPath(); + FileSystem hdfs = tablePath.getFileSystem(conf); + assertTrue(hdfs.exists(tablePath)); + + client.updateQuery("drop table " + tableName + " purge"); + assertFalse(client.existTable(tableName)); + assertFalse(hdfs.exists(tablePath)); + } + + @Test + public final void testDDLByExecuteQuery() throws IOException, ServiceException { + final String tableName = CatalogUtil.normalizeIdentifier("testDDLByExecuteQuery"); + Path tablePath = writeTmpTable(tableName); + + assertFalse(client.existTable(tableName)); + String sql = + "create external table " + tableName + " (deptname text, score int4) " + + "using csv location '" + tablePath + "'"; + client.executeQueryAndGetResult(sql); + assertTrue(client.existTable(tableName)); + } + + @Test + public final void testGetTableList() throws IOException, ServiceException { + String tableName1 = "GetTableList1".toLowerCase(); + String tableName2 = "GetTableList2".toLowerCase(); + + assertFalse(client.existTable(tableName1)); + assertFalse(client.existTable(tableName2)); + client.updateQuery("create table GetTableList1 (age int, name text);"); + client.updateQuery("create table GetTableList2 (age int, name text);"); + + assertTrue(client.existTable(tableName1)); + assertTrue(client.existTable(tableName2)); + + Set tables = Sets.newHashSet(client.getTableList(null)); + assertTrue(tables.contains(tableName1)); + assertTrue(tables.contains(tableName2)); + } + + Log LOG = LogFactory.getLog(TestTajoClient.class); + + @Test + public final void testGetTableDesc() throws IOException, ServiceException, SQLException { + final String tableName1 = CatalogUtil.normalizeIdentifier("table3"); + Path tablePath = writeTmpTable(tableName1); + LOG.error("Full path:" + tablePath.toUri().getRawPath()); + FileSystem fs = tablePath.getFileSystem(conf); + assertTrue(fs.exists(tablePath)); + + assertNotNull(tablePath); + assertFalse(client.existTable(tableName1)); + + client.createExternalTable("table3", BackendTestingUtil.mockupSchema, tablePath, BackendTestingUtil.mockupMeta); + assertTrue(client.existTable(tableName1)); + + TableDesc desc = client.getTableDesc(tableName1); + assertNotNull(desc); + assertEquals(CatalogUtil.buildFQName(TajoConstants.DEFAULT_DATABASE_NAME, tableName1), desc.getName()); + assertTrue(desc.getStats().getNumBytes() > 0); + } + + //@Test + public final void testCreateAndDropTablePartitionedHash1ByExecuteQuery() throws IOException, + ServiceException, SQLException { + TajoConf conf = cluster.getConfiguration(); + final String tableName = "testCreateAndDropTablePartitionedHash1ByExecuteQuery"; + + assertFalse(client.existTable(tableName)); + + String sql = "create table " + tableName + " (deptname text, score int4)"; + sql += " PARTITION BY HASH (deptname)"; + sql += " (PARTITION sub_part1, PARTITION sub_part2, PARTITION sub_part3)"; + + client.updateQuery(sql); + assertTrue(client.existTable(tableName)); + + Path tablePath = client.getTableDesc(tableName).getPath(); + FileSystem hdfs = tablePath.getFileSystem(conf); + assertTrue(hdfs.exists(tablePath)); + + client.updateQuery("drop table " + tableName); + assertFalse(client.existTable(tableName)); + assertTrue(hdfs.exists(tablePath)); + } + + //@Test + public final void testCreateAndPurgeTablePartitionedHash1ByExecuteQuery() throws IOException, + ServiceException, SQLException { + TajoConf conf = cluster.getConfiguration(); + final String tableName = "testCreateAndPurgeTablePartitionedHash1ByExecuteQuery"; + + assertFalse(client.existTable(tableName)); + + String sql = "create table " + tableName + " (deptname text, score int4)"; + sql += " PARTITION BY HASH (deptname)"; + sql += " (PARTITION sub_part1, PARTITION sub_part2, PARTITION sub_part3)"; + + client.updateQuery(sql); + assertTrue(client.existTable(tableName)); + + Path tablePath = client.getTableDesc(tableName).getPath(); + FileSystem hdfs = tablePath.getFileSystem(conf); + assertTrue(hdfs.exists(tablePath)); + + client.updateQuery("drop table " + tableName + " purge"); + assertFalse(client.existTable(tableName)); + assertFalse(hdfs.exists(tablePath)); + } + + //@Test + public final void testCreateAndDropTablePartitionedHash2ByExecuteQuery() throws IOException, + ServiceException, SQLException { + TajoConf conf = cluster.getConfiguration(); + final String tableName = "testCreateAndDropTablePartitionedHash2ByExecuteQuery"; + + assertFalse(client.existTable(tableName)); + + String sql = "create table " + tableName + " (deptname text, score int4)"; + sql += "PARTITION BY HASH (deptname)"; + sql += "PARTITIONS 2"; + + client.updateQuery(sql); + assertTrue(client.existTable(tableName)); + + Path tablePath = client.getTableDesc(tableName).getPath(); + FileSystem hdfs = tablePath.getFileSystem(conf); + assertTrue(hdfs.exists(tablePath)); + + client.updateQuery("drop table " + tableName + " purge"); + assertFalse(client.existTable(tableName)); + assertFalse(hdfs.exists(tablePath)); + } + + //@Test + public final void testCreateAndDropTablePartitionedListByExecuteQuery() throws IOException, + ServiceException, SQLException { + TajoConf conf = cluster.getConfiguration(); + final String tableName = "testCreateAndDropTablePartitionedListByExecuteQuery"; + + assertFalse(client.existTable(tableName)); + + String sql = "create table " + tableName + " (deptname text, score int4)"; + sql += "PARTITION BY LIST (deptname)"; + sql += "( PARTITION sub_part1 VALUES('r&d', 'design'),"; + sql += "PARTITION sub_part2 VALUES('sales', 'hr') )"; + + client.updateQuery(sql); + assertTrue(client.existTable(tableName)); + + Path tablePath = client.getTableDesc(tableName).getPath(); + FileSystem hdfs = tablePath.getFileSystem(conf); + assertTrue(hdfs.exists(tablePath)); + + client.updateQuery("drop table " + tableName + " purge"); + assertFalse(client.existTable(tableName)); + assertFalse(hdfs.exists(tablePath)); + } + + //@Test + public final void testCreateAndDropTablePartitionedRangeByExecuteQuery() throws IOException, + ServiceException, SQLException { + TajoConf conf = cluster.getConfiguration(); + final String tableName = "testCreateAndDropTablePartitionedRangeByExecuteQuery"; + + assertFalse(client.existTable(tableName)); + + String sql = "create table " + tableName + " (deptname text, score int4)"; + sql += "PARTITION BY RANGE (score)"; + sql += "( PARTITION sub_part1 VALUES LESS THAN (2),"; + sql += "PARTITION sub_part2 VALUES LESS THAN (5),"; + sql += "PARTITION sub_part2 VALUES LESS THAN (MAXVALUE) )"; + + client.updateQuery(sql); + assertTrue(client.existTable(tableName)); + + Path tablePath = client.getTableDesc(tableName).getPath(); + FileSystem hdfs = tablePath.getFileSystem(conf); + assertTrue(hdfs.exists(tablePath)); + + client.updateQuery("drop table " + tableName +" purge"); + assertFalse(client.existTable(tableName)); + assertFalse(hdfs.exists(tablePath)); + } + + @Test + public final void testFailCreateTablePartitionedOtherExceptColumn() throws IOException, + ServiceException, SQLException { + TajoConf conf = cluster.getConfiguration(); + final String tableName = "testFailCreateTablePartitionedOtherExceptColumn"; + + assertFalse(client.existTable(tableName)); + + String rangeSql = "create table " + tableName + " (deptname text, score int4)"; + rangeSql += "PARTITION BY RANGE (score)"; + rangeSql += "( PARTITION sub_part1 VALUES LESS THAN (2),"; + rangeSql += "PARTITION sub_part2 VALUES LESS THAN (5),"; + rangeSql += "PARTITION sub_part2 VALUES LESS THAN (MAXVALUE) )"; + + assertFalse(client.updateQuery(rangeSql)); + + String listSql = "create table " + tableName + " (deptname text, score int4)"; + listSql += "PARTITION BY LIST (deptname)"; + listSql += "( PARTITION sub_part1 VALUES('r&d', 'design'),"; + listSql += "PARTITION sub_part2 VALUES('sales', 'hr') )"; + + assertFalse(client.updateQuery(listSql)); + + String hashSql = "create table " + tableName + " (deptname text, score int4)"; + hashSql += "PARTITION BY HASH (deptname)"; + hashSql += "PARTITIONS 2"; + + assertFalse(client.updateQuery(hashSql)); + } + + @Test + public final void testCreateAndDropTablePartitionedColumnByExecuteQuery() throws IOException, + ServiceException, SQLException { + TajoConf conf = cluster.getConfiguration(); + final String tableName = CatalogUtil.normalizeIdentifier("testCreateAndDropTablePartitionedColumnByExecuteQuery"); + + assertFalse(client.existTable(tableName)); + + String sql = "create table " + tableName + " (deptname text, score int4)"; + sql += "PARTITION BY COLUMN (key1 text)"; + + client.updateQuery(sql); + assertTrue(client.existTable(tableName)); + + Path tablePath = client.getTableDesc(tableName).getPath(); + FileSystem hdfs = tablePath.getFileSystem(conf); + assertTrue(hdfs.exists(tablePath)); + + client.updateQuery("drop table " + tableName + " purge"); + assertFalse(client.existTable(tableName)); + assertFalse(hdfs.exists(tablePath)); + } + + @Test + public final void testGetFunctions() throws IOException, + ServiceException, SQLException { + Collection catalogFunctions = cluster.getMaster().getCatalog().getFunctions(); + String functionName = "sum"; + int numFunctions = 0; + for(FunctionDesc eachFunction: catalogFunctions) { + if(functionName.equals(eachFunction.getSignature())) { + numFunctions++; + } + } + + List functions = client.getFunctions(functionName); + assertEquals(numFunctions, functions.size()); + + functions = client.getFunctions("notmatched"); + assertEquals(0, functions.size()); + + functions = client.getFunctions(null); + assertEquals(catalogFunctions.size(), functions.size()); + } + + @Test + public final void testGetFinishedQueryList() throws IOException, + ServiceException, SQLException { + final String tableName = CatalogUtil.normalizeIdentifier("testGetFinishedQueryList"); + String sql = "create table " + tableName + " (deptname text, score int4)"; + + client.updateQuery(sql); + assertTrue(client.existTable(tableName)); + + int numFinishedQueries = client.getFinishedQueryList().size(); + ResultSet resultSet = client.executeQueryAndGetResult("select * from " + tableName + " order by deptname"); + assertNotNull(resultSet); + + resultSet = client.executeQueryAndGetResult("select * from " + tableName + " order by deptname"); + assertNotNull(resultSet); + assertEquals(numFinishedQueries + 2, client.getFinishedQueryList().size()); + + resultSet.close(); + } + + /** + * The main objective of this test is to get the status of a query which is actually finished. + * Statuses of queries regardless of its status should be available for a specified time duration. + */ + @Test(timeout = 20 * 1000) + public final void testGetQueryStatusAndResultAfterFinish() throws Exception { + String sql = "select * from lineitem order by l_orderkey"; + ClientProtos.SubmitQueryResponse response = client.executeQuery(sql); + + assertNotNull(response); + QueryId queryId = new QueryId(response.getQueryId()); + + try { + long startTime = System.currentTimeMillis(); + while (true) { + Thread.sleep(5 * 1000); + + List finishedQueries = client.getFinishedQueryList(); + boolean finished = false; + if (finishedQueries != null) { + for (ClientProtos.BriefQueryInfo eachQuery: finishedQueries) { + if (eachQuery.getQueryId().equals(queryId.getProto())) { + finished = true; + break; + } + } + } + + if (finished) { + break; + } + if(System.currentTimeMillis() - startTime > 20 * 1000) { + fail("Too long time execution query"); + } + } + + QueryStatus queryStatus = client.getQueryStatus(queryId); + assertNotNull(queryStatus); + assertTrue(!TajoClient.isQueryRunnning(queryStatus.getState())); + + TajoResultSet resultSet = (TajoResultSet) client.getQueryResult(queryId); + assertNotNull(resultSet); + + int count = 0; + while(resultSet.next()) { + count++; + } + + assertEquals(5, count); + } finally { + client.closeQuery(queryId); + } + } +} http://git-wip-us.apache.org/repos/asf/tajo/blob/026368be/tajo-core/src/test/java/org/apache/tajo/cluster/TestServerName.java ---------------------------------------------------------------------- diff --git a/tajo-core/src/test/java/org/apache/tajo/cluster/TestServerName.java b/tajo-core/src/test/java/org/apache/tajo/cluster/TestServerName.java new file mode 100644 index 0000000..513187d --- /dev/null +++ b/tajo-core/src/test/java/org/apache/tajo/cluster/TestServerName.java @@ -0,0 +1,102 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.tajo.cluster; + +import org.junit.Test; +import org.apache.tajo.master.cluster.ServerName; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +public class TestServerName { + + @Test + public void testServerNameStringInt() { + ServerName server = new ServerName("ex1.com",50030); + assertEquals("ex1.com", server.getHostname()); + assertEquals(50030, server.getPort()); + } + + @Test + public void testServerNameString() { + ServerName server = new ServerName("ex1.com:50030"); + assertEquals("ex1.com", server.getHostname()); + assertEquals(50030, server.getPort()); + } + + @Test + public void testParseHostname() { + assertEquals("ex1.com",ServerName.parseHostname("ex1.com:50030")); + } + + @Test + public void testParsePort() { + assertEquals(50030,ServerName.parsePort("ex1.com:50030")); + } + + @Test + public void testToString() { + ServerName server = new ServerName("ex1.com",50030); + assertEquals("ex1.com:50030", server.toString()); + } + + @Test + public void testGetServerName() { + ServerName server = new ServerName("ex1.com",50030); + assertEquals("ex1.com:50030", server.getServerName()); + } + + @Test + public void testGetHostname() { + ServerName server = new ServerName("ex1.com",50030); + assertEquals("ex1.com", server.getHostname()); + } + + @Test + public void testGetPort() { + ServerName server = new ServerName("ex1.com",50030); + assertEquals(50030, server.getPort()); + } + + @Test + public void testGetServerNameStringInt() { + assertEquals("ex2.com:50030",ServerName.getServerName("ex2.com", 50030)); + } + + @Test + public void testCompareTo() { + ServerName s1 = new ServerName("ex1.com:50030"); + ServerName s2 = new ServerName("ex1.com:60030"); + + assertTrue(s1.compareTo(s2) < 0); + assertTrue(s2.compareTo(s1) > 0); + + ServerName s3 = new ServerName("ex1.com:50030"); + assertTrue(s1.compareTo(s3) == 0); + + ServerName s4 = new ServerName("ex2.com:50030"); + assertTrue(s1.compareTo(s4) < 0); + assertTrue(s4.compareTo(s1) > 0); + } + + @Test (expected = IllegalArgumentException.class) + public void testException() { + new ServerName("ex1.com"); + } +} http://git-wip-us.apache.org/repos/asf/tajo/blob/026368be/tajo-core/src/test/java/org/apache/tajo/engine/eval/ExprTestBase.java ---------------------------------------------------------------------- diff --git a/tajo-core/src/test/java/org/apache/tajo/engine/eval/ExprTestBase.java b/tajo-core/src/test/java/org/apache/tajo/engine/eval/ExprTestBase.java new file mode 100644 index 0000000..d19b4d6 --- /dev/null +++ b/tajo-core/src/test/java/org/apache/tajo/engine/eval/ExprTestBase.java @@ -0,0 +1,210 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.tajo.engine.eval; + +import org.apache.tajo.LocalTajoTestingUtility; +import org.apache.tajo.TajoTestingCluster; +import org.apache.tajo.algebra.Expr; +import org.apache.tajo.catalog.*; +import org.apache.tajo.catalog.proto.CatalogProtos; +import org.apache.tajo.cli.InvalidStatementException; +import org.apache.tajo.cli.ParsedResult; +import org.apache.tajo.cli.SimpleParser; +import org.apache.tajo.datum.NullDatum; +import org.apache.tajo.datum.TextDatum; +import org.apache.tajo.engine.json.CoreGsonHelper; +import org.apache.tajo.engine.parser.SQLAnalyzer; +import org.apache.tajo.engine.planner.*; +import org.apache.tajo.engine.utils.SchemaUtil; +import org.apache.tajo.master.TajoMaster; +import org.apache.tajo.master.session.Session; +import org.apache.tajo.storage.LazyTuple; +import org.apache.tajo.storage.Tuple; +import org.apache.tajo.storage.VTuple; +import org.apache.tajo.util.Bytes; +import org.apache.tajo.util.CommonTestingUtil; +import org.junit.AfterClass; +import org.junit.BeforeClass; + +import java.io.IOException; +import java.util.List; + +import static org.apache.tajo.TajoConstants.DEFAULT_DATABASE_NAME; +import static org.apache.tajo.TajoConstants.DEFAULT_TABLESPACE_NAME; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; + +public class ExprTestBase { + private static TajoTestingCluster util; + private static CatalogService cat; + private static SQLAnalyzer analyzer; + private static PreLogicalPlanVerifier preLogicalPlanVerifier; + private static LogicalPlanner planner; + private static LogicalOptimizer optimizer; + private static LogicalPlanVerifier annotatedPlanVerifier; + + @BeforeClass + public static void setUp() throws Exception { + util = new TajoTestingCluster(); + util.startCatalogCluster(); + cat = util.getMiniCatalogCluster().getCatalog(); + cat.createTablespace(DEFAULT_TABLESPACE_NAME, "hdfs://localhost:1234/warehouse"); + cat.createDatabase(DEFAULT_DATABASE_NAME, DEFAULT_TABLESPACE_NAME); + for (FunctionDesc funcDesc : TajoMaster.initBuiltinFunctions()) { + cat.createFunction(funcDesc); + } + + analyzer = new SQLAnalyzer(); + preLogicalPlanVerifier = new PreLogicalPlanVerifier(cat); + planner = new LogicalPlanner(cat); + optimizer = new LogicalOptimizer(util.getConfiguration()); + annotatedPlanVerifier = new LogicalPlanVerifier(util.getConfiguration(), cat); + } + + @AfterClass + public static void tearDown() throws Exception { + util.shutdownCatalogCluster(); + } + + private static void assertJsonSerDer(EvalNode expr) { + String json = CoreGsonHelper.toJson(expr, EvalNode.class); + EvalNode fromJson = CoreGsonHelper.fromJson(json, EvalNode.class); + assertEquals(expr, fromJson); + } + + /** + * verify query syntax and get raw targets. + * + * @param query a query for execution + * @param condition this parameter means whether it is for success case or is not for failure case. + * @return + * @throws PlanningException + */ + private static Target[] getRawTargets(String query, boolean condition) throws PlanningException, + InvalidStatementException { + + Session session = LocalTajoTestingUtility.createDummySession(); + List parsedResults = SimpleParser.parseScript(query); + if (parsedResults.size() > 1) { + throw new RuntimeException("this query includes two or more statements."); + } + Expr expr = analyzer.parse(parsedResults.get(0).getStatement()); + VerificationState state = new VerificationState(); + preLogicalPlanVerifier.verify(session, state, expr); + if (state.getErrorMessages().size() > 0) { + if (!condition && state.getErrorMessages().size() > 0) { + throw new PlanningException(state.getErrorMessages().get(0)); + } + assertFalse(state.getErrorMessages().get(0), true); + } + LogicalPlan plan = planner.createPlan(session, expr, true); + optimizer.optimize(plan); + annotatedPlanVerifier.verify(session, state, plan); + + if (state.getErrorMessages().size() > 0) { + assertFalse(state.getErrorMessages().get(0), true); + } + + Target [] targets = plan.getRootBlock().getRawTargets(); + if (targets == null) { + throw new PlanningException("Wrong query statement or query plan: " + parsedResults.get(0).getStatement()); + } + for (Target t : targets) { + assertJsonSerDer(t.getEvalTree()); + } + return targets; + } + + public void testSimpleEval(String query, String [] expected) throws IOException { + testEval(null, null, null, query, expected); + } + + public void testSimpleEval(String query, String [] expected, boolean condition) throws IOException { + testEval(null, null, null, query, expected, ',', condition); + } + + public void testEval(Schema schema, String tableName, String csvTuple, String query, String [] expected) + throws IOException { + testEval(schema, tableName != null ? CatalogUtil.normalizeIdentifier(tableName) : null, csvTuple, query, + expected, ',', true); + } + + public void testEval(Schema schema, String tableName, String csvTuple, String query, String [] expected, + char delimiter, boolean condition) throws IOException { + LazyTuple lazyTuple; + VTuple vtuple = null; + String qualifiedTableName = + CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, + tableName != null ? CatalogUtil.normalizeIdentifier(tableName) : null); + Schema inputSchema = null; + if (schema != null) { + inputSchema = SchemaUtil.clone(schema); + inputSchema.setQualifier(qualifiedTableName); + + int targetIdx [] = new int[inputSchema.size()]; + for (int i = 0; i < targetIdx.length; i++) { + targetIdx[i] = i; + } + + lazyTuple = + new LazyTuple(inputSchema, Bytes.splitPreserveAllTokens(csvTuple.getBytes(), delimiter, targetIdx),0); + vtuple = new VTuple(inputSchema.size()); + for (int i = 0; i < inputSchema.size(); i++) { + // If null value occurs, null datum is manually inserted to an input tuple. + if (lazyTuple.get(i) instanceof TextDatum && lazyTuple.get(i).asChars().equals("")) { + vtuple.put(i, NullDatum.get()); + } else { + vtuple.put(i, lazyTuple.get(i)); + } + } + cat.createTable(new TableDesc(qualifiedTableName, inputSchema, + CatalogProtos.StoreType.CSV, new Options(), CommonTestingUtil.getTestDir())); + } + + Target [] targets; + + try { + targets = getRawTargets(query, condition); + + Tuple outTuple = new VTuple(targets.length); + for (int i = 0; i < targets.length; i++) { + EvalNode eval = targets[i].getEvalTree(); + outTuple.put(i, eval.eval(inputSchema, vtuple)); + } + + for (int i = 0; i < expected.length; i++) { + assertEquals(query, expected[i], outTuple.get(i).asChars()); + } + } catch (InvalidStatementException e) { + assertFalse(e.getMessage(), true); + } catch (PlanningException e) { + // In failure test case, an exception must occur while executing query. + // So, we should check an error message, and return it. + if (!condition) { + assertEquals(expected[0], e.getMessage()); + } else { + assertFalse(e.getMessage(), true); + } + } finally { + if (schema != null) { + cat.dropTable(qualifiedTableName); + } + } + } +} http://git-wip-us.apache.org/repos/asf/tajo/blob/026368be/tajo-core/src/test/java/org/apache/tajo/engine/eval/TestEvalTree.java ---------------------------------------------------------------------- diff --git a/tajo-core/src/test/java/org/apache/tajo/engine/eval/TestEvalTree.java b/tajo-core/src/test/java/org/apache/tajo/engine/eval/TestEvalTree.java new file mode 100644 index 0000000..9d7e438 --- /dev/null +++ b/tajo-core/src/test/java/org/apache/tajo/engine/eval/TestEvalTree.java @@ -0,0 +1,323 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.tajo.engine.eval; + +import org.apache.tajo.catalog.CatalogUtil; +import org.apache.tajo.catalog.Schema; +import org.apache.tajo.common.TajoDataTypes.DataType; +import org.apache.tajo.datum.Datum; +import org.apache.tajo.datum.DatumFactory; +import org.apache.tajo.engine.json.CoreGsonHelper; +import org.apache.tajo.storage.Tuple; +import org.apache.tajo.storage.VTuple; +import org.junit.Test; + +import static org.apache.tajo.common.TajoDataTypes.Type.*; +import static org.junit.Assert.*; + +public class TestEvalTree extends ExprTestBase{ + @Test + public void testTupleEval() throws CloneNotSupportedException { + ConstEval e1 = new ConstEval(DatumFactory.createInt4(1)); + assertCloneEqual(e1); + FieldEval e2 = new FieldEval("table1.score", CatalogUtil.newSimpleDataType(INT4)); // it indicates + assertCloneEqual(e2); + + Schema schema1 = new Schema(); + schema1.addColumn("table1.id", INT4); + schema1.addColumn("table1.score", INT4); + + BinaryEval expr = new BinaryEval(EvalType.PLUS, e1, e2); + assertCloneEqual(expr); + VTuple tuple = new VTuple(2); + tuple.put(0, DatumFactory.createInt4(1)); // put 0th field + tuple.put(1, DatumFactory.createInt4(99)); // put 0th field + + // the result of evaluation must be 100. + assertEquals(expr.eval(schema1, tuple).asInt4(), 100); + } + + public static class MockTrueEval extends EvalNode { + + public MockTrueEval() { + super(EvalType.CONST); + } + + @Override + public String getName() { + return this.getClass().getName(); + } + + @Override + public Datum eval(Schema schema, Tuple tuple) { + return DatumFactory.createBool(true); + } + + @Override + public boolean equals(Object obj) { + return true; + } + + @Override + public DataType getValueType() { + return CatalogUtil.newSimpleDataType(BOOLEAN); + } + + } + + public static class MockFalseExpr extends EvalNode { + + public MockFalseExpr() { + super(EvalType.CONST); + } + + @Override + public Datum eval(Schema schema, Tuple tuple) { + return DatumFactory.createBool(false); + } + + @Override + public boolean equals(Object obj) { + return true; + } + + @Override + public String getName() { + return this.getClass().getName(); + } + + @Override + public DataType getValueType() { + return CatalogUtil.newSimpleDataType(BOOLEAN); + } + } + + @Test + public void testAndTest() { + MockTrueEval trueExpr = new MockTrueEval(); + MockFalseExpr falseExpr = new MockFalseExpr(); + + BinaryEval andExpr = new BinaryEval(EvalType.AND, trueExpr, trueExpr); + assertTrue(andExpr.eval(null, null).asBool()); + + andExpr = new BinaryEval(EvalType.AND, falseExpr, trueExpr); + assertFalse(andExpr.eval(null, null).asBool()); + + andExpr = new BinaryEval(EvalType.AND, trueExpr, falseExpr); + assertFalse(andExpr.eval(null, null).asBool()); + + andExpr = new BinaryEval(EvalType.AND, falseExpr, falseExpr); + assertFalse(andExpr.eval(null, null).asBool()); + } + + @Test + public void testOrTest() { + MockTrueEval trueExpr = new MockTrueEval(); + MockFalseExpr falseExpr = new MockFalseExpr(); + + BinaryEval orExpr = new BinaryEval(EvalType.OR, trueExpr, trueExpr); + assertTrue(orExpr.eval(null, null).asBool()); + + orExpr = new BinaryEval(EvalType.OR, falseExpr, trueExpr); + assertTrue(orExpr.eval(null, null).asBool()); + + orExpr = new BinaryEval(EvalType.OR, trueExpr, falseExpr); + assertTrue(orExpr.eval(null, null).asBool()); + + orExpr = new BinaryEval(EvalType.OR, falseExpr, falseExpr); + assertFalse(orExpr.eval(null, null).asBool()); + } + + @Test + public final void testCompOperator() { + ConstEval e1; + ConstEval e2; + BinaryEval expr; + + // Constant + e1 = new ConstEval(DatumFactory.createInt4(9)); + e2 = new ConstEval(DatumFactory.createInt4(34)); + expr = new BinaryEval(EvalType.LTH, e1, e2); + assertTrue(expr.eval(null, null).asBool()); + expr = new BinaryEval(EvalType.LEQ, e1, e2); + assertTrue(expr.eval(null, null).asBool()); + expr = new BinaryEval(EvalType.LTH, e2, e1); + assertFalse(expr.eval(null, null).asBool()); + expr = new BinaryEval(EvalType.LEQ, e2, e1); + assertFalse(expr.eval(null, null).asBool()); + + expr = new BinaryEval(EvalType.GTH, e2, e1); + assertTrue(expr.eval(null, null).asBool()); + expr = new BinaryEval(EvalType.GEQ, e2, e1); + assertTrue(expr.eval(null, null).asBool()); + expr = new BinaryEval(EvalType.GTH, e1, e2); + assertFalse(expr.eval(null, null).asBool()); + expr = new BinaryEval(EvalType.GEQ, e1, e2); + assertFalse(expr.eval(null, null).asBool()); + + BinaryEval plus = new BinaryEval(EvalType.PLUS, e1, e2); + expr = new BinaryEval(EvalType.LTH, e1, plus); + assertTrue(expr.eval(null, null).asBool()); + expr = new BinaryEval(EvalType.LEQ, e1, plus); + assertTrue(expr.eval(null, null).asBool()); + expr = new BinaryEval(EvalType.LTH, plus, e1); + assertFalse(expr.eval(null, null).asBool()); + expr = new BinaryEval(EvalType.LEQ, plus, e1); + assertFalse(expr.eval(null, null).asBool()); + + expr = new BinaryEval(EvalType.GTH, plus, e1); + assertTrue(expr.eval(null, null).asBool()); + expr = new BinaryEval(EvalType.GEQ, plus, e1); + assertTrue(expr.eval(null, null).asBool()); + expr = new BinaryEval(EvalType.GTH, e1, plus); + assertFalse(expr.eval(null, null).asBool()); + expr = new BinaryEval(EvalType.GEQ, e1, plus); + assertFalse(expr.eval(null, null).asBool()); + } + + @Test + public final void testArithmaticsOperator() + throws CloneNotSupportedException { + ConstEval e1; + ConstEval e2; + + // PLUS + e1 = new ConstEval(DatumFactory.createInt4(9)); + e2 = new ConstEval(DatumFactory.createInt4(34)); + BinaryEval expr = new BinaryEval(EvalType.PLUS, e1, e2); + assertEquals(expr.eval(null, null).asInt4(), 43); + assertCloneEqual(expr); + + // MINUS + e1 = new ConstEval(DatumFactory.createInt4(5)); + e2 = new ConstEval(DatumFactory.createInt4(2)); + expr = new BinaryEval(EvalType.MINUS, e1, e2); + assertEquals(expr.eval(null, null).asInt4(), 3); + assertCloneEqual(expr); + + // MULTIPLY + e1 = new ConstEval(DatumFactory.createInt4(5)); + e2 = new ConstEval(DatumFactory.createInt4(2)); + expr = new BinaryEval(EvalType.MULTIPLY, e1, e2); + assertEquals(expr.eval(null, null).asInt4(), 10); + assertCloneEqual(expr); + + // DIVIDE + e1 = new ConstEval(DatumFactory.createInt4(10)); + e2 = new ConstEval(DatumFactory.createInt4(5)); + expr = new BinaryEval(EvalType.DIVIDE, e1, e2); + assertEquals(expr.eval(null, null).asInt4(), 2); + assertCloneEqual(expr); + } + + @Test + public final void testGetReturnType() { + ConstEval e1; + ConstEval e2; + + // PLUS + e1 = new ConstEval(DatumFactory.createInt4(9)); + e2 = new ConstEval(DatumFactory.createInt4(34)); + BinaryEval expr = new BinaryEval(EvalType.PLUS, e1, e2); + assertEquals(CatalogUtil.newSimpleDataType(INT4), expr.getValueType()); + + expr = new BinaryEval(EvalType.LTH, e1, e2); + assertTrue(expr.eval(null, null).asBool()); + assertEquals(CatalogUtil.newSimpleDataType(BOOLEAN), expr.getValueType()); + + e1 = new ConstEval(DatumFactory.createFloat8(9.3)); + e2 = new ConstEval(DatumFactory.createFloat8(34.2)); + expr = new BinaryEval(EvalType.PLUS, e1, e2); + assertEquals(CatalogUtil.newSimpleDataType(FLOAT8), expr.getValueType()); + } + + @Test + public final void testEquals() throws CloneNotSupportedException { + ConstEval e1; + ConstEval e2; + + // PLUS + e1 = new ConstEval(DatumFactory.createInt4(34)); + e2 = new ConstEval(DatumFactory.createInt4(34)); + assertEquals(e1, e2); + + BinaryEval plus1 = new BinaryEval(EvalType.PLUS, e1, e2); + BinaryEval plus2 = new BinaryEval(EvalType.PLUS, e2, e1); + assertEquals(plus1, plus2); + + ConstEval e3 = new ConstEval(DatumFactory.createInt4(29)); + BinaryEval plus3 = new BinaryEval(EvalType.PLUS, e1, e3); + assertFalse(plus1.equals(plus3)); + + // LTH + ConstEval e4 = new ConstEval(DatumFactory.createInt4(9)); + ConstEval e5 = new ConstEval(DatumFactory.createInt4(34)); + BinaryEval compExpr1 = new BinaryEval(EvalType.LTH, e4, e5); + assertCloneEqual(compExpr1); + + ConstEval e6 = new ConstEval(DatumFactory.createInt4(9)); + ConstEval e7 = new ConstEval(DatumFactory.createInt4(34)); + BinaryEval compExpr2 = new BinaryEval(EvalType.LTH, e6, e7); + assertCloneEqual(compExpr2); + + assertTrue(compExpr1.equals(compExpr2)); + } + + @Test + public final void testJson() throws CloneNotSupportedException { + ConstEval e1; + ConstEval e2; + + // 29 > (34 + 5) + (5 + 34) + e1 = new ConstEval(DatumFactory.createInt4(34)); + e2 = new ConstEval(DatumFactory.createInt4(5)); + assertCloneEqual(e1); + + BinaryEval plus1 = new BinaryEval(EvalType.PLUS, e1, e2); + assertCloneEqual(plus1); + BinaryEval plus2 = new BinaryEval(EvalType.PLUS, e2, e1); + assertCloneEqual(plus2); + BinaryEval plus3 = new BinaryEval(EvalType.PLUS, plus2, plus1); + assertCloneEqual(plus3); + + ConstEval e3 = new ConstEval(DatumFactory.createInt4(29)); + BinaryEval gth = new BinaryEval(EvalType.GTH, e3, plus3); + assertCloneEqual(gth); + + String json = gth.toJson(); + EvalNode eval = CoreGsonHelper.fromJson(json, EvalNode.class); + assertCloneEqual(eval); + + assertEquals(gth.getType(), eval.getType()); + assertEquals(e3.getType(), eval.getLeftExpr().getType()); + assertEquals(plus3.getType(), eval.getRightExpr().getType()); + assertEquals(plus3.getLeftExpr(), eval.getRightExpr().getLeftExpr()); + assertEquals(plus3.getRightExpr(), eval.getRightExpr().getRightExpr()); + assertEquals(plus2.getLeftExpr(), eval.getRightExpr().getLeftExpr().getLeftExpr()); + assertEquals(plus2.getRightExpr(), eval.getRightExpr().getLeftExpr().getRightExpr()); + assertEquals(plus1.getLeftExpr(), eval.getRightExpr().getRightExpr().getLeftExpr()); + assertEquals(plus1.getRightExpr(), eval.getRightExpr().getRightExpr().getRightExpr()); + } + + private void assertCloneEqual(EvalNode eval) throws CloneNotSupportedException { + EvalNode copy = (EvalNode) eval.clone(); + assertEquals(eval, copy); + assertFalse(eval == copy); + } +} http://git-wip-us.apache.org/repos/asf/tajo/blob/026368be/tajo-core/src/test/java/org/apache/tajo/engine/eval/TestEvalTreeUtil.java ---------------------------------------------------------------------- diff --git a/tajo-core/src/test/java/org/apache/tajo/engine/eval/TestEvalTreeUtil.java b/tajo-core/src/test/java/org/apache/tajo/engine/eval/TestEvalTreeUtil.java new file mode 100644 index 0000000..d916bbc --- /dev/null +++ b/tajo-core/src/test/java/org/apache/tajo/engine/eval/TestEvalTreeUtil.java @@ -0,0 +1,359 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.tajo.engine.eval; + +import com.google.common.collect.Sets; +import org.apache.tajo.LocalTajoTestingUtility; +import org.apache.tajo.TajoConstants; +import org.apache.tajo.TajoTestingCluster; +import org.apache.tajo.algebra.Expr; +import org.apache.tajo.algebra.OpType; +import org.apache.tajo.algebra.Selection; +import org.apache.tajo.catalog.*; +import org.apache.tajo.catalog.proto.CatalogProtos.FunctionType; +import org.apache.tajo.catalog.proto.CatalogProtos.StoreType; +import org.apache.tajo.common.TajoDataTypes; +import org.apache.tajo.datum.Datum; +import org.apache.tajo.datum.DatumFactory; +import org.apache.tajo.engine.function.GeneralFunction; +import org.apache.tajo.engine.parser.SQLAnalyzer; +import org.apache.tajo.engine.planner.LogicalPlan; +import org.apache.tajo.engine.planner.LogicalPlanner; +import org.apache.tajo.engine.planner.PlanningException; +import org.apache.tajo.engine.planner.Target; +import org.apache.tajo.engine.planner.logical.GroupbyNode; +import org.apache.tajo.engine.planner.logical.NodeType; +import org.apache.tajo.exception.InternalException; +import org.apache.tajo.master.TajoMaster; +import org.apache.tajo.master.session.Session; +import org.apache.tajo.storage.Tuple; +import org.apache.tajo.util.CommonTestingUtil; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Set; + +import static org.apache.tajo.TajoConstants.DEFAULT_TABLESPACE_NAME; +import static org.apache.tajo.common.TajoDataTypes.Type.INT4; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +public class TestEvalTreeUtil { + static TajoTestingCluster util; + static CatalogService catalog = null; + static EvalNode expr1; + static EvalNode expr2; + static EvalNode expr3; + static SQLAnalyzer analyzer; + static LogicalPlanner planner; + static Session session = LocalTajoTestingUtility.createDummySession(); + + public static class TestSum extends GeneralFunction { + private Integer x; + private Integer y; + + public TestSum() { + super(new Column[] { new Column("arg1", INT4), + new Column("arg2", INT4) }); + } + + @Override + public Datum eval(Tuple params) { + x = params.get(0).asInt4(); + y = params.get(1).asInt4(); + return DatumFactory.createInt4(x + y); + } + } + + @BeforeClass + public static void setUp() throws Exception { + util = new TajoTestingCluster(); + util.startCatalogCluster(); + catalog = util.getMiniCatalogCluster().getCatalog(); + for (FunctionDesc funcDesc : TajoMaster.initBuiltinFunctions()) { + catalog.createFunction(funcDesc); + } + catalog.createTablespace(DEFAULT_TABLESPACE_NAME, "hdfs://localhost:1234/warehouse"); + catalog.createDatabase(TajoConstants.DEFAULT_DATABASE_NAME, DEFAULT_TABLESPACE_NAME); + + Schema schema = new Schema(); + schema.addColumn("name", TajoDataTypes.Type.TEXT); + schema.addColumn("score", TajoDataTypes.Type.INT4); + schema.addColumn("age", TajoDataTypes.Type.INT4); + + TableMeta meta = CatalogUtil.newTableMeta(StoreType.CSV); + TableDesc desc = new TableDesc( + CatalogUtil.buildFQName(TajoConstants.DEFAULT_DATABASE_NAME, "people"), schema, meta, + CommonTestingUtil.getTestDir()); + catalog.createTable(desc); + + FunctionDesc funcMeta = new FunctionDesc("test_sum", TestSum.class, + FunctionType.GENERAL, + CatalogUtil.newSimpleDataType(TajoDataTypes.Type.INT4), + CatalogUtil.newSimpleDataTypeArray(TajoDataTypes.Type.INT4, TajoDataTypes.Type.INT4)); + catalog.createFunction(funcMeta); + + analyzer = new SQLAnalyzer(); + planner = new LogicalPlanner(catalog); + + String[] QUERIES = { + "select name, score, age from people where score > 30", // 0 + "select name, score, age from people where score * age", // 1 + "select name, score, age from people where test_sum(score * age, 50)", // 2 + }; + + expr1 = getRootSelection(QUERIES[0]); + expr2 = getRootSelection(QUERIES[1]); + expr3 = getRootSelection(QUERIES[2]); + } + + @AfterClass + public static void tearDown() throws Exception { + util.shutdownCatalogCluster(); + } + + public static Target [] getRawTargets(String query) { + Expr expr = analyzer.parse(query); + LogicalPlan plan = null; + try { + plan = planner.createPlan(session, expr); + } catch (PlanningException e) { + e.printStackTrace(); + } + + return plan.getRootBlock().getRawTargets(); + } + + public static EvalNode getRootSelection(String query) throws PlanningException { + Expr block = analyzer.parse(query); + LogicalPlan plan = null; + try { + plan = planner.createPlan(session, block); + } catch (PlanningException e) { + e.printStackTrace(); + } + + Selection selection = plan.getRootBlock().getSingletonExpr(OpType.Filter); + return planner.getExprAnnotator().createEvalNode(plan, plan.getRootBlock(), selection.getQual()); + } + + @Test + public final void testChangeColumnRef() throws CloneNotSupportedException { + EvalNode copy = (EvalNode)expr1.clone(); + EvalTreeUtil.changeColumnRef(copy, "default.people.score", "newscore"); + Set set = EvalTreeUtil.findUniqueColumns(copy); + assertEquals(1, set.size()); + assertTrue(set.contains(new Column("newscore", TajoDataTypes.Type.INT4))); + + copy = (EvalNode)expr2.clone(); + EvalTreeUtil.changeColumnRef(copy, "default.people.age", "sum_age"); + set = EvalTreeUtil.findUniqueColumns(copy); + assertEquals(2, set.size()); + assertTrue(set.contains(new Column("default.people.score", TajoDataTypes.Type.INT4))); + assertTrue(set.contains(new Column("sum_age", TajoDataTypes.Type.INT4))); + + copy = (EvalNode)expr3.clone(); + EvalTreeUtil.changeColumnRef(copy, "default.people.age", "sum_age"); + set = EvalTreeUtil.findUniqueColumns(copy); + assertEquals(2, set.size()); + assertTrue(set.contains(new Column("default.people.score", TajoDataTypes.Type.INT4))); + assertTrue(set.contains(new Column("sum_age", TajoDataTypes.Type.INT4))); + } + + @Test + public final void testFindAllRefColumns() { + Set set = EvalTreeUtil.findUniqueColumns(expr1); + assertEquals(1, set.size()); + assertTrue(set.contains(new Column("default.people.score", TajoDataTypes.Type.INT4))); + + set = EvalTreeUtil.findUniqueColumns(expr2); + assertEquals(2, set.size()); + assertTrue(set.contains(new Column("default.people.score", TajoDataTypes.Type.INT4))); + assertTrue(set.contains(new Column("default.people.age", TajoDataTypes.Type.INT4))); + + set = EvalTreeUtil.findUniqueColumns(expr3); + assertEquals(2, set.size()); + assertTrue(set.contains(new Column("default.people.score", TajoDataTypes.Type.INT4))); + assertTrue(set.contains(new Column("default.people.age", TajoDataTypes.Type.INT4))); + } + + public static final String [] QUERIES = { + "select 3 + 4 as plus, (3.5 * 2) as mul", // 0 + "select (score + 3) < 4, age > 5 from people", // 1 + "select score from people where score > 7", // 2 + "select score from people where (10 * 2) * (score + 2) > 20 + 30 + 10", // 3 + "select score from people where 10 * 2 > score * 10", // 4 + "select score from people where score < 10 and 4 < score", // 5 + "select score from people where score < 10 and 4 < score and age > 5", // 6 + "select score from people where (score > 1 and score < 3) or (7 < score and score < 10)", // 7 + }; + + @Test + public final void testGetSchemaFromTargets() throws InternalException { + Target [] targets = getRawTargets(QUERIES[0]); + Schema schema = EvalTreeUtil.getSchemaByTargets(null, targets); + Column col1 = schema.getColumn(0); + Column col2 = schema.getColumn(1); + assertEquals("plus", col1.getSimpleName()); + assertEquals(TajoDataTypes.Type.INT4, col1.getDataType().getType()); + assertEquals("mul", col2.getSimpleName()); + assertEquals(TajoDataTypes.Type.FLOAT8, col2.getDataType().getType()); + } + + @Test + public final void testGetContainExprs() throws CloneNotSupportedException, PlanningException { + Expr expr = analyzer.parse(QUERIES[1]); + LogicalPlan plan = planner.createPlan(session, expr, true); + Target [] targets = plan.getRootBlock().getRawTargets(); + Column col1 = new Column("default.people.score", TajoDataTypes.Type.INT4); + Collection exprs = + EvalTreeUtil.getContainExpr(targets[0].getEvalTree(), col1); + EvalNode node = exprs.iterator().next(); + assertEquals(EvalType.LTH, node.getType()); + assertEquals(EvalType.PLUS, node.getLeftExpr().getType()); + assertEquals(new ConstEval(DatumFactory.createInt4(4)), node.getRightExpr()); + + Column col2 = new Column("default.people.age", TajoDataTypes.Type.INT4); + exprs = EvalTreeUtil.getContainExpr(targets[1].getEvalTree(), col2); + node = exprs.iterator().next(); + assertEquals(EvalType.GTH, node.getType()); + assertEquals("default.people.age", node.getLeftExpr().getName()); + assertEquals(new ConstEval(DatumFactory.createInt4(5)), node.getRightExpr()); + } + + @Test + public final void testGetCNF() throws PlanningException { + // "select score from people where score < 10 and 4 < score " + EvalNode node = getRootSelection(QUERIES[5]); + EvalNode [] cnf = AlgebraicUtil.toConjunctiveNormalFormArray(node); + + Column col1 = new Column("default.people.score", TajoDataTypes.Type.INT4); + + assertEquals(2, cnf.length); + EvalNode first = cnf[0]; + EvalNode second = cnf[1]; + + FieldEval field = first.getLeftExpr(); + assertEquals(col1, field.getColumnRef()); + assertEquals(EvalType.LTH, first.getType()); + assertEquals(10, first.getRightExpr().eval(null, null).asInt4()); + + field = second.getRightExpr(); + assertEquals(col1, field.getColumnRef()); + assertEquals(EvalType.LTH, second.getType()); + assertEquals(4, second.getLeftExpr().eval(null, null).asInt4()); + } + + @Test + public final void testTransformCNF2Singleton() throws PlanningException { + // "select score from people where score < 10 and 4 < score " + EvalNode node = getRootSelection(QUERIES[6]); + EvalNode [] cnf1 = AlgebraicUtil.toConjunctiveNormalFormArray(node); + assertEquals(3, cnf1.length); + + EvalNode conj = AlgebraicUtil.createSingletonExprFromCNF(cnf1); + EvalNode [] cnf2 = AlgebraicUtil.toConjunctiveNormalFormArray(conj); + + Set set1 = Sets.newHashSet(cnf1); + Set set2 = Sets.newHashSet(cnf2); + assertEquals(set1, set2); + } + + @Test + public final void testGetDNF() throws PlanningException { + // "select score from people where score > 1 and score < 3 or score > 7 and score < 10", // 7 + EvalNode node = getRootSelection(QUERIES[7]); + EvalNode [] cnf = AlgebraicUtil.toDisjunctiveNormalFormArray(node); + assertEquals(2, cnf.length); + + assertEquals("default.people.score (INT4) > 1 AND default.people.score (INT4) < 3", cnf[0].toString()); + assertEquals("7 < default.people.score (INT4) AND default.people.score (INT4) < 10", cnf[1].toString()); + } + + @Test + public final void testSimplify() throws PlanningException { + Target [] targets = getRawTargets(QUERIES[0]); + EvalNode node = AlgebraicUtil.eliminateConstantExprs(targets[0].getEvalTree()); + assertEquals(EvalType.CONST, node.getType()); + assertEquals(7, node.eval(null, null).asInt4()); + node = AlgebraicUtil.eliminateConstantExprs(targets[1].getEvalTree()); + assertEquals(EvalType.CONST, node.getType()); + assertTrue(7.0d == node.eval(null, null).asFloat8()); + + Expr expr = analyzer.parse(QUERIES[1]); + LogicalPlan plan = planner.createPlan(session, expr, true); + targets = plan.getRootBlock().getRawTargets(); + Column col1 = new Column("default.people.score", TajoDataTypes.Type.INT4); + Collection exprs = + EvalTreeUtil.getContainExpr(targets[0].getEvalTree(), col1); + node = exprs.iterator().next(); + } + + @Test + public final void testConatainSingleVar() throws PlanningException { + EvalNode node = getRootSelection(QUERIES[2]); + assertEquals(true, AlgebraicUtil.containSingleVar(node)); + node = getRootSelection(QUERIES[3]); + assertEquals(true, AlgebraicUtil.containSingleVar(node)); + } + + @Test + public final void testTranspose() throws PlanningException { + Column col1 = new Column("default.people.score", TajoDataTypes.Type.INT4); + EvalNode node = getRootSelection(QUERIES[3]); + // we expect that score < 3 + EvalNode transposed = AlgebraicUtil.transpose(node, col1); + assertEquals(EvalType.GTH, transposed.getType()); + FieldEval field = transposed.getLeftExpr(); + assertEquals(col1, field.getColumnRef()); + assertEquals(1, transposed.getRightExpr().eval(null, null).asInt4()); + + node = getRootSelection(QUERIES[4]); + // we expect that score < 3 + transposed = AlgebraicUtil.transpose(node, col1); + assertEquals(EvalType.LTH, transposed.getType()); + field = transposed.getLeftExpr(); + assertEquals(col1, field.getColumnRef()); + assertEquals(2, transposed.getRightExpr().eval(null, null).asInt4()); + } + + @Test + public final void testFindDistinctAggFunctions() throws PlanningException { + String query = "select sum(score) + max(age) from people"; + Expr expr = analyzer.parse(query); + LogicalPlan plan = planner.createPlan(session, expr); + GroupbyNode groupByNode = plan.getRootBlock().getNode(NodeType.GROUP_BY); + EvalNode [] aggEvals = groupByNode.getAggFunctions(); + + List list = new ArrayList(); + for (int i = 0; i < aggEvals.length; i++) { + list.addAll(EvalTreeUtil.findDistinctAggFunction(aggEvals[i])); + } + assertEquals(2, list.size()); + + Set result = Sets.newHashSet("max", "sum"); + for (AggregationFunctionCallEval eval : list) { + assertTrue(result.contains(eval.getName())); + } + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/tajo/blob/026368be/tajo-core/src/test/java/org/apache/tajo/engine/eval/TestPredicates.java ---------------------------------------------------------------------- diff --git a/tajo-core/src/test/java/org/apache/tajo/engine/eval/TestPredicates.java b/tajo-core/src/test/java/org/apache/tajo/engine/eval/TestPredicates.java new file mode 100644 index 0000000..7811e69 --- /dev/null +++ b/tajo-core/src/test/java/org/apache/tajo/engine/eval/TestPredicates.java @@ -0,0 +1,396 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.tajo.engine.eval; + +import org.apache.tajo.catalog.Schema; +import org.junit.Test; + +import java.io.IOException; + +import static org.apache.tajo.common.TajoDataTypes.Type.BOOLEAN; +import static org.apache.tajo.common.TajoDataTypes.Type.INT4; +import static org.apache.tajo.common.TajoDataTypes.Type.TEXT; + +public class TestPredicates extends ExprTestBase { + + ////////////////////////////////////////////////////////////////// + // Logical Operator + ////////////////////////////////////////////////////////////////// + + @Test + public void testAnd() throws IOException { + testSimpleEval("select true;", new String[] {"t"}); + + testSimpleEval("select true and true;", new String[] {"t"}); + testSimpleEval("select true and false;", new String[] {"f"}); + testSimpleEval("select false and true;", new String[] {"f"}); + testSimpleEval("select false and false;", new String[] {"f"}); + } + + @Test + public void testOr() throws IOException { + testSimpleEval("select true or true;", new String[] {"t"}); + testSimpleEval("select true or false;", new String[] {"t"}); + testSimpleEval("select false or true;", new String[] {"t"}); + testSimpleEval("select false or false;", new String[] {"f"}); + } + + @Test + public void testLogicalOperatorPrecedence() throws IOException { + testSimpleEval("select true or (false or false) or false;", new String[] {"t"}); + testSimpleEval("select false or (true or false) or false;", new String[] {"t"}); + testSimpleEval("select false or (false or true) or false;", new String[] {"t"}); + testSimpleEval("select false or (false or false) or true;", new String[] {"t"}); + + testSimpleEval("select true and (false or false) or false;", new String[] {"f"}); + testSimpleEval("select false and (true or false) or false;", new String[] {"f"}); + testSimpleEval("select false and (false or true) or false;", new String[] {"f"}); + testSimpleEval("select false and (false or false) or true;", new String[] {"t"}); + + testSimpleEval("select true or (false and false) or false;", new String[] {"t"}); + testSimpleEval("select false or (true and false) or false;", new String[] {"f"}); + testSimpleEval("select false or (false and true) or false;", new String[] {"f"}); + testSimpleEval("select false or (false and true) or true;", new String[] {"t"}); + + testSimpleEval("select true or (false or false) and false;", new String[] {"t"}); + testSimpleEval("select false or (true or false) and false;", new String[] {"f"}); + testSimpleEval("select false or (false or true) and false;", new String[] {"f"}); + testSimpleEval("select false or (false or false) and true;", new String[] {"f"}); + } + + @Test + public void testNot() throws IOException { + + testSimpleEval("select true;", new String[] {"t"}); + testSimpleEval("select not true;", new String[] {"f"}); + testSimpleEval("select (true);", new String[] {"t"}); + testSimpleEval("select not (true);", new String[] {"f"}); + testSimpleEval("select not (not (true));", new String[] {"t"}); + + testSimpleEval("select (not (1 > null)) is null;", new String[] {"t"}); + + Schema schema1 = new Schema(); + schema1.addColumn("col1", INT4); + schema1.addColumn("col2", INT4); + schema1.addColumn("col3", INT4); + + testEval(schema1, + "table1", "123,123,456,-123", + "select col1 = col2, col1 = col3 from table1", + new String[]{"t", "f"}); + } + + @Test + public void testParenthesizedValues() throws IOException { + testSimpleEval("select ((true));", new String[] {"t"}); + testSimpleEval("select ((((true))));", new String[] {"t"}); + testSimpleEval("select not(not(not(false)));", new String[] {"t"}); + } + + ////////////////////////////////////////////////////////////////// + // Comparison Predicate + ////////////////////////////////////////////////////////////////// + + @Test + public void testComparisonEqual() throws IOException { + Schema schema1 = new Schema(); + schema1.addColumn("col1", INT4); + schema1.addColumn("col2", INT4); + schema1.addColumn("col3", INT4); + schema1.addColumn("col4", INT4); + testEval(schema1, + "table1", "123,123,456,-123", + "select col1 = col2, col1 = col3, col1 = col4 from table1", + new String[]{"t", "f", "f"}); + testEval(schema1, + "table1", "123,123,,", + "select col1 = col2, (col1 = col3) is null, (col3 = col2) is null from table1", + new String[]{"t", "t", "t"}); + } + + @Test + public void testComparisonNotEqual() throws IOException { + Schema schema1 = new Schema(); + schema1.addColumn("col1", INT4); + schema1.addColumn("col2", INT4); + schema1.addColumn("col3", INT4); + schema1.addColumn("col4", INT4); + testEval(schema1, + "table1", "123,123,456,-123", + "select col1 <> col2, col1 <> col3, col1 <> col4 from table1", + new String[]{"f", "t", "t"}); + testEval(schema1, + "table1", "123,123,,", + "select col1 <> col2, (col1 <> col3) is null, (col3 <> col2) is null from table1", + new String[]{"f", "t", "t"}); + } + + @Test + public void testComparisonLessThan() throws IOException { + Schema schema1 = new Schema(); + schema1.addColumn("col1", INT4); + schema1.addColumn("col2", INT4); + schema1.addColumn("col3", INT4); + schema1.addColumn("col4", INT4); + testEval(schema1, + "table1", "123,123,456,-123", + "select col1 < col2, col1 < col3, col1 < col4 from table1", + new String[]{"f", "t", "f"}); + testEval(schema1, + "table1", "123,456,,", + "select col1 < col2, (col1 = col3) is null, (col4 = col1) is null from table1", + new String[]{"t", "t", "t"}); + } + + @Test + public void testComparisonLessThanEqual() throws IOException { + Schema schema1 = new Schema(); + schema1.addColumn("col1", INT4); + schema1.addColumn("col2", INT4); + schema1.addColumn("col3", INT4); + schema1.addColumn("col4", INT4); + testEval(schema1, + "table1", "123,123,456,-123", + "select col1 <= col2, col1 <= col3, col1 <= col4 from table1", + new String[]{"t", "t", "f"}); + testEval(schema1, + "table1", "123,456,,", + "select col1 <= col2, (col1 <= col3) is null, (col4 <= col1) is null from table1", + new String[]{"t", "t", "t"}); + } + + @Test + public void testComparisonGreaterThan() throws IOException { + Schema schema1 = new Schema(); + schema1.addColumn("col1", INT4); + schema1.addColumn("col2", INT4); + schema1.addColumn("col3", INT4); + schema1.addColumn("col4", INT4); + testEval(schema1, + "table1", "123,123,456,-123", + "select col1 > col2, col3 > col2, col1 > col4 from table1", + new String[]{"f", "t", "t"}); + testEval(schema1, + "table1", "123,456,,", + "select col2 > col1, col1 > col2, (col1 > col3) is null, (col4 > col1) is null from table1", + new String[]{"t", "f", "t", "t"}); + } + + @Test + public void testComparisonGreaterThanEqual() throws IOException { + Schema schema1 = new Schema(); + schema1.addColumn("col1", INT4); + schema1.addColumn("col2", INT4); + schema1.addColumn("col3", INT4); + schema1.addColumn("col4", INT4); + testEval(schema1, + "table1", "123,123,456,-123", + "select col1 >= col2, col3 >= col2, col1 >= col4 from table1", + new String[]{"t", "t", "t"}); + testEval(schema1, + "table1", "123,456,,", + "select col2 >= col1, col1 >= col2, (col1 >= col3) is null, (col4 >= col1) is null from table1", + new String[]{"t", "f", "t", "t"}); + } + + ////////////////////////////////////////////////////////////////// + // Between Predicate + ////////////////////////////////////////////////////////////////// + + @Test + public void testBetween() throws IOException { + Schema schema2 = new Schema(); + schema2.addColumn("col1", TEXT); + schema2.addColumn("col2", TEXT); + schema2.addColumn("col3", TEXT); + + // constant checker + testEval(schema2, "table1", "b,a,c", "select col1 between 'a' and 'c' from table1", new String[]{"t"}); + testEval(schema2, "table1", "b,a,c", "select col1 between 'c' and 'a' from table1", new String[]{"f"}); + testEval(schema2, "table1", "b,a,c", "select col1 between symmetric 'c' and 'a' from table1", new String[]{"t"}); + testEval(schema2, "table1", "d,a,c", "select col1 between 'a' and 'c' from table1", new String[]{"f"}); + + // tests for inclusive + testEval(schema2, "table1", "a,a,c", "select col1 between col2 and col3 from table1", new String[]{"t"}); + testEval(schema2, "table1", "b,a,c", "select col1 between col2 and col3 from table1", new String[]{"t"}); + testEval(schema2, "table1", "c,a,c", "select col1 between col2 and col3 from table1", new String[]{"t"}); + testEval(schema2, "table1", "d,a,c", "select col1 between col2 and col3 from table1", new String[]{"f"}); + + // tests for asymmetric and symmetric + testEval(schema2, "table1", "b,a,c", "select col1 between col3 and col2 from table1", new String[]{"f"}); + testEval(schema2, "table1", "b,a,c", "select col1 between symmetric col3 and col2 from table1", new String[]{"t"}); + } + + @Test + public void testBetween2() throws IOException { // for TAJO-249 + Schema schema3 = new Schema(); + schema3.addColumn("date_a", INT4); + schema3.addColumn("date_b", INT4); + schema3.addColumn("date_c", INT4); + schema3.addColumn("date_d", INT4); + + String query = "select " + + "case " + + "when date_a BETWEEN 20130705 AND 20130715 AND ((date_b BETWEEN 20100101 AND 20120601) OR date_b > 20130715) " + + "AND (date_c < 20120601 OR date_c > 20130715) AND date_d > 20130715" + + "then 1 else 0 end from table1"; + + testEval(schema3, "table1", "20130715,20100102,20120525,20130716", query, new String [] {"1"}); + testEval(schema3, "table1", "20130716,20100102,20120525,20130716", query, new String [] {"0"}); + + // date_b + testEval(schema3, "table1", "20130715,20100102,20120525,20130716", query, new String [] {"1"}); + testEval(schema3, "table1", "20130715,20120602,20120525,20130716", query, new String [] {"0"}); + testEval(schema3, "table1", "20130715,20091201,20120525,20130716", query, new String [] {"0"}); + testEval(schema3, "table1", "20130715,20130716,20120525,20130716", query, new String [] {"1"}); + + // date_c + testEval(schema3, "table1", "20130715,20100102,20120525,20130716", query, new String [] {"1"}); + testEval(schema3, "table1", "20130715,20100102,20120602,20130716", query, new String [] {"0"}); + + testEval(schema3, "table1", "20130715,20100102,20130716,20130716", query, new String [] {"1"}); + testEval(schema3, "table1", "20130715,20100102,20130714,20130716", query, new String [] {"0"}); + + // date_d + testEval(schema3, "table1", "20130715,20100102,20120525,20130716", query, new String [] {"1"}); + testEval(schema3, "table1", "20130715,20100102,20120525,20130705", query, new String [] {"0"}); + } + + ////////////////////////////////////////////////////////////////// + // In Predicate + ////////////////////////////////////////////////////////////////// + + @Test + public void testInPredicateWithConstant() throws IOException { + Schema schema2 = new Schema(); + schema2.addColumn("col1", TEXT); + schema2.addColumn("col2", TEXT); + schema2.addColumn("col3", TEXT); + + testEval(schema2, "table1", "a,b,c", "select col1 in ('a'), col2 in ('a', 'c') from table1", new String[]{"t","f"}); + testEval(schema2, "table1", "a,,c", "select col1 in ('a','b','c'), (col2 in ('a', 'c')) is null from table1", + new String[]{"t","t"}); + + testEval(schema2, + "table1", + "2014-03-21,2015-04-01,2016-04-01", + "select substr(col1,1,4) in ('2014','2015','2016'), substr(col1,6,2)::int4 in (1,2,3) from table1", + new String[]{"t", "t"}); + + // null handling test + testEval(schema2, + "table1", + "2014-03-21,,2015-04-01", + "select (substr(col2,1,4)::int4 in (2014,2015,2016)) is null from table1", + new String[]{"t"}); + } + + @Test + public void testInPredicateWithSimpleExprs() throws IOException { + Schema schema2 = new Schema(); + schema2.addColumn("col1", TEXT); + schema2.addColumn("col2", INT4); + schema2.addColumn("col3", TEXT); + + testEval(schema2, "table1", "abc,2,3", "select col1 in ('a'||'b'||'c'), col2 in (1 + 1, 2 * 10, 2003) from table1", + new String[]{"t","t"}); + + testEval(schema2, "table1", "abc,2,3", "select col1 in ('a'||'b'), col2 in ('1'::int, '2'::int, 3) from table1", + new String[]{"f","t"}); + + testEval(schema2, + "table1", + "abc,,3", + "select col1 in (reverse('cba')), (col2 in ('1'::int, '2'::int, 3)) is null from table1", + new String[]{"t","t"}); + } + + ////////////////////////////////////////////////////////////////// + // Null Predicate + ////////////////////////////////////////////////////////////////// + + @Test + public void testIsNullPredicate() throws IOException { + Schema schema1 = new Schema(); + schema1.addColumn("col1", INT4); + schema1.addColumn("col2", INT4); + testEval(schema1, "table1", "123,", "select col1 is null, col2 is null as a from table1", + new String[]{"f", "t"}); + testEval(schema1, "table1", "123,", "select col1 is not null, col2 is not null as a from table1", + new String[]{"t", "f"}); + } + + @Test + public void testIsNullPredicateWithFunction() throws IOException { + Schema schema2 = new Schema(); + schema2.addColumn("col1", TEXT); + schema2.addColumn("col2", TEXT); + testEval(schema2, "table1", "_123,", "select ltrim(col1, '_') is null, upper(col2) is null as a from table1", + new String[]{"f", "t"}); + + testEval(schema2, "table1", "_123,", + "select ltrim(col1, '_') is not null, upper(col2) is not null as a from table1", new String[]{"t", "f"}); + } + + ////////////////////////////////////////////////////////////////// + // Boolean Test + ////////////////////////////////////////////////////////////////// + + @Test + public void testBooleanTest() throws IOException { + testSimpleEval("select 1 < 3 is true", new String [] {"t"}); + testSimpleEval("select 1 < 3 is not true", new String [] {"f"}); + testSimpleEval("select 1 < 3 is false", new String [] {"f"}); + testSimpleEval("select 1 < 3 is not false", new String [] {"t"}); + + testSimpleEval("select not (1 < 3 is true)", new String [] {"f"}); + testSimpleEval("select not (1 < 3 is not true)", new String [] {"t"}); + testSimpleEval("select not (1 < 3 is false)", new String [] {"t"}); + testSimpleEval("select not (1 < 3 is not false)", new String [] {"f"}); + + testSimpleEval("select 1 > 3 is true", new String [] {"f"}); + testSimpleEval("select 1 > 3 is not true", new String [] {"t"}); + testSimpleEval("select 1 > 3 is false", new String [] {"t"}); + testSimpleEval("select 1 > 3 is not false", new String [] {"f"}); + + testSimpleEval("select not (1 > 3 is true)", new String [] {"t"}); + testSimpleEval("select not (1 > 3 is not true)", new String [] {"f"}); + testSimpleEval("select not (1 > 3 is false)", new String [] {"f"}); + testSimpleEval("select not (1 > 3 is not false)", new String [] {"t"}); + } + + @Test + public void testBooleanTestOnTable() throws IOException { + Schema schema = new Schema(); + schema.addColumn("col1", BOOLEAN); + schema.addColumn("col2", BOOLEAN); + testEval(schema, "table1", "t,f", "select col1 is true, col2 is false from table1", new String [] {"t", "t"}); + testEval(schema, "table1", "t,f", "select col1 is not true, col2 is not false from table1", + new String [] {"f", "f"}); + testEval(schema, "table1", "t,f", "select not col1 is not true, not col2 is not false from table1", + new String [] {"t", "t"}); + } + + @Test + public void testCreateTableWithUnsupportedStoreType() throws IOException { + testSimpleEval("create table table1 (name text, age int) using RAW;", + new String[] {"Wrong query statement or query plan: create table table1 (name text, age int) using RAW"}, + false); + } +} http://git-wip-us.apache.org/repos/asf/tajo/blob/026368be/tajo-core/src/test/java/org/apache/tajo/engine/eval/TestSQLDateTimeTypes.java ---------------------------------------------------------------------- diff --git a/tajo-core/src/test/java/org/apache/tajo/engine/eval/TestSQLDateTimeTypes.java b/tajo-core/src/test/java/org/apache/tajo/engine/eval/TestSQLDateTimeTypes.java new file mode 100644 index 0000000..c9c8dd4 --- /dev/null +++ b/tajo-core/src/test/java/org/apache/tajo/engine/eval/TestSQLDateTimeTypes.java @@ -0,0 +1,53 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.tajo.engine.eval; + +import org.junit.Test; + +import java.io.IOException; + +public class TestSQLDateTimeTypes extends ExprTestBase { + + @Test + public void testTimestamp() throws IOException { + testSimpleEval("select TIMESTAMP '1970-01-17 10:09:37';", new String[]{"1970-01-17 10:09:37"}); + testSimpleEval("select TIMESTAMP '1970-01-17 10:09:37.5';", new String[]{"1970-01-17 10:09:37.5"}); + testSimpleEval("select TIMESTAMP '1970-01-17 10:09:37.01';", new String[]{"1970-01-17 10:09:37.01"}); + testSimpleEval("select TIMESTAMP '1970-01-17 10:09:37.003';", new String[]{"1970-01-17 10:09:37.003"}); + } + + @Test + public void testToTimestamp() throws IOException { + testSimpleEval("select to_char(TIMESTAMP '1970-01-17 10:09:37', 'yyyy-MM-dd HH:mm:ss');", + new String[]{"1970-01-17 10:09:37"}); + } + + @Test + public void testTimeLiteral() throws IOException { + testSimpleEval("select TIME '10:09:37';", + new String[]{"10:09:37"}); + } + + @Test + public void testDateLiteral() throws IOException { + testSimpleEval("select DATE '1970-01-17';", + new String[]{"1970-01-17"}); + } + +}