diff --git a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/CatalogUtil.java b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/CatalogUtil.java index ac76387394..1222a18589 100644 --- a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/CatalogUtil.java +++ b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/CatalogUtil.java @@ -873,7 +873,11 @@ public static Pair, String> getPartitionKeyNamePair(Stri return pair; } - /* It is the relationship graph of type conversions. */ + /* + * It is the relationship graph of type conversions. + * It contains tuples, each of which (LHS type, RHS type, Result type). + */ + public static final Map> OPERATION_CASTING_MAP = Maps.newHashMap(); static { @@ -928,10 +932,22 @@ public static Pair, String> getPartitionKeyNamePair(Stri TUtil.putToNestedMap(OPERATION_CASTING_MAP, Type.FLOAT8, Type.FLOAT8, Type.FLOAT8); TUtil.putToNestedMap(OPERATION_CASTING_MAP, Type.FLOAT8, Type.TEXT, Type.TEXT); + + TUtil.putToNestedMap(OPERATION_CASTING_MAP, Type.TEXT, Type.DATE, Type.DATE); + TUtil.putToNestedMap(OPERATION_CASTING_MAP, Type.TEXT, Type.TIME, Type.TIME); TUtil.putToNestedMap(OPERATION_CASTING_MAP, Type.TEXT, Type.TIMESTAMP, Type.TIMESTAMP); + TUtil.putToNestedMap(OPERATION_CASTING_MAP, Type.TEXT, Type.TEXT, Type.TEXT); + TUtil.putToNestedMap(OPERATION_CASTING_MAP, Type.TEXT, Type.VARCHAR, Type.TEXT); + + TUtil.putToNestedMap(OPERATION_CASTING_MAP, Type.VARCHAR, Type.DATE, Type.DATE); + TUtil.putToNestedMap(OPERATION_CASTING_MAP, Type.VARCHAR, Type.TIME, Type.TIME); + TUtil.putToNestedMap(OPERATION_CASTING_MAP, Type.VARCHAR, Type.TIMESTAMP, Type.TIMESTAMP); + TUtil.putToNestedMap(OPERATION_CASTING_MAP, Type.VARCHAR, Type.TEXT, Type.TEXT); + TUtil.putToNestedMap(OPERATION_CASTING_MAP, Type.VARCHAR, Type.VARCHAR, Type.TEXT); + TUtil.putToNestedMap(OPERATION_CASTING_MAP, Type.TIMESTAMP, Type.TIMESTAMP, Type.TIMESTAMP); TUtil.putToNestedMap(OPERATION_CASTING_MAP, Type.TIMESTAMP, Type.TEXT, Type.TEXT); - TUtil.putToNestedMap(OPERATION_CASTING_MAP, Type.TEXT, Type.TEXT, Type.TEXT); + TUtil.putToNestedMap(OPERATION_CASTING_MAP, Type.TIMESTAMP, Type.VARCHAR, Type.TEXT); TUtil.putToNestedMap(OPERATION_CASTING_MAP, Type.TIME, Type.TIME, Type.TIME); TUtil.putToNestedMap(OPERATION_CASTING_MAP, Type.DATE, Type.DATE, Type.DATE); diff --git a/tajo-core-tests/src/test/java/org/apache/tajo/engine/query/TestTablePartitions.java b/tajo-core-tests/src/test/java/org/apache/tajo/engine/query/TestTablePartitions.java index 52e7b54cfa..fc0db1224b 100644 --- a/tajo-core-tests/src/test/java/org/apache/tajo/engine/query/TestTablePartitions.java +++ b/tajo-core-tests/src/test/java/org/apache/tajo/engine/query/TestTablePartitions.java @@ -37,14 +37,11 @@ import org.apache.tajo.engine.planner.global.ExecutionBlock; import org.apache.tajo.engine.planner.global.MasterPlan; import org.apache.tajo.ipc.ClientProtos; -import org.apache.tajo.jdbc.FetchResultSet; -import org.apache.tajo.jdbc.TajoMemoryResultSet; import org.apache.tajo.plan.logical.NodeType; import org.apache.tajo.querymaster.QueryMasterTask; import org.apache.tajo.storage.StorageConstants; import org.apache.tajo.util.CommonTestingUtil; import org.apache.tajo.util.KeyValueSet; -import org.apache.tajo.worker.TajoWorker; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; @@ -1081,25 +1078,6 @@ public final void testColumnPartitionedTableWithSmallerExpressions6() throws Exc executeString("DROP TABLE " + tableName + " PURGE").close(); } - private MasterPlan getQueryPlan(ResultSet res) { - QueryId queryId; - if (res instanceof TajoMemoryResultSet) { - queryId = ((TajoMemoryResultSet) res).getQueryId(); - } else { - queryId = ((FetchResultSet) res).getQueryId(); - } - - for (TajoWorker eachWorker : testingCluster.getTajoWorkers()) { - QueryMasterTask queryMasterTask = eachWorker.getWorkerContext().getQueryMaster().getQueryMasterTask(queryId, true); - if (queryMasterTask != null) { - return queryMasterTask.getQuery().getPlan(); - } - } - - fail("Can't find query from workers" + queryId); - return null; - } - @Test public void testScatteredHashShuffle() throws Exception { testingCluster.setAllTajoDaemonConfValue(TajoConf.ConfVars.$DIST_QUERY_TABLE_PARTITION_VOLUME.varname, "2"); diff --git a/tajo-core-tests/src/test/resources/queries/TestCreateTable/negative/type_mismatch.sql b/tajo-core-tests/src/test/resources/queries/TestCreateTable/negative/type_mismatch.sql new file mode 100644 index 0000000000..1bff25cd0d --- /dev/null +++ b/tajo-core-tests/src/test/resources/queries/TestCreateTable/negative/type_mismatch.sql @@ -0,0 +1,2 @@ +CREATE TABLE MISMATCH1 (n_name text, n_comment text, n_nationkey int8, n_regionkey int8) AS SELECT * FROM default.nation; +CREATE TABLE MISMATCH2 (n_name text, n_comment text) PARTITION BY COLUMN (n_nationkey int8, n_regionkey int8) AS SELECT * FROM default.nation; diff --git a/tajo-plan/src/main/java/org/apache/tajo/plan/verifier/LogicalPlanVerifier.java b/tajo-plan/src/main/java/org/apache/tajo/plan/verifier/LogicalPlanVerifier.java index 0b0968e747..c87ceb3379 100644 --- a/tajo-plan/src/main/java/org/apache/tajo/plan/verifier/LogicalPlanVerifier.java +++ b/tajo-plan/src/main/java/org/apache/tajo/plan/verifier/LogicalPlanVerifier.java @@ -19,6 +19,7 @@ package org.apache.tajo.plan.verifier; import com.google.common.base.Preconditions; +import org.apache.tajo.catalog.CatalogUtil; import org.apache.tajo.catalog.Column; import org.apache.tajo.catalog.Schema; import org.apache.tajo.common.TajoDataTypes.Type; @@ -31,6 +32,7 @@ import org.apache.tajo.plan.logical.*; import org.apache.tajo.plan.util.PlannerUtil; import org.apache.tajo.plan.visitor.BasicLogicalPlanVisitor; +import org.apache.tajo.util.TUtil; import java.util.Stack; @@ -241,7 +243,15 @@ public LogicalNode visitInsert(Context context, LogicalPlan plan, LogicalPlan.Qu private static void ensureDomains(VerificationState state, Schema targetTableScheme, Schema schema) throws TajoException { for (int i = 0; i < schema.size(); i++) { - if (!schema.getColumn(i).getDataType().equals(targetTableScheme.getColumn(i).getDataType())) { + + // null can be used anywhere + if (schema.getColumn(i).getDataType().getType() == Type.NULL_TYPE) { + continue; + } + + // checking castable between two data types + if (!TUtil.containsInNestedMap(CatalogUtil.OPERATION_CASTING_MAP, + schema.getColumn(i).getDataType().getType(), targetTableScheme.getColumn(i).getDataType().getType())) { Column targetColumn = targetTableScheme.getColumn(i); Column insertColumn = schema.getColumn(i); state.addVerification(makeDataTypeMisMatch(insertColumn, targetColumn)); @@ -254,6 +264,10 @@ public LogicalNode visitCreateTable(Context context, LogicalPlan plan, LogicalPl CreateTableNode node, Stack stack) throws TajoException { super.visitCreateTable(context, plan, block, node, stack); // here, we don't need check table existence because this check is performed in PreLogicalPlanVerifier. + + if (node.hasSubQuery()) { + ensureDomains(context.state, node.getLogicalSchema(), node.getChild(0).getOutSchema()); + } return node; } diff --git a/tajo-plan/src/main/java/org/apache/tajo/plan/verifier/SyntaxErrorUtil.java b/tajo-plan/src/main/java/org/apache/tajo/plan/verifier/SyntaxErrorUtil.java index 3c11b8ce6e..bf4a0d6bbd 100644 --- a/tajo-plan/src/main/java/org/apache/tajo/plan/verifier/SyntaxErrorUtil.java +++ b/tajo-plan/src/main/java/org/apache/tajo/plan/verifier/SyntaxErrorUtil.java @@ -21,6 +21,7 @@ import org.apache.tajo.catalog.Column; import org.apache.tajo.common.TajoDataTypes.DataType; import org.apache.tajo.error.Errors.ResultCode; +import org.apache.tajo.exception.DataTypeMismatchException; import org.apache.tajo.plan.logical.NodeType; public class SyntaxErrorUtil { @@ -29,8 +30,8 @@ public static SyntaxErrorException makeSyntaxError(String message) { return new SyntaxErrorException(ResultCode.SYNTAX_ERROR, message); } - public static SyntaxErrorException makeDataTypeMisMatch(Column src, Column target) { - return new SyntaxErrorException(ResultCode.DATATYPE_MISMATCH, + public static DataTypeMismatchException makeDataTypeMisMatch(Column src, Column target) { + return new DataTypeMismatchException( src.getSimpleName(), src.getDataType().getType().name(), target.getSimpleName(), target.getDataType().getType().name()); }