risingwave_frontend/handler/
drop_function.rs1use super::*;
16use crate::catalog::CatalogError;
17use crate::catalog::root_catalog::SchemaPath;
18use crate::{Binder, bind_data_type};
19
20pub async fn handle_drop_function(
22 handler_args: HandlerArgs,
23 if_exists: bool,
24 mut func_desc: Vec<FunctionDesc>,
25 _option: Option<ReferentialAction>,
26 aggregate: bool,
27) -> Result<RwPgResponse> {
28 if func_desc.len() != 1 {
29 bail_not_implemented!("only support dropping 1 function");
30 }
31 let stmt_type = if aggregate {
32 StatementType::DROP_AGGREGATE
33 } else {
34 StatementType::DROP_FUNCTION
35 };
36 let func_desc = func_desc.remove(0);
37
38 let session = handler_args.session;
39 let db_name = &session.database();
40 let (schema_name, function_name) =
41 Binder::resolve_schema_qualified_name(db_name, func_desc.name)?;
42 let search_path = session.config().search_path();
43 let user_name = &session.user_name();
44 let schema_path = SchemaPath::new(schema_name.as_deref(), &search_path, user_name);
45
46 let arg_types = match func_desc.args {
47 Some(args) => {
48 let mut arg_types = vec![];
49 for arg in args {
50 arg_types.push(bind_data_type(&arg.data_type)?);
51 }
52 Some(arg_types)
53 }
54 None => None,
55 };
56
57 let function_id = {
58 let reader = session.env().catalog_reader().read_guard();
59 let res = match arg_types {
60 Some(arg_types) => {
61 reader.get_function_by_name_args(db_name, schema_path, &function_name, &arg_types)
62 }
63 None => match reader.get_functions_by_name(db_name, schema_path, &function_name) {
65 Ok((functions, schema_name)) => {
66 if functions.len() > 1 {
67 return Err(ErrorCode::CatalogError(format!("function name {function_name:?} is not unique\nHINT: Specify the argument list to select the function unambiguously.").into()).into());
68 }
69 Ok((
70 functions.into_iter().next().expect("no functions"),
71 schema_name,
72 ))
73 }
74 Err(e) => Err(e),
75 },
76 };
77 match res {
78 Ok((function, schema_name)) => {
79 session.check_privilege_for_drop_alter(schema_name, &**function)?;
80 if !aggregate && function.kind.is_aggregate() {
81 return Err(ErrorCode::CatalogError(
82 format!("\"{function_name}\" is an aggregate function\nHINT: Use DROP AGGREGATE to drop aggregate functions.").into(),
83 )
84 .into());
85 } else if aggregate && !function.kind.is_aggregate() {
86 return Err(ErrorCode::CatalogError(
87 format!("\"{function_name}\" is not an aggregate").into(),
88 )
89 .into());
90 }
91 function.id
92 }
93 Err(CatalogError::NotFound(kind, _)) if kind == "function" && if_exists => {
94 return Ok(RwPgResponse::builder(stmt_type)
95 .notice(format!(
96 "function \"{}\" does not exist, skipping",
97 function_name
98 ))
99 .into());
100 }
101 Err(e) => return Err(e.into()),
102 }
103 };
104
105 let catalog_writer = session.catalog_writer()?;
106 catalog_writer.drop_function(function_id).await?;
107
108 Ok(PgResponse::empty_result(stmt_type))
109}