00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include "postgres.h"
00017
00018 #include "access/htup_details.h"
00019 #include "access/sysattr.h"
00020 #include "catalog/catalog.h"
00021 #include "catalog/indexing.h"
00022 #include "catalog/objectaddress.h"
00023 #include "catalog/pg_amop.h"
00024 #include "catalog/pg_amproc.h"
00025 #include "catalog/pg_attrdef.h"
00026 #include "catalog/pg_authid.h"
00027 #include "catalog/pg_cast.h"
00028 #include "catalog/pg_default_acl.h"
00029 #include "catalog/pg_event_trigger.h"
00030 #include "catalog/pg_collation.h"
00031 #include "catalog/pg_constraint.h"
00032 #include "catalog/pg_conversion.h"
00033 #include "catalog/pg_database.h"
00034 #include "catalog/pg_extension.h"
00035 #include "catalog/pg_foreign_data_wrapper.h"
00036 #include "catalog/pg_foreign_server.h"
00037 #include "catalog/pg_language.h"
00038 #include "catalog/pg_largeobject.h"
00039 #include "catalog/pg_largeobject_metadata.h"
00040 #include "catalog/pg_namespace.h"
00041 #include "catalog/pg_opclass.h"
00042 #include "catalog/pg_opfamily.h"
00043 #include "catalog/pg_operator.h"
00044 #include "catalog/pg_proc.h"
00045 #include "catalog/pg_rewrite.h"
00046 #include "catalog/pg_tablespace.h"
00047 #include "catalog/pg_trigger.h"
00048 #include "catalog/pg_ts_config.h"
00049 #include "catalog/pg_ts_dict.h"
00050 #include "catalog/pg_ts_parser.h"
00051 #include "catalog/pg_ts_template.h"
00052 #include "catalog/pg_type.h"
00053 #include "catalog/pg_user_mapping.h"
00054 #include "commands/dbcommands.h"
00055 #include "commands/defrem.h"
00056 #include "commands/event_trigger.h"
00057 #include "commands/extension.h"
00058 #include "commands/proclang.h"
00059 #include "commands/tablespace.h"
00060 #include "commands/trigger.h"
00061 #include "foreign/foreign.h"
00062 #include "funcapi.h"
00063 #include "libpq/be-fsstubs.h"
00064 #include "miscadmin.h"
00065 #include "nodes/makefuncs.h"
00066 #include "parser/parse_func.h"
00067 #include "parser/parse_oper.h"
00068 #include "parser/parse_type.h"
00069 #include "rewrite/rewriteSupport.h"
00070 #include "storage/lmgr.h"
00071 #include "storage/sinval.h"
00072 #include "utils/builtins.h"
00073 #include "utils/fmgroids.h"
00074 #include "utils/lsyscache.h"
00075 #include "utils/syscache.h"
00076 #include "utils/tqual.h"
00077
00078
00079
00080
00081
00082
00083
00084 typedef struct
00085 {
00086 Oid class_oid;
00087 Oid oid_index_oid;
00088 int oid_catcache_id;
00089 int name_catcache_id;
00090
00091
00092 AttrNumber attnum_name;
00093 AttrNumber attnum_namespace;
00094 AttrNumber attnum_owner;
00095 AttrNumber attnum_acl;
00096 AclObjectKind acl_kind;
00097 bool is_nsp_name_unique;
00098
00099
00100
00101 } ObjectPropertyType;
00102
00103 static ObjectPropertyType ObjectProperty[] =
00104 {
00105 {
00106 CastRelationId,
00107 CastOidIndexId,
00108 -1,
00109 -1,
00110 InvalidAttrNumber,
00111 InvalidAttrNumber,
00112 InvalidAttrNumber,
00113 InvalidAttrNumber,
00114 -1,
00115 false
00116 },
00117 {
00118 CollationRelationId,
00119 CollationOidIndexId,
00120 COLLOID,
00121 -1,
00122 Anum_pg_collation_collname,
00123 Anum_pg_collation_collnamespace,
00124 Anum_pg_collation_collowner,
00125 InvalidAttrNumber,
00126 ACL_KIND_COLLATION,
00127 true
00128 },
00129 {
00130 ConstraintRelationId,
00131 ConstraintOidIndexId,
00132 CONSTROID,
00133 -1,
00134 Anum_pg_constraint_conname,
00135 Anum_pg_constraint_connamespace,
00136 InvalidAttrNumber,
00137 InvalidAttrNumber,
00138 -1,
00139 false
00140 },
00141 {
00142 ConversionRelationId,
00143 ConversionOidIndexId,
00144 CONVOID,
00145 CONNAMENSP,
00146 Anum_pg_conversion_conname,
00147 Anum_pg_conversion_connamespace,
00148 Anum_pg_conversion_conowner,
00149 InvalidAttrNumber,
00150 ACL_KIND_CONVERSION,
00151 true
00152 },
00153 {
00154 DatabaseRelationId,
00155 DatabaseOidIndexId,
00156 DATABASEOID,
00157 -1,
00158 Anum_pg_database_datname,
00159 InvalidAttrNumber,
00160 Anum_pg_database_datdba,
00161 Anum_pg_database_datacl,
00162 ACL_KIND_DATABASE,
00163 true
00164 },
00165 {
00166 ExtensionRelationId,
00167 ExtensionOidIndexId,
00168 -1,
00169 -1,
00170 Anum_pg_extension_extname,
00171 InvalidAttrNumber,
00172 Anum_pg_extension_extowner,
00173 InvalidAttrNumber,
00174 ACL_KIND_EXTENSION,
00175 true
00176 },
00177 {
00178 ForeignDataWrapperRelationId,
00179 ForeignDataWrapperOidIndexId,
00180 FOREIGNDATAWRAPPEROID,
00181 FOREIGNDATAWRAPPERNAME,
00182 Anum_pg_foreign_data_wrapper_fdwname,
00183 InvalidAttrNumber,
00184 Anum_pg_foreign_data_wrapper_fdwowner,
00185 Anum_pg_foreign_data_wrapper_fdwacl,
00186 ACL_KIND_FDW,
00187 true
00188 },
00189 {
00190 ForeignServerRelationId,
00191 ForeignServerOidIndexId,
00192 FOREIGNSERVEROID,
00193 FOREIGNSERVERNAME,
00194 Anum_pg_foreign_server_srvname,
00195 InvalidAttrNumber,
00196 Anum_pg_foreign_server_srvowner,
00197 Anum_pg_foreign_server_srvacl,
00198 ACL_KIND_FOREIGN_SERVER,
00199 true
00200 },
00201 {
00202 ProcedureRelationId,
00203 ProcedureOidIndexId,
00204 PROCOID,
00205 -1,
00206 Anum_pg_proc_proname,
00207 Anum_pg_proc_pronamespace,
00208 Anum_pg_proc_proowner,
00209 Anum_pg_proc_proacl,
00210 ACL_KIND_PROC,
00211 false
00212 },
00213 {
00214 LanguageRelationId,
00215 LanguageOidIndexId,
00216 LANGOID,
00217 LANGNAME,
00218 Anum_pg_language_lanname,
00219 InvalidAttrNumber,
00220 Anum_pg_language_lanowner,
00221 Anum_pg_language_lanacl,
00222 ACL_KIND_LANGUAGE,
00223 true
00224 },
00225 {
00226 LargeObjectMetadataRelationId,
00227 LargeObjectMetadataOidIndexId,
00228 -1,
00229 -1,
00230 InvalidAttrNumber,
00231 InvalidAttrNumber,
00232 Anum_pg_largeobject_metadata_lomowner,
00233 Anum_pg_largeobject_metadata_lomacl,
00234 ACL_KIND_LARGEOBJECT,
00235 false
00236 },
00237 {
00238 OperatorClassRelationId,
00239 OpclassOidIndexId,
00240 CLAOID,
00241 -1,
00242 Anum_pg_opclass_opcname,
00243 Anum_pg_opclass_opcnamespace,
00244 Anum_pg_opclass_opcowner,
00245 InvalidAttrNumber,
00246 ACL_KIND_OPCLASS,
00247 true
00248 },
00249 {
00250 OperatorRelationId,
00251 OperatorOidIndexId,
00252 OPEROID,
00253 -1,
00254 Anum_pg_operator_oprname,
00255 Anum_pg_operator_oprnamespace,
00256 Anum_pg_operator_oprowner,
00257 InvalidAttrNumber,
00258 ACL_KIND_OPER,
00259 false
00260 },
00261 {
00262 OperatorFamilyRelationId,
00263 OpfamilyOidIndexId,
00264 OPFAMILYOID,
00265 -1,
00266 Anum_pg_opfamily_opfname,
00267 Anum_pg_opfamily_opfnamespace,
00268 Anum_pg_opfamily_opfowner,
00269 InvalidAttrNumber,
00270 ACL_KIND_OPFAMILY,
00271 true
00272 },
00273 {
00274 AuthIdRelationId,
00275 AuthIdOidIndexId,
00276 AUTHOID,
00277 AUTHNAME,
00278 Anum_pg_authid_rolname,
00279 InvalidAttrNumber,
00280 InvalidAttrNumber,
00281 InvalidAttrNumber,
00282 -1,
00283 true
00284 },
00285 {
00286 RewriteRelationId,
00287 RewriteOidIndexId,
00288 -1,
00289 -1,
00290 Anum_pg_rewrite_rulename,
00291 InvalidAttrNumber,
00292 InvalidAttrNumber,
00293 InvalidAttrNumber,
00294 -1,
00295 false
00296 },
00297 {
00298 NamespaceRelationId,
00299 NamespaceOidIndexId,
00300 NAMESPACEOID,
00301 NAMESPACENAME,
00302 Anum_pg_namespace_nspname,
00303 InvalidAttrNumber,
00304 Anum_pg_namespace_nspowner,
00305 Anum_pg_namespace_nspacl,
00306 ACL_KIND_NAMESPACE,
00307 true
00308 },
00309 {
00310 RelationRelationId,
00311 ClassOidIndexId,
00312 RELOID,
00313 RELNAMENSP,
00314 Anum_pg_class_relname,
00315 Anum_pg_class_relnamespace,
00316 Anum_pg_class_relowner,
00317 Anum_pg_class_relacl,
00318 ACL_KIND_CLASS,
00319 true
00320 },
00321 {
00322 TableSpaceRelationId,
00323 TablespaceOidIndexId,
00324 TABLESPACEOID,
00325 -1,
00326 Anum_pg_tablespace_spcname,
00327 InvalidAttrNumber,
00328 Anum_pg_tablespace_spcowner,
00329 Anum_pg_tablespace_spcacl,
00330 ACL_KIND_TABLESPACE,
00331 true
00332 },
00333 {
00334 TriggerRelationId,
00335 TriggerOidIndexId,
00336 -1,
00337 -1,
00338 Anum_pg_trigger_tgname,
00339 InvalidAttrNumber,
00340 InvalidAttrNumber,
00341 InvalidAttrNumber,
00342 -1,
00343 false
00344 },
00345 {
00346 EventTriggerRelationId,
00347 EventTriggerOidIndexId,
00348 EVENTTRIGGEROID,
00349 EVENTTRIGGERNAME,
00350 Anum_pg_event_trigger_evtname,
00351 InvalidAttrNumber,
00352 Anum_pg_event_trigger_evtowner,
00353 InvalidAttrNumber,
00354 ACL_KIND_EVENT_TRIGGER,
00355 true
00356 },
00357 {
00358 TSConfigRelationId,
00359 TSConfigOidIndexId,
00360 TSCONFIGOID,
00361 TSCONFIGNAMENSP,
00362 Anum_pg_ts_config_cfgname,
00363 Anum_pg_ts_config_cfgnamespace,
00364 Anum_pg_ts_config_cfgowner,
00365 InvalidAttrNumber,
00366 ACL_KIND_TSCONFIGURATION,
00367 true
00368 },
00369 {
00370 TSDictionaryRelationId,
00371 TSDictionaryOidIndexId,
00372 TSDICTOID,
00373 TSDICTNAMENSP,
00374 Anum_pg_ts_dict_dictname,
00375 Anum_pg_ts_dict_dictnamespace,
00376 Anum_pg_ts_dict_dictowner,
00377 InvalidAttrNumber,
00378 ACL_KIND_TSDICTIONARY,
00379 true
00380 },
00381 {
00382 TSParserRelationId,
00383 TSParserOidIndexId,
00384 TSPARSEROID,
00385 TSPARSERNAMENSP,
00386 Anum_pg_ts_parser_prsname,
00387 Anum_pg_ts_parser_prsnamespace,
00388 InvalidAttrNumber,
00389 InvalidAttrNumber,
00390 -1,
00391 true
00392 },
00393 {
00394 TSTemplateRelationId,
00395 TSTemplateOidIndexId,
00396 TSTEMPLATEOID,
00397 TSTEMPLATENAMENSP,
00398 Anum_pg_ts_template_tmplname,
00399 Anum_pg_ts_template_tmplnamespace,
00400 InvalidAttrNumber,
00401 InvalidAttrNumber,
00402 -1,
00403 true,
00404 },
00405 {
00406 TypeRelationId,
00407 TypeOidIndexId,
00408 TYPEOID,
00409 TYPENAMENSP,
00410 Anum_pg_type_typname,
00411 Anum_pg_type_typnamespace,
00412 Anum_pg_type_typowner,
00413 Anum_pg_type_typacl,
00414 ACL_KIND_TYPE,
00415 true
00416 }
00417 };
00418
00419 static ObjectAddress get_object_address_unqualified(ObjectType objtype,
00420 List *qualname, bool missing_ok);
00421 static ObjectAddress get_relation_by_qualified_name(ObjectType objtype,
00422 List *objname, Relation *relp,
00423 LOCKMODE lockmode, bool missing_ok);
00424 static ObjectAddress get_object_address_relobject(ObjectType objtype,
00425 List *objname, Relation *relp, bool missing_ok);
00426 static ObjectAddress get_object_address_attribute(ObjectType objtype,
00427 List *objname, Relation *relp,
00428 LOCKMODE lockmode, bool missing_ok);
00429 static ObjectAddress get_object_address_type(ObjectType objtype,
00430 List *objname, bool missing_ok);
00431 static ObjectAddress get_object_address_opcf(ObjectType objtype, List *objname,
00432 List *objargs, bool missing_ok);
00433 static ObjectPropertyType *get_object_property_data(Oid class_id);
00434
00435 static void getRelationDescription(StringInfo buffer, Oid relid);
00436 static void getOpFamilyDescription(StringInfo buffer, Oid opfid);
00437 static void getRelationTypeDescription(StringInfo buffer, Oid relid,
00438 int32 objectSubId);
00439 static void getProcedureTypeDescription(StringInfo buffer, Oid procid);
00440 static void getConstraintTypeDescription(StringInfo buffer, Oid constroid);
00441 static void getOpFamilyIdentity(StringInfo buffer, Oid opfid);
00442 static void getRelationIdentity(StringInfo buffer, Oid relid);
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464 ObjectAddress
00465 get_object_address(ObjectType objtype, List *objname, List *objargs,
00466 Relation *relp, LOCKMODE lockmode, bool missing_ok)
00467 {
00468 ObjectAddress address;
00469 ObjectAddress old_address = {InvalidOid, InvalidOid, 0};
00470 Relation relation = NULL;
00471 uint64 inval_count;
00472
00473
00474 Assert(lockmode != NoLock);
00475
00476 for (;;)
00477 {
00478
00479
00480
00481
00482
00483 inval_count = SharedInvalidMessageCounter;
00484
00485
00486 switch (objtype)
00487 {
00488 case OBJECT_INDEX:
00489 case OBJECT_SEQUENCE:
00490 case OBJECT_TABLE:
00491 case OBJECT_VIEW:
00492 case OBJECT_MATVIEW:
00493 case OBJECT_FOREIGN_TABLE:
00494 address =
00495 get_relation_by_qualified_name(objtype, objname,
00496 &relation, lockmode,
00497 missing_ok);
00498 break;
00499 case OBJECT_COLUMN:
00500 address =
00501 get_object_address_attribute(objtype, objname,
00502 &relation, lockmode,
00503 missing_ok);
00504 break;
00505 case OBJECT_RULE:
00506 case OBJECT_TRIGGER:
00507 case OBJECT_CONSTRAINT:
00508 address = get_object_address_relobject(objtype, objname,
00509 &relation, missing_ok);
00510 break;
00511 case OBJECT_DATABASE:
00512 case OBJECT_EXTENSION:
00513 case OBJECT_TABLESPACE:
00514 case OBJECT_ROLE:
00515 case OBJECT_SCHEMA:
00516 case OBJECT_LANGUAGE:
00517 case OBJECT_FDW:
00518 case OBJECT_FOREIGN_SERVER:
00519 case OBJECT_EVENT_TRIGGER:
00520 address = get_object_address_unqualified(objtype,
00521 objname, missing_ok);
00522 break;
00523 case OBJECT_TYPE:
00524 case OBJECT_DOMAIN:
00525 address = get_object_address_type(objtype, objname, missing_ok);
00526 break;
00527 case OBJECT_AGGREGATE:
00528 address.classId = ProcedureRelationId;
00529 address.objectId =
00530 LookupAggNameTypeNames(objname, objargs, missing_ok);
00531 address.objectSubId = 0;
00532 break;
00533 case OBJECT_FUNCTION:
00534 address.classId = ProcedureRelationId;
00535 address.objectId =
00536 LookupFuncNameTypeNames(objname, objargs, missing_ok);
00537 address.objectSubId = 0;
00538 break;
00539 case OBJECT_OPERATOR:
00540 Assert(list_length(objargs) == 2);
00541 address.classId = OperatorRelationId;
00542 address.objectId =
00543 LookupOperNameTypeNames(NULL, objname,
00544 (TypeName *) linitial(objargs),
00545 (TypeName *) lsecond(objargs),
00546 missing_ok, -1);
00547 address.objectSubId = 0;
00548 break;
00549 case OBJECT_COLLATION:
00550 address.classId = CollationRelationId;
00551 address.objectId = get_collation_oid(objname, missing_ok);
00552 address.objectSubId = 0;
00553 break;
00554 case OBJECT_CONVERSION:
00555 address.classId = ConversionRelationId;
00556 address.objectId = get_conversion_oid(objname, missing_ok);
00557 address.objectSubId = 0;
00558 break;
00559 case OBJECT_OPCLASS:
00560 case OBJECT_OPFAMILY:
00561 address = get_object_address_opcf(objtype,
00562 objname, objargs, missing_ok);
00563 break;
00564 case OBJECT_LARGEOBJECT:
00565 Assert(list_length(objname) == 1);
00566 address.classId = LargeObjectRelationId;
00567 address.objectId = oidparse(linitial(objname));
00568 address.objectSubId = 0;
00569 if (!LargeObjectExists(address.objectId))
00570 {
00571 if (!missing_ok)
00572 ereport(ERROR,
00573 (errcode(ERRCODE_UNDEFINED_OBJECT),
00574 errmsg("large object %u does not exist",
00575 address.objectId)));
00576 }
00577 break;
00578 case OBJECT_CAST:
00579 {
00580 TypeName *sourcetype = (TypeName *) linitial(objname);
00581 TypeName *targettype = (TypeName *) linitial(objargs);
00582 Oid sourcetypeid = typenameTypeId(NULL, sourcetype);
00583 Oid targettypeid = typenameTypeId(NULL, targettype);
00584
00585 address.classId = CastRelationId;
00586 address.objectId =
00587 get_cast_oid(sourcetypeid, targettypeid, missing_ok);
00588 address.objectSubId = 0;
00589 }
00590 break;
00591 case OBJECT_TSPARSER:
00592 address.classId = TSParserRelationId;
00593 address.objectId = get_ts_parser_oid(objname, missing_ok);
00594 address.objectSubId = 0;
00595 break;
00596 case OBJECT_TSDICTIONARY:
00597 address.classId = TSDictionaryRelationId;
00598 address.objectId = get_ts_dict_oid(objname, missing_ok);
00599 address.objectSubId = 0;
00600 break;
00601 case OBJECT_TSTEMPLATE:
00602 address.classId = TSTemplateRelationId;
00603 address.objectId = get_ts_template_oid(objname, missing_ok);
00604 address.objectSubId = 0;
00605 break;
00606 case OBJECT_TSCONFIGURATION:
00607 address.classId = TSConfigRelationId;
00608 address.objectId = get_ts_config_oid(objname, missing_ok);
00609 address.objectSubId = 0;
00610 break;
00611 default:
00612 elog(ERROR, "unrecognized objtype: %d", (int) objtype);
00613
00614 address.classId = InvalidOid;
00615 address.objectId = InvalidOid;
00616 address.objectSubId = 0;
00617 }
00618
00619
00620
00621
00622 if (!OidIsValid(address.objectId))
00623 {
00624 Assert(missing_ok);
00625 return address;
00626 }
00627
00628
00629
00630
00631
00632
00633 if (OidIsValid(old_address.classId))
00634 {
00635 if (old_address.classId == address.classId
00636 && old_address.objectId == address.objectId
00637 && old_address.objectSubId == address.objectSubId)
00638 break;
00639 if (old_address.classId != RelationRelationId)
00640 {
00641 if (IsSharedRelation(old_address.classId))
00642 UnlockSharedObject(old_address.classId,
00643 old_address.objectId,
00644 0, lockmode);
00645 else
00646 UnlockDatabaseObject(old_address.classId,
00647 old_address.objectId,
00648 0, lockmode);
00649 }
00650 }
00651
00652
00653
00654
00655
00656 if (address.classId != RelationRelationId)
00657 {
00658 if (IsSharedRelation(address.classId))
00659 LockSharedObject(address.classId, address.objectId, 0,
00660 lockmode);
00661 else
00662 LockDatabaseObject(address.classId, address.objectId, 0,
00663 lockmode);
00664 }
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686 if (inval_count == SharedInvalidMessageCounter || relation != NULL)
00687 break;
00688 old_address = address;
00689 }
00690
00691
00692 *relp = relation;
00693 return address;
00694 }
00695
00696
00697
00698
00699
00700 static ObjectAddress
00701 get_object_address_unqualified(ObjectType objtype,
00702 List *qualname, bool missing_ok)
00703 {
00704 const char *name;
00705 ObjectAddress address;
00706
00707
00708
00709
00710
00711 if (list_length(qualname) != 1)
00712 {
00713 const char *msg;
00714
00715 switch (objtype)
00716 {
00717 case OBJECT_DATABASE:
00718 msg = gettext_noop("database name cannot be qualified");
00719 break;
00720 case OBJECT_EXTENSION:
00721 msg = gettext_noop("extension name cannot be qualified");
00722 break;
00723 case OBJECT_TABLESPACE:
00724 msg = gettext_noop("tablespace name cannot be qualified");
00725 break;
00726 case OBJECT_ROLE:
00727 msg = gettext_noop("role name cannot be qualified");
00728 break;
00729 case OBJECT_SCHEMA:
00730 msg = gettext_noop("schema name cannot be qualified");
00731 break;
00732 case OBJECT_LANGUAGE:
00733 msg = gettext_noop("language name cannot be qualified");
00734 break;
00735 case OBJECT_FDW:
00736 msg = gettext_noop("foreign-data wrapper name cannot be qualified");
00737 break;
00738 case OBJECT_FOREIGN_SERVER:
00739 msg = gettext_noop("server name cannot be qualified");
00740 break;
00741 case OBJECT_EVENT_TRIGGER:
00742 msg = gettext_noop("event trigger name cannot be qualified");
00743 break;
00744 default:
00745 elog(ERROR, "unrecognized objtype: %d", (int) objtype);
00746 msg = NULL;
00747 }
00748 ereport(ERROR,
00749 (errcode(ERRCODE_SYNTAX_ERROR),
00750 errmsg("%s", _(msg))));
00751 }
00752
00753
00754 name = strVal(linitial(qualname));
00755
00756
00757 switch (objtype)
00758 {
00759 case OBJECT_DATABASE:
00760 address.classId = DatabaseRelationId;
00761 address.objectId = get_database_oid(name, missing_ok);
00762 address.objectSubId = 0;
00763 break;
00764 case OBJECT_EXTENSION:
00765 address.classId = ExtensionRelationId;
00766 address.objectId = get_extension_oid(name, missing_ok);
00767 address.objectSubId = 0;
00768 break;
00769 case OBJECT_TABLESPACE:
00770 address.classId = TableSpaceRelationId;
00771 address.objectId = get_tablespace_oid(name, missing_ok);
00772 address.objectSubId = 0;
00773 break;
00774 case OBJECT_ROLE:
00775 address.classId = AuthIdRelationId;
00776 address.objectId = get_role_oid(name, missing_ok);
00777 address.objectSubId = 0;
00778 break;
00779 case OBJECT_SCHEMA:
00780 address.classId = NamespaceRelationId;
00781 address.objectId = get_namespace_oid(name, missing_ok);
00782 address.objectSubId = 0;
00783 break;
00784 case OBJECT_LANGUAGE:
00785 address.classId = LanguageRelationId;
00786 address.objectId = get_language_oid(name, missing_ok);
00787 address.objectSubId = 0;
00788 break;
00789 case OBJECT_FDW:
00790 address.classId = ForeignDataWrapperRelationId;
00791 address.objectId = get_foreign_data_wrapper_oid(name, missing_ok);
00792 address.objectSubId = 0;
00793 break;
00794 case OBJECT_FOREIGN_SERVER:
00795 address.classId = ForeignServerRelationId;
00796 address.objectId = get_foreign_server_oid(name, missing_ok);
00797 address.objectSubId = 0;
00798 break;
00799 case OBJECT_EVENT_TRIGGER:
00800 address.classId = EventTriggerRelationId;
00801 address.objectId = get_event_trigger_oid(name, missing_ok);
00802 address.objectSubId = 0;
00803 break;
00804 default:
00805 elog(ERROR, "unrecognized objtype: %d", (int) objtype);
00806
00807 address.classId = InvalidOid;
00808 address.objectId = InvalidOid;
00809 address.objectSubId = 0;
00810 }
00811
00812 return address;
00813 }
00814
00815
00816
00817
00818 static ObjectAddress
00819 get_relation_by_qualified_name(ObjectType objtype, List *objname,
00820 Relation *relp, LOCKMODE lockmode,
00821 bool missing_ok)
00822 {
00823 Relation relation;
00824 ObjectAddress address;
00825
00826 address.classId = RelationRelationId;
00827 address.objectId = InvalidOid;
00828 address.objectSubId = 0;
00829
00830 relation = relation_openrv_extended(makeRangeVarFromNameList(objname),
00831 lockmode, missing_ok);
00832 if (!relation)
00833 return address;
00834
00835 switch (objtype)
00836 {
00837 case OBJECT_INDEX:
00838 if (relation->rd_rel->relkind != RELKIND_INDEX)
00839 ereport(ERROR,
00840 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
00841 errmsg("\"%s\" is not an index",
00842 RelationGetRelationName(relation))));
00843 break;
00844 case OBJECT_SEQUENCE:
00845 if (relation->rd_rel->relkind != RELKIND_SEQUENCE)
00846 ereport(ERROR,
00847 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
00848 errmsg("\"%s\" is not a sequence",
00849 RelationGetRelationName(relation))));
00850 break;
00851 case OBJECT_TABLE:
00852 if (relation->rd_rel->relkind != RELKIND_RELATION)
00853 ereport(ERROR,
00854 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
00855 errmsg("\"%s\" is not a table",
00856 RelationGetRelationName(relation))));
00857 break;
00858 case OBJECT_VIEW:
00859 if (relation->rd_rel->relkind != RELKIND_VIEW)
00860 ereport(ERROR,
00861 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
00862 errmsg("\"%s\" is not a view",
00863 RelationGetRelationName(relation))));
00864 break;
00865 case OBJECT_MATVIEW:
00866 if (relation->rd_rel->relkind != RELKIND_MATVIEW)
00867 ereport(ERROR,
00868 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
00869 errmsg("\"%s\" is not a materialized view",
00870 RelationGetRelationName(relation))));
00871 break;
00872 case OBJECT_FOREIGN_TABLE:
00873 if (relation->rd_rel->relkind != RELKIND_FOREIGN_TABLE)
00874 ereport(ERROR,
00875 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
00876 errmsg("\"%s\" is not a foreign table",
00877 RelationGetRelationName(relation))));
00878 break;
00879 default:
00880 elog(ERROR, "unrecognized objtype: %d", (int) objtype);
00881 break;
00882 }
00883
00884
00885 address.objectId = RelationGetRelid(relation);
00886 *relp = relation;
00887
00888 return address;
00889 }
00890
00891
00892
00893
00894
00895
00896
00897
00898 static ObjectAddress
00899 get_object_address_relobject(ObjectType objtype, List *objname,
00900 Relation *relp, bool missing_ok)
00901 {
00902 ObjectAddress address;
00903 Relation relation = NULL;
00904 int nnames;
00905 const char *depname;
00906
00907
00908 depname = strVal(lfirst(list_tail(objname)));
00909
00910
00911 nnames = list_length(objname);
00912 if (nnames < 2)
00913 {
00914 Oid reloid;
00915
00916
00917
00918
00919
00920
00921
00922
00923 if (objtype != OBJECT_RULE)
00924 elog(ERROR, "must specify relation and object name");
00925 address.classId = RewriteRelationId;
00926 address.objectId =
00927 get_rewrite_oid_without_relid(depname, &reloid, missing_ok);
00928 address.objectSubId = 0;
00929
00930
00931
00932
00933
00934 if (OidIsValid(address.objectId))
00935 relation = heap_open(reloid, AccessShareLock);
00936 }
00937 else
00938 {
00939 List *relname;
00940 Oid reloid;
00941
00942
00943 relname = list_truncate(list_copy(objname), nnames - 1);
00944 relation = heap_openrv(makeRangeVarFromNameList(relname),
00945 AccessShareLock);
00946 reloid = RelationGetRelid(relation);
00947
00948 switch (objtype)
00949 {
00950 case OBJECT_RULE:
00951 address.classId = RewriteRelationId;
00952 address.objectId = get_rewrite_oid(reloid, depname, missing_ok);
00953 address.objectSubId = 0;
00954 break;
00955 case OBJECT_TRIGGER:
00956 address.classId = TriggerRelationId;
00957 address.objectId = get_trigger_oid(reloid, depname, missing_ok);
00958 address.objectSubId = 0;
00959 break;
00960 case OBJECT_CONSTRAINT:
00961 address.classId = ConstraintRelationId;
00962 address.objectId =
00963 get_relation_constraint_oid(reloid, depname, missing_ok);
00964 address.objectSubId = 0;
00965 break;
00966 default:
00967 elog(ERROR, "unrecognized objtype: %d", (int) objtype);
00968
00969 address.classId = InvalidOid;
00970 address.objectId = InvalidOid;
00971 address.objectSubId = 0;
00972 }
00973
00974
00975 if (!OidIsValid(address.objectId))
00976 {
00977 heap_close(relation, AccessShareLock);
00978 relation = NULL;
00979 return address;
00980 }
00981 }
00982
00983
00984 *relp = relation;
00985 return address;
00986 }
00987
00988
00989
00990
00991 static ObjectAddress
00992 get_object_address_attribute(ObjectType objtype, List *objname,
00993 Relation *relp, LOCKMODE lockmode,
00994 bool missing_ok)
00995 {
00996 ObjectAddress address;
00997 List *relname;
00998 Oid reloid;
00999 Relation relation;
01000 const char *attname;
01001 AttrNumber attnum;
01002
01003
01004 if (list_length(objname) < 2)
01005 ereport(ERROR,
01006 (errcode(ERRCODE_SYNTAX_ERROR),
01007 errmsg("column name must be qualified")));
01008 attname = strVal(lfirst(list_tail(objname)));
01009 relname = list_truncate(list_copy(objname), list_length(objname) - 1);
01010 relation = relation_openrv(makeRangeVarFromNameList(relname), lockmode);
01011 reloid = RelationGetRelid(relation);
01012
01013
01014 attnum = get_attnum(reloid, attname);
01015 if (attnum == InvalidAttrNumber)
01016 {
01017 if (!missing_ok)
01018 ereport(ERROR,
01019 (errcode(ERRCODE_UNDEFINED_COLUMN),
01020 errmsg("column \"%s\" of relation \"%s\" does not exist",
01021 attname, NameListToString(relname))));
01022
01023 address.classId = RelationRelationId;
01024 address.objectId = InvalidOid;
01025 address.objectSubId = InvalidAttrNumber;
01026 return address;
01027 }
01028
01029 address.classId = RelationRelationId;
01030 address.objectId = reloid;
01031 address.objectSubId = attnum;
01032
01033 *relp = relation;
01034 return address;
01035 }
01036
01037
01038
01039
01040 static ObjectAddress
01041 get_object_address_type(ObjectType objtype,
01042 List *objname, bool missing_ok)
01043 {
01044 ObjectAddress address;
01045 TypeName *typename;
01046 Type tup;
01047
01048 typename = makeTypeNameFromNameList(objname);
01049
01050 address.classId = TypeRelationId;
01051 address.objectId = InvalidOid;
01052 address.objectSubId = 0;
01053
01054 tup = LookupTypeName(NULL, typename, NULL);
01055 if (!HeapTupleIsValid(tup))
01056 {
01057 if (!missing_ok)
01058 ereport(ERROR,
01059 (errcode(ERRCODE_UNDEFINED_OBJECT),
01060 errmsg("type \"%s\" does not exist",
01061 TypeNameToString(typename))));
01062 return address;
01063 }
01064 address.objectId = typeTypeId(tup);
01065
01066 if (objtype == OBJECT_DOMAIN)
01067 {
01068 if (((Form_pg_type) GETSTRUCT(tup))->typtype != TYPTYPE_DOMAIN)
01069 ereport(ERROR,
01070 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
01071 errmsg("\"%s\" is not a domain",
01072 TypeNameToString(typename))));
01073 }
01074
01075 ReleaseSysCache(tup);
01076
01077 return address;
01078 }
01079
01080
01081
01082
01083 static ObjectAddress
01084 get_object_address_opcf(ObjectType objtype,
01085 List *objname, List *objargs, bool missing_ok)
01086 {
01087 Oid amoid;
01088 ObjectAddress address;
01089
01090 Assert(list_length(objargs) == 1);
01091 amoid = get_am_oid(strVal(linitial(objargs)), false);
01092
01093 switch (objtype)
01094 {
01095 case OBJECT_OPCLASS:
01096 address.classId = OperatorClassRelationId;
01097 address.objectId = get_opclass_oid(amoid, objname, missing_ok);
01098 address.objectSubId = 0;
01099 break;
01100 case OBJECT_OPFAMILY:
01101 address.classId = OperatorFamilyRelationId;
01102 address.objectId = get_opfamily_oid(amoid, objname, missing_ok);
01103 address.objectSubId = 0;
01104 break;
01105 default:
01106 elog(ERROR, "unrecognized objtype: %d", (int) objtype);
01107
01108 address.classId = InvalidOid;
01109 address.objectId = InvalidOid;
01110 address.objectSubId = 0;
01111 }
01112
01113 return address;
01114 }
01115
01116
01117
01118
01119 void
01120 check_object_ownership(Oid roleid, ObjectType objtype, ObjectAddress address,
01121 List *objname, List *objargs, Relation relation)
01122 {
01123 switch (objtype)
01124 {
01125 case OBJECT_INDEX:
01126 case OBJECT_SEQUENCE:
01127 case OBJECT_TABLE:
01128 case OBJECT_VIEW:
01129 case OBJECT_MATVIEW:
01130 case OBJECT_FOREIGN_TABLE:
01131 case OBJECT_COLUMN:
01132 case OBJECT_RULE:
01133 case OBJECT_TRIGGER:
01134 case OBJECT_CONSTRAINT:
01135 if (!pg_class_ownercheck(RelationGetRelid(relation), roleid))
01136 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS,
01137 RelationGetRelationName(relation));
01138 break;
01139 case OBJECT_DATABASE:
01140 if (!pg_database_ownercheck(address.objectId, roleid))
01141 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_DATABASE,
01142 NameListToString(objname));
01143 break;
01144 case OBJECT_TYPE:
01145 case OBJECT_DOMAIN:
01146 case OBJECT_ATTRIBUTE:
01147 if (!pg_type_ownercheck(address.objectId, roleid))
01148 aclcheck_error_type(ACLCHECK_NOT_OWNER, address.objectId);
01149 break;
01150 case OBJECT_AGGREGATE:
01151 case OBJECT_FUNCTION:
01152 if (!pg_proc_ownercheck(address.objectId, roleid))
01153 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_PROC,
01154 NameListToString(objname));
01155 break;
01156 case OBJECT_OPERATOR:
01157 if (!pg_oper_ownercheck(address.objectId, roleid))
01158 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_OPER,
01159 NameListToString(objname));
01160 break;
01161 case OBJECT_SCHEMA:
01162 if (!pg_namespace_ownercheck(address.objectId, roleid))
01163 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_NAMESPACE,
01164 NameListToString(objname));
01165 break;
01166 case OBJECT_COLLATION:
01167 if (!pg_collation_ownercheck(address.objectId, roleid))
01168 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_COLLATION,
01169 NameListToString(objname));
01170 break;
01171 case OBJECT_CONVERSION:
01172 if (!pg_conversion_ownercheck(address.objectId, roleid))
01173 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CONVERSION,
01174 NameListToString(objname));
01175 break;
01176 case OBJECT_EXTENSION:
01177 if (!pg_extension_ownercheck(address.objectId, roleid))
01178 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_EXTENSION,
01179 NameListToString(objname));
01180 break;
01181 case OBJECT_FDW:
01182 if (!pg_foreign_data_wrapper_ownercheck(address.objectId, roleid))
01183 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_FDW,
01184 NameListToString(objname));
01185 break;
01186 case OBJECT_FOREIGN_SERVER:
01187 if (!pg_foreign_server_ownercheck(address.objectId, roleid))
01188 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_FOREIGN_SERVER,
01189 NameListToString(objname));
01190 break;
01191 case OBJECT_EVENT_TRIGGER:
01192 if (!pg_event_trigger_ownercheck(address.objectId, roleid))
01193 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_EVENT_TRIGGER,
01194 NameListToString(objname));
01195 break;
01196 case OBJECT_LANGUAGE:
01197 if (!pg_language_ownercheck(address.objectId, roleid))
01198 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_LANGUAGE,
01199 NameListToString(objname));
01200 break;
01201 case OBJECT_OPCLASS:
01202 if (!pg_opclass_ownercheck(address.objectId, roleid))
01203 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_OPCLASS,
01204 NameListToString(objname));
01205 break;
01206 case OBJECT_OPFAMILY:
01207 if (!pg_opfamily_ownercheck(address.objectId, roleid))
01208 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_OPFAMILY,
01209 NameListToString(objname));
01210 break;
01211 case OBJECT_LARGEOBJECT:
01212 if (!lo_compat_privileges &&
01213 !pg_largeobject_ownercheck(address.objectId, roleid))
01214 ereport(ERROR,
01215 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
01216 errmsg("must be owner of large object %u",
01217 address.objectId)));
01218 break;
01219 case OBJECT_CAST:
01220 {
01221
01222 TypeName *sourcetype = (TypeName *) linitial(objname);
01223 TypeName *targettype = (TypeName *) linitial(objargs);
01224 Oid sourcetypeid = typenameTypeId(NULL, sourcetype);
01225 Oid targettypeid = typenameTypeId(NULL, targettype);
01226
01227 if (!pg_type_ownercheck(sourcetypeid, roleid)
01228 && !pg_type_ownercheck(targettypeid, roleid))
01229 ereport(ERROR,
01230 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
01231 errmsg("must be owner of type %s or type %s",
01232 format_type_be(sourcetypeid),
01233 format_type_be(targettypeid))));
01234 }
01235 break;
01236 case OBJECT_TABLESPACE:
01237 if (!pg_tablespace_ownercheck(address.objectId, roleid))
01238 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TABLESPACE,
01239 NameListToString(objname));
01240 break;
01241 case OBJECT_TSDICTIONARY:
01242 if (!pg_ts_dict_ownercheck(address.objectId, roleid))
01243 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TSDICTIONARY,
01244 NameListToString(objname));
01245 break;
01246 case OBJECT_TSCONFIGURATION:
01247 if (!pg_ts_config_ownercheck(address.objectId, roleid))
01248 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TSCONFIGURATION,
01249 NameListToString(objname));
01250 break;
01251 case OBJECT_ROLE:
01252
01253
01254
01255
01256
01257 if (superuser_arg(address.objectId))
01258 {
01259 if (!superuser_arg(roleid))
01260 ereport(ERROR,
01261 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
01262 errmsg("must be superuser")));
01263 }
01264 else
01265 {
01266 if (!has_createrole_privilege(roleid))
01267 ereport(ERROR,
01268 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
01269 errmsg("must have CREATEROLE privilege")));
01270 }
01271 break;
01272 case OBJECT_TSPARSER:
01273 case OBJECT_TSTEMPLATE:
01274
01275 if (!superuser_arg(roleid))
01276 ereport(ERROR,
01277 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
01278 errmsg("must be superuser")));
01279 break;
01280 default:
01281 elog(ERROR, "unrecognized object type: %d",
01282 (int) objtype);
01283 }
01284 }
01285
01286
01287
01288
01289
01290
01291
01292 Oid
01293 get_object_namespace(const ObjectAddress *address)
01294 {
01295 int cache;
01296 HeapTuple tuple;
01297 bool isnull;
01298 Oid oid;
01299 ObjectPropertyType *property;
01300
01301
01302 property = get_object_property_data(address->classId);
01303 if (property->attnum_namespace == InvalidAttrNumber)
01304 return InvalidOid;
01305
01306
01307 cache = property->oid_catcache_id;
01308 Assert(cache != -1);
01309
01310
01311 tuple = SearchSysCache1(cache, ObjectIdGetDatum(address->objectId));
01312 if (!HeapTupleIsValid(tuple))
01313 elog(ERROR, "cache lookup failed for cache %d oid %u",
01314 cache, address->objectId);
01315 oid = DatumGetObjectId(SysCacheGetAttr(cache,
01316 tuple,
01317 property->attnum_namespace,
01318 &isnull));
01319 Assert(!isnull);
01320 ReleaseSysCache(tuple);
01321
01322 return oid;
01323 }
01324
01325
01326
01327
01328 Oid
01329 get_object_oid_index(Oid class_id)
01330 {
01331 ObjectPropertyType *prop = get_object_property_data(class_id);
01332
01333 return prop->oid_index_oid;
01334 }
01335
01336 int
01337 get_object_catcache_oid(Oid class_id)
01338 {
01339 ObjectPropertyType *prop = get_object_property_data(class_id);
01340
01341 return prop->oid_catcache_id;
01342 }
01343
01344 int
01345 get_object_catcache_name(Oid class_id)
01346 {
01347 ObjectPropertyType *prop = get_object_property_data(class_id);
01348
01349 return prop->name_catcache_id;
01350 }
01351
01352 AttrNumber
01353 get_object_attnum_name(Oid class_id)
01354 {
01355 ObjectPropertyType *prop = get_object_property_data(class_id);
01356
01357 return prop->attnum_name;
01358 }
01359
01360 AttrNumber
01361 get_object_attnum_namespace(Oid class_id)
01362 {
01363 ObjectPropertyType *prop = get_object_property_data(class_id);
01364
01365 return prop->attnum_namespace;
01366 }
01367
01368 AttrNumber
01369 get_object_attnum_owner(Oid class_id)
01370 {
01371 ObjectPropertyType *prop = get_object_property_data(class_id);
01372
01373 return prop->attnum_owner;
01374 }
01375
01376 AttrNumber
01377 get_object_attnum_acl(Oid class_id)
01378 {
01379 ObjectPropertyType *prop = get_object_property_data(class_id);
01380
01381 return prop->attnum_acl;
01382 }
01383
01384 AclObjectKind
01385 get_object_aclkind(Oid class_id)
01386 {
01387 ObjectPropertyType *prop = get_object_property_data(class_id);
01388
01389 return prop->acl_kind;
01390 }
01391
01392 bool
01393 get_object_namensp_unique(Oid class_id)
01394 {
01395 ObjectPropertyType *prop = get_object_property_data(class_id);
01396
01397 return prop->is_nsp_name_unique;
01398 }
01399
01400
01401
01402
01403
01404 bool
01405 is_objectclass_supported(Oid class_id)
01406 {
01407 int index;
01408
01409 for (index = 0; index < lengthof(ObjectProperty); index++)
01410 {
01411 if (ObjectProperty[index].class_oid == class_id)
01412 return true;
01413 }
01414
01415 return false;
01416 }
01417
01418
01419
01420
01421 static ObjectPropertyType *
01422 get_object_property_data(Oid class_id)
01423 {
01424 static ObjectPropertyType *prop_last = NULL;
01425 int index;
01426
01427
01428
01429
01430
01431 if (prop_last && prop_last->class_oid == class_id)
01432 return prop_last;
01433
01434 for (index = 0; index < lengthof(ObjectProperty); index++)
01435 {
01436 if (ObjectProperty[index].class_oid == class_id)
01437 {
01438 prop_last = &ObjectProperty[index];
01439 return &ObjectProperty[index];
01440 }
01441 }
01442
01443 ereport(ERROR,
01444 (errmsg_internal("unrecognized class id: %u", class_id)));
01445
01446 return NULL;
01447 }
01448
01449
01450
01451
01452
01453
01454
01455
01456 HeapTuple
01457 get_catalog_object_by_oid(Relation catalog, Oid objectId)
01458 {
01459 HeapTuple tuple;
01460 Oid classId = RelationGetRelid(catalog);
01461 int oidCacheId = get_object_catcache_oid(classId);
01462
01463 if (oidCacheId > 0)
01464 {
01465 tuple = SearchSysCacheCopy1(oidCacheId, ObjectIdGetDatum(objectId));
01466 if (!HeapTupleIsValid(tuple))
01467 return NULL;
01468 }
01469 else
01470 {
01471 Oid oidIndexId = get_object_oid_index(classId);
01472 SysScanDesc scan;
01473 ScanKeyData skey;
01474
01475 Assert(OidIsValid(oidIndexId));
01476
01477 ScanKeyInit(&skey,
01478 ObjectIdAttributeNumber,
01479 BTEqualStrategyNumber, F_OIDEQ,
01480 ObjectIdGetDatum(objectId));
01481
01482 scan = systable_beginscan(catalog, oidIndexId, true,
01483 SnapshotNow, 1, &skey);
01484 tuple = systable_getnext(scan);
01485 if (!HeapTupleIsValid(tuple))
01486 {
01487 systable_endscan(scan);
01488 return NULL;
01489 }
01490 tuple = heap_copytuple(tuple);
01491
01492 systable_endscan(scan);
01493 }
01494
01495 return tuple;
01496 }
01497
01498
01499
01500
01501
01502
01503 char *
01504 getObjectDescription(const ObjectAddress *object)
01505 {
01506 StringInfoData buffer;
01507
01508 initStringInfo(&buffer);
01509
01510 switch (getObjectClass(object))
01511 {
01512 case OCLASS_CLASS:
01513 getRelationDescription(&buffer, object->objectId);
01514 if (object->objectSubId != 0)
01515 appendStringInfo(&buffer, _(" column %s"),
01516 get_relid_attribute_name(object->objectId,
01517 object->objectSubId));
01518 break;
01519
01520 case OCLASS_PROC:
01521 appendStringInfo(&buffer, _("function %s"),
01522 format_procedure(object->objectId));
01523 break;
01524
01525 case OCLASS_TYPE:
01526 appendStringInfo(&buffer, _("type %s"),
01527 format_type_be(object->objectId));
01528 break;
01529
01530 case OCLASS_CAST:
01531 {
01532 Relation castDesc;
01533 ScanKeyData skey[1];
01534 SysScanDesc rcscan;
01535 HeapTuple tup;
01536 Form_pg_cast castForm;
01537
01538 castDesc = heap_open(CastRelationId, AccessShareLock);
01539
01540 ScanKeyInit(&skey[0],
01541 ObjectIdAttributeNumber,
01542 BTEqualStrategyNumber, F_OIDEQ,
01543 ObjectIdGetDatum(object->objectId));
01544
01545 rcscan = systable_beginscan(castDesc, CastOidIndexId, true,
01546 SnapshotNow, 1, skey);
01547
01548 tup = systable_getnext(rcscan);
01549
01550 if (!HeapTupleIsValid(tup))
01551 elog(ERROR, "could not find tuple for cast %u",
01552 object->objectId);
01553
01554 castForm = (Form_pg_cast) GETSTRUCT(tup);
01555
01556 appendStringInfo(&buffer, _("cast from %s to %s"),
01557 format_type_be(castForm->castsource),
01558 format_type_be(castForm->casttarget));
01559
01560 systable_endscan(rcscan);
01561 heap_close(castDesc, AccessShareLock);
01562 break;
01563 }
01564
01565 case OCLASS_COLLATION:
01566 {
01567 HeapTuple collTup;
01568 Form_pg_collation coll;
01569
01570 collTup = SearchSysCache1(COLLOID,
01571 ObjectIdGetDatum(object->objectId));
01572 if (!HeapTupleIsValid(collTup))
01573 elog(ERROR, "cache lookup failed for collation %u",
01574 object->objectId);
01575 coll = (Form_pg_collation) GETSTRUCT(collTup);
01576 appendStringInfo(&buffer, _("collation %s"),
01577 NameStr(coll->collname));
01578 ReleaseSysCache(collTup);
01579 break;
01580 }
01581
01582 case OCLASS_CONSTRAINT:
01583 {
01584 HeapTuple conTup;
01585 Form_pg_constraint con;
01586
01587 conTup = SearchSysCache1(CONSTROID,
01588 ObjectIdGetDatum(object->objectId));
01589 if (!HeapTupleIsValid(conTup))
01590 elog(ERROR, "cache lookup failed for constraint %u",
01591 object->objectId);
01592 con = (Form_pg_constraint) GETSTRUCT(conTup);
01593
01594 if (OidIsValid(con->conrelid))
01595 {
01596 StringInfoData rel;
01597
01598 initStringInfo(&rel);
01599 getRelationDescription(&rel, con->conrelid);
01600 appendStringInfo(&buffer, _("constraint %s on %s"),
01601 NameStr(con->conname), rel.data);
01602 pfree(rel.data);
01603 }
01604 else
01605 {
01606 appendStringInfo(&buffer, _("constraint %s"),
01607 NameStr(con->conname));
01608 }
01609
01610 ReleaseSysCache(conTup);
01611 break;
01612 }
01613
01614 case OCLASS_CONVERSION:
01615 {
01616 HeapTuple conTup;
01617
01618 conTup = SearchSysCache1(CONVOID,
01619 ObjectIdGetDatum(object->objectId));
01620 if (!HeapTupleIsValid(conTup))
01621 elog(ERROR, "cache lookup failed for conversion %u",
01622 object->objectId);
01623 appendStringInfo(&buffer, _("conversion %s"),
01624 NameStr(((Form_pg_conversion) GETSTRUCT(conTup))->conname));
01625 ReleaseSysCache(conTup);
01626 break;
01627 }
01628
01629 case OCLASS_DEFAULT:
01630 {
01631 Relation attrdefDesc;
01632 ScanKeyData skey[1];
01633 SysScanDesc adscan;
01634 HeapTuple tup;
01635 Form_pg_attrdef attrdef;
01636 ObjectAddress colobject;
01637
01638 attrdefDesc = heap_open(AttrDefaultRelationId, AccessShareLock);
01639
01640 ScanKeyInit(&skey[0],
01641 ObjectIdAttributeNumber,
01642 BTEqualStrategyNumber, F_OIDEQ,
01643 ObjectIdGetDatum(object->objectId));
01644
01645 adscan = systable_beginscan(attrdefDesc, AttrDefaultOidIndexId,
01646 true, SnapshotNow, 1, skey);
01647
01648 tup = systable_getnext(adscan);
01649
01650 if (!HeapTupleIsValid(tup))
01651 elog(ERROR, "could not find tuple for attrdef %u",
01652 object->objectId);
01653
01654 attrdef = (Form_pg_attrdef) GETSTRUCT(tup);
01655
01656 colobject.classId = RelationRelationId;
01657 colobject.objectId = attrdef->adrelid;
01658 colobject.objectSubId = attrdef->adnum;
01659
01660 appendStringInfo(&buffer, _("default for %s"),
01661 getObjectDescription(&colobject));
01662
01663 systable_endscan(adscan);
01664 heap_close(attrdefDesc, AccessShareLock);
01665 break;
01666 }
01667
01668 case OCLASS_LANGUAGE:
01669 {
01670 HeapTuple langTup;
01671
01672 langTup = SearchSysCache1(LANGOID,
01673 ObjectIdGetDatum(object->objectId));
01674 if (!HeapTupleIsValid(langTup))
01675 elog(ERROR, "cache lookup failed for language %u",
01676 object->objectId);
01677 appendStringInfo(&buffer, _("language %s"),
01678 NameStr(((Form_pg_language) GETSTRUCT(langTup))->lanname));
01679 ReleaseSysCache(langTup);
01680 break;
01681 }
01682 case OCLASS_LARGEOBJECT:
01683 appendStringInfo(&buffer, _("large object %u"),
01684 object->objectId);
01685 break;
01686
01687 case OCLASS_OPERATOR:
01688 appendStringInfo(&buffer, _("operator %s"),
01689 format_operator(object->objectId));
01690 break;
01691
01692 case OCLASS_OPCLASS:
01693 {
01694 HeapTuple opcTup;
01695 Form_pg_opclass opcForm;
01696 HeapTuple amTup;
01697 Form_pg_am amForm;
01698 char *nspname;
01699
01700 opcTup = SearchSysCache1(CLAOID,
01701 ObjectIdGetDatum(object->objectId));
01702 if (!HeapTupleIsValid(opcTup))
01703 elog(ERROR, "cache lookup failed for opclass %u",
01704 object->objectId);
01705 opcForm = (Form_pg_opclass) GETSTRUCT(opcTup);
01706
01707 amTup = SearchSysCache1(AMOID,
01708 ObjectIdGetDatum(opcForm->opcmethod));
01709 if (!HeapTupleIsValid(amTup))
01710 elog(ERROR, "cache lookup failed for access method %u",
01711 opcForm->opcmethod);
01712 amForm = (Form_pg_am) GETSTRUCT(amTup);
01713
01714
01715 if (OpclassIsVisible(object->objectId))
01716 nspname = NULL;
01717 else
01718 nspname = get_namespace_name(opcForm->opcnamespace);
01719
01720 appendStringInfo(&buffer, _("operator class %s for access method %s"),
01721 quote_qualified_identifier(nspname,
01722 NameStr(opcForm->opcname)),
01723 NameStr(amForm->amname));
01724
01725 ReleaseSysCache(amTup);
01726 ReleaseSysCache(opcTup);
01727 break;
01728 }
01729
01730 case OCLASS_OPFAMILY:
01731 getOpFamilyDescription(&buffer, object->objectId);
01732 break;
01733
01734 case OCLASS_AMOP:
01735 {
01736 Relation amopDesc;
01737 HeapTuple tup;
01738 ScanKeyData skey[1];
01739 SysScanDesc amscan;
01740 Form_pg_amop amopForm;
01741 StringInfoData opfam;
01742
01743 amopDesc = heap_open(AccessMethodOperatorRelationId,
01744 AccessShareLock);
01745
01746 ScanKeyInit(&skey[0],
01747 ObjectIdAttributeNumber,
01748 BTEqualStrategyNumber, F_OIDEQ,
01749 ObjectIdGetDatum(object->objectId));
01750
01751 amscan = systable_beginscan(amopDesc, AccessMethodOperatorOidIndexId, true,
01752 SnapshotNow, 1, skey);
01753
01754 tup = systable_getnext(amscan);
01755
01756 if (!HeapTupleIsValid(tup))
01757 elog(ERROR, "could not find tuple for amop entry %u",
01758 object->objectId);
01759
01760 amopForm = (Form_pg_amop) GETSTRUCT(tup);
01761
01762 initStringInfo(&opfam);
01763 getOpFamilyDescription(&opfam, amopForm->amopfamily);
01764
01765
01766
01767
01768
01769
01770 appendStringInfo(&buffer, _("operator %d (%s, %s) of %s: %s"),
01771 amopForm->amopstrategy,
01772 format_type_be(amopForm->amoplefttype),
01773 format_type_be(amopForm->amoprighttype),
01774 opfam.data,
01775 format_operator(amopForm->amopopr));
01776
01777 pfree(opfam.data);
01778
01779 systable_endscan(amscan);
01780 heap_close(amopDesc, AccessShareLock);
01781 break;
01782 }
01783
01784 case OCLASS_AMPROC:
01785 {
01786 Relation amprocDesc;
01787 ScanKeyData skey[1];
01788 SysScanDesc amscan;
01789 HeapTuple tup;
01790 Form_pg_amproc amprocForm;
01791 StringInfoData opfam;
01792
01793 amprocDesc = heap_open(AccessMethodProcedureRelationId,
01794 AccessShareLock);
01795
01796 ScanKeyInit(&skey[0],
01797 ObjectIdAttributeNumber,
01798 BTEqualStrategyNumber, F_OIDEQ,
01799 ObjectIdGetDatum(object->objectId));
01800
01801 amscan = systable_beginscan(amprocDesc, AccessMethodProcedureOidIndexId, true,
01802 SnapshotNow, 1, skey);
01803
01804 tup = systable_getnext(amscan);
01805
01806 if (!HeapTupleIsValid(tup))
01807 elog(ERROR, "could not find tuple for amproc entry %u",
01808 object->objectId);
01809
01810 amprocForm = (Form_pg_amproc) GETSTRUCT(tup);
01811
01812 initStringInfo(&opfam);
01813 getOpFamilyDescription(&opfam, amprocForm->amprocfamily);
01814
01815
01816
01817
01818
01819
01820 appendStringInfo(&buffer, _("function %d (%s, %s) of %s: %s"),
01821 amprocForm->amprocnum,
01822 format_type_be(amprocForm->amproclefttype),
01823 format_type_be(amprocForm->amprocrighttype),
01824 opfam.data,
01825 format_procedure(amprocForm->amproc));
01826
01827 pfree(opfam.data);
01828
01829 systable_endscan(amscan);
01830 heap_close(amprocDesc, AccessShareLock);
01831 break;
01832 }
01833
01834 case OCLASS_REWRITE:
01835 {
01836 Relation ruleDesc;
01837 ScanKeyData skey[1];
01838 SysScanDesc rcscan;
01839 HeapTuple tup;
01840 Form_pg_rewrite rule;
01841
01842 ruleDesc = heap_open(RewriteRelationId, AccessShareLock);
01843
01844 ScanKeyInit(&skey[0],
01845 ObjectIdAttributeNumber,
01846 BTEqualStrategyNumber, F_OIDEQ,
01847 ObjectIdGetDatum(object->objectId));
01848
01849 rcscan = systable_beginscan(ruleDesc, RewriteOidIndexId, true,
01850 SnapshotNow, 1, skey);
01851
01852 tup = systable_getnext(rcscan);
01853
01854 if (!HeapTupleIsValid(tup))
01855 elog(ERROR, "could not find tuple for rule %u",
01856 object->objectId);
01857
01858 rule = (Form_pg_rewrite) GETSTRUCT(tup);
01859
01860 appendStringInfo(&buffer, _("rule %s on "),
01861 NameStr(rule->rulename));
01862 getRelationDescription(&buffer, rule->ev_class);
01863
01864 systable_endscan(rcscan);
01865 heap_close(ruleDesc, AccessShareLock);
01866 break;
01867 }
01868
01869 case OCLASS_TRIGGER:
01870 {
01871 Relation trigDesc;
01872 ScanKeyData skey[1];
01873 SysScanDesc tgscan;
01874 HeapTuple tup;
01875 Form_pg_trigger trig;
01876
01877 trigDesc = heap_open(TriggerRelationId, AccessShareLock);
01878
01879 ScanKeyInit(&skey[0],
01880 ObjectIdAttributeNumber,
01881 BTEqualStrategyNumber, F_OIDEQ,
01882 ObjectIdGetDatum(object->objectId));
01883
01884 tgscan = systable_beginscan(trigDesc, TriggerOidIndexId, true,
01885 SnapshotNow, 1, skey);
01886
01887 tup = systable_getnext(tgscan);
01888
01889 if (!HeapTupleIsValid(tup))
01890 elog(ERROR, "could not find tuple for trigger %u",
01891 object->objectId);
01892
01893 trig = (Form_pg_trigger) GETSTRUCT(tup);
01894
01895 appendStringInfo(&buffer, _("trigger %s on "),
01896 NameStr(trig->tgname));
01897 getRelationDescription(&buffer, trig->tgrelid);
01898
01899 systable_endscan(tgscan);
01900 heap_close(trigDesc, AccessShareLock);
01901 break;
01902 }
01903
01904 case OCLASS_SCHEMA:
01905 {
01906 char *nspname;
01907
01908 nspname = get_namespace_name(object->objectId);
01909 if (!nspname)
01910 elog(ERROR, "cache lookup failed for namespace %u",
01911 object->objectId);
01912 appendStringInfo(&buffer, _("schema %s"), nspname);
01913 break;
01914 }
01915
01916 case OCLASS_TSPARSER:
01917 {
01918 HeapTuple tup;
01919
01920 tup = SearchSysCache1(TSPARSEROID,
01921 ObjectIdGetDatum(object->objectId));
01922 if (!HeapTupleIsValid(tup))
01923 elog(ERROR, "cache lookup failed for text search parser %u",
01924 object->objectId);
01925 appendStringInfo(&buffer, _("text search parser %s"),
01926 NameStr(((Form_pg_ts_parser) GETSTRUCT(tup))->prsname));
01927 ReleaseSysCache(tup);
01928 break;
01929 }
01930
01931 case OCLASS_TSDICT:
01932 {
01933 HeapTuple tup;
01934
01935 tup = SearchSysCache1(TSDICTOID,
01936 ObjectIdGetDatum(object->objectId));
01937 if (!HeapTupleIsValid(tup))
01938 elog(ERROR, "cache lookup failed for text search dictionary %u",
01939 object->objectId);
01940 appendStringInfo(&buffer, _("text search dictionary %s"),
01941 NameStr(((Form_pg_ts_dict) GETSTRUCT(tup))->dictname));
01942 ReleaseSysCache(tup);
01943 break;
01944 }
01945
01946 case OCLASS_TSTEMPLATE:
01947 {
01948 HeapTuple tup;
01949
01950 tup = SearchSysCache1(TSTEMPLATEOID,
01951 ObjectIdGetDatum(object->objectId));
01952 if (!HeapTupleIsValid(tup))
01953 elog(ERROR, "cache lookup failed for text search template %u",
01954 object->objectId);
01955 appendStringInfo(&buffer, _("text search template %s"),
01956 NameStr(((Form_pg_ts_template) GETSTRUCT(tup))->tmplname));
01957 ReleaseSysCache(tup);
01958 break;
01959 }
01960
01961 case OCLASS_TSCONFIG:
01962 {
01963 HeapTuple tup;
01964
01965 tup = SearchSysCache1(TSCONFIGOID,
01966 ObjectIdGetDatum(object->objectId));
01967 if (!HeapTupleIsValid(tup))
01968 elog(ERROR, "cache lookup failed for text search configuration %u",
01969 object->objectId);
01970 appendStringInfo(&buffer, _("text search configuration %s"),
01971 NameStr(((Form_pg_ts_config) GETSTRUCT(tup))->cfgname));
01972 ReleaseSysCache(tup);
01973 break;
01974 }
01975
01976 case OCLASS_ROLE:
01977 {
01978 appendStringInfo(&buffer, _("role %s"),
01979 GetUserNameFromId(object->objectId));
01980 break;
01981 }
01982
01983 case OCLASS_DATABASE:
01984 {
01985 char *datname;
01986
01987 datname = get_database_name(object->objectId);
01988 if (!datname)
01989 elog(ERROR, "cache lookup failed for database %u",
01990 object->objectId);
01991 appendStringInfo(&buffer, _("database %s"), datname);
01992 break;
01993 }
01994
01995 case OCLASS_TBLSPACE:
01996 {
01997 char *tblspace;
01998
01999 tblspace = get_tablespace_name(object->objectId);
02000 if (!tblspace)
02001 elog(ERROR, "cache lookup failed for tablespace %u",
02002 object->objectId);
02003 appendStringInfo(&buffer, _("tablespace %s"), tblspace);
02004 break;
02005 }
02006
02007 case OCLASS_FDW:
02008 {
02009 ForeignDataWrapper *fdw;
02010
02011 fdw = GetForeignDataWrapper(object->objectId);
02012 appendStringInfo(&buffer, _("foreign-data wrapper %s"), fdw->fdwname);
02013 break;
02014 }
02015
02016 case OCLASS_FOREIGN_SERVER:
02017 {
02018 ForeignServer *srv;
02019
02020 srv = GetForeignServer(object->objectId);
02021 appendStringInfo(&buffer, _("server %s"), srv->servername);
02022 break;
02023 }
02024
02025 case OCLASS_USER_MAPPING:
02026 {
02027 HeapTuple tup;
02028 Oid useid;
02029 char *usename;
02030
02031 tup = SearchSysCache1(USERMAPPINGOID,
02032 ObjectIdGetDatum(object->objectId));
02033 if (!HeapTupleIsValid(tup))
02034 elog(ERROR, "cache lookup failed for user mapping %u",
02035 object->objectId);
02036
02037 useid = ((Form_pg_user_mapping) GETSTRUCT(tup))->umuser;
02038
02039 ReleaseSysCache(tup);
02040
02041 if (OidIsValid(useid))
02042 usename = GetUserNameFromId(useid);
02043 else
02044 usename = "public";
02045
02046 appendStringInfo(&buffer, _("user mapping for %s"), usename);
02047 break;
02048 }
02049
02050 case OCLASS_DEFACL:
02051 {
02052 Relation defaclrel;
02053 ScanKeyData skey[1];
02054 SysScanDesc rcscan;
02055 HeapTuple tup;
02056 Form_pg_default_acl defacl;
02057
02058 defaclrel = heap_open(DefaultAclRelationId, AccessShareLock);
02059
02060 ScanKeyInit(&skey[0],
02061 ObjectIdAttributeNumber,
02062 BTEqualStrategyNumber, F_OIDEQ,
02063 ObjectIdGetDatum(object->objectId));
02064
02065 rcscan = systable_beginscan(defaclrel, DefaultAclOidIndexId,
02066 true, SnapshotNow, 1, skey);
02067
02068 tup = systable_getnext(rcscan);
02069
02070 if (!HeapTupleIsValid(tup))
02071 elog(ERROR, "could not find tuple for default ACL %u",
02072 object->objectId);
02073
02074 defacl = (Form_pg_default_acl) GETSTRUCT(tup);
02075
02076 switch (defacl->defaclobjtype)
02077 {
02078 case DEFACLOBJ_RELATION:
02079 appendStringInfo(&buffer,
02080 _("default privileges on new relations belonging to role %s"),
02081 GetUserNameFromId(defacl->defaclrole));
02082 break;
02083 case DEFACLOBJ_SEQUENCE:
02084 appendStringInfo(&buffer,
02085 _("default privileges on new sequences belonging to role %s"),
02086 GetUserNameFromId(defacl->defaclrole));
02087 break;
02088 case DEFACLOBJ_FUNCTION:
02089 appendStringInfo(&buffer,
02090 _("default privileges on new functions belonging to role %s"),
02091 GetUserNameFromId(defacl->defaclrole));
02092 break;
02093 case DEFACLOBJ_TYPE:
02094 appendStringInfo(&buffer,
02095 _("default privileges on new types belonging to role %s"),
02096 GetUserNameFromId(defacl->defaclrole));
02097 break;
02098 default:
02099
02100 appendStringInfo(&buffer,
02101 _("default privileges belonging to role %s"),
02102 GetUserNameFromId(defacl->defaclrole));
02103 break;
02104 }
02105
02106 if (OidIsValid(defacl->defaclnamespace))
02107 {
02108 appendStringInfo(&buffer,
02109 _(" in schema %s"),
02110 get_namespace_name(defacl->defaclnamespace));
02111 }
02112
02113 systable_endscan(rcscan);
02114 heap_close(defaclrel, AccessShareLock);
02115 break;
02116 }
02117
02118 case OCLASS_EXTENSION:
02119 {
02120 char *extname;
02121
02122 extname = get_extension_name(object->objectId);
02123 if (!extname)
02124 elog(ERROR, "cache lookup failed for extension %u",
02125 object->objectId);
02126 appendStringInfo(&buffer, _("extension %s"), extname);
02127 break;
02128 }
02129
02130 case OCLASS_EVENT_TRIGGER:
02131 {
02132 HeapTuple tup;
02133
02134 tup = SearchSysCache1(EVENTTRIGGEROID,
02135 ObjectIdGetDatum(object->objectId));
02136 if (!HeapTupleIsValid(tup))
02137 elog(ERROR, "cache lookup failed for event trigger %u",
02138 object->objectId);
02139 appendStringInfo(&buffer, _("event trigger %s"),
02140 NameStr(((Form_pg_event_trigger) GETSTRUCT(tup))->evtname));
02141 ReleaseSysCache(tup);
02142 break;
02143 }
02144
02145 default:
02146 appendStringInfo(&buffer, "unrecognized object %u %u %d",
02147 object->classId,
02148 object->objectId,
02149 object->objectSubId);
02150 break;
02151 }
02152
02153 return buffer.data;
02154 }
02155
02156
02157
02158
02159 char *
02160 getObjectDescriptionOids(Oid classid, Oid objid)
02161 {
02162 ObjectAddress address;
02163
02164 address.classId = classid;
02165 address.objectId = objid;
02166 address.objectSubId = 0;
02167
02168 return getObjectDescription(&address);
02169 }
02170
02171
02172
02173
02174 static void
02175 getRelationDescription(StringInfo buffer, Oid relid)
02176 {
02177 HeapTuple relTup;
02178 Form_pg_class relForm;
02179 char *nspname;
02180 char *relname;
02181
02182 relTup = SearchSysCache1(RELOID,
02183 ObjectIdGetDatum(relid));
02184 if (!HeapTupleIsValid(relTup))
02185 elog(ERROR, "cache lookup failed for relation %u", relid);
02186 relForm = (Form_pg_class) GETSTRUCT(relTup);
02187
02188
02189 if (RelationIsVisible(relid))
02190 nspname = NULL;
02191 else
02192 nspname = get_namespace_name(relForm->relnamespace);
02193
02194 relname = quote_qualified_identifier(nspname, NameStr(relForm->relname));
02195
02196 switch (relForm->relkind)
02197 {
02198 case RELKIND_RELATION:
02199 appendStringInfo(buffer, _("table %s"),
02200 relname);
02201 break;
02202 case RELKIND_INDEX:
02203 appendStringInfo(buffer, _("index %s"),
02204 relname);
02205 break;
02206 case RELKIND_SEQUENCE:
02207 appendStringInfo(buffer, _("sequence %s"),
02208 relname);
02209 break;
02210 case RELKIND_TOASTVALUE:
02211 appendStringInfo(buffer, _("toast table %s"),
02212 relname);
02213 break;
02214 case RELKIND_VIEW:
02215 appendStringInfo(buffer, _("view %s"),
02216 relname);
02217 break;
02218 case RELKIND_MATVIEW:
02219 appendStringInfo(buffer, _("materialized view %s"),
02220 relname);
02221 break;
02222 case RELKIND_COMPOSITE_TYPE:
02223 appendStringInfo(buffer, _("composite type %s"),
02224 relname);
02225 break;
02226 case RELKIND_FOREIGN_TABLE:
02227 appendStringInfo(buffer, _("foreign table %s"),
02228 relname);
02229 break;
02230 default:
02231
02232 appendStringInfo(buffer, _("relation %s"),
02233 relname);
02234 break;
02235 }
02236
02237 ReleaseSysCache(relTup);
02238 }
02239
02240
02241
02242
02243 static void
02244 getOpFamilyDescription(StringInfo buffer, Oid opfid)
02245 {
02246 HeapTuple opfTup;
02247 Form_pg_opfamily opfForm;
02248 HeapTuple amTup;
02249 Form_pg_am amForm;
02250 char *nspname;
02251
02252 opfTup = SearchSysCache1(OPFAMILYOID, ObjectIdGetDatum(opfid));
02253 if (!HeapTupleIsValid(opfTup))
02254 elog(ERROR, "cache lookup failed for opfamily %u", opfid);
02255 opfForm = (Form_pg_opfamily) GETSTRUCT(opfTup);
02256
02257 amTup = SearchSysCache1(AMOID, ObjectIdGetDatum(opfForm->opfmethod));
02258 if (!HeapTupleIsValid(amTup))
02259 elog(ERROR, "cache lookup failed for access method %u",
02260 opfForm->opfmethod);
02261 amForm = (Form_pg_am) GETSTRUCT(amTup);
02262
02263
02264 if (OpfamilyIsVisible(opfid))
02265 nspname = NULL;
02266 else
02267 nspname = get_namespace_name(opfForm->opfnamespace);
02268
02269 appendStringInfo(buffer, _("operator family %s for access method %s"),
02270 quote_qualified_identifier(nspname,
02271 NameStr(opfForm->opfname)),
02272 NameStr(amForm->amname));
02273
02274 ReleaseSysCache(amTup);
02275 ReleaseSysCache(opfTup);
02276 }
02277
02278
02279
02280
02281 Datum
02282 pg_describe_object(PG_FUNCTION_ARGS)
02283 {
02284 Oid classid = PG_GETARG_OID(0);
02285 Oid objid = PG_GETARG_OID(1);
02286 int32 subobjid = PG_GETARG_INT32(2);
02287 char *description;
02288 ObjectAddress address;
02289
02290
02291 if (!OidIsValid(classid) && !OidIsValid(objid))
02292 PG_RETURN_NULL();
02293
02294 address.classId = classid;
02295 address.objectId = objid;
02296 address.objectSubId = subobjid;
02297
02298 description = getObjectDescription(&address);
02299 PG_RETURN_TEXT_P(cstring_to_text(description));
02300 }
02301
02302
02303
02304
02305 Datum
02306 pg_identify_object(PG_FUNCTION_ARGS)
02307 {
02308 Oid classid = PG_GETARG_OID(0);
02309 Oid objid = PG_GETARG_OID(1);
02310 int32 subobjid = PG_GETARG_INT32(2);
02311 Oid schema_oid = InvalidOid;
02312 const char *objname = NULL;
02313 ObjectAddress address;
02314 Datum values[4];
02315 bool nulls[4];
02316 TupleDesc tupdesc;
02317 HeapTuple htup;
02318
02319 address.classId = classid;
02320 address.objectId = objid;
02321 address.objectSubId = subobjid;
02322
02323
02324
02325
02326
02327 tupdesc = CreateTemplateTupleDesc(4, false);
02328 TupleDescInitEntry(tupdesc, (AttrNumber) 1, "type",
02329 TEXTOID, -1, 0);
02330 TupleDescInitEntry(tupdesc, (AttrNumber) 2, "schema",
02331 TEXTOID, -1, 0);
02332 TupleDescInitEntry(tupdesc, (AttrNumber) 3, "name",
02333 TEXTOID, -1, 0);
02334 TupleDescInitEntry(tupdesc, (AttrNumber) 4, "identity",
02335 TEXTOID, -1, 0);
02336
02337 tupdesc = BlessTupleDesc(tupdesc);
02338
02339 if (is_objectclass_supported(address.classId))
02340 {
02341 HeapTuple objtup;
02342 Relation catalog = heap_open(address.classId, AccessShareLock);
02343
02344 objtup = get_catalog_object_by_oid(catalog, address.objectId);
02345 if (objtup != NULL)
02346 {
02347 bool isnull;
02348 AttrNumber nspAttnum;
02349 AttrNumber nameAttnum;
02350
02351 nspAttnum = get_object_attnum_namespace(address.classId);
02352 if (nspAttnum != InvalidAttrNumber)
02353 {
02354 schema_oid = heap_getattr(objtup, nspAttnum,
02355 RelationGetDescr(catalog), &isnull);
02356 if (isnull)
02357 elog(ERROR, "invalid null namespace in object %u/%u/%d",
02358 address.classId, address.objectId, address.objectSubId);
02359 }
02360
02361
02362
02363
02364
02365 if (get_object_namensp_unique(address.classId))
02366 {
02367 nameAttnum = get_object_attnum_name(address.classId);
02368 if (nameAttnum != InvalidAttrNumber)
02369 {
02370 Datum nameDatum;
02371
02372 nameDatum = heap_getattr(objtup, nameAttnum,
02373 RelationGetDescr(catalog), &isnull);
02374 if (isnull)
02375 elog(ERROR, "invalid null name in object %u/%u/%d",
02376 address.classId, address.objectId, address.objectSubId);
02377 objname = quote_identifier(NameStr(*(DatumGetName(nameDatum))));
02378 }
02379 }
02380 }
02381
02382 heap_close(catalog, AccessShareLock);
02383 }
02384
02385
02386 values[0] = CStringGetTextDatum(getObjectTypeDescription(&address));
02387 nulls[0] = false;
02388
02389
02390 if (OidIsValid(schema_oid))
02391 {
02392 const char *schema = quote_identifier(get_namespace_name(schema_oid));
02393
02394 values[1] = CStringGetTextDatum(schema);
02395 nulls[1] = false;
02396 }
02397 else
02398 nulls[1] = true;
02399
02400
02401 if (objname)
02402 {
02403 values[2] = CStringGetTextDatum(objname);
02404 nulls[2] = false;
02405 }
02406 else
02407 nulls[2] = true;
02408
02409
02410 values[3] = CStringGetTextDatum(getObjectIdentity(&address));
02411 nulls[3] = false;
02412
02413 htup = heap_form_tuple(tupdesc, values, nulls);
02414
02415 PG_RETURN_DATUM(HeapTupleGetDatum(htup));
02416 }
02417
02418
02419
02420
02421
02422 char *
02423 getObjectTypeDescription(const ObjectAddress *object)
02424 {
02425 StringInfoData buffer;
02426
02427 initStringInfo(&buffer);
02428
02429 switch (getObjectClass(object))
02430 {
02431 case OCLASS_CLASS:
02432 getRelationTypeDescription(&buffer, object->objectId,
02433 object->objectSubId);
02434 break;
02435
02436 case OCLASS_PROC:
02437 getProcedureTypeDescription(&buffer, object->objectId);
02438 break;
02439
02440 case OCLASS_TYPE:
02441 appendStringInfo(&buffer, "type");
02442 break;
02443
02444 case OCLASS_CAST:
02445 appendStringInfo(&buffer, "cast");
02446 break;
02447
02448 case OCLASS_COLLATION:
02449 appendStringInfo(&buffer, "collation");
02450 break;
02451
02452 case OCLASS_CONSTRAINT:
02453 getConstraintTypeDescription(&buffer, object->objectId);
02454 break;
02455
02456 case OCLASS_CONVERSION:
02457 appendStringInfo(&buffer, "conversion");
02458 break;
02459
02460 case OCLASS_DEFAULT:
02461 appendStringInfo(&buffer, "default value");
02462 break;
02463
02464 case OCLASS_LANGUAGE:
02465 appendStringInfo(&buffer, "language");
02466 break;
02467
02468 case OCLASS_LARGEOBJECT:
02469 appendStringInfo(&buffer, "large object");
02470 break;
02471
02472 case OCLASS_OPERATOR:
02473 appendStringInfo(&buffer, "operator");
02474 break;
02475
02476 case OCLASS_OPCLASS:
02477 appendStringInfo(&buffer, "operator class");
02478 break;
02479
02480 case OCLASS_OPFAMILY:
02481 appendStringInfo(&buffer, "operator family");
02482 break;
02483
02484 case OCLASS_AMOP:
02485 appendStringInfo(&buffer, "operator of access method");
02486 break;
02487
02488 case OCLASS_AMPROC:
02489 appendStringInfo(&buffer, "function of access method");
02490 break;
02491
02492 case OCLASS_REWRITE:
02493 appendStringInfo(&buffer, "rule");
02494 break;
02495
02496 case OCLASS_TRIGGER:
02497 appendStringInfo(&buffer, "trigger");
02498 break;
02499
02500 case OCLASS_SCHEMA:
02501 appendStringInfo(&buffer, "schema");
02502 break;
02503
02504 case OCLASS_TSPARSER:
02505 appendStringInfo(&buffer, "text search parser");
02506 break;
02507
02508 case OCLASS_TSDICT:
02509 appendStringInfo(&buffer, "text search dictionary");
02510 break;
02511
02512 case OCLASS_TSTEMPLATE:
02513 appendStringInfo(&buffer, "text search template");
02514 break;
02515
02516 case OCLASS_TSCONFIG:
02517 appendStringInfo(&buffer, "text search configuration");
02518 break;
02519
02520 case OCLASS_ROLE:
02521 appendStringInfo(&buffer, "role");
02522 break;
02523
02524 case OCLASS_DATABASE:
02525 appendStringInfo(&buffer, "database");
02526 break;
02527
02528 case OCLASS_TBLSPACE:
02529 appendStringInfo(&buffer, "tablespace");
02530 break;
02531
02532 case OCLASS_FDW:
02533 appendStringInfo(&buffer, "foreign-data wrapper");
02534 break;
02535
02536 case OCLASS_FOREIGN_SERVER:
02537 appendStringInfo(&buffer, "server");
02538 break;
02539
02540 case OCLASS_USER_MAPPING:
02541 appendStringInfo(&buffer, "user mapping");
02542 break;
02543
02544 case OCLASS_DEFACL:
02545 appendStringInfo(&buffer, "default acl");
02546 break;
02547
02548 case OCLASS_EXTENSION:
02549 appendStringInfo(&buffer, "extension");
02550 break;
02551
02552 case OCLASS_EVENT_TRIGGER:
02553 appendStringInfo(&buffer, "event trigger");
02554 break;
02555
02556 default:
02557 appendStringInfo(&buffer, "unrecognized %u", object->classId);
02558 break;
02559 }
02560
02561 return buffer.data;
02562 }
02563
02564
02565
02566
02567 static void
02568 getRelationTypeDescription(StringInfo buffer, Oid relid, int32 objectSubId)
02569 {
02570 HeapTuple relTup;
02571 Form_pg_class relForm;
02572
02573 relTup = SearchSysCache1(RELOID,
02574 ObjectIdGetDatum(relid));
02575 if (!HeapTupleIsValid(relTup))
02576 elog(ERROR, "cache lookup failed for relation %u", relid);
02577 relForm = (Form_pg_class) GETSTRUCT(relTup);
02578
02579 switch (relForm->relkind)
02580 {
02581 case RELKIND_RELATION:
02582 appendStringInfo(buffer, "table");
02583 break;
02584 case RELKIND_INDEX:
02585 appendStringInfo(buffer, "index");
02586 break;
02587 case RELKIND_SEQUENCE:
02588 appendStringInfo(buffer, "sequence");
02589 break;
02590 case RELKIND_TOASTVALUE:
02591 appendStringInfo(buffer, "toast table");
02592 break;
02593 case RELKIND_VIEW:
02594 appendStringInfo(buffer, "view");
02595 break;
02596 case RELKIND_MATVIEW:
02597 appendStringInfo(buffer, "materialized view");
02598 break;
02599 case RELKIND_COMPOSITE_TYPE:
02600 appendStringInfo(buffer, "composite type");
02601 break;
02602 case RELKIND_FOREIGN_TABLE:
02603 appendStringInfo(buffer, "foreign table");
02604 break;
02605 default:
02606
02607 appendStringInfo(buffer, "relation");
02608 break;
02609 }
02610
02611 if (objectSubId != 0)
02612 appendStringInfo(buffer, " column");
02613
02614 ReleaseSysCache(relTup);
02615 }
02616
02617
02618
02619
02620 static void
02621 getConstraintTypeDescription(StringInfo buffer, Oid constroid)
02622 {
02623 Relation constrRel;
02624 HeapTuple constrTup;
02625 Form_pg_constraint constrForm;
02626
02627 constrRel = heap_open(ConstraintRelationId, AccessShareLock);
02628 constrTup = get_catalog_object_by_oid(constrRel, constroid);
02629 if (!HeapTupleIsValid(constrTup))
02630 elog(ERROR, "cache lookup failed for constraint %u", constroid);
02631
02632 constrForm = (Form_pg_constraint) GETSTRUCT(constrTup);
02633
02634 if (OidIsValid(constrForm->conrelid))
02635 appendStringInfoString(buffer, "table constraint");
02636 else if (OidIsValid(constrForm->contypid))
02637 appendStringInfoString(buffer, "domain constraint");
02638 else
02639 elog(ERROR, "invalid constraint %u", HeapTupleGetOid(constrTup));
02640
02641 heap_close(constrRel, AccessShareLock);
02642 }
02643
02644
02645
02646
02647 static void
02648 getProcedureTypeDescription(StringInfo buffer, Oid procid)
02649 {
02650 HeapTuple procTup;
02651 Form_pg_proc procForm;
02652
02653 procTup = SearchSysCache1(PROCOID,
02654 ObjectIdGetDatum(procid));
02655 if (!HeapTupleIsValid(procTup))
02656 elog(ERROR, "cache lookup failed for procedure %u", procid);
02657 procForm = (Form_pg_proc) GETSTRUCT(procTup);
02658
02659 if (procForm->proisagg)
02660 appendStringInfo(buffer, "aggregate");
02661 else
02662 appendStringInfo(buffer, "function");
02663
02664 ReleaseSysCache(procTup);
02665 }
02666
02667
02668
02669
02670
02671
02672
02673 char *
02674 getObjectIdentity(const ObjectAddress *object)
02675 {
02676 StringInfoData buffer;
02677
02678 initStringInfo(&buffer);
02679
02680 switch (getObjectClass(object))
02681 {
02682 case OCLASS_CLASS:
02683 getRelationIdentity(&buffer, object->objectId);
02684 if (object->objectSubId != 0)
02685 {
02686 char *attr;
02687
02688 attr = get_relid_attribute_name(object->objectId,
02689 object->objectSubId);
02690 appendStringInfo(&buffer, ".%s", quote_identifier(attr));
02691 }
02692 break;
02693
02694 case OCLASS_PROC:
02695 appendStringInfo(&buffer, "%s",
02696 format_procedure_qualified(object->objectId));
02697 break;
02698
02699 case OCLASS_TYPE:
02700 appendStringInfo(&buffer, "%s",
02701 format_type_be_qualified(object->objectId));
02702 break;
02703
02704 case OCLASS_CAST:
02705 {
02706 Relation castRel;
02707 HeapTuple tup;
02708 Form_pg_cast castForm;
02709
02710 castRel = heap_open(CastRelationId, AccessShareLock);
02711
02712 tup = get_catalog_object_by_oid(castRel, object->objectId);
02713
02714 if (!HeapTupleIsValid(tup))
02715 elog(ERROR, "could not find tuple for cast %u",
02716 object->objectId);
02717
02718 castForm = (Form_pg_cast) GETSTRUCT(tup);
02719
02720 appendStringInfo(&buffer, "(%s AS %s)",
02721 format_type_be_qualified(castForm->castsource),
02722 format_type_be_qualified(castForm->casttarget));
02723
02724 heap_close(castRel, AccessShareLock);
02725 break;
02726 }
02727
02728 case OCLASS_COLLATION:
02729 {
02730 HeapTuple collTup;
02731 Form_pg_collation coll;
02732 char *schema;
02733
02734 collTup = SearchSysCache1(COLLOID,
02735 ObjectIdGetDatum(object->objectId));
02736 if (!HeapTupleIsValid(collTup))
02737 elog(ERROR, "cache lookup failed for collation %u",
02738 object->objectId);
02739 coll = (Form_pg_collation) GETSTRUCT(collTup);
02740 schema = get_namespace_name(coll->collnamespace);
02741 appendStringInfoString(&buffer,
02742 quote_qualified_identifier(schema,
02743 NameStr(coll->collname)));
02744 ReleaseSysCache(collTup);
02745 break;
02746 }
02747
02748 case OCLASS_CONSTRAINT:
02749 {
02750 HeapTuple conTup;
02751 Form_pg_constraint con;
02752
02753 conTup = SearchSysCache1(CONSTROID,
02754 ObjectIdGetDatum(object->objectId));
02755 if (!HeapTupleIsValid(conTup))
02756 elog(ERROR, "cache lookup failed for constraint %u",
02757 object->objectId);
02758 con = (Form_pg_constraint) GETSTRUCT(conTup);
02759
02760 if (OidIsValid(con->conrelid))
02761 {
02762 appendStringInfo(&buffer, "%s on ",
02763 quote_identifier(NameStr(con->conname)));
02764 getRelationIdentity(&buffer, con->conrelid);
02765 }
02766 else
02767 {
02768 ObjectAddress domain;
02769
02770 domain.classId = TypeRelationId;
02771 domain.objectId = con->contypid;
02772 domain.objectSubId = 0;
02773
02774 appendStringInfo(&buffer, "%s on %s",
02775 quote_identifier(NameStr(con->conname)),
02776 getObjectIdentity(&domain));
02777 }
02778
02779 ReleaseSysCache(conTup);
02780 break;
02781 }
02782
02783 case OCLASS_CONVERSION:
02784 {
02785 HeapTuple conTup;
02786 Form_pg_conversion conForm;
02787
02788 conTup = SearchSysCache1(CONVOID,
02789 ObjectIdGetDatum(object->objectId));
02790 if (!HeapTupleIsValid(conTup))
02791 elog(ERROR, "cache lookup failed for conversion %u",
02792 object->objectId);
02793 conForm = (Form_pg_conversion) GETSTRUCT(conTup);
02794 appendStringInfo(&buffer, "%s",
02795 quote_identifier(NameStr(conForm->conname)));
02796 ReleaseSysCache(conTup);
02797 break;
02798 }
02799
02800 case OCLASS_DEFAULT:
02801 {
02802 Relation attrdefDesc;
02803 ScanKeyData skey[1];
02804 SysScanDesc adscan;
02805
02806 HeapTuple tup;
02807 Form_pg_attrdef attrdef;
02808 ObjectAddress colobject;
02809
02810 attrdefDesc = heap_open(AttrDefaultRelationId, AccessShareLock);
02811
02812 ScanKeyInit(&skey[0],
02813 ObjectIdAttributeNumber,
02814 BTEqualStrategyNumber, F_OIDEQ,
02815 ObjectIdGetDatum(object->objectId));
02816
02817 adscan = systable_beginscan(attrdefDesc, AttrDefaultOidIndexId,
02818 true, SnapshotNow, 1, skey);
02819
02820 tup = systable_getnext(adscan);
02821
02822 if (!HeapTupleIsValid(tup))
02823 elog(ERROR, "could not find tuple for attrdef %u",
02824 object->objectId);
02825
02826 attrdef = (Form_pg_attrdef) GETSTRUCT(tup);
02827
02828 colobject.classId = RelationRelationId;
02829 colobject.objectId = attrdef->adrelid;
02830 colobject.objectSubId = attrdef->adnum;
02831
02832 appendStringInfo(&buffer, "for %s",
02833 getObjectIdentity(&colobject));
02834
02835 systable_endscan(adscan);
02836 heap_close(attrdefDesc, AccessShareLock);
02837 break;
02838 }
02839
02840 case OCLASS_LANGUAGE:
02841 {
02842 HeapTuple langTup;
02843 Form_pg_language langForm;
02844
02845 langTup = SearchSysCache1(LANGOID,
02846 ObjectIdGetDatum(object->objectId));
02847 if (!HeapTupleIsValid(langTup))
02848 elog(ERROR, "cache lookup failed for language %u",
02849 object->objectId);
02850 langForm = (Form_pg_language) GETSTRUCT(langTup);
02851 appendStringInfo(&buffer, "%s",
02852 quote_identifier(NameStr(langForm->lanname)));
02853 ReleaseSysCache(langTup);
02854 break;
02855 }
02856 case OCLASS_LARGEOBJECT:
02857 appendStringInfo(&buffer, "%u",
02858 object->objectId);
02859 break;
02860
02861 case OCLASS_OPERATOR:
02862 appendStringInfo(&buffer, "%s",
02863 format_operator_qualified(object->objectId));
02864 break;
02865
02866 case OCLASS_OPCLASS:
02867 {
02868 HeapTuple opcTup;
02869 Form_pg_opclass opcForm;
02870 HeapTuple amTup;
02871 Form_pg_am amForm;
02872 char *schema;
02873
02874 opcTup = SearchSysCache1(CLAOID,
02875 ObjectIdGetDatum(object->objectId));
02876 if (!HeapTupleIsValid(opcTup))
02877 elog(ERROR, "cache lookup failed for opclass %u",
02878 object->objectId);
02879 opcForm = (Form_pg_opclass) GETSTRUCT(opcTup);
02880 schema = get_namespace_name(opcForm->opcnamespace);
02881
02882 amTup = SearchSysCache1(AMOID,
02883 ObjectIdGetDatum(opcForm->opcmethod));
02884 if (!HeapTupleIsValid(amTup))
02885 elog(ERROR, "cache lookup failed for access method %u",
02886 opcForm->opcmethod);
02887 amForm = (Form_pg_am) GETSTRUCT(amTup);
02888
02889 appendStringInfo(&buffer,
02890 "%s",
02891 quote_qualified_identifier(schema,
02892 NameStr(opcForm->opcname)));
02893 appendStringInfo(&buffer, " for %s",
02894 quote_identifier(NameStr(amForm->amname)));
02895
02896 ReleaseSysCache(amTup);
02897 ReleaseSysCache(opcTup);
02898 break;
02899 }
02900
02901 case OCLASS_OPFAMILY:
02902 getOpFamilyIdentity(&buffer, object->objectId);
02903 break;
02904
02905 case OCLASS_AMOP:
02906 {
02907 Relation amopDesc;
02908 HeapTuple tup;
02909 ScanKeyData skey[1];
02910 SysScanDesc amscan;
02911 Form_pg_amop amopForm;
02912 StringInfoData opfam;
02913
02914 amopDesc = heap_open(AccessMethodOperatorRelationId,
02915 AccessShareLock);
02916
02917 ScanKeyInit(&skey[0],
02918 ObjectIdAttributeNumber,
02919 BTEqualStrategyNumber, F_OIDEQ,
02920 ObjectIdGetDatum(object->objectId));
02921
02922 amscan = systable_beginscan(amopDesc, AccessMethodOperatorOidIndexId, true,
02923 SnapshotNow, 1, skey);
02924
02925 tup = systable_getnext(amscan);
02926
02927 if (!HeapTupleIsValid(tup))
02928 elog(ERROR, "could not find tuple for amop entry %u",
02929 object->objectId);
02930
02931 amopForm = (Form_pg_amop) GETSTRUCT(tup);
02932
02933 initStringInfo(&opfam);
02934 getOpFamilyIdentity(&opfam, amopForm->amopfamily);
02935
02936 appendStringInfo(&buffer, "operator %d (%s, %s) of %s",
02937 amopForm->amopstrategy,
02938 format_type_be_qualified(amopForm->amoplefttype),
02939 format_type_be_qualified(amopForm->amoprighttype),
02940 opfam.data);
02941
02942 pfree(opfam.data);
02943
02944 systable_endscan(amscan);
02945 heap_close(amopDesc, AccessShareLock);
02946 break;
02947 }
02948
02949 case OCLASS_AMPROC:
02950 {
02951 Relation amprocDesc;
02952 ScanKeyData skey[1];
02953 SysScanDesc amscan;
02954 HeapTuple tup;
02955 Form_pg_amproc amprocForm;
02956 StringInfoData opfam;
02957
02958 amprocDesc = heap_open(AccessMethodProcedureRelationId,
02959 AccessShareLock);
02960
02961 ScanKeyInit(&skey[0],
02962 ObjectIdAttributeNumber,
02963 BTEqualStrategyNumber, F_OIDEQ,
02964 ObjectIdGetDatum(object->objectId));
02965
02966 amscan = systable_beginscan(amprocDesc, AccessMethodProcedureOidIndexId, true,
02967 SnapshotNow, 1, skey);
02968
02969 tup = systable_getnext(amscan);
02970
02971 if (!HeapTupleIsValid(tup))
02972 elog(ERROR, "could not find tuple for amproc entry %u",
02973 object->objectId);
02974
02975 amprocForm = (Form_pg_amproc) GETSTRUCT(tup);
02976
02977 initStringInfo(&opfam);
02978 getOpFamilyIdentity(&opfam, amprocForm->amprocfamily);
02979
02980 appendStringInfo(&buffer, "function %d (%s, %s) of %s",
02981 amprocForm->amprocnum,
02982 format_type_be_qualified(amprocForm->amproclefttype),
02983 format_type_be_qualified(amprocForm->amprocrighttype),
02984 opfam.data);
02985
02986 pfree(opfam.data);
02987
02988 systable_endscan(amscan);
02989 heap_close(amprocDesc, AccessShareLock);
02990 break;
02991 }
02992
02993 case OCLASS_REWRITE:
02994 {
02995 Relation ruleDesc;
02996 HeapTuple tup;
02997 Form_pg_rewrite rule;
02998
02999 ruleDesc = heap_open(RewriteRelationId, AccessShareLock);
03000
03001 tup = get_catalog_object_by_oid(ruleDesc, object->objectId);
03002
03003 if (!HeapTupleIsValid(tup))
03004 elog(ERROR, "could not find tuple for rule %u",
03005 object->objectId);
03006
03007 rule = (Form_pg_rewrite) GETSTRUCT(tup);
03008
03009 appendStringInfo(&buffer, "%s on ",
03010 quote_identifier(NameStr(rule->rulename)));
03011 getRelationIdentity(&buffer, rule->ev_class);
03012
03013 heap_close(ruleDesc, AccessShareLock);
03014 break;
03015 }
03016
03017 case OCLASS_TRIGGER:
03018 {
03019 Relation trigDesc;
03020 HeapTuple tup;
03021 Form_pg_trigger trig;
03022
03023 trigDesc = heap_open(TriggerRelationId, AccessShareLock);
03024
03025 tup = get_catalog_object_by_oid(trigDesc, object->objectId);
03026
03027 if (!HeapTupleIsValid(tup))
03028 elog(ERROR, "could not find tuple for trigger %u",
03029 object->objectId);
03030
03031 trig = (Form_pg_trigger) GETSTRUCT(tup);
03032
03033 appendStringInfo(&buffer, "%s on ",
03034 quote_identifier(NameStr(trig->tgname)));
03035 getRelationIdentity(&buffer, trig->tgrelid);
03036
03037 heap_close(trigDesc, AccessShareLock);
03038 break;
03039 }
03040
03041 case OCLASS_SCHEMA:
03042 {
03043 char *nspname;
03044
03045 nspname = get_namespace_name(object->objectId);
03046 if (!nspname)
03047 elog(ERROR, "cache lookup failed for namespace %u",
03048 object->objectId);
03049 appendStringInfo(&buffer, "%s",
03050 quote_identifier(nspname));
03051 break;
03052 }
03053
03054 case OCLASS_TSPARSER:
03055 {
03056 HeapTuple tup;
03057 Form_pg_ts_parser formParser;
03058
03059 tup = SearchSysCache1(TSPARSEROID,
03060 ObjectIdGetDatum(object->objectId));
03061 if (!HeapTupleIsValid(tup))
03062 elog(ERROR, "cache lookup failed for text search parser %u",
03063 object->objectId);
03064 formParser = (Form_pg_ts_parser) GETSTRUCT(tup);
03065 appendStringInfo(&buffer, "%s",
03066 quote_identifier(NameStr(formParser->prsname)));
03067 ReleaseSysCache(tup);
03068 break;
03069 }
03070
03071 case OCLASS_TSDICT:
03072 {
03073 HeapTuple tup;
03074 Form_pg_ts_dict formDict;
03075
03076 tup = SearchSysCache1(TSDICTOID,
03077 ObjectIdGetDatum(object->objectId));
03078 if (!HeapTupleIsValid(tup))
03079 elog(ERROR, "cache lookup failed for text search dictionary %u",
03080 object->objectId);
03081 formDict = (Form_pg_ts_dict) GETSTRUCT(tup);
03082 appendStringInfo(&buffer, "%s",
03083 quote_identifier(NameStr(formDict->dictname)));
03084 ReleaseSysCache(tup);
03085 break;
03086 }
03087
03088 case OCLASS_TSTEMPLATE:
03089 {
03090 HeapTuple tup;
03091 Form_pg_ts_template formTmpl;
03092
03093 tup = SearchSysCache1(TSTEMPLATEOID,
03094 ObjectIdGetDatum(object->objectId));
03095 if (!HeapTupleIsValid(tup))
03096 elog(ERROR, "cache lookup failed for text search template %u",
03097 object->objectId);
03098 formTmpl = (Form_pg_ts_template) GETSTRUCT(tup);
03099 appendStringInfo(&buffer, "%s",
03100 quote_identifier(NameStr(formTmpl->tmplname)));
03101 ReleaseSysCache(tup);
03102 break;
03103 }
03104
03105 case OCLASS_TSCONFIG:
03106 {
03107 HeapTuple tup;
03108 Form_pg_ts_config formCfg;
03109
03110 tup = SearchSysCache1(TSCONFIGOID,
03111 ObjectIdGetDatum(object->objectId));
03112 if (!HeapTupleIsValid(tup))
03113 elog(ERROR, "cache lookup failed for text search configuration %u",
03114 object->objectId);
03115 formCfg = (Form_pg_ts_config) GETSTRUCT(tup);
03116 appendStringInfo(&buffer, "%s",
03117 quote_identifier(NameStr(formCfg->cfgname)));
03118 ReleaseSysCache(tup);
03119 break;
03120 }
03121
03122 case OCLASS_ROLE:
03123 {
03124 char *username;
03125
03126 username = GetUserNameFromId(object->objectId);
03127 appendStringInfo(&buffer, "%s",
03128 quote_identifier(username));
03129 break;
03130 }
03131
03132 case OCLASS_DATABASE:
03133 {
03134 char *datname;
03135
03136 datname = get_database_name(object->objectId);
03137 if (!datname)
03138 elog(ERROR, "cache lookup failed for database %u",
03139 object->objectId);
03140 appendStringInfo(&buffer, "%s",
03141 quote_identifier(datname));
03142 break;
03143 }
03144
03145 case OCLASS_TBLSPACE:
03146 {
03147 char *tblspace;
03148
03149 tblspace = get_tablespace_name(object->objectId);
03150 if (!tblspace)
03151 elog(ERROR, "cache lookup failed for tablespace %u",
03152 object->objectId);
03153 appendStringInfo(&buffer, "%s",
03154 quote_identifier(tblspace));
03155 break;
03156 }
03157
03158 case OCLASS_FDW:
03159 {
03160 ForeignDataWrapper *fdw;
03161
03162 fdw = GetForeignDataWrapper(object->objectId);
03163 appendStringInfo(&buffer, "%s",
03164 quote_identifier(fdw->fdwname));
03165 break;
03166 }
03167
03168 case OCLASS_FOREIGN_SERVER:
03169 {
03170 ForeignServer *srv;
03171
03172 srv = GetForeignServer(object->objectId);
03173 appendStringInfo(&buffer, "%s",
03174 quote_identifier(srv->servername));
03175 break;
03176 }
03177
03178 case OCLASS_USER_MAPPING:
03179 {
03180 HeapTuple tup;
03181 Oid useid;
03182 const char *usename;
03183
03184 tup = SearchSysCache1(USERMAPPINGOID,
03185 ObjectIdGetDatum(object->objectId));
03186 if (!HeapTupleIsValid(tup))
03187 elog(ERROR, "cache lookup failed for user mapping %u",
03188 object->objectId);
03189
03190 useid = ((Form_pg_user_mapping) GETSTRUCT(tup))->umuser;
03191
03192 ReleaseSysCache(tup);
03193
03194 if (OidIsValid(useid))
03195 usename = quote_identifier(GetUserNameFromId(useid));
03196 else
03197 usename = "public";
03198
03199 appendStringInfo(&buffer, "%s", usename);
03200 break;
03201 }
03202
03203 case OCLASS_DEFACL:
03204 {
03205 Relation defaclrel;
03206 ScanKeyData skey[1];
03207 SysScanDesc rcscan;
03208
03209 HeapTuple tup;
03210 Form_pg_default_acl defacl;
03211
03212 defaclrel = heap_open(DefaultAclRelationId, AccessShareLock);
03213
03214 ScanKeyInit(&skey[0],
03215 ObjectIdAttributeNumber,
03216 BTEqualStrategyNumber, F_OIDEQ,
03217 ObjectIdGetDatum(object->objectId));
03218
03219 rcscan = systable_beginscan(defaclrel, DefaultAclOidIndexId,
03220 true, SnapshotNow, 1, skey);
03221
03222 tup = systable_getnext(rcscan);
03223
03224 if (!HeapTupleIsValid(tup))
03225 elog(ERROR, "could not find tuple for default ACL %u",
03226 object->objectId);
03227
03228 defacl = (Form_pg_default_acl) GETSTRUCT(tup);
03229
03230 appendStringInfo(&buffer,
03231 "for role %s",
03232 quote_identifier(GetUserNameFromId(defacl->defaclrole)));
03233
03234 if (OidIsValid(defacl->defaclnamespace))
03235 {
03236 char *schema;
03237
03238 schema = get_namespace_name(defacl->defaclnamespace);
03239 appendStringInfo(&buffer,
03240 " in schema %s",
03241 quote_identifier(schema));
03242 }
03243
03244 switch (defacl->defaclobjtype)
03245 {
03246 case DEFACLOBJ_RELATION:
03247 appendStringInfoString(&buffer,
03248 " on tables");
03249 break;
03250 case DEFACLOBJ_SEQUENCE:
03251 appendStringInfoString(&buffer,
03252 " on sequences");
03253 break;
03254 case DEFACLOBJ_FUNCTION:
03255 appendStringInfoString(&buffer,
03256 " on functions");
03257 break;
03258 case DEFACLOBJ_TYPE:
03259 appendStringInfoString(&buffer,
03260 " on types");
03261 break;
03262 }
03263
03264 systable_endscan(rcscan);
03265 heap_close(defaclrel, AccessShareLock);
03266 break;
03267 }
03268
03269 case OCLASS_EXTENSION:
03270 {
03271 char *extname;
03272
03273 extname = get_extension_name(object->objectId);
03274 if (!extname)
03275 elog(ERROR, "cache lookup failed for extension %u",
03276 object->objectId);
03277 appendStringInfo(&buffer, "%s",
03278 quote_identifier(extname));
03279 break;
03280 }
03281
03282 case OCLASS_EVENT_TRIGGER:
03283 {
03284 HeapTuple tup;
03285 Form_pg_event_trigger trigForm;
03286
03287 tup = SearchSysCache1(EVENTTRIGGEROID,
03288 ObjectIdGetDatum(object->objectId));
03289 if (!HeapTupleIsValid(tup))
03290 elog(ERROR, "cache lookup failed for event trigger %u",
03291 object->objectId);
03292 trigForm = (Form_pg_event_trigger) GETSTRUCT(tup);
03293 appendStringInfo(&buffer, "%s",
03294 quote_identifier(NameStr(trigForm->evtname)));
03295 ReleaseSysCache(tup);
03296 break;
03297 }
03298
03299 default:
03300 appendStringInfo(&buffer, "unrecognized object %u %u %d",
03301 object->classId,
03302 object->objectId,
03303 object->objectSubId);
03304 break;
03305 }
03306
03307 return buffer.data;
03308 }
03309
03310 static void
03311 getOpFamilyIdentity(StringInfo buffer, Oid opfid)
03312 {
03313 HeapTuple opfTup;
03314 Form_pg_opfamily opfForm;
03315 HeapTuple amTup;
03316 Form_pg_am amForm;
03317 char *schema;
03318
03319 opfTup = SearchSysCache1(OPFAMILYOID, ObjectIdGetDatum(opfid));
03320 if (!HeapTupleIsValid(opfTup))
03321 elog(ERROR, "cache lookup failed for opfamily %u", opfid);
03322 opfForm = (Form_pg_opfamily) GETSTRUCT(opfTup);
03323
03324 amTup = SearchSysCache1(AMOID, ObjectIdGetDatum(opfForm->opfmethod));
03325 if (!HeapTupleIsValid(amTup))
03326 elog(ERROR, "cache lookup failed for access method %u",
03327 opfForm->opfmethod);
03328 amForm = (Form_pg_am) GETSTRUCT(amTup);
03329
03330 schema = get_namespace_name(opfForm->opfnamespace);
03331 appendStringInfo(buffer, "%s for %s",
03332 quote_qualified_identifier(schema,
03333 NameStr(opfForm->opfname)),
03334 NameStr(amForm->amname));
03335
03336 ReleaseSysCache(amTup);
03337 ReleaseSysCache(opfTup);
03338 }
03339
03340
03341
03342
03343
03344 static void
03345 getRelationIdentity(StringInfo buffer, Oid relid)
03346 {
03347 HeapTuple relTup;
03348 Form_pg_class relForm;
03349 char *schema;
03350
03351 relTup = SearchSysCache1(RELOID,
03352 ObjectIdGetDatum(relid));
03353 if (!HeapTupleIsValid(relTup))
03354 elog(ERROR, "cache lookup failed for relation %u", relid);
03355 relForm = (Form_pg_class) GETSTRUCT(relTup);
03356
03357 schema = get_namespace_name(relForm->relnamespace);
03358 appendStringInfo(buffer, "%s",
03359 quote_qualified_identifier(schema,
03360 NameStr(relForm->relname)));
03361
03362 ReleaseSysCache(relTup);
03363 }