diff --git a/doc/src/sgml/ref/create_function.sgmlin b/doc/src/sgml/ref/create_function.sgmlin index 6f91c9859..d4d52f5f7 100755 --- a/doc/src/sgml/ref/create_function.sgmlin +++ b/doc/src/sgml/ref/create_function.sgmlin @@ -10,7 +10,7 @@ -CREATE [ OR REPLACE ] FUNCTION function_name +CREATE [ OR REPLACE ] [DEFINER = user] FUNCTION function_name ( [ { argname [ argmode ] argtype [ { DEFAULT | := | = } expression ]} [, ...] ] ) [ RETURNS rettype [ DETERMINISTIC ] | RETURNS TABLE ( { column_name column_type } [, ...] )] @@ -33,7 +33,7 @@ CREATE [ OR REPLACE ] FUNCTION function_name | AS 'obj_file', 'link_symbol' } -CREATE [ OR REPLACE ] FUNCTION function_name +CREATE [ OR REPLACE ] [DEFINER = user] FUNCTION function_name ( [ { argname [ argmode ] argtype [ { DEFAULT | := | = } expression ] } [, ...] ] ) RETURN rettype [ DETERMINISTIC ] [ diff --git a/doc/src/sgml/ref/create_procedure.sgmlin b/doc/src/sgml/ref/create_procedure.sgmlin index f8757911a..22612fb0d 100644 --- a/doc/src/sgml/ref/create_procedure.sgmlin +++ b/doc/src/sgml/ref/create_procedure.sgmlin @@ -10,7 +10,7 @@ -CREATE [ OR REPLACE ] PROCEDURE procedure_name +CREATE [ OR REPLACE ] [DEFINER = user] PROCEDURE procedure_name [ ( {[ argmode ] [ argname ] argtype [ { DEFAULT | := | = } expression ]}[,...]) ] { IS | AS } plsql_body / diff --git a/src/bin/pg_dump/dumputils.cpp b/src/bin/pg_dump/dumputils.cpp index 4f8f28acb..b16437fe2 100644 --- a/src/bin/pg_dump/dumputils.cpp +++ b/src/bin/pg_dump/dumputils.cpp @@ -41,6 +41,7 @@ int quote_all_identifiers = 0; const char* progname = NULL; const char* dbname = NULL; const char* instport = NULL; +const char *gdatcompatibility = NULL; char* binary_upgrade_oldowner = NULL; char* binary_upgrade_newowner = NULL; diff --git a/src/bin/pg_dump/dumputils.h b/src/bin/pg_dump/dumputils.h index 19e237f8c..86b61c9ab 100644 --- a/src/bin/pg_dump/dumputils.h +++ b/src/bin/pg_dump/dumputils.h @@ -40,6 +40,11 @@ #define FILE_PERMISSION 0600 #define MAX_PASSWDLEN 100 +#define A_FORMAT "A" +#define B_FORMAT "B" +#define C_FORMAT "C" +#define PG_FORMAT "PG" + /* Data structures for simple lists of OIDs and strings. The support for * these is very primitive compared to the backend's List facilities, but * it's all we need in pg_dump. @@ -87,6 +92,7 @@ extern int quote_all_identifiers; extern const char* progname; extern const char* dbname; extern const char* instport; +extern const char *gdatcompatibility; extern char* binary_upgrade_oldowner; extern char* binary_upgrade_newowner; diff --git a/src/bin/pg_dump/pg_dump.cpp b/src/bin/pg_dump/pg_dump.cpp index 3bf07ee22..717234021 100644 --- a/src/bin/pg_dump/pg_dump.cpp +++ b/src/bin/pg_dump/pg_dump.cpp @@ -73,7 +73,7 @@ #include "knl/knl_variable.h" #include "openssl/rand.h" - +#include "miscadmin.h" #include "bin/elog.h" #ifdef HAVE_CE #include "client_logic_cache/types_to_oid.h" @@ -3168,6 +3168,7 @@ static void dumpDatabase(Archive* fout) if (isHasDatcompatibility) { i_datcompatibility = PQfnumber(res, "datcompatibility"); datcompatibility = PQgetvalue(res, 0, i_datcompatibility); + gdatcompatibility = datcompatibility; } appendPQExpBuffer(creaQry, "CREATE DATABASE %s WITH TEMPLATE = template0", fmtId(datname)); @@ -12707,11 +12708,13 @@ static char* format_function_signature(Archive* fout, FuncInfo* finfo, bool hono static void dumpFunc(Archive* fout, FuncInfo* finfo) { PQExpBuffer query; + PQExpBuffer definerquery; PQExpBuffer q; PQExpBuffer delqry; PQExpBuffer labelq; PQExpBuffer asPart; PGresult* res = NULL; + PGresult* defres = NULL; char* funcsig = NULL; /* identity signature */ char* funcfullsig = NULL; /* full signature */ char* funcsig_tag = NULL; @@ -12740,6 +12743,7 @@ static void dumpFunc(Archive* fout, FuncInfo* finfo) char* propackage = NULL; char* rettypename = NULL; char* propackageid = NULL; + char* definer = NULL; int nallargs = 0; char** allargtypes = NULL; char** argmodes = NULL; @@ -12769,6 +12773,7 @@ static void dumpFunc(Archive* fout, FuncInfo* finfo) delqry = createPQExpBuffer(); labelq = createPQExpBuffer(); asPart = createPQExpBuffer(); + definerquery = createPQExpBuffer(); /* Set proper schema search path so type references list correctly */ selectSourceSchema(fout, finfo->dobj.nmspace->dobj.name); @@ -12788,7 +12793,7 @@ static void dumpFunc(Archive* fout, FuncInfo* finfo) "pg_catalog.pg_get_function_identity_arguments(oid) AS funciargs, " "pg_catalog.pg_get_function_result(oid) AS funcresult, " "proiswindow, provolatile, proisstrict, prosecdef, " - "proleakproof, proconfig, procost, prorows, propackageid, " + "proleakproof, proconfig, procost, prorows, propackageid, proowner," "%s, " "%s, " "%s, " @@ -12827,6 +12832,13 @@ static void dumpFunc(Archive* fout, FuncInfo* finfo) propackage = PQgetvalue(res, 0, PQfnumber(res, "propackage")); propackageid = PQgetvalue(res, 0, PQfnumber(res, "propackageid")); + if ((gdatcompatibility != NULL) && strcmp(gdatcompatibility, B_FORMAT) == 0) { + /* get definer user name */ + appendPQExpBuffer(definerquery, "SELECT rolname from pg_authid where oid=%s", PQgetvalue(res, 0, PQfnumber(res, "proowner"))); + defres = ExecuteSqlQueryForSingleRow(fout, definerquery->data); + definer = PQgetvalue(defres, 0, PQfnumber(defres, "rolname")); + } + if (propackageid != NULL) { if (strcmp(propackageid, "0") != 0) { PQclear(res); @@ -12951,7 +12963,15 @@ static void dumpFunc(Archive* fout, FuncInfo* finfo) appendPQExpBuffer(delqry, "DROP %s IF EXISTS %s.%s%s;\n", funcKind, fmtId(finfo->dobj.nmspace->dobj.name), funcsig, if_cascade); - appendPQExpBuffer(q, "CREATE %s %s ", funcKind, funcfullsig); + if ((gdatcompatibility != NULL) && strcmp(gdatcompatibility, B_FORMAT) == 0) { + appendPQExpBuffer(q, "CREATE DEFINER = %s %s %s ", definer, funcKind, funcfullsig); + PQclear(defres); + destroyPQExpBuffer(definerquery); + + } else { + appendPQExpBuffer(q, "CREATE %s %s ", funcKind, funcfullsig); + } + if (isProcedure) { /* For procedure, no return type, do nothing */ diff --git a/src/bin/psql/psqlscan.l b/src/bin/psql/psqlscan.l index 82af110e9..d7edd6af3 100644 --- a/src/bin/psql/psqlscan.l +++ b/src/bin/psql/psqlscan.l @@ -75,6 +75,7 @@ typedef enum IDEN_CREATE, IDEN_OR, IDEN_REPLACE, + IDEN_DEFINER, IDEN_PROCEDURE, IDEN_RETURN, IDEN_RETURNS, @@ -2146,6 +2147,8 @@ keywordRead(const char* text) return IDEN_OR; else if (!upperstrcmp(text, "replace")) return IDEN_REPLACE; + else if (!upperstrcmp(text, "definer")) + return IDEN_DEFINER; else if (!upperstrcmp(text, "procedure")) return IDEN_PROCEDURE; else if (!upperstrcmp(text, "package")) @@ -2216,6 +2219,7 @@ analyze_state(const char* text,PsqlScanStateData* state) { case IDEN_CREATE: state->gram_state[IDEN_OR] = true; + state->gram_state[IDEN_DEFINER] = true; state->gram_state[IDEN_PROCEDURE] = true; state->gram_state[IDEN_FUNCTION] = true; state->gram_state[IDEN_TRIGGER] = true; @@ -2224,15 +2228,25 @@ analyze_state(const char* text,PsqlScanStateData* state) break; case IDEN_OR: state->gram_state[IDEN_REPLACE] = true; + state->gram_state[IDEN_DEFINER] = true; state->count_to_read++; break; case IDEN_REPLACE: + state->gram_state[IDEN_DEFINER] = true; state->gram_state[IDEN_PROCEDURE] = true; state->gram_state[IDEN_FUNCTION] = true; state->gram_state[IDEN_PACKAGE] = true; state->gram_state[IDEN_TRIGGER] = true; state->count_to_read++; break; + case IDEN_DEFINER: + state->gram_state[IDEN_PROCEDURE] = true; + state->gram_state[IDEN_FUNCTION] = true; + state->gram_state[IDEN_PACKAGE] = true; + state->gram_state[IDEN_TRIGGER] = true; + state->count_to_read++; + state->count_to_read = -1; + break; case IDEN_PROCEDURE: state->gram_state[IDEN_AS] = true; state->gram_state[IDEN_IS] = true; diff --git a/src/common/backend/nodes/copyfuncs.cpp b/src/common/backend/nodes/copyfuncs.cpp index b9ce9cf61..6c0270bc9 100644 --- a/src/common/backend/nodes/copyfuncs.cpp +++ b/src/common/backend/nodes/copyfuncs.cpp @@ -5134,6 +5134,9 @@ static CreateFunctionStmt* _copyCreateFunctionStmt(const CreateFunctionStmt* fro COPY_NODE_FIELD(options); COPY_NODE_FIELD(withClause); COPY_STRING_FIELD(inputHeaderSrc); + if (t_thrd.proc->workingVersionNum >= CREATE_FUNCTION_DEFINER_VERSION) { + COPY_STRING_FIELD(definer); + } return newnode; } diff --git a/src/common/backend/nodes/equalfuncs.cpp b/src/common/backend/nodes/equalfuncs.cpp index 97bbe18d2..6cfe83dcb 100644 --- a/src/common/backend/nodes/equalfuncs.cpp +++ b/src/common/backend/nodes/equalfuncs.cpp @@ -1411,6 +1411,9 @@ static bool _equalCreateFunctionStmt(const CreateFunctionStmt* a, const CreateFu COMPARE_NODE_FIELD(returnType); COMPARE_NODE_FIELD(options); COMPARE_NODE_FIELD(withClause); + if (t_thrd.proc->workingVersionNum >= CREATE_FUNCTION_DEFINER_VERSION) { + COMPARE_STRING_FIELD(definer); + } return true; } diff --git a/src/common/backend/parser/gram.y b/src/common/backend/parser/gram.y index 4f598c7f1..6344e8e02 100644 --- a/src/common/backend/parser/gram.y +++ b/src/common/backend/parser/gram.y @@ -610,7 +610,7 @@ static int errstate; %type Iconst SignedIconst %type Sconst comment_text notify_payload -%type RoleId TypeOwner opt_granted_by opt_boolean_or_string ColId_or_Sconst +%type RoleId TypeOwner opt_granted_by opt_boolean_or_string ColId_or_Sconst definer_user %type var_list %type ColId ColLabel var_name type_function_name param_name %type var_value zone_value @@ -11967,53 +11967,65 @@ range_subpartition_index_item: *****************************************************************************/ CreateFunctionStmt: - CREATE opt_or_replace FUNCTION func_name_opt_arg proc_args + CREATE opt_or_replace definer_user FUNCTION func_name_opt_arg proc_args RETURNS func_return createfunc_opt_list opt_definition { CreateFunctionStmt *n = makeNode(CreateFunctionStmt); n->isOraStyle = false; n->isPrivate = false; n->replace = $2; - n->funcname = $4; - n->parameters = $5; - n->returnType = $7; - n->options = $8; - n->withClause = $9; + n->definer = $3; + if (n->replace && NULL != n->definer) { + parser_yyerror("not support DEFINER function"); + } + n->funcname = $5; + n->parameters = $6; + n->returnType = $8; + n->options = $9; + n->withClause = $10; n->isProcedure = false; $$ = (Node *)n; } - | CREATE opt_or_replace FUNCTION func_name_opt_arg proc_args + | CREATE opt_or_replace definer_user FUNCTION func_name_opt_arg proc_args RETURNS TABLE '(' table_func_column_list ')' createfunc_opt_list opt_definition { CreateFunctionStmt *n = makeNode(CreateFunctionStmt); n->isOraStyle = false; n->isPrivate = false; n->replace = $2; - n->funcname = $4; - n->parameters = mergeTableFuncParameters($5, $9); - n->returnType = TableFuncTypeName($9); - n->returnType->location = @7; - n->options = $11; - n->withClause = $12; + n->definer = $3; + if (n->replace && NULL != n->definer) { + parser_yyerror("not support DEFINER function"); + } + n->funcname = $5; + n->parameters = mergeTableFuncParameters($6, $10); + n->returnType = TableFuncTypeName($10); + n->returnType->location = @8; + n->options = $12; + n->withClause = $13; n->isProcedure = false; $$ = (Node *)n; } - | CREATE opt_or_replace FUNCTION func_name_opt_arg proc_args + | CREATE opt_or_replace definer_user FUNCTION func_name_opt_arg proc_args createfunc_opt_list opt_definition { CreateFunctionStmt *n = makeNode(CreateFunctionStmt); n->isOraStyle = false; n->isPrivate = false; n->replace = $2; - n->funcname = $4; - n->parameters = $5; + n->definer = $3; + if (n->replace && NULL != n->definer) { + parser_yyerror("not support DEFINER function"); + } + n->funcname = $5; + n->parameters = $6; n->returnType = NULL; - n->options = $6; - n->withClause = $7; + n->options = $7; + n->withClause = $8; n->isProcedure = false; $$ = (Node *)n; } - | CREATE opt_or_replace FUNCTION func_name_opt_arg proc_args + | CREATE opt_or_replace definer_user FUNCTION func_name_opt_arg proc_args RETURN func_return opt_createproc_opt_list as_is { u_sess->parser_cxt.eaten_declare = false; u_sess->parser_cxt.eaten_begin = false; @@ -12024,18 +12036,22 @@ CreateFunctionStmt: int rc = 0; rc = CompileWhich(); if (rc == PLPGSQL_COMPILE_PROC || rc == PLPGSQL_COMPILE_NULL) { - u_sess->plsql_cxt.procedure_first_line = GetLineNumber(t_thrd.postgres_cxt.debug_query_string, @9); + u_sess->plsql_cxt.procedure_first_line = GetLineNumber(t_thrd.postgres_cxt.debug_query_string, @10); } CreateFunctionStmt *n = makeNode(CreateFunctionStmt); - FunctionSources *funSource = (FunctionSources *)$11; + FunctionSources *funSource = (FunctionSources *)$12; n->isOraStyle = true; n->isPrivate = false; n->replace = $2; - n->funcname = $4; - n->parameters = $5; + n->definer = $3; + if (n->replace && NULL != n->definer) { + parser_yyerror("not support DEFINER function"); + } + n->funcname = $5; + n->parameters = $6; n->inputHeaderSrc = FormatFuncArgType(yyscanner, funSource->headerSrc, n->parameters); - n->returnType = $7; - n->options = $8; + n->returnType = $8; + n->options = $9; n->options = lappend(n->options, makeDefElem("as", (Node *)list_make1(makeString(funSource->bodySrc)))); n->options = lappend(n->options, makeDefElem("language", @@ -12075,7 +12091,7 @@ callfunc_args: func_arg_expr } ; CreateProcedureStmt: - CREATE opt_or_replace PROCEDURE func_name_opt_arg proc_args + CREATE opt_or_replace definer_user PROCEDURE func_name_opt_arg proc_args opt_createproc_opt_list as_is { u_sess->parser_cxt.eaten_declare = false; u_sess->parser_cxt.eaten_begin = false; @@ -12086,18 +12102,22 @@ CreateProcedureStmt: int rc = 0; rc = CompileWhich(); if ((rc == PLPGSQL_COMPILE_PROC || rc == PLPGSQL_COMPILE_NULL) && u_sess->cmd_cxt.CurrentExtensionObject == InvalidOid) { - u_sess->plsql_cxt.procedure_first_line = GetLineNumber(t_thrd.postgres_cxt.debug_query_string, @7); + u_sess->plsql_cxt.procedure_first_line = GetLineNumber(t_thrd.postgres_cxt.debug_query_string, @8); } rc = CompileWhich(); CreateFunctionStmt *n = makeNode(CreateFunctionStmt); - FunctionSources *funSource = (FunctionSources *)$9; - int count = get_outarg_num($5); + FunctionSources *funSource = (FunctionSources *)$10; + int count = get_outarg_num($6); n->isOraStyle = true; n->isPrivate = false; n->replace = $2; - n->funcname = $4; - n->parameters = $5; + n->definer = $3; + if (n->replace && NULL != n->definer) { + parser_yyerror("not support DEFINER function"); + } + n->funcname = $5; + n->parameters = $6; n->inputHeaderSrc = FormatFuncArgType(yyscanner, funSource->headerSrc, n->parameters); n->returnType = NULL; n->isProcedure = true; @@ -12107,7 +12127,7 @@ CreateProcedureStmt: n->returnType->typmods = NULL; n->returnType->arrayBounds = NULL; } - n->options = $6; + n->options = $7; n->options = lappend(n->options, makeDefElem("as", (Node *)list_make1(makeString(funSource->bodySrc)))); n->options = lappend(n->options, makeDefElem("language", @@ -12298,7 +12318,19 @@ invoker_rights: AUTHID DEFINER } ; - +definer_user: DEFINER '=' RoleId + { + if (u_sess->attr.attr_sql.sql_compatibility == B_FORMAT) { + $$ = $3; + } else { + parser_yyerror("not support DEFINER function"); + } + } + | /* EMPTY */ + { + $$ = NULL; + } + ; pkg_body_subprogram: { int proc_b = 0; int proc_e = 0; diff --git a/src/common/backend/utils/adt/ruleutils.cpp b/src/common/backend/utils/adt/ruleutils.cpp index 5ec750219..2fea73042 100644 --- a/src/common/backend/utils/adt/ruleutils.cpp +++ b/src/common/backend/utils/adt/ruleutils.cpp @@ -4220,16 +4220,23 @@ char* pg_get_functiondef_worker(Oid funcid, int* headerlines) if (pkgname != NULL) { appendStringInfo(&buf, "CREATE OR REPLACE PROCEDURE %s(", quote_qualified_identifier(nsp, pkgname->data, name)); + } else if (u_sess->attr.attr_sql.sql_compatibility == B_FORMAT) { + appendStringInfo(&buf, "CREATE DEFINER = %s PROCEDURE %s(", + GetUserNameFromId(proc->proowner), quote_qualified_identifier(nsp, name)); } else { - appendStringInfo(&buf, "CREATE OR REPLACE PROCEDURE %s(", - quote_qualified_identifier(nsp, name)); + appendStringInfo(&buf, "CREATE OR REPLACE PROCEDURE %s(", + quote_qualified_identifier(nsp, name)); } + } else { if (pkgname != NULL) { appendStringInfo(&buf, "CREATE OR REPLACE FUNCTION %s(", quote_qualified_identifier(nsp, pkgname->data, name)); + } else if (u_sess->attr.attr_sql.sql_compatibility == B_FORMAT) { + appendStringInfo(&buf, "CREATE DEFINER = %s FUNCTION %s(", + GetUserNameFromId(proc->proowner), quote_qualified_identifier(nsp, name)); } else { - appendStringInfo(&buf, "CREATE OR REPLACE FUNCTION %s(", + appendStringInfo(&buf, "CREATE OR REPLACE FUNCTION %s(", quote_qualified_identifier(nsp, name)); } } diff --git a/src/common/backend/utils/init/globals.cpp b/src/common/backend/utils/init/globals.cpp index 6fa314a39..9612e92ae 100644 --- a/src/common/backend/utils/init/globals.cpp +++ b/src/common/backend/utils/init/globals.cpp @@ -59,7 +59,7 @@ bool open_join_children = true; bool will_shutdown = false; /* hard-wired binary version number */ -const uint32 GRAND_VERSION_NUM = 92607; +const uint32 GRAND_VERSION_NUM = 92608; const uint32 PREDPUSH_SAME_LEVEL_VERSION_NUM = 92522; const uint32 UPSERT_WHERE_VERSION_NUM = 92514; @@ -120,6 +120,7 @@ uint32 volatile WorkingGrandVersionNum = GRAND_VERSION_NUM; const uint32 INVALID_INVISIBLE_TUPLE_VERSION = 92605; const uint32 ENHANCED_TUPLE_LOCK_VERSION_NUM = 92583; +const uint32 CREATE_FUNCTION_DEFINER_VERSION = 92608; const uint32 TWOPHASE_FILE_VERSION = 92414; const uint32 HASUID_VERSION_NUM = 92550; diff --git a/src/gausskernel/optimizer/commands/functioncmds.cpp b/src/gausskernel/optimizer/commands/functioncmds.cpp index 37b69a6d7..edce46a83 100644 --- a/src/gausskernel/optimizer/commands/functioncmds.cpp +++ b/src/gausskernel/optimizer/commands/functioncmds.cpp @@ -999,6 +999,21 @@ void CreateFunction(CreateFunctionStmt* stmt, const char* queryString, Oid pkg_o } else { proowner = GetUserId(); } + + if (u_sess->attr.attr_sql.sql_compatibility == B_FORMAT) { + if (stmt->definer) { + HeapTuple roletuple = SearchSysCache1(AUTHNAME, PointerGetDatum(stmt->definer)); + + if (!HeapTupleIsValid(roletuple)) + ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), errmsg("role \"%s\" does not exist", stmt->definer))); + + proowner = HeapTupleGetOid(roletuple); + ReleaseSysCache(roletuple); + } + else { + proowner = GetUserId(); + } + } /* default attributes */ volatility = PROVOLATILE_VOLATILE; procost = -1; /* indicates not set */ diff --git a/src/gausskernel/runtime/executor/execQual.cpp b/src/gausskernel/runtime/executor/execQual.cpp index ba37b055f..ec246a861 100644 --- a/src/gausskernel/runtime/executor/execQual.cpp +++ b/src/gausskernel/runtime/executor/execQual.cpp @@ -1432,9 +1432,26 @@ static void init_fcache( { AclResult aclresult; MemoryContext oldcontext; + Form_pg_proc procStruct; + HeapTuple procTup; + Oid definer = GetUserId(); + + if (u_sess->attr.attr_sql.sql_compatibility == B_FORMAT) + { + /* Get the function's pg_proc entry */ + procTup = SearchSysCache1(PROCOID, ObjectIdGetDatum(foid)); + if (!HeapTupleIsValid(procTup)) { + ereport(ERROR, (errmodule(MOD_EXECUTOR), errcode(ERRCODE_CACHE_LOOKUP_FAILED), + errmsg("cache lookup failed for function %u", foid))); + } + procStruct = (Form_pg_proc)GETSTRUCT(procTup); + if (procStruct->prosecdef) + definer = procStruct->proowner; + ReleaseSysCache(procTup); + } /* Check permission to call function */ - aclresult = pg_proc_aclcheck(foid, GetUserId(), ACL_EXECUTE); + aclresult = pg_proc_aclcheck(foid, definer, ACL_EXECUTE); if (aclresult != ACLCHECK_OK) aclcheck_error(aclresult, ACL_KIND_PROC, get_func_name(foid)); diff --git a/src/include/miscadmin.h b/src/include/miscadmin.h index 2d102a53a..a974e00cb 100644 --- a/src/include/miscadmin.h +++ b/src/include/miscadmin.h @@ -97,6 +97,7 @@ extern const uint32 ANALYZER_HOOK_VERSION_NUM; extern const uint32 SUPPORT_HASH_XLOG_VERSION_NUM; extern const uint32 PITR_INIT_VERSION_NUM; extern const uint32 PUBLICATION_INITIAL_DATA_VERSION_NAME; +extern const uint32 CREATE_FUNCTION_DEFINER_VERSION; extern void register_backend_version(uint32 backend_version); extern bool contain_backend_version(uint32 version_number); diff --git a/src/include/nodes/parsenodes_common.h b/src/include/nodes/parsenodes_common.h index cd4147dc3..f7ae33116 100644 --- a/src/include/nodes/parsenodes_common.h +++ b/src/include/nodes/parsenodes_common.h @@ -2076,6 +2076,7 @@ typedef struct CreateFunctionStmt { char* queryStr; int startLineNumber; int firstLineNumber; + char *definer; } CreateFunctionStmt; typedef struct FunctionSources { diff --git a/src/test/regress/input/mysql_function.source b/src/test/regress/input/mysql_function.source new file mode 100644 index 000000000..4c5011cba --- /dev/null +++ b/src/test/regress/input/mysql_function.source @@ -0,0 +1,199 @@ +--test create function/procedure definer=user +drop database if exists mysqltest; +CREATE DATABASE mysqltest DBCOMPATIBILITY 'B'; +create schema mysqlschema; +create user usr1 password '12345@abc'; +create user usr2 password '12345@abc'; +--grammar test +\c mysqltest +create schema mysqlschema; +grant ALL on SCHEMA mysqlschema to PUBLIC; +CREATE DEFINER=testusr1 FUNCTION testfunc_definer1(integer, integer) RETURNS integer SECURITY DEFINER +AS 'select $1 + $2;' +LANGUAGE SQL +IMMUTABLE +RETURNS NULL ON NULL INPUT; + +CREATE OR REPLACE DEFINER=testusr1 FUNCTION func_definer2(integer, integer) RETURNS integer SECURITY DEFINER +AS 'select $1 + $2;' +LANGUAGE SQL +IMMUTABLE +RETURNS NULL ON NULL INPUT; + +CREATE DEFINER=testusr1 procedure proc_definer1() SECURITY DEFINER +AS +BEGIN + raise info 'create definer procedure.'; +END; +/ + + +CREATE OR REPLACE DEFINER=testusr1 procedure proc_definer2() SECURITY DEFINER +AS +BEGIN + raise info 'create definer procedure.'; +END; +/ + +CREATE USER testusr1 password '12345@abc'; +CREATE DEFINER=testusr1 FUNCTION func_definer1(integer, integer) RETURNS integer SECURITY INVOKER +AS 'select $1 + $2;' +LANGUAGE SQL +IMMUTABLE +RETURNS NULL ON NULL INPUT; + +CREATE DEFINER=testusr1 procedure proc_definer1() +AS +BEGIN + raise info 'create definer procedure.'; +END; +/ + +--test \sf +\sf func_definer1 +\sf proc_definer1 + +--test create or replace function or procedure +select usename from pg_user where usesysid = (select proowner from pg_proc where proname='proc_definer1'); +CREATE or replace procedure proc_definer1() +AS +BEGIN + raise info 'create definer procedure.'; +END; +/ + + +select usename from pg_user where usesysid = (select proowner from pg_proc where proname='proc_definer1'); + +--dump test +-- dump function +\! @abs_bindir@/gs_dump mysqltest -p @portstring@ -f @abs_bindir@/mysql_function_back.sql + +CREATE DATABASE mysqltestbak DBCOMPATIBILITY 'B'; +-- restore data +\! @abs_bindir@/gsql -p @portstring@ -d mysqltestbak -f @abs_bindir@/mysql_function_back.sql + +\c mysqltestbak +\sf proc_definer1 + +--test security--general user create definer function +\! @abs_bindir@/gsql -r -p @portstring@ -d mysqltest -U usr1 -W '12345@abc' -f @abs_srcdir@/sql/mysql_function_test.sql + +--super user opengauss execute +\! @abs_bindir@/gsql -r -p @portstring@ -d mysqltest -c "select mysqlschema.definer(); select mysqlschema.invoker()" +-- usr1 execute +\! @abs_bindir@/gsql -r -p @portstring@ -d mysqltest -U usr1 -W '12345@abc' -c "select mysqlschema.definer(); select mysqlschema.invoker()" +-- usr2 execute +\! @abs_bindir@/gsql -r -p @portstring@ -d mysqltest -U usr2 -W '12345@abc' -c "select mysqlschema.definer(); select mysqlschema.invoker()" + +--revoke execute from public +--super user opengauss execute +\! @abs_bindir@/gsql -r -p @portstring@ -d mysqltest -c "revoke EXECUTE on procedure mysqlschema.definer() from public;revoke EXECUTE on procedure mysqlschema.invoker() from public; select mysqlschema.definer(); select mysqlschema.invoker()" +-- usr1 execute +\! @abs_bindir@/gsql -r -p @portstring@ -d mysqltest -U usr1 -W '12345@abc' -c "select mysqlschema.definer(); select mysqlschema.invoker()" +-- usr2 execute +\! @abs_bindir@/gsql -r -p @portstring@ -d mysqltest -U usr2 -W '12345@abc' -c "select mysqlschema.definer(); select mysqlschema.invoker()" + +--revoke execute from usr1 +--super user opengauss execute +\! @abs_bindir@/gsql -r -p @portstring@ -d mysqltest -c "revoke EXECUTE on procedure mysqlschema.definer() from usr1;revoke EXECUTE on procedure mysqlschema.invoker() from usr1; select mysqlschema.definer(); select mysqlschema.invoker()" +-- usr1 execute +\! @abs_bindir@/gsql -r -p @portstring@ -d mysqltest -U usr1 -W '12345@abc' -c "select mysqlschema.definer(); select mysqlschema.invoker()" +-- usr2 execute +\! @abs_bindir@/gsql -r -p @portstring@ -d mysqltest -U usr2 -W '12345@abc' -c "select mysqlschema.definer(); select mysqlschema.invoker()" + +--revoke execute from usr2 +--super user opengauss execute +\! @abs_bindir@/gsql -r -p @portstring@ -d mysqltest -c "revoke EXECUTE on procedure mysqlschema.definer() from usr2;revoke EXECUTE on procedure mysqlschema.invoker() from usr2; select mysqlschema.definer(); select mysqlschema.invoker()" +-- usr1 execute +\! @abs_bindir@/gsql -r -p @portstring@ -d mysqltest -U usr1 -W '12345@abc' -c "select mysqlschema.definer(); select mysqlschema.invoker()" +-- usr2 execute +\! @abs_bindir@/gsql -r -p @portstring@ -d mysqltest -U usr2 -W '12345@abc' -c "select mysqlschema.definer(); select mysqlschema.invoker()" + +--grant execute from usr1 +--super user opengauss execute +\! @abs_bindir@/gsql -r -p @portstring@ -d mysqltest -c "grant EXECUTE on procedure mysqlschema.definer() to usr1;grant EXECUTE on procedure mysqlschema.invoker() to usr1; select mysqlschema.definer(); select mysqlschema.invoker()" +-- usr1 execute +\! @abs_bindir@/gsql -r -p @portstring@ -d mysqltest -U usr1 -W '12345@abc' -c "select mysqlschema.definer(); select mysqlschema.invoker()" +-- usr2 execute +\! @abs_bindir@/gsql -r -p @portstring@ -d mysqltest -U usr2 -W '12345@abc' -c "select mysqlschema.definer(); select mysqlschema.invoker()" + +--grant execute from usr2 +--super user opengauss execute +\! @abs_bindir@/gsql -r -p @portstring@ -d mysqltest -c "grant EXECUTE on procedure mysqlschema.definer() to usr2;grant EXECUTE on procedure mysqlschema.invoker() to usr2; select mysqlschema.definer(); select mysqlschema.invoker()" +-- usr1 execute +\! @abs_bindir@/gsql -r -p @portstring@ -d mysqltest -U usr1 -W '12345@abc' -c "select mysqlschema.definer(); select mysqlschema.invoker()" +-- usr2 execute +\! @abs_bindir@/gsql -r -p @portstring@ -d mysqltest -U usr2 -W '12345@abc' -c "select mysqlschema.definer(); select mysqlschema.invoker()" + +--revoke execute from usr1 +--super user opengauss execute +\! @abs_bindir@/gsql -r -p @portstring@ -d mysqltest -c "revoke EXECUTE on procedure mysqlschema.definer() from usr1;revoke EXECUTE on procedure mysqlschema.invoker() from usr1; select mysqlschema.definer(); select mysqlschema.invoker()" +-- usr1 execute +\! @abs_bindir@/gsql -r -p @portstring@ -d mysqltest -U usr1 -W '12345@abc' -c "select mysqlschema.definer(); select mysqlschema.invoker()" +-- usr2 execute +\! @abs_bindir@/gsql -r -p @portstring@ -d mysqltest -U usr2 -W '12345@abc' -c "select mysqlschema.definer(); select mysqlschema.invoker()" + + + +--test security--super user create definer function +\! @abs_bindir@/gsql -r -p @portstring@ -d mysqltest -f @abs_srcdir@/sql/mysql_function_test.sql + +--super user opengauss execute +\! @abs_bindir@/gsql -r -p @portstring@ -d mysqltest -c "select mysqlschema.definer(); select mysqlschema.invoker()" +-- usr1 execute +\! @abs_bindir@/gsql -r -p @portstring@ -d mysqltest -U usr1 -W '12345@abc' -c "select mysqlschema.definer(); select mysqlschema.invoker()" +-- usr2 execute +\! @abs_bindir@/gsql -r -p @portstring@ -d mysqltest -U usr2 -W '12345@abc' -c "select mysqlschema.definer(); select mysqlschema.invoker()" + +--revoke execute from public +--super user opengauss execute +\! @abs_bindir@/gsql -r -p @portstring@ -d mysqltest -c "revoke EXECUTE on procedure mysqlschema.definer() from public;revoke EXECUTE on procedure mysqlschema.invoker() from public; select mysqlschema.definer(); select mysqlschema.invoker()" +-- usr1 execute +\! @abs_bindir@/gsql -r -p @portstring@ -d mysqltest -U usr1 -W '12345@abc' -c "select mysqlschema.definer(); select mysqlschema.invoker()" +-- usr2 execute +\! @abs_bindir@/gsql -r -p @portstring@ -d mysqltest -U usr2 -W '12345@abc' -c "select mysqlschema.definer(); select mysqlschema.invoker()" + +--revoke execute from usr1 +--super user opengauss execute +\! @abs_bindir@/gsql -r -p @portstring@ -d mysqltest -c "revoke EXECUTE on procedure mysqlschema.definer() from usr1;revoke EXECUTE on procedure mysqlschema.invoker() from usr1; select mysqlschema.definer(); select mysqlschema.invoker()" +-- usr1 execute +\! @abs_bindir@/gsql -r -p @portstring@ -d mysqltest -U usr1 -W '12345@abc' -c "select mysqlschema.definer(); select mysqlschema.invoker()" +-- usr2 execute +\! @abs_bindir@/gsql -r -p @portstring@ -d mysqltest -U usr2 -W '12345@abc' -c "select mysqlschema.definer(); select mysqlschema.invoker()" + +--revoke execute from usr2 +--super user opengauss execute +\! @abs_bindir@/gsql -r -p @portstring@ -d mysqltest -c "revoke EXECUTE on procedure mysqlschema.definer() from usr2;revoke EXECUTE on procedure mysqlschema.invoker() from usr2; select mysqlschema.definer(); select mysqlschema.invoker()" +-- usr1 execute +\! @abs_bindir@/gsql -r -p @portstring@ -d mysqltest -U usr1 -W '12345@abc' -c "select mysqlschema.definer(); select mysqlschema.invoker()" +-- usr2 execute +\! @abs_bindir@/gsql -r -p @portstring@ -d mysqltest -U usr2 -W '12345@abc' -c "select mysqlschema.definer(); select mysqlschema.invoker()" + +--grant execute from usr1 +--super user opengauss execute +\! @abs_bindir@/gsql -r -p @portstring@ -d mysqltest -c "grant EXECUTE on procedure mysqlschema.definer() to usr1;grant EXECUTE on procedure mysqlschema.invoker() to usr1; select mysqlschema.definer(); select mysqlschema.invoker()" +-- usr1 execute +\! @abs_bindir@/gsql -r -p @portstring@ -d mysqltest -U usr1 -W '12345@abc' -c "select mysqlschema.definer(); select mysqlschema.invoker()" +-- usr2 execute +\! @abs_bindir@/gsql -r -p @portstring@ -d mysqltest -U usr2 -W '12345@abc' -c "select mysqlschema.definer(); select mysqlschema.invoker()" + +--grant execute from usr2 +--super user opengauss execute +\! @abs_bindir@/gsql -r -p @portstring@ -d mysqltest -c "grant EXECUTE on procedure mysqlschema.definer() to usr2;grant EXECUTE on procedure mysqlschema.invoker() to usr2; select mysqlschema.definer(); select mysqlschema.invoker()" +-- usr1 execute +\! @abs_bindir@/gsql -r -p @portstring@ -d mysqltest -U usr1 -W '12345@abc' -c "select mysqlschema.definer(); select mysqlschema.invoker()" +-- usr2 execute +\! @abs_bindir@/gsql -r -p @portstring@ -d mysqltest -U usr2 -W '12345@abc' -c "select mysqlschema.definer(); select mysqlschema.invoker()" + +--revoke execute from usr1 +--super user opengauss execute +\! @abs_bindir@/gsql -r -p @portstring@ -d mysqltest -c "revoke EXECUTE on procedure mysqlschema.definer() from usr1;revoke EXECUTE on procedure mysqlschema.invoker() from usr1; select mysqlschema.definer(); select mysqlschema.invoker()" +-- usr1 execute +\! @abs_bindir@/gsql -r -p @portstring@ -d mysqltest -U usr1 -W '12345@abc' -c "select mysqlschema.definer(); select mysqlschema.invoker()" +-- usr2 execute +\! @abs_bindir@/gsql -r -p @portstring@ -d mysqltest -U usr2 -W '12345@abc' -c "select mysqlschema.definer(); select mysqlschema.invoker()" + +\c regression +drop database IF EXISTS mysqltest; +drop database IF EXISTS mysqltestbak; \ No newline at end of file diff --git a/src/test/regress/output/mysql_function.source b/src/test/regress/output/mysql_function.source new file mode 100644 index 000000000..0c1ffd0ed --- /dev/null +++ b/src/test/regress/output/mysql_function.source @@ -0,0 +1,760 @@ +--test create function/procedure definer=user +drop database if exists mysqltest; +CREATE DATABASE mysqltest DBCOMPATIBILITY 'B'; +create schema mysqlschema; +create user usr1 password '12345@abc'; +create user usr2 password '12345@abc'; +--grammar test +\c mysqltest +create schema mysqlschema; +grant ALL on SCHEMA mysqlschema to PUBLIC; +CREATE DEFINER=testusr1 FUNCTION testfunc_definer1(integer, integer) RETURNS integer SECURITY DEFINER +AS 'select $1 + $2;' +LANGUAGE SQL +IMMUTABLE +RETURNS NULL ON NULL INPUT; +ERROR: role "testusr1" does not exist +CREATE OR REPLACE DEFINER=testusr1 FUNCTION func_definer2(integer, integer) RETURNS integer SECURITY DEFINER +AS 'select $1 + $2;' +LANGUAGE SQL +IMMUTABLE +RETURNS NULL ON NULL INPUT; +ERROR: not support DEFINER function at or near ";" +LINE 5: RETURNS NULL ON NULL INPUT; + ^ +CREATE DEFINER=testusr1 procedure proc_definer1() SECURITY DEFINER +AS +BEGIN + raise info 'create definer procedure.'; +END; +/ +ERROR: role "testusr1" does not exist +CREATE OR REPLACE DEFINER=testusr1 procedure proc_definer2() SECURITY DEFINER +AS +BEGIN + raise info 'create definer procedure.'; +END; +/ +ERROR: not support DEFINER function at or near ";" +LINE 5: END; + ^ + +CREATE USER testusr1 password '12345@abc'; +CREATE DEFINER=testusr1 FUNCTION func_definer1(integer, integer) RETURNS integer SECURITY INVOKER +AS 'select $1 + $2;' +LANGUAGE SQL +IMMUTABLE +RETURNS NULL ON NULL INPUT; +CREATE DEFINER=testusr1 procedure proc_definer1() +AS +BEGIN + raise info 'create definer procedure.'; +END; +/ +--test \sf +\sf func_definer1 +CREATE DEFINER = testusr1 FUNCTION public.func_definer1(integer, integer) + RETURNS integer + LANGUAGE sql + IMMUTABLE STRICT NOT FENCED NOT SHIPPABLE +AS $function$select $1 + $2;$function$; +\sf proc_definer1 +CREATE DEFINER = testusr1 PROCEDURE public.proc_definer1() +AS DECLARE +BEGIN + raise info 'create definer procedure.'; +END; +/ +--test create or replace function or procedure +select usename from pg_user where usesysid = (select proowner from pg_proc where proname='proc_definer1'); + usename +---------- + testusr1 +(1 row) + +CREATE or replace procedure proc_definer1() +AS +BEGIN + raise info 'create definer procedure.'; +END; +/ +select usename from pg_user where usesysid = (select proowner from pg_proc where proname='proc_definer1'); + usename +---------- + testusr1 +(1 row) + +--dump test +-- dump function +\! @abs_bindir@/gs_dump mysqltest -p @portstring@ -f @abs_bindir@/mysql_function_back.sql +--? .* +--? .* +--? .* +--? .* +CREATE DATABASE mysqltestbak DBCOMPATIBILITY 'B'; +-- restore data +\! @abs_bindir@/gsql -p @portstring@ -d mysqltestbak -f @abs_bindir@/mysql_function_back.sql +--? .* +--? .* +--? .* +--? .* +--? .* +--? .* +--? .* +--? .* +--? .* +--? .* +--? .* +--? .* +--? .* +--? .* +--? .* +--? .* +--? .* +--? .* +--? .* +--? .* +--? .* +--? .* +--? .* +--? .* +--? .* +\c mysqltestbak +\sf proc_definer1 +CREATE DEFINER = testusr1 PROCEDURE public.proc_definer1() +AS DECLARE +BEGIN + raise info 'create definer procedure.'; +END; +/ +--test security--general user create definer function +\! @abs_bindir@/gsql -r -p @portstring@ -d mysqltest -U usr1 -W '12345@abc' -f @abs_srcdir@/sql/mysql_function_test.sql +gsql:@abs_srcdir@/sql/mysql_function_test.sql:2: NOTICE: function mysqlschema.definer() does not exist, skipping +DROP PROCEDURE +gsql:@abs_srcdir@/sql/mysql_function_test.sql:3: NOTICE: function mysqlschema.invoker() does not exist, skipping +DROP PROCEDURE +CREATE PROCEDURE +CREATE PROCEDURE +--? .* +--super user opengauss execute +\! @abs_bindir@/gsql -r -p @portstring@ -d mysqltest -c "select mysqlschema.definer(); select mysqlschema.invoker()" +INFO: create definer procedure. +CONTEXT: referenced column: definer + definer +--------- + +(1 row) + +INFO: create invoker procedure. +CONTEXT: referenced column: invoker + invoker +--------- + +(1 row) + +-- usr1 execute +\! @abs_bindir@/gsql -r -p @portstring@ -d mysqltest -U usr1 -W '12345@abc' -c "select mysqlschema.definer(); select mysqlschema.invoker()" +INFO: create definer procedure. +CONTEXT: referenced column: definer + definer +--------- + +(1 row) + +INFO: create invoker procedure. +CONTEXT: referenced column: invoker + invoker +--------- + +(1 row) + +-- usr2 execute +\! @abs_bindir@/gsql -r -p @portstring@ -d mysqltest -U usr2 -W '12345@abc' -c "select mysqlschema.definer(); select mysqlschema.invoker()" +INFO: create definer procedure. +CONTEXT: referenced column: definer + definer +--------- + +(1 row) + +INFO: create invoker procedure. +CONTEXT: referenced column: invoker + invoker +--------- + +(1 row) + +--revoke execute from public +--super user opengauss execute +\! @abs_bindir@/gsql -r -p @portstring@ -d mysqltest -c "revoke EXECUTE on procedure mysqlschema.definer() from public;revoke EXECUTE on procedure mysqlschema.invoker() from public; select mysqlschema.definer(); select mysqlschema.invoker()" +REVOKE +REVOKE +INFO: create definer procedure. +CONTEXT: referenced column: definer + definer +--------- + +(1 row) + +INFO: create invoker procedure. +CONTEXT: referenced column: invoker + invoker +--------- + +(1 row) + +-- usr1 execute +\! @abs_bindir@/gsql -r -p @portstring@ -d mysqltest -U usr1 -W '12345@abc' -c "select mysqlschema.definer(); select mysqlschema.invoker()" +INFO: create definer procedure. +CONTEXT: referenced column: definer + definer +--------- + +(1 row) + +ERROR: permission denied for function invoker +DETAIL: N/A +CONTEXT: referenced column: invoker +-- usr2 execute +\! @abs_bindir@/gsql -r -p @portstring@ -d mysqltest -U usr2 -W '12345@abc' -c "select mysqlschema.definer(); select mysqlschema.invoker()" +INFO: create definer procedure. +CONTEXT: referenced column: definer + definer +--------- + +(1 row) + +INFO: create invoker procedure. +CONTEXT: referenced column: invoker + invoker +--------- + +(1 row) + +--revoke execute from usr1 +--super user opengauss execute +\! @abs_bindir@/gsql -r -p @portstring@ -d mysqltest -c "revoke EXECUTE on procedure mysqlschema.definer() from usr1;revoke EXECUTE on procedure mysqlschema.invoker() from usr1; select mysqlschema.definer(); select mysqlschema.invoker()" +REVOKE +REVOKE +INFO: create definer procedure. +CONTEXT: referenced column: definer + definer +--------- + +(1 row) + +INFO: create invoker procedure. +CONTEXT: referenced column: invoker + invoker +--------- + +(1 row) + +-- usr1 execute +\! @abs_bindir@/gsql -r -p @portstring@ -d mysqltest -U usr1 -W '12345@abc' -c "select mysqlschema.definer(); select mysqlschema.invoker()" +INFO: create definer procedure. +CONTEXT: referenced column: definer + definer +--------- + +(1 row) + +ERROR: permission denied for function invoker +DETAIL: N/A +CONTEXT: referenced column: invoker +-- usr2 execute +\! @abs_bindir@/gsql -r -p @portstring@ -d mysqltest -U usr2 -W '12345@abc' -c "select mysqlschema.definer(); select mysqlschema.invoker()" +INFO: create definer procedure. +CONTEXT: referenced column: definer + definer +--------- + +(1 row) + +INFO: create invoker procedure. +CONTEXT: referenced column: invoker + invoker +--------- + +(1 row) + +--revoke execute from usr2 +--super user opengauss execute +\! @abs_bindir@/gsql -r -p @portstring@ -d mysqltest -c "revoke EXECUTE on procedure mysqlschema.definer() from usr2;revoke EXECUTE on procedure mysqlschema.invoker() from usr2; select mysqlschema.definer(); select mysqlschema.invoker()" +REVOKE +REVOKE +ERROR: permission denied for function definer +DETAIL: N/A +CONTEXT: referenced column: definer +INFO: create invoker procedure. +CONTEXT: referenced column: invoker + invoker +--------- + +(1 row) + +-- usr1 execute +\! @abs_bindir@/gsql -r -p @portstring@ -d mysqltest -U usr1 -W '12345@abc' -c "select mysqlschema.definer(); select mysqlschema.invoker()" +ERROR: permission denied for function definer +DETAIL: N/A +CONTEXT: referenced column: definer +ERROR: permission denied for function invoker +DETAIL: N/A +CONTEXT: referenced column: invoker +-- usr2 execute +\! @abs_bindir@/gsql -r -p @portstring@ -d mysqltest -U usr2 -W '12345@abc' -c "select mysqlschema.definer(); select mysqlschema.invoker()" +ERROR: permission denied for function definer +DETAIL: N/A +CONTEXT: referenced column: definer +ERROR: permission denied for function invoker +DETAIL: N/A +CONTEXT: referenced column: invoker +--grant execute from usr1 +--super user opengauss execute +\! @abs_bindir@/gsql -r -p @portstring@ -d mysqltest -c "grant EXECUTE on procedure mysqlschema.definer() to usr1;grant EXECUTE on procedure mysqlschema.invoker() to usr1; select mysqlschema.definer(); select mysqlschema.invoker()" +GRANT +GRANT +ERROR: permission denied for function definer +DETAIL: N/A +CONTEXT: referenced column: definer +INFO: create invoker procedure. +CONTEXT: referenced column: invoker + invoker +--------- + +(1 row) + +-- usr1 execute +\! @abs_bindir@/gsql -r -p @portstring@ -d mysqltest -U usr1 -W '12345@abc' -c "select mysqlschema.definer(); select mysqlschema.invoker()" +ERROR: permission denied for function definer +DETAIL: N/A +CONTEXT: referenced column: definer +INFO: create invoker procedure. +CONTEXT: referenced column: invoker + invoker +--------- + +(1 row) + +-- usr2 execute +\! @abs_bindir@/gsql -r -p @portstring@ -d mysqltest -U usr2 -W '12345@abc' -c "select mysqlschema.definer(); select mysqlschema.invoker()" +ERROR: permission denied for function definer +DETAIL: N/A +CONTEXT: referenced column: definer +ERROR: permission denied for function invoker +DETAIL: N/A +CONTEXT: referenced column: invoker +--grant execute from usr2 +--super user opengauss execute +\! @abs_bindir@/gsql -r -p @portstring@ -d mysqltest -c "grant EXECUTE on procedure mysqlschema.definer() to usr2;grant EXECUTE on procedure mysqlschema.invoker() to usr2; select mysqlschema.definer(); select mysqlschema.invoker()" +GRANT +GRANT +INFO: create definer procedure. +CONTEXT: referenced column: definer + definer +--------- + +(1 row) + +INFO: create invoker procedure. +CONTEXT: referenced column: invoker + invoker +--------- + +(1 row) + +-- usr1 execute +\! @abs_bindir@/gsql -r -p @portstring@ -d mysqltest -U usr1 -W '12345@abc' -c "select mysqlschema.definer(); select mysqlschema.invoker()" +INFO: create definer procedure. +CONTEXT: referenced column: definer + definer +--------- + +(1 row) + +INFO: create invoker procedure. +CONTEXT: referenced column: invoker + invoker +--------- + +(1 row) + +-- usr2 execute +\! @abs_bindir@/gsql -r -p @portstring@ -d mysqltest -U usr2 -W '12345@abc' -c "select mysqlschema.definer(); select mysqlschema.invoker()" +INFO: create definer procedure. +CONTEXT: referenced column: definer + definer +--------- + +(1 row) + +INFO: create invoker procedure. +CONTEXT: referenced column: invoker + invoker +--------- + +(1 row) + +--revoke execute from usr1 +--super user opengauss execute +\! @abs_bindir@/gsql -r -p @portstring@ -d mysqltest -c "revoke EXECUTE on procedure mysqlschema.definer() from usr1;revoke EXECUTE on procedure mysqlschema.invoker() from usr1; select mysqlschema.definer(); select mysqlschema.invoker()" +REVOKE +REVOKE +INFO: create definer procedure. +CONTEXT: referenced column: definer + definer +--------- + +(1 row) + +INFO: create invoker procedure. +CONTEXT: referenced column: invoker + invoker +--------- + +(1 row) + +-- usr1 execute +\! @abs_bindir@/gsql -r -p @portstring@ -d mysqltest -U usr1 -W '12345@abc' -c "select mysqlschema.definer(); select mysqlschema.invoker()" +INFO: create definer procedure. +CONTEXT: referenced column: definer + definer +--------- + +(1 row) + +ERROR: permission denied for function invoker +DETAIL: N/A +CONTEXT: referenced column: invoker +-- usr2 execute +\! @abs_bindir@/gsql -r -p @portstring@ -d mysqltest -U usr2 -W '12345@abc' -c "select mysqlschema.definer(); select mysqlschema.invoker()" +INFO: create definer procedure. +CONTEXT: referenced column: definer + definer +--------- + +(1 row) + +INFO: create invoker procedure. +CONTEXT: referenced column: invoker + invoker +--------- + +(1 row) + +--test security--super user create definer function +\! @abs_bindir@/gsql -r -p @portstring@ -d mysqltest -f @abs_srcdir@/sql/mysql_function_test.sql +DROP PROCEDURE +DROP PROCEDURE +CREATE PROCEDURE +CREATE PROCEDURE +--? .* +--super user opengauss execute +\! @abs_bindir@/gsql -r -p @portstring@ -d mysqltest -c "select mysqlschema.definer(); select mysqlschema.invoker()" +INFO: create definer procedure. +CONTEXT: referenced column: definer + definer +--------- + +(1 row) + +INFO: create invoker procedure. +CONTEXT: referenced column: invoker + invoker +--------- + +(1 row) + +-- usr1 execute +\! @abs_bindir@/gsql -r -p @portstring@ -d mysqltest -U usr1 -W '12345@abc' -c "select mysqlschema.definer(); select mysqlschema.invoker()" +INFO: create definer procedure. +CONTEXT: referenced column: definer + definer +--------- + +(1 row) + +INFO: create invoker procedure. +CONTEXT: referenced column: invoker + invoker +--------- + +(1 row) + +-- usr2 execute +\! @abs_bindir@/gsql -r -p @portstring@ -d mysqltest -U usr2 -W '12345@abc' -c "select mysqlschema.definer(); select mysqlschema.invoker()" +INFO: create definer procedure. +CONTEXT: referenced column: definer + definer +--------- + +(1 row) + +INFO: create invoker procedure. +CONTEXT: referenced column: invoker + invoker +--------- + +(1 row) + +--revoke execute from public +--super user opengauss execute +\! @abs_bindir@/gsql -r -p @portstring@ -d mysqltest -c "revoke EXECUTE on procedure mysqlschema.definer() from public;revoke EXECUTE on procedure mysqlschema.invoker() from public; select mysqlschema.definer(); select mysqlschema.invoker()" +REVOKE +REVOKE +INFO: create definer procedure. +CONTEXT: referenced column: definer + definer +--------- + +(1 row) + +INFO: create invoker procedure. +CONTEXT: referenced column: invoker + invoker +--------- + +(1 row) + +-- usr1 execute +\! @abs_bindir@/gsql -r -p @portstring@ -d mysqltest -U usr1 -W '12345@abc' -c "select mysqlschema.definer(); select mysqlschema.invoker()" +INFO: create definer procedure. +CONTEXT: referenced column: definer + definer +--------- + +(1 row) + +ERROR: permission denied for function invoker +DETAIL: N/A +CONTEXT: referenced column: invoker +-- usr2 execute +\! @abs_bindir@/gsql -r -p @portstring@ -d mysqltest -U usr2 -W '12345@abc' -c "select mysqlschema.definer(); select mysqlschema.invoker()" +INFO: create definer procedure. +CONTEXT: referenced column: definer + definer +--------- + +(1 row) + +INFO: create invoker procedure. +CONTEXT: referenced column: invoker + invoker +--------- + +(1 row) + +--revoke execute from usr1 +--super user opengauss execute +\! @abs_bindir@/gsql -r -p @portstring@ -d mysqltest -c "revoke EXECUTE on procedure mysqlschema.definer() from usr1;revoke EXECUTE on procedure mysqlschema.invoker() from usr1; select mysqlschema.definer(); select mysqlschema.invoker()" +REVOKE +REVOKE +INFO: create definer procedure. +CONTEXT: referenced column: definer + definer +--------- + +(1 row) + +INFO: create invoker procedure. +CONTEXT: referenced column: invoker + invoker +--------- + +(1 row) + +-- usr1 execute +\! @abs_bindir@/gsql -r -p @portstring@ -d mysqltest -U usr1 -W '12345@abc' -c "select mysqlschema.definer(); select mysqlschema.invoker()" +INFO: create definer procedure. +CONTEXT: referenced column: definer + definer +--------- + +(1 row) + +ERROR: permission denied for function invoker +DETAIL: N/A +CONTEXT: referenced column: invoker +-- usr2 execute +\! @abs_bindir@/gsql -r -p @portstring@ -d mysqltest -U usr2 -W '12345@abc' -c "select mysqlschema.definer(); select mysqlschema.invoker()" +INFO: create definer procedure. +CONTEXT: referenced column: definer + definer +--------- + +(1 row) + +INFO: create invoker procedure. +CONTEXT: referenced column: invoker + invoker +--------- + +(1 row) + +--revoke execute from usr2 +--super user opengauss execute +\! @abs_bindir@/gsql -r -p @portstring@ -d mysqltest -c "revoke EXECUTE on procedure mysqlschema.definer() from usr2;revoke EXECUTE on procedure mysqlschema.invoker() from usr2; select mysqlschema.definer(); select mysqlschema.invoker()" +REVOKE +REVOKE +ERROR: permission denied for function definer +DETAIL: N/A +CONTEXT: referenced column: definer +INFO: create invoker procedure. +CONTEXT: referenced column: invoker + invoker +--------- + +(1 row) + +-- usr1 execute +\! @abs_bindir@/gsql -r -p @portstring@ -d mysqltest -U usr1 -W '12345@abc' -c "select mysqlschema.definer(); select mysqlschema.invoker()" +ERROR: permission denied for function definer +DETAIL: N/A +CONTEXT: referenced column: definer +ERROR: permission denied for function invoker +DETAIL: N/A +CONTEXT: referenced column: invoker +-- usr2 execute +\! @abs_bindir@/gsql -r -p @portstring@ -d mysqltest -U usr2 -W '12345@abc' -c "select mysqlschema.definer(); select mysqlschema.invoker()" +ERROR: permission denied for function definer +DETAIL: N/A +CONTEXT: referenced column: definer +ERROR: permission denied for function invoker +DETAIL: N/A +CONTEXT: referenced column: invoker +--grant execute from usr1 +--super user opengauss execute +\! @abs_bindir@/gsql -r -p @portstring@ -d mysqltest -c "grant EXECUTE on procedure mysqlschema.definer() to usr1;grant EXECUTE on procedure mysqlschema.invoker() to usr1; select mysqlschema.definer(); select mysqlschema.invoker()" +GRANT +GRANT +ERROR: permission denied for function definer +DETAIL: N/A +CONTEXT: referenced column: definer +INFO: create invoker procedure. +CONTEXT: referenced column: invoker + invoker +--------- + +(1 row) + +-- usr1 execute +\! @abs_bindir@/gsql -r -p @portstring@ -d mysqltest -U usr1 -W '12345@abc' -c "select mysqlschema.definer(); select mysqlschema.invoker()" +ERROR: permission denied for function definer +DETAIL: N/A +CONTEXT: referenced column: definer +INFO: create invoker procedure. +CONTEXT: referenced column: invoker + invoker +--------- + +(1 row) + +-- usr2 execute +\! @abs_bindir@/gsql -r -p @portstring@ -d mysqltest -U usr2 -W '12345@abc' -c "select mysqlschema.definer(); select mysqlschema.invoker()" +ERROR: permission denied for function definer +DETAIL: N/A +CONTEXT: referenced column: definer +ERROR: permission denied for function invoker +DETAIL: N/A +CONTEXT: referenced column: invoker +--grant execute from usr2 +--super user opengauss execute +\! @abs_bindir@/gsql -r -p @portstring@ -d mysqltest -c "grant EXECUTE on procedure mysqlschema.definer() to usr2;grant EXECUTE on procedure mysqlschema.invoker() to usr2; select mysqlschema.definer(); select mysqlschema.invoker()" +GRANT +GRANT +INFO: create definer procedure. +CONTEXT: referenced column: definer + definer +--------- + +(1 row) + +INFO: create invoker procedure. +CONTEXT: referenced column: invoker + invoker +--------- + +(1 row) + +-- usr1 execute +\! @abs_bindir@/gsql -r -p @portstring@ -d mysqltest -U usr1 -W '12345@abc' -c "select mysqlschema.definer(); select mysqlschema.invoker()" +INFO: create definer procedure. +CONTEXT: referenced column: definer + definer +--------- + +(1 row) + +INFO: create invoker procedure. +CONTEXT: referenced column: invoker + invoker +--------- + +(1 row) + +-- usr2 execute +\! @abs_bindir@/gsql -r -p @portstring@ -d mysqltest -U usr2 -W '12345@abc' -c "select mysqlschema.definer(); select mysqlschema.invoker()" +INFO: create definer procedure. +CONTEXT: referenced column: definer + definer +--------- + +(1 row) + +INFO: create invoker procedure. +CONTEXT: referenced column: invoker + invoker +--------- + +(1 row) + +--revoke execute from usr1 +--super user opengauss execute +\! @abs_bindir@/gsql -r -p @portstring@ -d mysqltest -c "revoke EXECUTE on procedure mysqlschema.definer() from usr1;revoke EXECUTE on procedure mysqlschema.invoker() from usr1; select mysqlschema.definer(); select mysqlschema.invoker()" +REVOKE +REVOKE +INFO: create definer procedure. +CONTEXT: referenced column: definer + definer +--------- + +(1 row) + +INFO: create invoker procedure. +CONTEXT: referenced column: invoker + invoker +--------- + +(1 row) + +-- usr1 execute +\! @abs_bindir@/gsql -r -p @portstring@ -d mysqltest -U usr1 -W '12345@abc' -c "select mysqlschema.definer(); select mysqlschema.invoker()" +INFO: create definer procedure. +CONTEXT: referenced column: definer + definer +--------- + +(1 row) + +ERROR: permission denied for function invoker +DETAIL: N/A +CONTEXT: referenced column: invoker +-- usr2 execute +\! @abs_bindir@/gsql -r -p @portstring@ -d mysqltest -U usr2 -W '12345@abc' -c "select mysqlschema.definer(); select mysqlschema.invoker()" +INFO: create definer procedure. +CONTEXT: referenced column: definer + definer +--------- + +(1 row) + +INFO: create invoker procedure. +CONTEXT: referenced column: invoker + invoker +--------- + +(1 row) + +\c regression +drop database IF EXISTS mysqltest; +drop database IF EXISTS mysqltestbak; diff --git a/src/test/regress/parallel_schedule0 b/src/test/regress/parallel_schedule0 index 0bf627e89..d67cf9db3 100644 --- a/src/test/regress/parallel_schedule0 +++ b/src/test/regress/parallel_schedule0 @@ -916,6 +916,6 @@ test: fdw_audit test: gs_global_config_audit test: detail declare_multiple_variable test: gs_dump_encrypt -test: composite_datum_record +test: composite_datum_record mysql_function test: join_test_alias diff --git a/src/test/regress/sql/mysql_function_test.sql b/src/test/regress/sql/mysql_function_test.sql new file mode 100644 index 000000000..71c8e6922 --- /dev/null +++ b/src/test/regress/sql/mysql_function_test.sql @@ -0,0 +1,16 @@ +--test create function/procedure definer=user +drop procedure IF EXISTS mysqlschema.definer(); +drop procedure IF EXISTS mysqlschema.invoker(); +CREATE DEFINER=usr2 PROCEDURE mysqlschema.definer() SECURITY DEFINER +AS +BEGIN + raise info 'create definer procedure.'; +END; +/ + +CREATE DEFINER=usr2 PROCEDURE mysqlschema.invoker() SECURITY INVOKER +AS +BEGIN + raise info 'create invoker procedure.'; +END; +/