From 62cae74aca0efe291e532096745873ef62743f85 Mon Sep 17 00:00:00 2001 From: zhangstar333 <2561612514@qq.com> Date: Fri, 12 Apr 2024 17:15:00 +0800 Subject: [PATCH] add udtf fe --- fe/fe-core/src/main/cup/sql_parser.cup | 92 +++++++++++-------- .../doris/analysis/CreateFunctionStmt.java | 17 +++- 2 files changed, 67 insertions(+), 42 deletions(-) diff --git a/fe/fe-core/src/main/cup/sql_parser.cup b/fe/fe-core/src/main/cup/sql_parser.cup index 08b793c43522f2d..0ab092772e08ffc 100644 --- a/fe/fe-core/src/main/cup/sql_parser.cup +++ b/fe/fe-core/src/main/cup/sql_parser.cup @@ -927,8 +927,8 @@ nonterminal ParseNode load_property; nonterminal List opt_load_property_list; // Boolean -nonterminal Boolean opt_negative, opt_is_allow_null, opt_is_key, opt_read_only, opt_aggregate, opt_local; -nonterminal String opt_from_rollup, opt_to_rollup; +nonterminal Boolean opt_negative, opt_is_allow_null, opt_is_key, opt_read_only, opt_local; +nonterminal String opt_from_rollup, function_type, opt_to_rollup; nonterminal ColumnPosition opt_col_pos; // Alter statement @@ -964,7 +964,7 @@ nonterminal List> opt_with_analysis_properties; nonterminal String opt_db, procedure_or_function, opt_comment, opt_comment_null, opt_engine; nonterminal ColumnDef.DefaultValue opt_default_value; nonterminal Boolean opt_if_exists, opt_if_not_exists; -nonterminal Boolean opt_external; +nonterminal Boolean externalable_table, externalable_resource; nonterminal Boolean opt_force; nonterminal Boolean opt_cached; nonterminal IndexDef.IndexType opt_index_type; @@ -1025,7 +1025,8 @@ precedence right KW_TEMPORARY; precedence right LBRACKET; precedence right LBRACE; precedence left KW_ENGINE; - +precedence left KW_FUNCTION; +precedence left KW_TABLE; // unused // nonterminal Expr where_clause_without_null, List col_list, opt_charset_name; @@ -1792,10 +1793,10 @@ create_stmt ::= RESULT = new CreateCatalogStmt(ifNotExists, catalogName, resourceName, properties, comment); :} /* Function */ - | KW_CREATE opt_var_type:type opt_aggregate:isAggregate KW_FUNCTION opt_if_not_exists:ifNotExists function_name:functionName LPAREN func_args_def:args RPAREN + | KW_CREATE opt_var_type:type function_type:functionType opt_if_not_exists:ifNotExists function_name:functionName LPAREN func_args_def:args RPAREN KW_RETURNS type_def:returnType opt_intermediate_type:intermediateType opt_properties:properties {: - RESULT = new CreateFunctionStmt(type, ifNotExists, isAggregate, functionName, args, returnType, intermediateType, properties); + RESULT = new CreateFunctionStmt(type, ifNotExists, functionType, functionName, args, returnType, intermediateType, properties); :} | KW_CREATE opt_var_type:type KW_ALIAS KW_FUNCTION opt_if_not_exists:ifNotExists function_name:functionName LPAREN func_args_def:args RPAREN KW_WITH KW_PARAMETER LPAREN opt_ident_list:parameters RPAREN KW_AS expr:func @@ -1803,19 +1804,19 @@ create_stmt ::= RESULT = new CreateFunctionStmt(type, ifNotExists, functionName, args, parameters, func); :} /* Table */ - | KW_CREATE opt_external:isExternal KW_TABLE opt_if_not_exists:ifNotExists table_name:name KW_LIKE table_name:existed_name KW_WITH KW_ROLLUP LPAREN ident_list:rollupNames RPAREN + | KW_CREATE externalable_table:isExternal opt_if_not_exists:ifNotExists table_name:name KW_LIKE table_name:existed_name KW_WITH KW_ROLLUP LPAREN ident_list:rollupNames RPAREN {: RESULT = new CreateTableLikeStmt(ifNotExists, name, existed_name, rollupNames, false); :} - | KW_CREATE opt_external:isExternal KW_TABLE opt_if_not_exists:ifNotExists table_name:name KW_LIKE table_name:existed_name KW_WITH KW_ROLLUP + | KW_CREATE externalable_table:isExternal opt_if_not_exists:ifNotExists table_name:name KW_LIKE table_name:existed_name KW_WITH KW_ROLLUP {: RESULT = new CreateTableLikeStmt(ifNotExists, name, existed_name, null, true); :} - | KW_CREATE opt_external:isExternal KW_TABLE opt_if_not_exists:ifNotExists table_name:name KW_LIKE table_name:existed_name + | KW_CREATE externalable_table:isExternal opt_if_not_exists:ifNotExists table_name:name KW_LIKE table_name:existed_name {: RESULT = new CreateTableLikeStmt(ifNotExists, name, existed_name, null, false); :} - | KW_CREATE opt_external:isExternal KW_TABLE opt_if_not_exists:ifNotExists table_name:name + | KW_CREATE externalable_table:isExternal opt_if_not_exists:ifNotExists table_name:name LPAREN column_definition_list:columns RPAREN opt_engine:engineName opt_keys:keys opt_comment:tableComment @@ -1828,7 +1829,7 @@ create_stmt ::= RESULT = new CreateTableStmt(ifNotExists, isExternal, name, columns, engineName, keys, partition, distribution, tblProperties, extProperties, tableComment, index); :} - | KW_CREATE opt_external:isExternal KW_TABLE opt_if_not_exists:ifNotExists table_name:name + | KW_CREATE externalable_table:isExternal opt_if_not_exists:ifNotExists table_name:name LPAREN column_definition_list:columns COMMA RPAREN opt_engine:engineName opt_keys:keys opt_comment:tableComment @@ -1841,7 +1842,7 @@ create_stmt ::= RESULT = new CreateTableStmt(ifNotExists, isExternal, name, columns, null, engineName, keys, partition, distribution, tblProperties, extProperties, tableComment, index); :} - | KW_CREATE opt_external:isExternal KW_TABLE opt_if_not_exists:ifNotExists table_name:name + | KW_CREATE externalable_table:isExternal opt_if_not_exists:ifNotExists table_name:name LPAREN column_definition_list:columns COMMA index_definition_list:indexes RPAREN opt_engine:engineName opt_keys:keys opt_comment:tableComment @@ -1854,7 +1855,7 @@ 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 + | KW_CREATE externalable_table:isExternal opt_if_not_exists:ifNotExists table_name:name LPAREN column_definition_list:columns COMMA index_definition_list:indexes COMMA RPAREN opt_engine:engineName opt_keys:keys opt_comment:tableComment @@ -1867,7 +1868,7 @@ 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 + | KW_CREATE externalable_table:isExternal opt_if_not_exists:ifNotExists table_name:name opt_col_list:columns opt_engine:engineName opt_keys:keys @@ -1921,15 +1922,10 @@ create_stmt ::= {: RESULT = new AlterTableStmt(tableName, Lists.newArrayList(new CreateIndexClause(tableName, new IndexDef(indexName, ifNotExists, cols, indexType, properties, comment), false))); :} - /* external resource */ - | KW_CREATE KW_EXTERNAL KW_RESOURCE opt_if_not_exists:ifNotExists ident_or_text:resourceName opt_properties:properties - {: - RESULT = new CreateResourceStmt(true, ifNotExists, resourceName, properties); - :} - /* resource */ - | KW_CREATE KW_RESOURCE opt_if_not_exists:ifNotExists ident_or_text:resourceName opt_properties:properties + /* resource or external resource */ + | KW_CREATE externalable_resource:isExternal opt_if_not_exists:ifNotExists ident_or_text:resourceName opt_properties:properties {: - RESULT = new CreateResourceStmt(false, ifNotExists, resourceName, properties); + RESULT = new CreateResourceStmt(isExternal, ifNotExists, resourceName, properties); :} /* storage vault */ | KW_CREATE KW_STORAGE KW_VAULT opt_if_not_exists:ifNotExists ident_or_text:storageVaultName opt_properties:properties @@ -2041,14 +2037,19 @@ job_name ::= :} ; -opt_aggregate ::= - {: - RESULT = false; - :} - | KW_AGGREGATE - {: - RESULT = true; - :} +function_type ::= + KW_FUNCTION + {: + RESULT = "scalar"; + :} + | KW_TABLE:table KW_FUNCTION + {: + RESULT = "table"; + :} + | KW_AGGREGATE:aggregate KW_FUNCTION + {: + RESULT = "aggregate"; + :} ; storage_backend ::= @@ -3918,16 +3919,27 @@ opt_if_not_exists ::= :} ; -opt_external ::= - /* empty */ - {: - RESULT = false; - :} - | KW_EXTERNAL - {: - RESULT = true; - :} - ; +externalable_table ::= + KW_TABLE + {: + RESULT = false; + :} + | KW_EXTERNAL KW_TABLE + {: + RESULT = true; + :} + ; + +externalable_resource ::= + KW_RESOURCE + {: + RESULT = false; + :} + | KW_EXTERNAL KW_RESOURCE + {: + RESULT = true; + :} + ; opt_cached ::= /* empty */ diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/CreateFunctionStmt.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/CreateFunctionStmt.java index d498d1f75bc6656..6d12fab198797e3 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/CreateFunctionStmt.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/CreateFunctionStmt.java @@ -103,6 +103,7 @@ public class CreateFunctionStmt extends DdlStmt { private final boolean ifNotExists; private final FunctionName functionName; private final boolean isAggregate; + private final boolean isTableFunction; private final boolean isAlias; private final FunctionArgsDef argsDef; private final TypeDef returnType; @@ -124,13 +125,14 @@ public class CreateFunctionStmt extends DdlStmt { // timeout for both connection and read. 10 seconds is long enough. private static final int HTTP_TIMEOUT_MS = 10000; - public CreateFunctionStmt(SetType type, boolean ifNotExists, boolean isAggregate, FunctionName functionName, + public CreateFunctionStmt(SetType type, boolean ifNotExists, String functionType, FunctionName functionName, FunctionArgsDef argsDef, TypeDef returnType, TypeDef intermediateType, Map properties) { this.type = type; this.ifNotExists = ifNotExists; this.functionName = functionName; - this.isAggregate = isAggregate; + this.isAggregate = functionType.equalsIgnoreCase("AGGREGATE"); + this.isTableFunction = functionType.equalsIgnoreCase("TABLE"); this.argsDef = argsDef; this.returnType = returnType; this.intermediateType = intermediateType; @@ -158,6 +160,7 @@ public CreateFunctionStmt(SetType type, boolean ifNotExists, FunctionName functi } this.originFunction = originFunction; this.isAggregate = false; + this.isTableFunction = false; this.returnType = new TypeDef(Type.VARCHAR); this.properties = ImmutableSortedMap.of(); } @@ -208,6 +211,8 @@ public void analyze(Analyzer analyzer) throws UserException { analyzeUda(); } else if (isAlias) { analyzeAliasFunction(); + } else if (isTableFunction) { + analyzeTableFunction(); } else { analyzeUdf(); } @@ -301,6 +306,14 @@ private void computeObjectChecksum() throws IOException, NoSuchAlgorithmExceptio } } + private void analyzeTableFunction() throws AnalysisException { + String symbol = properties.get(SYMBOL_KEY); + if (Strings.isNullOrEmpty(symbol)) { + throw new AnalysisException("No 'symbol' in properties"); + } + analyzeJavaUdf(symbol); + } + private void analyzeUda() throws AnalysisException { AggregateFunction.AggregateFunctionBuilder builder = AggregateFunction.AggregateFunctionBuilder.createUdfBuilder();