diff --git a/src/common/backend/catalog/pg_proc.cpp b/src/common/backend/catalog/pg_proc.cpp index 49efdcc5e..5efeef1ec 100644 --- a/src/common/backend/catalog/pg_proc.cpp +++ b/src/common/backend/catalog/pg_proc.cpp @@ -1419,17 +1419,23 @@ Oid ProcedureCreate(const char* procedureName, Oid procNamespace, Oid propackage /* A db do not overload a function by arguments.*/ NameData* pkgname = NULL; + char* schemaName = get_namespace_name(procNamespace); + if (OidIsValid(propackageid)) { + pkgname = GetPackageName(propackageid); + } + if (pkgname == NULL) { + name = list_make2(makeString(schemaName), makeString(pstrdup(procedureName))); + } else { + name = list_make3(makeString(schemaName), makeString(pstrdup(pkgname->data)), makeString(pstrdup(procedureName))); + } +#ifndef ENABLE_MULTIPLE_NODES + if (pkgname == NULL) { + LockProcName(schemaName, NULL, procedureName); + } else { + LockProcName(schemaName, pkgname->data, procedureName); + } +#endif if (isOraStyle && !package) { - if (OidIsValid(propackageid)) { - pkgname = GetPackageName(propackageid); - } - if (pkgname == NULL) { - name = list_make2(makeString(get_namespace_name(procNamespace)), makeString(pstrdup(procedureName))); - } else { - name = list_make3(makeString(get_namespace_name(procNamespace)), makeString(pstrdup(pkgname->data)), makeString(pstrdup(procedureName))); - } - List* name = list_make2(makeString(get_namespace_name(procNamespace)), makeString(pstrdup(procedureName))); - FuncCandidateList listfunc = FuncnameGetCandidates(name, -1, NULL, false, false, true); if (listfunc) { if (listfunc->next) @@ -2663,4 +2669,27 @@ static void CheckInParameterConflicts(CatCList* catlist, const char* procedureNa } } } + +/* + * Due to procedure has no unique index on parameters, it maybe insert same data + * and this function prevent insert procedure with same funcname and funcargs, + */ +void LockProcName(char* schemaname, char* pkgname, const char* funcname) +{ + if (u_sess->attr.attr_common.upgrade_mode != 0) { + return; + } + Oid schemaOid = SchemaNameGetSchemaOid(schemaname, false); + if (IsPackageSchemaOid(schemaOid)) { + return; + } + if (pkgname != NULL) { + List* funcnameList = list_make2(makeString(pstrdup(pkgname)), makeString(pstrdup(funcname))); + uint32 hash_value = string_hash(NameListToQuotedString(funcnameList), NAMEDATALEN + NAMEDATALEN); + LockDatabaseObject(ProcedureRelationId, schemaOid, hash_value, ExclusiveLock); + } else { + uint32 hash_value = string_hash(funcname, NAMEDATALEN); + LockDatabaseObject(ProcedureRelationId, schemaOid, hash_value, ExclusiveLock); + } +} #endif diff --git a/src/common/pl/plpgsql/src/pl_handler.cpp b/src/common/pl/plpgsql/src/pl_handler.cpp index 2a95a7faf..0a51f16fa 100755 --- a/src/common/pl/plpgsql/src/pl_handler.cpp +++ b/src/common/pl/plpgsql/src/pl_handler.cpp @@ -1359,13 +1359,6 @@ Datum plpgsql_validator(PG_FUNCTION_ARGS) PG_RE_THROW(); } PG_END_TRY(); - /* Skip validation on Initdb */ -#ifndef ENABLE_MULTIPLE_NODES - if (!IsInitdb && u_sess->plsql_cxt.isCreateFunction) { - ProcInsertGsSource(funcoid, true); - } -#endif - bool isNotComipilePkg = u_sess->plsql_cxt.curr_compile_context == NULL || (u_sess->plsql_cxt.curr_compile_context != NULL && u_sess->plsql_cxt.curr_compile_context->plpgsql_curr_compile_package == NULL); @@ -1386,7 +1379,11 @@ Datum plpgsql_validator(PG_FUNCTION_ARGS) u_sess->ClientAuthInProgress = saved_client_auth; } } - +#ifndef ENABLE_MULTIPLE_NODES + if (!IsInitdb && u_sess->plsql_cxt.isCreateFunction) { + ProcInsertGsSource(funcoid, true); + } +#endif #ifndef ENABLE_MULTIPLE_NODES u_sess->plsql_cxt.isCreateFunction = false; u_sess->opt_cxt.query_dop = outerDop; diff --git a/src/gausskernel/optimizer/commands/functioncmds.cpp b/src/gausskernel/optimizer/commands/functioncmds.cpp index 37b69a6d7..a9011e740 100644 --- a/src/gausskernel/optimizer/commands/functioncmds.cpp +++ b/src/gausskernel/optimizer/commands/functioncmds.cpp @@ -1842,9 +1842,22 @@ void AlterFunction(AlterFunctionStmt* stmt) DefElem* shippable_item = NULL; DefElem* package_item = NULL; bool isNull = false; - rel = heap_open(ProcedureRelationId, RowExclusiveLock); funcOid = LookupFuncNameTypeNames(stmt->func->funcname, stmt->func->funcargs, false); + #ifndef ENABLE_MULTIPLE_NODES + char* schemaName = NULL; + char* pkgname = NULL; + char* procedureName = NULL; + DeconstructQualifiedName(stmt->func->funcname, &schemaName, &procedureName, &pkgname); + if (schemaName == NULL) { + tup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcOid)); + procForm = (Form_pg_proc)GETSTRUCT(tup); + schemaName = get_namespace_name(procForm->pronamespace); + ReleaseSysCache(tup); + } + LockProcName(schemaName, pkgname, procedureName); +#endif + rel = heap_open(ProcedureRelationId, RowExclusiveLock); /* if the function is a builtin function, its Oid is less than 10000. * we can't allow alter the builtin functions */ diff --git a/src/include/utils/plpgsql.h b/src/include/utils/plpgsql.h index 381ecf80b..ff616cc24 100644 --- a/src/include/utils/plpgsql.h +++ b/src/include/utils/plpgsql.h @@ -1640,6 +1640,7 @@ extern void exec_get_datum_type_info(PLpgSQL_execstate* estate, PLpgSQL_datum* d extern Datum exec_simple_cast_datum( PLpgSQL_execstate* estate, Datum value, Oid valtype, Oid reqtype, int32 reqtypmod, bool isnull); extern void ResetCursorOption(Portal portal, bool reset); +extern void LockProcName(char* schemaname, char* pkgname, const char* funcname); #ifndef ENABLE_MULTIPLE_NODES extern void ResetCursorAtrribute(Portal portal); #endif diff --git a/src/test/regress/expected/pldeveloper_gs_source.out b/src/test/regress/expected/pldeveloper_gs_source.out index bfc18b10e..bf5dae8f4 100644 --- a/src/test/regress/expected/pldeveloper_gs_source.out +++ b/src/test/regress/expected/pldeveloper_gs_source.out @@ -836,7 +836,12 @@ begin null; end; / +set behavior_compat_options=''; set plsql_show_all_error to on; +set check_function_bodies to off; +create or replace procedure test1 is begin null; end; +/ +set check_function_bodies to on; select name,type,status,src from DBE_PLDEVELOPER.gs_source order by name; name | type | status | src --------------+--------------+--------+--------------------------------------------------------------------------------- @@ -945,7 +950,8 @@ select name,type,status,src from DBE_PLDEVELOPER.gs_source order by name; | | | begin + | | | insert int a; + | | | end; -(16 rows) + test1 | procedure | t | create or replace procedure test1 is begin null; end; +(17 rows) select name,type,line,src from DBE_PLDEVELOPER.gs_errors order by name; name | type | line | src @@ -996,11 +1002,6 @@ select rolname, name, status, type, src from DBE_PLDEVELOPER.gs_source s join pg | | | | return var1; + | | | | end; + | | | | $$; - gs_developper | error2 | t | package | CREATE OR REPLACE PACKAGE error2 IS + - | | | | a int;b int; + - | | | | FUNCTION func1(a in int, b inout int, c out int) return int; + - | | | | FUNCTION func2(a in int, b inout int, c out int) return int; + - | | | | END error2; gs_developper | error2 | f | package body | CREATE OR REPLACE PACKAGE BODY error2 IS + | | | | FUNCTION func1 (a in int, b inout int c out int) return int + | | | | IS + @@ -1018,6 +1019,11 @@ select rolname, name, status, type, src from DBE_PLDEVELOPER.gs_source s join pg | | | | RETURN(a1 + a + b); + | | | | END; + | | | | END error2; + gs_developper | error2 | t | package | CREATE OR REPLACE PACKAGE error2 IS + + | | | | a int;b int; + + | | | | FUNCTION func1(a in int, b inout int, c out int) return int; + + | | | | FUNCTION func2(a in int, b inout int, c out int) return int; + + | | | | END error2; gs_developper | func00 | t | procedure | create or replace procedure func00 + | | | | is + | | | | begin + @@ -1051,19 +1057,6 @@ select rolname, name, status, type, src from DBE_PLDEVELOPER.gs_source s join pg | | | | a inv%d; + | | | | procedure proc1(c ff%F); + | | | | end pkg2; - gs_developper | pkg3 | f | package body | create or replace package body pkg3 + - | | | | is + - | | | | a b c d; + - | | | | procedure proc1() + - | | | | is + - | | | | begin + - | | | | insert int asd asd; + - | | | | end; + - | | | | end pkg3; - gs_developper | pkg3 | t | package | create or replace package pkg3 + - | | | | is + - | | | | a int; + - | | | | end pkg3; gs_developper | pkg4 | f | package | create or replace package pkg4 + | | | | is + | | | | a a; + @@ -1091,14 +1084,15 @@ select rolname, name, status, type, src from DBE_PLDEVELOPER.gs_source s join pg | | | | begin + | | | | insert int a; + | | | | end; -(16 rows) + gs_developper | test1 | t | procedure | create or replace procedure test1 is begin null; end; +(15 rows) truncate DBE_PLDEVELOPER.gs_source; truncate DBE_PLDEVELOPER.gs_errors; reset role; reset behavior_compat_options; drop schema gs_source cascade; -NOTICE: drop cascades to 14 other objects +NOTICE: drop cascades to 15 other objects DETAIL: drop cascades to function gourav88(integer,integer,integer) drop cascades to function func1() drop cascades to function mask() @@ -1113,5 +1107,6 @@ drop cascades to function gs_source.func1(integer,integer) drop cascades to function gs_source.func2(integer,integer) drop cascades to function func00() drop cascades to function skipinsertgssource() +drop cascades to function test1() drop role jackson_src; drop role gs_developper; diff --git a/src/test/regress/sql/pldeveloper_gs_source.sql b/src/test/regress/sql/pldeveloper_gs_source.sql index 6f837e503..713a4bfe4 100644 --- a/src/test/regress/sql/pldeveloper_gs_source.sql +++ b/src/test/regress/sql/pldeveloper_gs_source.sql @@ -283,7 +283,12 @@ begin null; end; / +set behavior_compat_options=''; set plsql_show_all_error to on; +set check_function_bodies to off; +create or replace procedure test1 is begin null; end; +/ +set check_function_bodies to on; select name,type,status,src from DBE_PLDEVELOPER.gs_source order by name; select name,type,line,src from DBE_PLDEVELOPER.gs_errors order by name; drop package if exists pkg4;