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