!108 【feature】【Opengauss回合】调用无参数函数省略()

Merge pull request !108 from chenyanfei/master
This commit is contained in:
opengauss-bot
2020-08-20 16:02:03 +08:00
committed by Gitee
3 changed files with 215 additions and 13 deletions

View File

@ -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;
}

View File

@ -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)

View File

@ -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();