From c945aff92132ed901d31b4cc66d0e15fbce99214 Mon Sep 17 00:00:00 2001 From: lukeman Date: Thu, 23 Nov 2023 12:00:24 +0800 Subject: [PATCH] =?UTF-8?q?=E8=A7=A3=E5=86=B3=E7=BC=BA=E9=99=B7=EF=BC=9A?= =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=AD=98=E5=9C=A8plsql=E4=BE=9D=E8=B5=96?= =?UTF-8?q?=E7=9A=84=E7=B1=BB=E5=9E=8B=E7=9A=84schema=E5=AF=BC=E8=87=B4?= =?UTF-8?q?=E9=87=8D=E5=BB=BA=E6=8A=A5=E9=94=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/bin/pg_dump/pg_backup_archiver.cpp | 5 +- .../backend/utils/gsplsql/gsdependencies.cpp | 134 ++++++++++++++++++ .../utils/gsplsql/gsobject_dependencies.cpp | 33 +---- src/gausskernel/optimizer/commands/alter.cpp | 16 +++ .../optimizer/commands/functioncmds.cpp | 28 ++++ .../optimizer/commands/schemacmds.cpp | 8 ++ .../optimizer/commands/tablecmds.cpp | 8 ++ .../optimizer/commands/typecmds.cpp | 7 + src/include/catalog/gs_dependencies_fn.h | 3 + .../plpgsql_depend/plpgsql_recompile.out | 84 ++++++++++- .../sql/plpgsql_depend/plpgsql_recompile.sql | 54 +++++++ 11 files changed, 342 insertions(+), 38 deletions(-) diff --git a/src/bin/pg_dump/pg_backup_archiver.cpp b/src/bin/pg_dump/pg_backup_archiver.cpp index e100fef91..a28775ddc 100644 --- a/src/bin/pg_dump/pg_backup_archiver.cpp +++ b/src/bin/pg_dump/pg_backup_archiver.cpp @@ -321,8 +321,7 @@ static void out_drop_stmt(ArchiveHandle* AH, const TocEntry* te) char* dropStmt = NULL; char* dropStmtOrig = NULL; errno_t rc = EOK; - if (*te->dropStmt != '\0') - { + if (*te->dropStmt != '\0') { dropStmt = try_remove_nsname_in_drop_stmt(ropt, te->dropStmt, strlen(te->dropStmt) + PATCH_LEN); dropStmtOrig = dropStmt; if (strstr(te->dropStmt, "IF EXISTS") != NULL || @@ -386,8 +385,8 @@ static void out_drop_stmt(ArchiveHandle* AH, const TocEntry* te) } ahprintf(AH, "%s", ftStmt->data); destroyPQExpBuffer(ftStmt); - free(dropStmtOrig); } + free(dropStmtOrig); } } /* Public */ diff --git a/src/common/backend/utils/gsplsql/gsdependencies.cpp b/src/common/backend/utils/gsplsql/gsdependencies.cpp index f4f8c53b7..25e9d7f30 100644 --- a/src/common/backend/utils/gsplsql/gsdependencies.cpp +++ b/src/common/backend/utils/gsplsql/gsdependencies.cpp @@ -72,6 +72,65 @@ static inline Oid gsplsql_parse_pkg_var_and_attrs4(GsDependObjDesc* obj, List* v static inline Oid gsplsql_parse_pkg_var_and_attrs3(GsDependObjDesc* obj, ListCell* var_name, ListCell** attr_list); static inline Oid gsplsql_parse_pkg_var_obj2(GsDependObjDesc* obj, ListCell* var_name); +static bool gsplsql_exist_func_object_in_dependencies_obj(char* nsp_name, char* pkg_name, + const char* old_func_head_name, const char* old_func_name); +static bool gsplsql_exist_func_object_in_dependencies(char* nsp_name, char* pkg_name, const char* old_func_head_name); + +bool gsplsql_exists_func_obj(Oid nsp_oid, Oid pkg_oid, const char* old_func_head_name, const char* old_func_name) +{ + char* nsp_name = get_namespace_name(nsp_oid); + char* pkg_name = pstrdup("null"); + if (OidIsValid(pkg_oid)) { + pfree_ext(pkg_name); + pkg_name = GetPackageName(pkg_oid); + } + bool exists_func = gsplsql_exist_func_object_in_dependencies_obj(nsp_name, pkg_name, old_func_head_name, old_func_name) || + gsplsql_exist_func_object_in_dependencies(nsp_name, pkg_name, old_func_head_name); + pfree_ext(pkg_name); + pfree_ext(nsp_name); + return exists_func; +} + +bool gsplsql_exists_schema_name(const char* schema_name) +{ + bool has_schema = false; + Assert(schema_name != NULL); + // check gs_dependencies_obj + int key_num = 0; + ScanKeyData key[1]; + ScanKeyInit(&key[key_num++], Anum_gs_dependencies_obj_schemaname, BTEqualStrategyNumber, + F_NAMEEQ, NameGetDatum(schema_name)); + bool is_null = false; + HeapTuple tuple; + Relation obj_rel = heap_open(DependenciesObjRelationId, AccessShareLock); + SysScanDesc scan = systable_beginscan(obj_rel, DependenciesObjNameIndexId, true, SnapshotSelf, key_num, key); + while (HeapTupleIsValid(tuple = systable_getnext(scan))) { + has_schema = true; + break; + } + systable_endscan(scan); + heap_close(obj_rel, AccessShareLock); + if (has_schema) { + return has_schema; + } + // check gs_dependencies + int key_num_dep = 0; + ScanKeyData key_dep[1]; + ScanKeyInit(&key_dep[key_num_dep++], Anum_gs_dependencies_schemaname, BTEqualStrategyNumber, + F_NAMEEQ, NameGetDatum(schema_name)); + HeapTuple tuple_dep; + Relation dep_rel = heap_open(DependenciesRelationId, AccessShareLock); + SysScanDesc scan_dep = systable_beginscan(dep_rel, DependenciesNameIndexId, true, SnapshotSelf, + key_num_dep, key_dep); + while (HeapTupleIsValid(tuple_dep = systable_getnext(scan_dep))) { + has_schema = true; + break; + } + systable_endscan(scan_dep); + heap_close(dep_rel, AccessShareLock); + return has_schema; +} + void gsplsql_init_gs_depend_obj_desc(GsDependObjDesc* object) { object->schemaName = NULL; @@ -1483,3 +1542,78 @@ static DependenciesDatum *gsplsql_make_var_depend_datum(const PLpgSQL_datum *dat } return (DependenciesDatum*)var_node; } + +static bool gsplsql_exist_func_object_in_dependencies_obj(char* nsp_name, char* pkg_name, + const char* old_func_head_name, const char* old_func_name) +{ + int keyNum = 0; + Assert(nsp_name != NULL && pkg_name != NULL); + ScanKeyData key[2]; + ScanKeyInit(&key[keyNum++], Anum_gs_dependencies_obj_schemaname, BTEqualStrategyNumber, + F_NAMEEQ, NameGetDatum(nsp_name)); + ScanKeyInit(&key[keyNum++], Anum_gs_dependencies_obj_packagename, BTEqualStrategyNumber, + F_NAMEEQ, NameGetDatum(pkg_name)); + bool is_null = false; + HeapTuple tuple; + Relation obj_rel = heap_open(DependenciesObjRelationId, AccessShareLock); + SysScanDesc scan = systable_beginscan(obj_rel, DependenciesObjNameIndexId, true, SnapshotSelf, keyNum, key); + while (HeapTupleIsValid(tuple = systable_getnext(scan))) { + Datum name_datum = heap_getattr(tuple, Anum_gs_dependencies_obj_name, + RelationGetDescr(obj_rel), &is_null); + Assert(name_datum != 0); + char* obj_name = TextDatumGetCString(name_datum); + if (strcmp(old_func_head_name, obj_name) == 0 || strcmp(old_func_name, obj_name) == 0) { + Datum type_datum = heap_getattr(tuple, Anum_gs_dependencies_obj_type, + RelationGetDescr(obj_rel), &is_null); + int type = DatumGetInt32(type_datum); + if (type == GSDEPEND_OBJECT_TYPE_FUNCTION || + type == GSDEPEND_OBJECT_TYPE_PROCHEAD || type == GSDEPEND_OBJECT_TYPE_UNDEFIND) { + pfree_ext(obj_name); + systable_endscan(scan); + heap_close(obj_rel, AccessShareLock); + return true; + } + } + pfree_ext(obj_name); + } + systable_endscan(scan); + heap_close(obj_rel, AccessShareLock); + return false; +} + +static bool gsplsql_exist_func_object_in_dependencies(char* nsp_name, char* pkg_name, const char* old_func_head_name) +{ + int keyNum = 0; + Assert(nsp_name != NULL && pkg_name != NULL); + ScanKeyData key[2]; + ScanKeyInit(&key[keyNum++], Anum_gs_dependencies_schemaname, BTEqualStrategyNumber, + F_NAMEEQ, NameGetDatum(nsp_name)); + ScanKeyInit(&key[keyNum++], Anum_gs_dependencies_packagename, BTEqualStrategyNumber, + F_NAMEEQ, NameGetDatum(pkg_name)); + bool is_null = false; + HeapTuple tuple; + Relation dep_rel = heap_open(DependenciesRelationId, AccessShareLock); + SysScanDesc scan = systable_beginscan(dep_rel, DependenciesNameIndexId, true, SnapshotSelf, keyNum, key); + while (HeapTupleIsValid(tuple = systable_getnext(scan))) { + Datum name_datum = heap_getattr(tuple, Anum_gs_dependencies_objectname, + RelationGetDescr(dep_rel), &is_null); + Assert(name_datum != 0); + char* obj_name = TextDatumGetCString(name_datum); + if (strcmp(old_func_head_name, obj_name) == 0) { + Datum refobj_pos_datum = heap_getattr(tuple, Anum_gs_dependencies_refobjpos, + RelationGetDescr(dep_rel), &is_null); + int refobj_pos = DatumGetInt32(refobj_pos_datum); + if (refobj_pos == GSDEPEND_REFOBJ_POS_IN_PROCHEAD || + refobj_pos == GSDEPEND_REFOBJ_POS_IN_PROCBODY) { + pfree_ext(obj_name); + systable_endscan(scan); + heap_close(dep_rel, AccessShareLock); + return true; + } + } + pfree_ext(obj_name); + } + systable_endscan(scan); + heap_close(dep_rel, AccessShareLock); + return false; +} diff --git a/src/common/backend/utils/gsplsql/gsobject_dependencies.cpp b/src/common/backend/utils/gsplsql/gsobject_dependencies.cpp index ee5c23a4e..7a0dec7fa 100644 --- a/src/common/backend/utils/gsplsql/gsobject_dependencies.cpp +++ b/src/common/backend/utils/gsplsql/gsobject_dependencies.cpp @@ -19,29 +19,6 @@ * IDENTIFICATION * src/common/backend/utils/gsplsql/gsobject_gsdependencies.cpp * -* --------------------------------------------------------------------------------------- - */ -/* -* Copyright (c) 2021 Huawei Technologies Co.,Ltd. -* -* openGauss is licensed under Mulan PSL v2. -* You can use this software according to the terms and conditions of the Mulan PSL v2. -* You may obtain a copy of Mulan PSL v2 at: -* -* http://license.coscl.org.cn/MulanPSL2 -* -* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, -* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, -* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. -* See the Mulan PSL v2 for more details. -* --------------------------------------------------------------------------------------- -* -* gsobject_gsdependencies.cpp -* -* -* IDENTIFICATION -* src/common/backend/utils/gsplsql/gsobject_gsdependencies.cpp -* * --------------------------------------------------------------------------------------- */ @@ -1086,10 +1063,6 @@ static bool gsplsql_update_proc_header(CreateFunctionStmt *stmt, Oid funcid) prorettype = VOIDOID; returnsSet = false; } - if (has_undefined) { - ereport( - LOG, (errmsg("the function header has an unknown dependency. function oid is %u", funcid))); - } char* parameter_defaults_str = NULL; if (parameter_defaults != NIL) { parameter_defaults_str = nodeToString(parameter_defaults); @@ -1139,8 +1112,6 @@ static bool gsplsql_update_proc_header(CreateFunctionStmt *stmt, Oid funcid) CacheInvalidateFunction(funcid, InvalidOid); if (!is_proc_info_changed(funcid, parameter_types, all_parameter_types, parameter_defaults_str, prorettype, returnsSet)) { - ereport(LOG, (errcode(ERRCODE_PLPGSQL_ERROR), - errmsg("The header of function %u does not need to be modified.", funcid))); pfree_ext(parameter_defaults_str); return has_undefined; } @@ -1252,7 +1223,7 @@ static bool is_proc_info_changed(Oid funcid, oidvector *new_parameter_types, Arr } size_tmp = allpara_count * sizeof(Oid); Oid *p_argtypes = (Oid *)palloc(size_tmp); - rc = memcpy_s(p_argtypes, size_tmp, ARR_DATA_PTR(new_all_parameter_types), size_tmp); + rc = memcpy_s(p_argtypes, size_tmp, ARR_DATA_PTR(arr), size_tmp); securec_check(rc, "\0", "\0"); oidvector *allpara_type = buildoidvector(p_argtypes, allpara_count); if (!DatumGetBool(DirectFunctionCall2(oidvectoreq, PointerGetDatum(allpara_type), @@ -1485,8 +1456,6 @@ static void gsplsql_delete_dependencies_object_by_oid(Oid oid) if (!HeapTupleIsValid(tuple)) { systable_endscan(scan); heap_close(dep_rel, RowExclusiveLock); - ereport(LOG, (errcode(ERRCODE_UNDEFINED_OBJECT), - errmsg("dependencies object %u does not exist.", oid))); return; } simple_heap_delete(dep_rel, &tuple->t_self, 0, true); diff --git a/src/gausskernel/optimizer/commands/alter.cpp b/src/gausskernel/optimizer/commands/alter.cpp index 6c9f208dd..fda4691ac 100644 --- a/src/gausskernel/optimizer/commands/alter.cpp +++ b/src/gausskernel/optimizer/commands/alter.cpp @@ -66,6 +66,7 @@ #include "utils/rel_gs.h" #include "utils/syscache.h" #include "gs_policy/gs_policy_masking.h" +#include "catalog/gs_dependencies_fn.h" /* * Executes an ALTER OBJECT / RENAME TO statement. Based on the object @@ -736,6 +737,21 @@ AlterObjectNamespace_internal(Relation rel, Oid objid, Oid nspOid) IsThereFunctionInNamespace(NameStr(proc->proname), proc->pronargs, &proc->proargtypes, nspOid); + + if (enable_plpgsql_gsdependency_guc()) { + const char* old_func_format = format_procedure_no_visible(objid); + const char* old_func_name = NameStr(proc->proname); + bool is_null = false; + Datum package_oid_datum = SysCacheGetAttr(PROCOID, tup, Anum_pg_proc_packageid, &is_null); + Oid pkg_oid = DatumGetObjectId(package_oid_datum); + if (gsplsql_exists_func_obj(oldNspOid, pkg_oid, old_func_format, old_func_name)) { + ereport(ERROR, + (errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST), + errmsg("The set schema operator of %s is not allowed, " + "because it is referenced by the other object.", + NameStr(proc->proname)))); + } + } } else if (classId == CollationRelationId) { Form_pg_collation coll = (Form_pg_collation) GETSTRUCT(tup); diff --git a/src/gausskernel/optimizer/commands/functioncmds.cpp b/src/gausskernel/optimizer/commands/functioncmds.cpp index 2976f911c..a62451b94 100644 --- a/src/gausskernel/optimizer/commands/functioncmds.cpp +++ b/src/gausskernel/optimizer/commands/functioncmds.cpp @@ -1977,6 +1977,20 @@ ObjectAddress RenameFunction(List* name, List* argtypes, const char* newname) if (aclresult != ACLCHECK_OK) aclcheck_error(aclresult, ACL_KIND_NAMESPACE, get_namespace_name(namespaceOid)); + if (enable_plpgsql_gsdependency_guc()) { + const char* old_func_format = format_procedure_no_visible(procOid); + const char* old_func_name = strVal(llast(name)); + bool is_null = false; + Datum package_oid_datum = SysCacheGetAttr(PROCOID, tup, Anum_pg_proc_packageid, &is_null); + Oid pkg_oid = DatumGetObjectId(package_oid_datum); + if (gsplsql_exists_func_obj(namespaceOid, pkg_oid, old_func_format, old_func_name)) { + ereport(ERROR, + (errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST), + errmsg("The rename operator of %s is not allowed, because it is referenced by the other object.", + NameStr(procForm->proname)))); + } + } + /* rename */ (void)namestrcpy(&(procForm->proname), newname); simple_heap_update(rel, &tup->t_self, tup); @@ -3232,6 +3246,20 @@ Oid AlterFunctionNamespace_oid(Oid procOid, Oid nspOid) } } #endif + if (enable_plpgsql_gsdependency_guc()) { + const char* old_func_format = format_procedure_no_visible(procOid); + const char* old_func_name = NameStr(proc->proname); + bool is_null = false; + Datum package_oid_datum = SysCacheGetAttr(PROCOID, tup, Anum_pg_proc_packageid, &is_null); + Oid pkg_oid = DatumGetObjectId(package_oid_datum); + if (gsplsql_exists_func_obj(oldNspOid, pkg_oid, old_func_format, old_func_name)) { + ereport(ERROR, + (errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST), + errmsg("The set schema operator of %s is not allowed, " + "because it is referenced by the other object.", + NameStr(proc->proname)))); + } + } /* OK, modify the pg_proc row */ /* tup is a copy, so we can scribble directly on it */ proc->pronamespace = nspOid; diff --git a/src/gausskernel/optimizer/commands/schemacmds.cpp b/src/gausskernel/optimizer/commands/schemacmds.cpp index 4f1d7a03d..266efb5b5 100644 --- a/src/gausskernel/optimizer/commands/schemacmds.cpp +++ b/src/gausskernel/optimizer/commands/schemacmds.cpp @@ -41,6 +41,7 @@ #include "utils/snapmgr.h" #include "gs_ledger/ledger_utils.h" #include "gs_ledger/userchain.h" +#include "catalog/gs_dependencies_fn.h" #ifdef PGXC #include "pgxc/pgxc.h" @@ -589,6 +590,13 @@ ObjectAddress RenameSchema(const char* oldname, const char* newname) existTimeSeriesTbl->data))); } + if (enable_plpgsql_gsdependency_guc() && gsplsql_exists_schema_name(oldname)) { + ereport(ERROR, + (errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST), + errmsg("The rename operator of %s is not allowed, because it is referenced by the other object.", + oldname))); + } + /* Before rename schema (with blockchain) rename related ledger tables first */ bool is_null = true; Datum datum = SysCacheGetAttr(NAMESPACENAME, tup, Anum_pg_namespace_nspblockchain, &is_null); diff --git a/src/gausskernel/optimizer/commands/tablecmds.cpp b/src/gausskernel/optimizer/commands/tablecmds.cpp index 98e1d17e6..e763b2643 100755 --- a/src/gausskernel/optimizer/commands/tablecmds.cpp +++ b/src/gausskernel/optimizer/commands/tablecmds.cpp @@ -21639,6 +21639,14 @@ void AlterTableNamespaceInternal(Relation rel, Oid oldNspOid, Oid nspOid, Object Assert(objsMoved != NULL); + if (enable_plpgsql_gsdependency_guc() && + gsplsql_is_object_depend(rel->rd_rel->reltype, GSDEPEND_OBJECT_TYPE_TYPE)) { + ereport(ERROR, + (errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST), + errmsg("The set schema operator of %s is not allowed, " + "because it is referenced by another object.", NameStr(rel->rd_rel->relname)))); + } + /* OK, modify the pg_class row and pg_depend entry */ classRel = heap_open(RelationRelationId, RowExclusiveLock); diff --git a/src/gausskernel/optimizer/commands/typecmds.cpp b/src/gausskernel/optimizer/commands/typecmds.cpp index e68c4ea1d..373f650b7 100644 --- a/src/gausskernel/optimizer/commands/typecmds.cpp +++ b/src/gausskernel/optimizer/commands/typecmds.cpp @@ -3688,6 +3688,13 @@ Oid AlterTypeNamespace_oid(Oid typeOid, Oid nspOid, ObjectAddresses* objsMoved) errmsg("cannot alter array type %s", format_type_be(typeOid)), errhint("You can alter type %s, which will alter the array type as well.", format_type_be(elemOid)))); + if (enable_plpgsql_gsdependency_guc() && + gsplsql_is_object_depend(typeOid, GSDEPEND_OBJECT_TYPE_TYPE)) { + ereport(ERROR, + (errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST), + errmsg("The set schema operator of %s is not allowed, because it is referenced by the other object.", + get_typename(typeOid)))); + } /* and do the work */ return AlterTypeNamespaceInternal(typeOid, nspOid, false, true, objsMoved); } diff --git a/src/include/catalog/gs_dependencies_fn.h b/src/include/catalog/gs_dependencies_fn.h index 4d1fe09c5..98dadddcc 100644 --- a/src/include/catalog/gs_dependencies_fn.h +++ b/src/include/catalog/gs_dependencies_fn.h @@ -143,4 +143,7 @@ extern void gsplsql_delete_unrefer_depend_obj_oid(Oid ref_obj_oid, bool skip_in_ extern bool gsplsql_check_type_depend_ast_equal(Relation obj_rel, Oid obj_oid, const char* equal_ast); extern bool gsplsql_search_depend_obj_by_oid(Oid oid, GsDependObjDesc* obj_desc); extern void gsplsql_remove_type_gs_dependency(const GsDependObjDesc* obj_desc); +extern bool gsplsql_exists_func_obj(Oid nsp_oid, Oid pkg_oid, const char* old_func_head_name, + const char* old_func_name); +extern bool gsplsql_exists_schema_name(const char* schema_name); #endif /* GS_DEPENDENCIES_FN_H */ diff --git a/src/test/regress/expected/plpgsql_depend/plpgsql_recompile.out b/src/test/regress/expected/plpgsql_depend/plpgsql_recompile.out index ebcbd7ccf..db25c0bec 100644 --- a/src/test/regress/expected/plpgsql_depend/plpgsql_recompile.out +++ b/src/test/regress/expected/plpgsql_depend/plpgsql_recompile.out @@ -387,13 +387,91 @@ INFO: call xxx: (1,aaa,aaaaa,,,), yyy: (2,bbb,bbbbb,,,), p_in: (1,zhang,M,1,2,3 (1 row) +-- test 6 +drop type if exists r1; +drop table if exists stu; +create table stu(sno int, name varchar, sex varchar, cno int); +create type r1 as (a int, c stu%RowType); +create schema plpgsql_recompile_new; +create or replace procedure test_proc(p_in r1) +is +declare +v1 stu%RowType; +begin +RAISE INFO 'call p_in: %', p_in; +end; +/ +call test_proc((1,(1,'zhang','M',1))); +INFO: call p_in: (1,"(1,zhang,M,1)") + test_proc +----------- + +(1 row) + +-- rename report error +ALTER TYPE r1 RENAME to r1_rename; +ERROR: The rename operator of r1 is not allowed, because it is referenced by the other object. +ALTER TYPE r1 RENAME ATTRIBUTE a TO new_a; +ERROR: cannot rename attribute of the type because it is dependent on another object. +ALTER TABLE stu RENAME TO stu_rename; +ERROR: The rename operator on stu is not allowed, because it is dependent on another object. +ALTER TABLE stu RENAME COLUMN cno TO new_cno; +ERROR: cannot rename attribute of the type because it is dependent on another object. +ALTER PROCEDURE test_proc(r1) RENAME TO test_proc_rename; +ERROR: The rename operator of test_proc is not allowed, because it is referenced by the other object. +ALTER SCHEMA plpgsql_recompile RENAME TO plpgsql_recompile_rename; +ERROR: The rename operator of plpgsql_recompile is not allowed, because it is referenced by the other object. +call test_proc((1.0,(1,'zhang','M',1))); +INFO: call p_in: (1,"(1,zhang,M,1)") + test_proc +----------- + +(1 row) + +-- set schema report error +ALTER TYPE r1 SET SCHEMA plpgsql_recompile_new; +ERROR: The set schema operator of r1 is not allowed, because it is referenced by the other object. +ALTER TABLE stu SET SCHEMA plpgsql_recompile_new; +ERROR: The set schema operator of stu is not allowed, because it is referenced by another object. +ALTER PROCEDURE test_proc(r1) SET SCHEMA plpgsql_recompile_new; +ERROR: The set schema operator of test_proc is not allowed, because it is referenced by the other object. +call test_proc((1.0,(1,'zhang','M',1))); +INFO: call p_in: (1,"(1,zhang,M,1)") + test_proc +----------- + +(1 row) + +-- drop and recreate +drop type r1; +drop table stu; +drop procedure test_proc; +create table stu(sno int, name varchar, sex varchar, cno int); +create type r1 as (a int, c stu%RowType); +create or replace procedure test_proc(p_in r1) +is +declare +v1 stu%RowType; +begin +RAISE INFO 'call p_in: %', p_in; +end; +/ +call test_proc((1,(1,'zhang','M',1))); +INFO: call p_in: (1,"(1,zhang,M,1)") + test_proc +----------- + +(1 row) + +drop type r1; +drop table stu; +drop procedure test_proc; -- clean +drop schema plpgsql_recompile_new cascade; drop schema plpgsql_recompile cascade; -NOTICE: drop cascades to 7 other objects +--?.* DETAIL: drop cascades to type s_type drop cascades to function type_alter(s_type) -drop cascades to table stu -drop cascades to type r1 drop cascades to function test_subtype_proc() --?.* drop cascades to function plpgsql_recompile.proc1(s_type) diff --git a/src/test/regress/sql/plpgsql_depend/plpgsql_recompile.sql b/src/test/regress/sql/plpgsql_depend/plpgsql_recompile.sql index 2654f6564..254346521 100644 --- a/src/test/regress/sql/plpgsql_depend/plpgsql_recompile.sql +++ b/src/test/regress/sql/plpgsql_depend/plpgsql_recompile.sql @@ -203,6 +203,60 @@ call pkg.proc1((1,'zhang','M',1,2,3)); alter package pkg compile; call pkg.proc1((1,'zhang','M',1,2,3)); +-- test 6 +drop type if exists r1; +drop table if exists stu; +create table stu(sno int, name varchar, sex varchar, cno int); +create type r1 as (a int, c stu%RowType); +create schema plpgsql_recompile_new; + +create or replace procedure test_proc(p_in r1) +is +declare +v1 stu%RowType; +begin +RAISE INFO 'call p_in: %', p_in; +end; +/ +call test_proc((1,(1,'zhang','M',1))); + +-- rename report error +ALTER TYPE r1 RENAME to r1_rename; +ALTER TYPE r1 RENAME ATTRIBUTE a TO new_a; +ALTER TABLE stu RENAME TO stu_rename; +ALTER TABLE stu RENAME COLUMN cno TO new_cno; +ALTER PROCEDURE test_proc(r1) RENAME TO test_proc_rename; +ALTER SCHEMA plpgsql_recompile RENAME TO plpgsql_recompile_rename; +call test_proc((1.0,(1,'zhang','M',1))); + +-- set schema report error +ALTER TYPE r1 SET SCHEMA plpgsql_recompile_new; +ALTER TABLE stu SET SCHEMA plpgsql_recompile_new; +ALTER PROCEDURE test_proc(r1) SET SCHEMA plpgsql_recompile_new; +call test_proc((1.0,(1,'zhang','M',1))); + +-- drop and recreate +drop type r1; +drop table stu; +drop procedure test_proc; + +create table stu(sno int, name varchar, sex varchar, cno int); +create type r1 as (a int, c stu%RowType); +create or replace procedure test_proc(p_in r1) +is +declare +v1 stu%RowType; +begin +RAISE INFO 'call p_in: %', p_in; +end; +/ +call test_proc((1,(1,'zhang','M',1))); + +drop type r1; +drop table stu; +drop procedure test_proc; + -- clean +drop schema plpgsql_recompile_new cascade; drop schema plpgsql_recompile cascade; reset behavior_compat_options;