From d02e67e0cd78111d8e15782607f5734c3ff1dd24 Mon Sep 17 00:00:00 2001 From: Michael Xu Date: Tue, 2 Jan 2024 03:45:36 -0500 Subject: [PATCH 1/4] feat(udf): add body field for udf body definition --- proto/catalog.proto | 1 + src/frontend/src/binder/expr/function.rs | 2 +- src/frontend/src/catalog/function_catalog.rs | 2 ++ src/frontend/src/expr/user_defined_function.rs | 2 ++ src/frontend/src/handler/create_function.rs | 1 + src/frontend/src/handler/create_sql_function.rs | 3 ++- src/meta/model_v2/src/function.rs | 2 ++ src/meta/src/controller/mod.rs | 1 + 8 files changed, 12 insertions(+), 2 deletions(-) diff --git a/proto/catalog.proto b/proto/catalog.proto index 01a7893383232..a5f046d2635cf 100644 --- a/proto/catalog.proto +++ b/proto/catalog.proto @@ -218,6 +218,7 @@ message Function { string language = 7; string link = 8; string identifier = 10; + string body = 14; oneof kind { ScalarFunction scalar = 11; diff --git a/src/frontend/src/binder/expr/function.rs b/src/frontend/src/binder/expr/function.rs index 65e7ced3c7b63..f31182480c1b8 100644 --- a/src/frontend/src/binder/expr/function.rs +++ b/src/frontend/src/binder/expr/function.rs @@ -233,7 +233,7 @@ impl Binder { if func.language == "sql" { // This represents the current user defined function is `language sql` let parse_result = - risingwave_sqlparser::parser::Parser::parse_sql(func.identifier.as_str()); + risingwave_sqlparser::parser::Parser::parse_sql(func.body.as_str()); if let Err(ParserError::ParserError(err)) | Err(ParserError::TokenizerError(err)) = parse_result { diff --git a/src/frontend/src/catalog/function_catalog.rs b/src/frontend/src/catalog/function_catalog.rs index 7197821b33ce6..bba187b834925 100644 --- a/src/frontend/src/catalog/function_catalog.rs +++ b/src/frontend/src/catalog/function_catalog.rs @@ -30,6 +30,7 @@ pub struct FunctionCatalog { pub return_type: DataType, pub language: String, pub identifier: String, + pub body: String, pub link: String, } @@ -63,6 +64,7 @@ impl From<&PbFunction> for FunctionCatalog { return_type: prost.return_type.as_ref().expect("no return type").into(), language: prost.language.clone(), identifier: prost.identifier.clone(), + body: prost.body.clone(), link: prost.link.clone(), } } diff --git a/src/frontend/src/expr/user_defined_function.rs b/src/frontend/src/expr/user_defined_function.rs index abd39fdbbc0c4..687bc5f9a4705 100644 --- a/src/frontend/src/expr/user_defined_function.rs +++ b/src/frontend/src/expr/user_defined_function.rs @@ -55,6 +55,8 @@ impl UserDefinedFunction { return_type, language: udf.get_language().clone(), identifier: udf.get_identifier().clone(), + // TODO: Ensure if we need `body` here + body: "".to_string(), link: udf.get_link().clone(), }; diff --git a/src/frontend/src/handler/create_function.rs b/src/frontend/src/handler/create_function.rs index 2bbc866a5491b..e268043b94ed5 100644 --- a/src/frontend/src/handler/create_function.rs +++ b/src/frontend/src/handler/create_function.rs @@ -162,6 +162,7 @@ pub async fn handle_create_function( return_type: Some(return_type.into()), language, identifier, + body: "".to_string(), link, owner: session.user_id(), }; diff --git a/src/frontend/src/handler/create_sql_function.rs b/src/frontend/src/handler/create_sql_function.rs index b39f740f4f5c5..04a237902cd99 100644 --- a/src/frontend/src/handler/create_sql_function.rs +++ b/src/frontend/src/handler/create_sql_function.rs @@ -168,7 +168,8 @@ pub async fn handle_create_sql_function( arg_types: arg_types.into_iter().map(|t| t.into()).collect(), return_type: Some(return_type.into()), language, - identifier: body, + identifier: "".to_string(), + body, link: "".to_string(), owner: session.user_id(), }; diff --git a/src/meta/model_v2/src/function.rs b/src/meta/model_v2/src/function.rs index 71391a3cc27b0..0794737305380 100644 --- a/src/meta/model_v2/src/function.rs +++ b/src/meta/model_v2/src/function.rs @@ -41,6 +41,7 @@ pub struct Model { pub language: String, pub link: String, pub identifier: String, + pub body: String, pub kind: FunctionKind, } @@ -94,6 +95,7 @@ impl From for ActiveModel { language: Set(function.language), link: Set(function.link), identifier: Set(function.identifier), + body: Set(function.body), kind: Set(function.kind.unwrap().into()), } } diff --git a/src/meta/src/controller/mod.rs b/src/meta/src/controller/mod.rs index 0ab0326bcfcc1..ca1536834f008 100644 --- a/src/meta/src/controller/mod.rs +++ b/src/meta/src/controller/mod.rs @@ -279,6 +279,7 @@ impl From> for PbFunction { language: value.0.language, link: value.0.link, identifier: value.0.identifier, + body: value.0.body, kind: Some(value.0.kind.into()), } } From 5b5bfd9a677a30b39b68d339bbc7474626161ddc Mon Sep 17 00:00:00 2001 From: Michael Xu Date: Tue, 2 Jan 2024 04:09:09 -0500 Subject: [PATCH 2/4] make body optional in Model & add necessary check --- src/meta/model_v2/migration/src/m20230908_072257_init.rs | 2 ++ src/meta/model_v2/src/function.rs | 4 ++-- src/meta/src/controller/mod.rs | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/meta/model_v2/migration/src/m20230908_072257_init.rs b/src/meta/model_v2/migration/src/m20230908_072257_init.rs index 5b3d55ab83bfb..bc9ce2b08c32b 100644 --- a/src/meta/model_v2/migration/src/m20230908_072257_init.rs +++ b/src/meta/model_v2/migration/src/m20230908_072257_init.rs @@ -708,6 +708,7 @@ impl MigrationTrait for Migration { .col(ColumnDef::new(Function::Language).string().not_null()) .col(ColumnDef::new(Function::Link).string().not_null()) .col(ColumnDef::new(Function::Identifier).string().not_null()) + .col(ColumnDef::new(Function::Body).string()) .col(ColumnDef::new(Function::Kind).string().not_null()) .foreign_key( &mut ForeignKey::create() @@ -1099,6 +1100,7 @@ enum Function { Language, Link, Identifier, + Body, Kind, } diff --git a/src/meta/model_v2/src/function.rs b/src/meta/model_v2/src/function.rs index 0794737305380..8a051fc1de20d 100644 --- a/src/meta/model_v2/src/function.rs +++ b/src/meta/model_v2/src/function.rs @@ -41,7 +41,7 @@ pub struct Model { pub language: String, pub link: String, pub identifier: String, - pub body: String, + pub body: Option, pub kind: FunctionKind, } @@ -95,7 +95,7 @@ impl From for ActiveModel { language: Set(function.language), link: Set(function.link), identifier: Set(function.identifier), - body: Set(function.body), + body: Set(Some(function.body)), kind: Set(function.kind.unwrap().into()), } } diff --git a/src/meta/src/controller/mod.rs b/src/meta/src/controller/mod.rs index ca1536834f008..eb327af67812f 100644 --- a/src/meta/src/controller/mod.rs +++ b/src/meta/src/controller/mod.rs @@ -279,7 +279,7 @@ impl From> for PbFunction { language: value.0.language, link: value.0.link, identifier: value.0.identifier, - body: value.0.body, + body: value.0.body.unwrap_or_default(), kind: Some(value.0.kind.into()), } } From 5dfa63c655f6d6e4eb68754511767b62513d5956 Mon Sep 17 00:00:00 2001 From: Michael Xu Date: Tue, 2 Jan 2024 04:27:31 -0500 Subject: [PATCH 3/4] change body to optional --- proto/catalog.proto | 2 +- src/frontend/src/binder/expr/function.rs | 8 +++++++- src/frontend/src/catalog/function_catalog.rs | 2 +- src/frontend/src/expr/user_defined_function.rs | 2 +- src/frontend/src/handler/create_function.rs | 2 +- src/frontend/src/handler/create_sql_function.rs | 2 +- src/meta/model_v2/src/function.rs | 2 +- src/meta/src/controller/mod.rs | 2 +- 8 files changed, 14 insertions(+), 8 deletions(-) diff --git a/proto/catalog.proto b/proto/catalog.proto index a5f046d2635cf..ec7c68a3802ba 100644 --- a/proto/catalog.proto +++ b/proto/catalog.proto @@ -218,7 +218,7 @@ message Function { string language = 7; string link = 8; string identifier = 10; - string body = 14; + optional string body = 14; oneof kind { ScalarFunction scalar = 11; diff --git a/src/frontend/src/binder/expr/function.rs b/src/frontend/src/binder/expr/function.rs index f31182480c1b8..4e5ba951eb9a1 100644 --- a/src/frontend/src/binder/expr/function.rs +++ b/src/frontend/src/binder/expr/function.rs @@ -231,9 +231,15 @@ impl Binder { { use crate::catalog::function_catalog::FunctionKind::*; if func.language == "sql" { + if func.body.is_none() { + return Err(ErrorCode::InvalidInputSyntax( + "`body` must exist for sql udf".to_string() + ) + .into()); + } // This represents the current user defined function is `language sql` let parse_result = - risingwave_sqlparser::parser::Parser::parse_sql(func.body.as_str()); + risingwave_sqlparser::parser::Parser::parse_sql(func.body.as_ref().unwrap().as_str()); if let Err(ParserError::ParserError(err)) | Err(ParserError::TokenizerError(err)) = parse_result { diff --git a/src/frontend/src/catalog/function_catalog.rs b/src/frontend/src/catalog/function_catalog.rs index bba187b834925..d0f037bcb47b5 100644 --- a/src/frontend/src/catalog/function_catalog.rs +++ b/src/frontend/src/catalog/function_catalog.rs @@ -30,7 +30,7 @@ pub struct FunctionCatalog { pub return_type: DataType, pub language: String, pub identifier: String, - pub body: String, + pub body: Option, pub link: String, } diff --git a/src/frontend/src/expr/user_defined_function.rs b/src/frontend/src/expr/user_defined_function.rs index 687bc5f9a4705..165774d1acb4b 100644 --- a/src/frontend/src/expr/user_defined_function.rs +++ b/src/frontend/src/expr/user_defined_function.rs @@ -56,7 +56,7 @@ impl UserDefinedFunction { language: udf.get_language().clone(), identifier: udf.get_identifier().clone(), // TODO: Ensure if we need `body` here - body: "".to_string(), + body: None, link: udf.get_link().clone(), }; diff --git a/src/frontend/src/handler/create_function.rs b/src/frontend/src/handler/create_function.rs index e268043b94ed5..4557b71223b98 100644 --- a/src/frontend/src/handler/create_function.rs +++ b/src/frontend/src/handler/create_function.rs @@ -162,7 +162,7 @@ pub async fn handle_create_function( return_type: Some(return_type.into()), language, identifier, - body: "".to_string(), + body: None, link, owner: session.user_id(), }; diff --git a/src/frontend/src/handler/create_sql_function.rs b/src/frontend/src/handler/create_sql_function.rs index 04a237902cd99..834e0bec3135d 100644 --- a/src/frontend/src/handler/create_sql_function.rs +++ b/src/frontend/src/handler/create_sql_function.rs @@ -169,7 +169,7 @@ pub async fn handle_create_sql_function( return_type: Some(return_type.into()), language, identifier: "".to_string(), - body, + body: Some(body), link: "".to_string(), owner: session.user_id(), }; diff --git a/src/meta/model_v2/src/function.rs b/src/meta/model_v2/src/function.rs index 8a051fc1de20d..5976685893afb 100644 --- a/src/meta/model_v2/src/function.rs +++ b/src/meta/model_v2/src/function.rs @@ -95,7 +95,7 @@ impl From for ActiveModel { language: Set(function.language), link: Set(function.link), identifier: Set(function.identifier), - body: Set(Some(function.body)), + body: Set(function.body), kind: Set(function.kind.unwrap().into()), } } diff --git a/src/meta/src/controller/mod.rs b/src/meta/src/controller/mod.rs index eb327af67812f..ca1536834f008 100644 --- a/src/meta/src/controller/mod.rs +++ b/src/meta/src/controller/mod.rs @@ -279,7 +279,7 @@ impl From> for PbFunction { language: value.0.language, link: value.0.link, identifier: value.0.identifier, - body: value.0.body.unwrap_or_default(), + body: value.0.body, kind: Some(value.0.kind.into()), } } From ebfa7085830754bf08a486c010b1c5d4be7f8fba Mon Sep 17 00:00:00 2001 From: Michael Xu Date: Tue, 2 Jan 2024 04:28:50 -0500 Subject: [PATCH 4/4] fix format --- src/frontend/src/binder/expr/function.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/frontend/src/binder/expr/function.rs b/src/frontend/src/binder/expr/function.rs index 4e5ba951eb9a1..2454069ac11a7 100644 --- a/src/frontend/src/binder/expr/function.rs +++ b/src/frontend/src/binder/expr/function.rs @@ -233,13 +233,14 @@ impl Binder { if func.language == "sql" { if func.body.is_none() { return Err(ErrorCode::InvalidInputSyntax( - "`body` must exist for sql udf".to_string() + "`body` must exist for sql udf".to_string(), ) .into()); } // This represents the current user defined function is `language sql` - let parse_result = - risingwave_sqlparser::parser::Parser::parse_sql(func.body.as_ref().unwrap().as_str()); + let parse_result = risingwave_sqlparser::parser::Parser::parse_sql( + func.body.as_ref().unwrap().as_str(), + ); if let Err(ParserError::ParserError(err)) | Err(ParserError::TokenizerError(err)) = parse_result {