You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tajo.apache.org by hy...@apache.org on 2014/04/18 13:44:12 UTC
[09/57] [abbrv] [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/6594ac1c/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<String, String> 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<String> 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<FunctionDesc> catalogFunctions = cluster.getMaster().getCatalog().getFunctions();
+ String functionName = "sum";
+ int numFunctions = 0;
+ for(FunctionDesc eachFunction: catalogFunctions) {
+ if(functionName.equals(eachFunction.getSignature())) {
+ numFunctions++;
+ }
+ }
+
+ List<CatalogProtos.FunctionDescProto> 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<ClientProtos.BriefQueryInfo> 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/6594ac1c/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/6594ac1c/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<ParsedResult> 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/6594ac1c/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/6594ac1c/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<Column> 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<Column> 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<EvalNode> 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<EvalNode> set1 = Sets.newHashSet(cnf1);
+ Set<EvalNode> 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<EvalNode> 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<AggregationFunctionCallEval> list = new ArrayList<AggregationFunctionCallEval>();
+ for (int i = 0; i < aggEvals.length; i++) {
+ list.addAll(EvalTreeUtil.findDistinctAggFunction(aggEvals[i]));
+ }
+ assertEquals(2, list.size());
+
+ Set<String> 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/6594ac1c/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/6594ac1c/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"});
+ }
+
+}