diff --git a/fe/fe-core/src/main/cup/sql_parser.cup b/fe/fe-core/src/main/cup/sql_parser.cup index f4e573d4253bc1..351a890eaed123 100644 --- a/fe/fe-core/src/main/cup/sql_parser.cup +++ b/fe/fe-core/src/main/cup/sql_parser.cup @@ -1236,6 +1236,21 @@ create_stmt ::= RESULT = new CreateTableStmt(ifNotExists, isExternal, name, columns, indexes, engineName, keys, partition, distribution, tblProperties, extProperties, tableComment, index); :} + | KW_CREATE opt_external:isExternal KW_TABLE opt_if_not_exists:ifNotExists table_name:name + opt_col_list:columns + opt_engine:engineName + opt_keys:keys + opt_comment:tableComment + opt_partition:partition + opt_distribution:distribution + opt_rollup:index + opt_properties:tblProperties + opt_ext_properties:extProperties + KW_AS query_stmt:query_def + {: + RESULT = new CreateTableAsSelectStmt(new CreateTableStmt(ifNotExists, isExternal, name, null, engineName, keys, partition, + distribution, tblProperties, extProperties, tableComment, index), columns, query_def); + :} /* User */ | KW_CREATE KW_USER opt_if_not_exists:ifNotExists grant_user:user opt_user_role:userRole {: diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/CreateTableAsSelectStmt.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/CreateTableAsSelectStmt.java index 9f2c188ec4e2d9..a5d17632f6a2aa 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/CreateTableAsSelectStmt.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/CreateTableAsSelectStmt.java @@ -17,12 +17,11 @@ package org.apache.doris.analysis; -import org.apache.doris.catalog.Table; -import org.apache.doris.common.AnalysisException; import org.apache.doris.common.ErrorCode; import org.apache.doris.common.ErrorReport; import org.apache.doris.common.UserException; +import java.util.ArrayList; import java.util.List; /** @@ -31,78 +30,49 @@ * CREATE TABLE table_name [( column_name_list )] * opt_engine opt_partition opt_properties KW_AS query_stmt */ -public class CreateTableAsSelectStmt extends StatementBase { +public class CreateTableAsSelectStmt extends DdlStmt { private final CreateTableStmt createTableStmt; private final List columnNames; - private final QueryStmt queryStmt; - private final InsertStmt insertStmt; - + private QueryStmt queryStmt; + public CreateTableAsSelectStmt(CreateTableStmt createTableStmt, - List columnNames, - QueryStmt queryStmt) { + List columnNames, QueryStmt queryStmt) { this.createTableStmt = createTableStmt; this.columnNames = columnNames; this.queryStmt = queryStmt; - this.insertStmt = new InsertStmt(createTableStmt.getDbTbl(), queryStmt); + // Insert is not currently supported } - + @Override - public void analyze(Analyzer analyzer) throws UserException, AnalysisException { + public void analyze(Analyzer analyzer) throws UserException { // first: we analyze queryStmt before create table. // To avoid duplicate registrations of table/colRefs, // create a new root analyzer and clone the query statement for this initial pass. Analyzer dummyRootAnalyzer = new Analyzer(analyzer.getCatalog(), analyzer.getContext()); QueryStmt tmpStmt = queryStmt.clone(); tmpStmt.analyze(dummyRootAnalyzer); - - // TODO(zc): support char, varchar and decimal - for (Expr expr : tmpStmt.getResultExprs()) { - if (expr.getType().isDecimalV2() || expr.getType().isStringType()) { + this.queryStmt = tmpStmt; + ArrayList resultExprs = getQueryStmt().getResultExprs(); + // TODO: support decimal + for (Expr expr : resultExprs) { + if (expr.getType().isDecimalV2()) { ErrorReport.reportAnalysisException(ErrorCode.ERR_UNSUPPORTED_TYPE_IN_CTAS, expr.getType()); } } - - // Check columnNames - if (columnNames != null) { - if (columnNames.size() != tmpStmt.getColLabels().size()) { - ErrorReport.report(ErrorCode.ERR_COL_NUMBER_NOT_MATCH); - } - for (int i = 0; i < columnNames.size(); ++i) { - createTableStmt.addColumnDef(new ColumnDef( - columnNames.get(i), new TypeDef(tmpStmt.getResultExprs().get(i).getType()))); - } - } else { - for (int i = 0; i < tmpStmt.getColLabels().size(); ++i) { - createTableStmt.addColumnDef(new ColumnDef( - tmpStmt.getColLabels().get(i), new TypeDef(tmpStmt.getResultExprs().get(i).getType()))); - } + if (columnNames != null && columnNames.size() != resultExprs.size()) { + ErrorReport.reportAnalysisException(ErrorCode.ERR_COL_NUMBER_NOT_MATCH); } - - // Analyze create table statement - createTableStmt.analyze(analyzer); - - // Analyze insert - Table newTable = null; - insertStmt.setTargetTable(newTable); - insertStmt.analyze(analyzer); } - - public void createTable(Analyzer analyzer) throws AnalysisException { - // TODO(zc): Support create table later. - // Create table - try { - analyzer.getCatalog().createTable(createTableStmt); - } catch (UserException e) { - throw new AnalysisException(e.getMessage()); - } + + public CreateTableStmt getCreateTableStmt() { + return createTableStmt; } - - public InsertStmt getInsertStmt() { - return insertStmt; + + public List getColumnNames() { + return columnNames; } - - @Override - public RedirectStatus getRedirectStatus() { - return RedirectStatus.FORWARD_WITH_SYNC; + + public QueryStmt getQueryStmt() { + return queryStmt; } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/CreateTableStmt.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/CreateTableStmt.java index 78fb1550e39015..854b81abe26d8d 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/CreateTableStmt.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/CreateTableStmt.java @@ -203,6 +203,10 @@ public DistributionDesc getDistributionDesc() { return this.distributionDesc; } + public void setDistributionDesc(DistributionDesc desc) { + this.distributionDesc = desc; + } + public Map getProperties() { return this.properties; } diff --git a/fe/fe-core/src/main/java/org/apache/doris/catalog/Catalog.java b/fe/fe-core/src/main/java/org/apache/doris/catalog/Catalog.java index bd8bf344da4304..924a798b17d6da 100755 --- a/fe/fe-core/src/main/java/org/apache/doris/catalog/Catalog.java +++ b/fe/fe-core/src/main/java/org/apache/doris/catalog/Catalog.java @@ -40,15 +40,19 @@ import org.apache.doris.analysis.AlterSystemStmt; import org.apache.doris.analysis.AlterTableStmt; import org.apache.doris.analysis.AlterViewStmt; +import org.apache.doris.analysis.Analyzer; import org.apache.doris.analysis.BackupStmt; import org.apache.doris.analysis.CancelAlterSystemStmt; import org.apache.doris.analysis.CancelAlterTableStmt; import org.apache.doris.analysis.CancelBackupStmt; +import org.apache.doris.analysis.ColumnDef; +import org.apache.doris.analysis.ColumnDef.DefaultValue; import org.apache.doris.analysis.ColumnRenameClause; import org.apache.doris.analysis.CreateClusterStmt; import org.apache.doris.analysis.CreateDbStmt; import org.apache.doris.analysis.CreateFunctionStmt; import org.apache.doris.analysis.CreateMaterializedViewStmt; +import org.apache.doris.analysis.CreateTableAsSelectStmt; import org.apache.doris.analysis.CreateTableLikeStmt; import org.apache.doris.analysis.CreateTableStmt; import org.apache.doris.analysis.CreateUserStmt; @@ -62,7 +66,9 @@ import org.apache.doris.analysis.DropMaterializedViewStmt; import org.apache.doris.analysis.DropPartitionClause; import org.apache.doris.analysis.DropTableStmt; +import org.apache.doris.analysis.Expr; import org.apache.doris.analysis.FunctionName; +import org.apache.doris.analysis.HashDistributionDesc; import org.apache.doris.analysis.InstallPluginStmt; import org.apache.doris.analysis.KeysDesc; import org.apache.doris.analysis.LinkDbStmt; @@ -70,6 +76,7 @@ import org.apache.doris.analysis.ModifyDistributionClause; import org.apache.doris.analysis.PartitionDesc; import org.apache.doris.analysis.PartitionRenameClause; +import org.apache.doris.analysis.QueryStmt; import org.apache.doris.analysis.RecoverDbStmt; import org.apache.doris.analysis.RecoverPartitionStmt; import org.apache.doris.analysis.RecoverTableStmt; @@ -82,6 +89,7 @@ import org.apache.doris.analysis.TableRef; import org.apache.doris.analysis.TableRenameClause; import org.apache.doris.analysis.TruncateTableStmt; +import org.apache.doris.analysis.TypeDef; import org.apache.doris.analysis.UninstallPluginStmt; import org.apache.doris.analysis.UserDesc; import org.apache.doris.analysis.UserIdentity; @@ -113,6 +121,7 @@ import org.apache.doris.common.ErrorReport; import org.apache.doris.common.FeConstants; import org.apache.doris.common.FeMetaVersion; +import org.apache.doris.common.FeNameFormat; import org.apache.doris.common.MarkedCountDownLatch; import org.apache.doris.common.MetaHeader; import org.apache.doris.common.MetaNotFoundException; @@ -3086,6 +3095,54 @@ public void createTableLike(CreateTableLikeStmt stmt) throws DdlException { throw new DdlException("Failed to execute CREATE TABLE LIKE " + stmt.getExistedTableName() + ". Reason: " + e.getMessage()); } } + + public void createTableAsSelect(CreateTableAsSelectStmt stmt) throws DdlException { + try { + List columnNames = stmt.getColumnNames(); + CreateTableStmt createTableStmt = stmt.getCreateTableStmt(); + QueryStmt queryStmt = stmt.getQueryStmt(); + ArrayList resultExprs = queryStmt.getResultExprs(); + ArrayList colLabels = queryStmt.getColLabels(); + int size = resultExprs.size(); + // Check columnNames + int colNameIndex = 0; + for (int i = 0; i < size; ++i) { + String name; + if (columnNames != null) { + // use custom column names + name = columnNames.get(i); + } else { + name = colLabels.get(i); + } + try { + FeNameFormat.checkColumnName(name); + } catch (AnalysisException exception) { + name = "_col" + (colNameIndex++); + } + TypeDef typeDef; + Expr resultExpr = resultExprs.get(i); + // varchar/char transfer to string + if (resultExpr.getType().isStringType()) { + typeDef = new TypeDef(Type.STRING); + } else { + typeDef = new TypeDef(resultExpr.getType()); + } + createTableStmt.addColumnDef(new ColumnDef(name, typeDef, false, + null, true, + new DefaultValue(false, null), + "")); + // set first column as default distribution + if (createTableStmt.getDistributionDesc() == null && i == 0) { + createTableStmt.setDistributionDesc(new HashDistributionDesc(10, Lists.newArrayList(name))); + } + } + Analyzer dummyRootAnalyzer = new Analyzer(this, ConnectContext.get()); + createTableStmt.analyze(dummyRootAnalyzer); + createTable(createTableStmt); + } catch (UserException e) { + throw new DdlException("Failed to execute CREATE TABLE AS SELECT Reason: " + e.getMessage()); + } + } public void addPartition(Database db, String tableName, AddPartitionClause addPartitionClause) throws DdlException { SinglePartitionDesc singlePartitionDesc = addPartitionClause.getSingeRangePartitionDesc(); diff --git a/fe/fe-core/src/main/java/org/apache/doris/qe/DdlExecutor.java b/fe/fe-core/src/main/java/org/apache/doris/qe/DdlExecutor.java index 89536ee5fdbc7c..d4f75ba9dde6b1 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/qe/DdlExecutor.java +++ b/fe/fe-core/src/main/java/org/apache/doris/qe/DdlExecutor.java @@ -51,6 +51,7 @@ import org.apache.doris.analysis.CreateRoleStmt; import org.apache.doris.analysis.CreateRoutineLoadStmt; import org.apache.doris.analysis.CreateSqlBlockRuleStmt; +import org.apache.doris.analysis.CreateTableAsSelectStmt; import org.apache.doris.analysis.CreateTableLikeStmt; import org.apache.doris.analysis.CreateTableStmt; import org.apache.doris.analysis.CreateUserStmt; @@ -126,6 +127,8 @@ public static void execute(Catalog catalog, DdlStmt ddlStmt) throws Exception { catalog.createTable((CreateTableStmt) ddlStmt); } else if (ddlStmt instanceof CreateTableLikeStmt) { catalog.createTableLike((CreateTableLikeStmt) ddlStmt); + } else if (ddlStmt instanceof CreateTableAsSelectStmt) { + catalog.createTableAsSelect((CreateTableAsSelectStmt) ddlStmt); } else if (ddlStmt instanceof DropTableStmt) { catalog.dropTable((DropTableStmt) ddlStmt); } else if (ddlStmt instanceof CreateMaterializedViewStmt) { diff --git a/fe/fe-core/src/main/java/org/apache/doris/qe/StmtExecutor.java b/fe/fe-core/src/main/java/org/apache/doris/qe/StmtExecutor.java index ec3a4c7bebfa67..c7d32a4c9c5a71 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/qe/StmtExecutor.java +++ b/fe/fe-core/src/main/java/org/apache/doris/qe/StmtExecutor.java @@ -367,8 +367,6 @@ public void execute(TUniqueId queryId) throws Exception { handleUseStmt(); } else if (parsedStmt instanceof TransactionStmt) { handleTransactionStmt(); - } else if (parsedStmt instanceof CreateTableAsSelectStmt) { - handleInsertStmt(); } else if (parsedStmt instanceof InsertStmt) { // Must ahead of DdlStmt because InserStmt is its subclass try { handleInsertStmt(); @@ -511,13 +509,12 @@ public void analyze(TQueryOptions tQueryOptions) throws UserException { if (parsedStmt instanceof QueryStmt) { queryStmt = (QueryStmt) parsedStmt; queryStmt.getTables(analyzer, tableMap, parentViewNameSet); + } else if (parsedStmt instanceof CreateTableAsSelectStmt) { + CreateTableAsSelectStmt parsedStmt = (CreateTableAsSelectStmt) this.parsedStmt; + queryStmt = parsedStmt.getQueryStmt(); + queryStmt.getTables(analyzer, tableMap, parentViewNameSet); } else { - InsertStmt insertStmt; - if (parsedStmt instanceof InsertStmt) { - insertStmt = (InsertStmt) parsedStmt; - } else { - insertStmt = ((CreateTableAsSelectStmt) parsedStmt).getInsertStmt(); - } + InsertStmt insertStmt = (InsertStmt) parsedStmt; insertStmt.getTables(analyzer, tableMap, parentViewNameSet); } // table id in tableList is in ascending order because that table map is a sorted map @@ -641,9 +638,6 @@ private void analyzeAndGenerateQueryPlan(TQueryOptions tQueryOptions) throws Use planner = new Planner(); if (parsedStmt instanceof QueryStmt || parsedStmt instanceof InsertStmt) { planner.plan(parsedStmt, analyzer, tQueryOptions); - } else { - planner.plan(((CreateTableAsSelectStmt) parsedStmt).getInsertStmt(), - analyzer, new TQueryOptions()); } // TODO(zc): // Preconditions.checkState(!analyzer.hasUnassignedConjuncts()); @@ -1155,14 +1149,7 @@ private void handleInsertStmt() throws Exception { // Every time set no send flag and clean all data in buffer context.getMysqlChannel().reset(); // create plan - InsertStmt insertStmt = null; - if (parsedStmt instanceof CreateTableAsSelectStmt) { - // Create table here - ((CreateTableAsSelectStmt) parsedStmt).createTable(analyzer); - insertStmt = ((CreateTableAsSelectStmt) parsedStmt).getInsertStmt(); - } else { - insertStmt = (InsertStmt) parsedStmt; - } + InsertStmt insertStmt = (InsertStmt) parsedStmt; if (insertStmt.getQueryStmt().hasOutFileClause()) { throw new DdlException("Not support OUTFILE clause in INSERT statement"); diff --git a/fe/fe-core/src/test/java/org/apache/doris/analysis/CreateTableAsSelectStmtTest.java b/fe/fe-core/src/test/java/org/apache/doris/analysis/CreateTableAsSelectStmtTest.java new file mode 100644 index 00000000000000..fdae9733eb90b6 --- /dev/null +++ b/fe/fe-core/src/test/java/org/apache/doris/analysis/CreateTableAsSelectStmtTest.java @@ -0,0 +1,298 @@ +// 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.doris.analysis; + +import org.apache.doris.catalog.Catalog; +import org.apache.doris.common.AnalysisException; +import org.apache.doris.common.ExceptionChecker; +import org.apache.doris.metric.MetricRepo; +import org.apache.doris.qe.ConnectContext; +import org.apache.doris.qe.ShowExecutor; +import org.apache.doris.qe.ShowResultSet; +import org.apache.doris.utframe.UtFrameUtils; + +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.util.UUID; + +public class CreateTableAsSelectStmtTest { + + private static String runningDir = "fe/mocked/CreateTableAsSelectStmtTest/" + UUID.randomUUID() + "/"; + private static ConnectContext connectContext; + + @AfterClass + public static void tearDown() throws Exception { + UtFrameUtils.cleanDorisFeDir(runningDir); + } + + @BeforeClass + public static void setUp() throws Exception { + UtFrameUtils.createDorisCluster(runningDir); + // create connect context + connectContext = UtFrameUtils.createDefaultCtx(); + // create database + String createDbStmtStr = "create database test"; + CreateDbStmt createDbStmt = (CreateDbStmt) UtFrameUtils.parseAndAnalyzeStmt(createDbStmtStr, connectContext); + Catalog.getCurrentCatalog().createDb(createDbStmt); + String varcharTable = "CREATE TABLE `test`.`varchar_table`\n" + + "(\n" + + " `userId` varchar(255) NOT NULL COMMENT '',\n" + + " `username` varchar(255) NOT NULL COMMENT ''\n" + + ") ENGINE = OLAP unique KEY(`userId`)\n" + + "COMMENT \"varchar_table\"\n" + + "DISTRIBUTED BY HASH(`userId`) BUCKETS 10\n" + + "PROPERTIES (\n" + + "\"replication_allocation\" = \"tag.location.default: 1\",\n" + + "\"in_memory\" = \"false\",\n" + + "\"storage_format\" = \"V2\"\n" + + ");"; + String decimalTable = "CREATE TABLE `test`.`decimal_table`\n" + + "(\n" + + " `userId` varchar(255) NOT NULL COMMENT '',\n" + + " `amount_decimal` decimal(10, 2) NOT NULL COMMENT ''\n" + + ") ENGINE = OLAP unique KEY(`userId`)\n" + + "COMMENT \"decimal_table\"\n" + + "DISTRIBUTED BY HASH(`userId`) BUCKETS 10\n" + + "PROPERTIES (\n" + + "\"replication_allocation\" = \"tag.location.default: 1\",\n" + + "\"in_memory\" = \"false\",\n" + + "\"storage_format\" = \"V2\"\n" + + ");"; + String joinTable = "CREATE TABLE `test`.`join_table`\n" + + "(\n" + + " `userId` varchar(255) NOT NULL COMMENT '',\n" + + " `status` int NOT NULL COMMENT ''\n" + + ") ENGINE = OLAP unique KEY(`userId`)\n" + + "COMMENT \"join_table\"\n" + + "DISTRIBUTED BY HASH(`userId`) BUCKETS 10\n" + + "PROPERTIES (\n" + + "\"replication_allocation\" = \"tag.location.default: 1\",\n" + + "\"in_memory\" = \"false\",\n" + + "\"storage_format\" = \"V2\"\n" + + ");"; + MetricRepo.init(); + createTable(varcharTable); + createTable(decimalTable); + createTable(joinTable); + } + + private static void createTable(String sql) throws Exception { + CreateTableStmt stmt = (CreateTableStmt) UtFrameUtils.parseAndAnalyzeStmt(sql, connectContext); + Catalog.getCurrentCatalog().createTable(stmt); + } + + private static void createTableAsSelect(String sql) throws Exception { + CreateTableAsSelectStmt stmt = (CreateTableAsSelectStmt) UtFrameUtils.parseAndAnalyzeStmt(sql, connectContext); + Catalog.getCurrentCatalog().createTableAsSelect(stmt); + } + + private static ShowResultSet showCreateTable(String tableName) throws Exception { + ShowCreateTableStmt stmt = new ShowCreateTableStmt(new TableName("test", tableName)); + Analyzer dummyRootAnalyzer = new Analyzer(Catalog.getCurrentCatalog(), connectContext); + stmt.analyze(dummyRootAnalyzer); + ShowExecutor executor = new ShowExecutor(connectContext, stmt); + return executor.execute(); + } + + @Test + public void testErrorType() throws Exception { + String selectFromDecimal = "create table `test`.`select_decimal_table` PROPERTIES(\"replication_num\" = \"1\") as select * from `test`.`decimal_table`"; + ExceptionChecker.expectThrowsWithMsg(AnalysisException.class, "Unsupported type", + () -> UtFrameUtils.parseAndAnalyzeStmt(selectFromDecimal, connectContext)); + } + + @Test + public void testErrorColumn() throws Exception { + String selectFromColumn = "create table `test`.`select_column_table`(test_error) PROPERTIES(\"replication_num\" = \"1\") as select * from `test`.`varchar_table`"; + ExceptionChecker.expectThrowsWithMsg(AnalysisException.class, "Number of columns don't equal number of SELECT statement's select list", + () -> UtFrameUtils.parseAndAnalyzeStmt(selectFromColumn, connectContext)); + } + + @Test + public void testVarchar() throws Exception { + String selectFromDecimal = "create table `test`.`select_varchar` PROPERTIES(\"replication_num\" = \"1\") as select * from `test`.`varchar_table`"; + createTableAsSelect(selectFromDecimal); + ShowResultSet showResultSet = showCreateTable("select_varchar"); + Assert.assertEquals("CREATE TABLE `select_varchar` (\n" + + " `userId` string NULL COMMENT \"\",\n" + + " `username` string NULL COMMENT \"\"\n" + + ") ENGINE=OLAP\n" + + "DUPLICATE KEY(`userId`)\n" + + "COMMENT \"OLAP\"\n" + + "DISTRIBUTED BY HASH(`userId`) BUCKETS 10\n" + + "PROPERTIES (\n" + + "\"replication_allocation\" = \"tag.location.default: 1\",\n" + + "\"in_memory\" = \"false\",\n" + + "\"storage_format\" = \"V2\"\n" + + ");", showResultSet.getResultRows().get(0).get(1)); + } + + @Test + public void testFunction() throws Exception { + String selectFromFunction1 = "create table `test`.`select_function_1` PROPERTIES(\"replication_num\" = \"1\") as select count(*) from `test`.`varchar_table`"; + createTableAsSelect(selectFromFunction1); + ShowResultSet showResultSet1 = showCreateTable("select_function_1"); + System.out.println(showResultSet1.getResultRows().get(0).get(1)); + Assert.assertEquals("CREATE TABLE `select_function_1` (\n" + + " `_col0` bigint(20) NULL COMMENT \"\"\n" + + ") ENGINE=OLAP\n" + + "DUPLICATE KEY(`_col0`)\n" + + "COMMENT \"OLAP\"\n" + + "DISTRIBUTED BY HASH(`_col0`) BUCKETS 10\n" + + "PROPERTIES (\n" + + "\"replication_allocation\" = \"tag.location.default: 1\",\n" + + "\"in_memory\" = \"false\",\n" + + "\"storage_format\" = \"V2\"\n" + + ");", showResultSet1.getResultRows().get(0).get(1)); + + String selectFromFunction2 = "create table `test`.`select_function_2` PROPERTIES(\"replication_num\" = \"1\") as select sum(status), sum(status), sum(status), count(status), count(status) from `test`.`join_table`"; + createTableAsSelect(selectFromFunction2); + ShowResultSet showResultSet2 = showCreateTable("select_function_2"); + Assert.assertEquals("CREATE TABLE `select_function_2` (\n" + + " `_col0` bigint(20) NULL COMMENT \"\",\n" + + " `_col1` bigint(20) NULL COMMENT \"\",\n" + + " `_col2` bigint(20) NULL COMMENT \"\",\n" + + " `_col3` bigint(20) NULL COMMENT \"\",\n" + + " `_col4` bigint(20) NULL COMMENT \"\"\n" + + ") ENGINE=OLAP\n" + + "DUPLICATE KEY(`_col0`, `_col1`, `_col2`)\n" + + "COMMENT \"OLAP\"\n" + + "DISTRIBUTED BY HASH(`_col0`) BUCKETS 10\n" + + "PROPERTIES (\n" + + "\"replication_allocation\" = \"tag.location.default: 1\",\n" + + "\"in_memory\" = \"false\",\n" + + "\"storage_format\" = \"V2\"\n" + + ");", showResultSet2.getResultRows().get(0).get(1)); + } + + @Test + public void testAlias() throws Exception { + String selectAlias1 = "create table `test`.`select_alias_1` PROPERTIES(\"replication_num\" = \"1\") as select count(*) as amount from `test`.`varchar_table`"; + createTableAsSelect(selectAlias1); + ShowResultSet showResultSet1 = showCreateTable("select_alias_1"); + Assert.assertEquals("CREATE TABLE `select_alias_1` (\n" + + " `amount` bigint(20) NULL COMMENT \"\"\n" + + ") ENGINE=OLAP\n" + + "DUPLICATE KEY(`amount`)\n" + + "COMMENT \"OLAP\"\n" + + "DISTRIBUTED BY HASH(`amount`) BUCKETS 10\n" + + "PROPERTIES (\n" + + "\"replication_allocation\" = \"tag.location.default: 1\",\n" + + "\"in_memory\" = \"false\",\n" + + "\"storage_format\" = \"V2\"\n" + + ");", showResultSet1.getResultRows().get(0).get(1)); + String selectAlias2 = "create table `test`.`select_alias_2` PROPERTIES(\"replication_num\" = \"1\") as select userId as alias_name, username from `test`.`varchar_table`"; + createTableAsSelect(selectAlias2); + ShowResultSet showResultSet2 = showCreateTable("select_alias_2"); + Assert.assertEquals("CREATE TABLE `select_alias_2` (\n" + + " `alias_name` string NULL COMMENT \"\",\n" + + " `username` string NULL COMMENT \"\"\n" + + ") ENGINE=OLAP\n" + + "DUPLICATE KEY(`alias_name`)\n" + + "COMMENT \"OLAP\"\n" + + "DISTRIBUTED BY HASH(`alias_name`) BUCKETS 10\n" + + "PROPERTIES (\n" + + "\"replication_allocation\" = \"tag.location.default: 1\",\n" + + "\"in_memory\" = \"false\",\n" + + "\"storage_format\" = \"V2\"\n" + + ");", showResultSet2.getResultRows().get(0).get(1)); + } + + @Test + public void testJoin() throws Exception { + String selectFromJoin = "create table `test`.`select_join` PROPERTIES(\"replication_num\" = \"1\") " + + "as select vt.userId, vt.username, jt.status from `test`.`varchar_table` vt join `test`.`join_table` jt on vt.userId=jt.userId"; + createTableAsSelect(selectFromJoin); + ShowResultSet showResultSet = showCreateTable("select_join"); + Assert.assertEquals("CREATE TABLE `select_join` (\n" + + " `userId` string NULL COMMENT \"\",\n" + + " `username` string NULL COMMENT \"\",\n" + + " `status` int(11) NULL COMMENT \"\"\n" + + ") ENGINE=OLAP\n" + + "DUPLICATE KEY(`userId`)\n" + + "COMMENT \"OLAP\"\n" + + "DISTRIBUTED BY HASH(`userId`) BUCKETS 10\n" + + "PROPERTIES (\n" + + "\"replication_allocation\" = \"tag.location.default: 1\",\n" + + "\"in_memory\" = \"false\",\n" + + "\"storage_format\" = \"V2\"\n" + + ");", showResultSet.getResultRows().get(0).get(1)); + } + + @Test + public void testName() throws Exception { + String selectFromName = "create table `test`.`select_name`(user, testname, userstatus) PROPERTIES(\"replication_num\" = \"1\") " + + "as select vt.userId, vt.username, jt.status from `test`.`varchar_table` vt join `test`.`join_table` jt on vt.userId=jt.userId"; + createTableAsSelect(selectFromName); + ShowResultSet showResultSet = showCreateTable("select_name"); + Assert.assertEquals("CREATE TABLE `select_name` (\n" + + " `user` string NULL COMMENT \"\",\n" + + " `testname` string NULL COMMENT \"\",\n" + + " `userstatus` int(11) NULL COMMENT \"\"\n" + + ") ENGINE=OLAP\n" + + "DUPLICATE KEY(`user`)\n" + + "COMMENT \"OLAP\"\n" + + "DISTRIBUTED BY HASH(`user`) BUCKETS 10\n" + + "PROPERTIES (\n" + + "\"replication_allocation\" = \"tag.location.default: 1\",\n" + + "\"in_memory\" = \"false\",\n" + + "\"storage_format\" = \"V2\"\n" + + ");", showResultSet.getResultRows().get(0).get(1)); + } + + @Test + public void testUnion() throws Exception { + String selectFromName = "create table `test`.`select_union` PROPERTIES(\"replication_num\" = \"1\") " + + "as select userId from `test`.`varchar_table` union select userId from `test`.`join_table`"; + createTableAsSelect(selectFromName); + ShowResultSet showResultSet = showCreateTable("select_union"); + Assert.assertEquals("CREATE TABLE `select_union` (\n" + + " `userId` string NULL COMMENT \"\"\n" + + ") ENGINE=OLAP\n" + + "DUPLICATE KEY(`userId`)\n" + + "COMMENT \"OLAP\"\n" + + "DISTRIBUTED BY HASH(`userId`) BUCKETS 10\n" + + "PROPERTIES (\n" + + "\"replication_allocation\" = \"tag.location.default: 1\",\n" + + "\"in_memory\" = \"false\",\n" + + "\"storage_format\" = \"V2\"\n" + + ");", showResultSet.getResultRows().get(0).get(1)); + } + + @Test + public void testCte() throws Exception { + String selectFromName = "create table `test`.`select_cte` PROPERTIES(\"replication_num\" = \"1\") " + + "as with cte_name1 as (select userId from `test`.`varchar_table`) select * from cte_name1"; + createTableAsSelect(selectFromName); + ShowResultSet showResultSet = showCreateTable("select_cte"); + Assert.assertEquals("CREATE TABLE `select_cte` (\n" + + " `userId` string NULL COMMENT \"\"\n" + + ") ENGINE=OLAP\n" + + "DUPLICATE KEY(`userId`)\n" + + "COMMENT \"OLAP\"\n" + + "DISTRIBUTED BY HASH(`userId`) BUCKETS 10\n" + + "PROPERTIES (\n" + + "\"replication_allocation\" = \"tag.location.default: 1\",\n" + + "\"in_memory\" = \"false\",\n" + + "\"storage_format\" = \"V2\"\n" + + ");", showResultSet.getResultRows().get(0).get(1)); + } +}