From d5125f6ce69a49cd185b751e672b3b7564cb529b Mon Sep 17 00:00:00 2001 From: houjibofa Date: Mon, 17 Aug 2020 23:22:09 +0800 Subject: [PATCH 1/2] =?UTF-8?q?=E3=80=90=E7=89=B9=E6=80=A7=E3=80=91?= =?UTF-8?q?=E5=87=BD=E6=95=B0=E3=80=81=E5=AD=98=E5=82=A8=E8=BF=87=E7=A8=8B?= =?UTF-8?q?=E6=88=96=E8=80=85=E8=A7=A6=E5=8F=91=E5=99=A8=E4=B8=AD=E8=B0=83?= =?UTF-8?q?=E7=94=A8=E6=97=A0=E5=8F=82=E6=95=B0=E5=87=BD=E6=95=B0=EF=BC=8C?= =?UTF-8?q?=E6=94=AF=E6=8C=81=E7=9C=81=E7=95=A5()?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/common/pl/plpgsql/src/gram.y | 118 +++++++++++++++++++-- src/test/regress/expected/hw_procedure.out | 59 ++++++++++- src/test/regress/sql/hw_procedure.sql | 51 +++++++++ 3 files changed, 215 insertions(+), 13 deletions(-) diff --git a/src/common/pl/plpgsql/src/gram.y b/src/common/pl/plpgsql/src/gram.y index b5ac29bab..c8fb857bb 100755 --- a/src/common/pl/plpgsql/src/gram.y +++ b/src/common/pl/plpgsql/src/gram.y @@ -106,6 +106,8 @@ static void plpgsql_parser_funcname(const char *s, char **output, int numidents); static PLpgSQL_stmt *make_callfunc_stmt(const char *sqlstart, int location, bool is_assign); + +static PLpgSQL_stmt *make_callfunc_stmt_no_arg(const char *sqlstart, int location); static PLpgSQL_expr *read_sql_construct5(int until, int until2, @@ -2343,23 +2345,36 @@ stmt_execsql : K_ALTER { int tok = -1; bool isCallFunc = false; + bool funcNoarg = false; + tok = yylex(); if ('(' == tok) isCallFunc = is_function($1.ident, false); else if ('=' ==tok || COLON_EQUALS == tok || '[' == tok) word_is_not_variable(&($1), @1); + else if (';' == tok) + funcNoarg = true; - plpgsql_push_back_token(tok); - if (isCallFunc) - $$ = make_callfunc_stmt($1.ident, @1, false); - else - $$ = make_execsql_stmt(T_WORD, @1); + if (funcNoarg) { + isCallFunc = is_function($1.ident, false); + if (isCallFunc) + $$ = make_callfunc_stmt_no_arg($1.ident, @1); + else + $$ = make_execsql_stmt(T_WORD, @1); + } else { + plpgsql_push_back_token(tok); + if (isCallFunc) + $$ = make_callfunc_stmt($1.ident, @1, false); + else + $$ = make_execsql_stmt(T_WORD, @1); + } } | T_CWORD { int tok = yylex(); char *name = NULL; bool isCallFunc = false; + bool funcNoarg = false; if ('(' == tok) { @@ -2370,12 +2385,26 @@ stmt_execsql : K_ALTER } else if ('=' == tok || COLON_EQUALS == tok || '[' == tok) cword_is_not_variable(&($1), @1); + else if (';' == tok) { + MemoryContext colCxt = MemoryContextSwitchTo(u_sess->plsql_cxt.compile_tmp_cxt); + name = NameListToString($1.idents); + (void)MemoryContextSwitchTo(colCxt); + isCallFunc = is_function(name, false); + funcNoarg = true; + } - plpgsql_push_back_token(tok); - if (isCallFunc) - $$ = make_callfunc_stmt(name, @1, false); - else - $$ = make_execsql_stmt(T_CWORD, @1); + if (funcNoarg) { + if (isCallFunc) + $$ = make_callfunc_stmt_no_arg(name, @1); + else + $$ = make_execsql_stmt(T_CWORD, @1); + } else { + plpgsql_push_back_token(tok); + if (isCallFunc) + $$ = make_callfunc_stmt(name, @1, false); + else + $$ = make_execsql_stmt(T_CWORD, @1); + } } | T_ARRAY_EXTEND { @@ -5924,3 +5953,72 @@ make_case(int location, PLpgSQL_expr *t_expr, return (PLpgSQL_stmt *) newp; } + +static PLpgSQL_stmt * +make_callfunc_stmt_no_arg(const char *sqlstart, int location) +{ + char *cp[3]; + + List *funcname = NIL; + PLpgSQL_expr* expr = NULL; + FuncCandidateList clist = NULL; + StringInfoData func_inparas; + char *quoted_sqlstart = NULL; + + MemoryContext oldCxt = NULL; + /*get the function's name*/ + cp[0] = NULL; + cp[1] = NULL; + cp[2] = NULL; + /* the function make_callfunc_stmt is only to assemble a sql statement, so the context is set to tmp context */ + oldCxt = MemoryContextSwitchTo(u_sess->plsql_cxt.compile_tmp_cxt); + plpgsql_parser_funcname(sqlstart, cp, 3); + + if (cp[2] && cp[2][0] != '\0') + funcname = list_make3(makeString(cp[0]), makeString(cp[1]), makeString(cp[2])); + else if (cp[1] && cp[1][0] != '\0') + funcname = list_make2(makeString(cp[0]), makeString(cp[1])); + else + funcname = list_make1(makeString(cp[0])); + + + /* search the function */ + clist = FuncnameGetCandidates(funcname, -1, NIL, false, false, false); + if (!clist) + { + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_FUNCTION), + errmsg("function \"%s\" doesn't exist ", sqlstart))); + return NULL; + } + + initStringInfo(&func_inparas); + + appendStringInfoString(&func_inparas, "CALL "); + + quoted_sqlstart = NameListToQuotedString(funcname); + appendStringInfoString(&func_inparas, quoted_sqlstart); + pfree_ext(quoted_sqlstart); + + appendStringInfoString(&func_inparas, "("); + + appendStringInfoString(&func_inparas, ")"); + + (void)MemoryContextSwitchTo(oldCxt); + + /* generate the expression */ + expr = (PLpgSQL_expr*)palloc0(sizeof(PLpgSQL_expr)); + expr->dtype = PLPGSQL_DTYPE_EXPR; + expr->query = pstrdup(func_inparas.data); + expr->plan = NULL; + expr->paramnos = NULL; + expr->ns = plpgsql_ns_top(); + + PLpgSQL_stmt_perform *perform = NULL; + perform = (PLpgSQL_stmt_perform*)palloc0(sizeof(PLpgSQL_stmt_perform)); + perform->cmd_type = PLPGSQL_STMT_PERFORM; + perform->lineno = plpgsql_location_to_lineno(location); + perform->expr = expr; + + return (PLpgSQL_stmt *)perform; +} \ No newline at end of file diff --git a/src/test/regress/expected/hw_procedure.out b/src/test/regress/expected/hw_procedure.out index 932aca1a4..e7bf9f868 100644 --- a/src/test/regress/expected/hw_procedure.out +++ b/src/test/regress/expected/hw_procedure.out @@ -578,9 +578,6 @@ BEGIN return q; END; $$ LANGUAGE plpgsql; -ERROR: syntax error at or near "hw_insertion5" -LINE 5: hw_insertion5; --IN, INOUT - ^ CREATE FUNCTION test_func_call_less_arg6() RETURNS integer AS $$ DECLARE q int := 1; @@ -1884,3 +1881,59 @@ END; / drop table test_table; +-----------------------------------------------------function without arguments +DROP FUNCTION IF EXISTS func_add_sql_arg2; +NOTICE: function func_add_sql_arg2() does not exist, skipping +DROP function IF EXISTS f_add_no_arg; +NOTICE: function f_add_no_arg() does not exist, skipping +DROP FUNCTION IF EXISTS f_add; +NOTICE: function f_add() does not exist, skipping +CREATE FUNCTION func_add_sql_arg2(num1 integer, num2 integer) RETURN integer +AS +BEGIN +RETURN num1 + num2; +END; +/ +CREATE FUNCTION func_add_sql_no_arg() RETURN integer +AS +BEGIN +RETURN 1; +END; +/ +create or replace procedure f_add_no_arg +as +begin + func_add_sql_arg2; +end; +/ +create or replace procedure f_add +as +begin + func_add_sql_arg2(3,4); +end; +/ +call f_add(); + f_add +------- + +(1 row) + +call f_add_no_arg(); +ERROR: function "func_add_sql_arg2" with 0 parameters doesn't exist +CONTEXT: SQL statement "CALL func_add_sql_arg2()" +PL/pgSQL function f_add_no_arg() line 3 at PERFORM +DROP FUNCTION IF EXISTS func_add_sql_arg2; +DROP function IF EXISTS f_add_no_arg; +DROP FUNCTION IF EXISTS f_add; +create or replace procedure func_proc_no_arg +as +begin + func_add_sql_no_arg; +end; +/ +call func_proc_no_arg(); + func_proc_no_arg +------------------ + +(1 row) + diff --git a/src/test/regress/sql/hw_procedure.sql b/src/test/regress/sql/hw_procedure.sql index 81ee6af7f..9951bf73c 100644 --- a/src/test/regress/sql/hw_procedure.sql +++ b/src/test/regress/sql/hw_procedure.sql @@ -1586,3 +1586,54 @@ END; / drop table test_table; + + + +-----------------------------------------------------function without arguments +DROP FUNCTION IF EXISTS func_add_sql_arg2; +DROP function IF EXISTS f_add_no_arg; +DROP FUNCTION IF EXISTS f_add; + +CREATE FUNCTION func_add_sql_arg2(num1 integer, num2 integer) RETURN integer +AS +BEGIN +RETURN num1 + num2; +END; +/ + +CREATE FUNCTION func_add_sql_no_arg() RETURN integer +AS +BEGIN +RETURN 1; +END; +/ + +create or replace procedure f_add_no_arg +as +begin + func_add_sql_arg2; +end; +/ + +create or replace procedure f_add +as +begin + func_add_sql_arg2(3,4); +end; +/ + +call f_add(); +call f_add_no_arg(); + +DROP FUNCTION IF EXISTS func_add_sql_arg2; +DROP function IF EXISTS f_add_no_arg; +DROP FUNCTION IF EXISTS f_add; + +create or replace procedure func_proc_no_arg +as +begin + func_add_sql_no_arg; +end; +/ + +call func_proc_no_arg(); \ No newline at end of file From a9deee80c3a255589790bd89af2b22cbe12832d7 Mon Sep 17 00:00:00 2001 From: houjibofa Date: Mon, 17 Aug 2020 23:22:09 +0800 Subject: [PATCH 2/2] =?UTF-8?q?=E3=80=90=E7=89=B9=E6=80=A7=E3=80=91?= =?UTF-8?q?=E5=87=BD=E6=95=B0=E3=80=81=E5=AD=98=E5=82=A8=E8=BF=87=E7=A8=8B?= =?UTF-8?q?=E6=88=96=E8=80=85=E8=A7=A6=E5=8F=91=E5=99=A8=E4=B8=AD=E8=B0=83?= =?UTF-8?q?=E7=94=A8=E6=97=A0=E5=8F=82=E6=95=B0=E5=87=BD=E6=95=B0=EF=BC=8C?= =?UTF-8?q?=E6=94=AF=E6=8C=81=E7=9C=81=E7=95=A5()?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit