PageRenderTime 84ms CodeModel.GetById 30ms RepoModel.GetById 1ms app.codeStats 1ms

/src/backend/catalog/objectaddress.c

https://github.com/bbt123/postgres
C | 3397 lines | 2696 code | 439 blank | 262 comment | 200 complexity | e4ebe8bc8b3ed47d5c85ecf17ebcbe94 MD5 | raw file
Possible License(s): AGPL-3.0

Large files files are truncated, but you can click here to view the full file

  1. /*-------------------------------------------------------------------------
  2. *
  3. * objectaddress.c
  4. * functions for working with ObjectAddresses
  5. *
  6. * Portions Copyright (c) 1996-2014, PostgreSQL Global Development Group
  7. * Portions Copyright (c) 1994, Regents of the University of California
  8. *
  9. *
  10. * IDENTIFICATION
  11. * src/backend/catalog/objectaddress.c
  12. *
  13. *-------------------------------------------------------------------------
  14. */
  15. #include "postgres.h"
  16. #include "access/htup_details.h"
  17. #include "access/sysattr.h"
  18. #include "catalog/catalog.h"
  19. #include "catalog/indexing.h"
  20. #include "catalog/objectaddress.h"
  21. #include "catalog/pg_amop.h"
  22. #include "catalog/pg_amproc.h"
  23. #include "catalog/pg_attrdef.h"
  24. #include "catalog/pg_authid.h"
  25. #include "catalog/pg_cast.h"
  26. #include "catalog/pg_default_acl.h"
  27. #include "catalog/pg_event_trigger.h"
  28. #include "catalog/pg_collation.h"
  29. #include "catalog/pg_constraint.h"
  30. #include "catalog/pg_conversion.h"
  31. #include "catalog/pg_database.h"
  32. #include "catalog/pg_extension.h"
  33. #include "catalog/pg_foreign_data_wrapper.h"
  34. #include "catalog/pg_foreign_server.h"
  35. #include "catalog/pg_language.h"
  36. #include "catalog/pg_largeobject.h"
  37. #include "catalog/pg_largeobject_metadata.h"
  38. #include "catalog/pg_namespace.h"
  39. #include "catalog/pg_opclass.h"
  40. #include "catalog/pg_opfamily.h"
  41. #include "catalog/pg_operator.h"
  42. #include "catalog/pg_proc.h"
  43. #include "catalog/pg_rewrite.h"
  44. #include "catalog/pg_tablespace.h"
  45. #include "catalog/pg_trigger.h"
  46. #include "catalog/pg_ts_config.h"
  47. #include "catalog/pg_ts_dict.h"
  48. #include "catalog/pg_ts_parser.h"
  49. #include "catalog/pg_ts_template.h"
  50. #include "catalog/pg_type.h"
  51. #include "catalog/pg_user_mapping.h"
  52. #include "commands/dbcommands.h"
  53. #include "commands/defrem.h"
  54. #include "commands/event_trigger.h"
  55. #include "commands/extension.h"
  56. #include "commands/proclang.h"
  57. #include "commands/tablespace.h"
  58. #include "commands/trigger.h"
  59. #include "foreign/foreign.h"
  60. #include "funcapi.h"
  61. #include "libpq/be-fsstubs.h"
  62. #include "miscadmin.h"
  63. #include "nodes/makefuncs.h"
  64. #include "parser/parse_func.h"
  65. #include "parser/parse_oper.h"
  66. #include "parser/parse_type.h"
  67. #include "rewrite/rewriteSupport.h"
  68. #include "storage/lmgr.h"
  69. #include "storage/sinval.h"
  70. #include "utils/builtins.h"
  71. #include "utils/fmgroids.h"
  72. #include "utils/lsyscache.h"
  73. #include "utils/syscache.h"
  74. #include "utils/tqual.h"
  75. /*
  76. * ObjectProperty
  77. *
  78. * This array provides a common part of system object structure; to help
  79. * consolidate routines to handle various kind of object classes.
  80. */
  81. typedef struct
  82. {
  83. Oid class_oid; /* oid of catalog */
  84. Oid oid_index_oid; /* oid of index on system oid column */
  85. int oid_catcache_id; /* id of catcache on system oid column */
  86. int name_catcache_id; /* id of catcache on (name,namespace),
  87. * or (name) if the object does not
  88. * live in a namespace */
  89. AttrNumber attnum_name; /* attnum of name field */
  90. AttrNumber attnum_namespace; /* attnum of namespace field */
  91. AttrNumber attnum_owner; /* attnum of owner field */
  92. AttrNumber attnum_acl; /* attnum of acl field */
  93. AclObjectKind acl_kind; /* ACL_KIND_* of this object type */
  94. bool is_nsp_name_unique; /* can the nsp/name combination (or
  95. * name alone, if there's no
  96. * namespace) be considered an unique
  97. * identifier for an object of this
  98. * class? */
  99. } ObjectPropertyType;
  100. static const ObjectPropertyType ObjectProperty[] =
  101. {
  102. {
  103. CastRelationId,
  104. CastOidIndexId,
  105. -1,
  106. -1,
  107. InvalidAttrNumber,
  108. InvalidAttrNumber,
  109. InvalidAttrNumber,
  110. InvalidAttrNumber,
  111. -1,
  112. false
  113. },
  114. {
  115. CollationRelationId,
  116. CollationOidIndexId,
  117. COLLOID,
  118. -1, /* COLLNAMEENCNSP also takes encoding */
  119. Anum_pg_collation_collname,
  120. Anum_pg_collation_collnamespace,
  121. Anum_pg_collation_collowner,
  122. InvalidAttrNumber,
  123. ACL_KIND_COLLATION,
  124. true
  125. },
  126. {
  127. ConstraintRelationId,
  128. ConstraintOidIndexId,
  129. CONSTROID,
  130. -1,
  131. Anum_pg_constraint_conname,
  132. Anum_pg_constraint_connamespace,
  133. InvalidAttrNumber,
  134. InvalidAttrNumber,
  135. -1,
  136. false
  137. },
  138. {
  139. ConversionRelationId,
  140. ConversionOidIndexId,
  141. CONVOID,
  142. CONNAMENSP,
  143. Anum_pg_conversion_conname,
  144. Anum_pg_conversion_connamespace,
  145. Anum_pg_conversion_conowner,
  146. InvalidAttrNumber,
  147. ACL_KIND_CONVERSION,
  148. true
  149. },
  150. {
  151. DatabaseRelationId,
  152. DatabaseOidIndexId,
  153. DATABASEOID,
  154. -1,
  155. Anum_pg_database_datname,
  156. InvalidAttrNumber,
  157. Anum_pg_database_datdba,
  158. Anum_pg_database_datacl,
  159. ACL_KIND_DATABASE,
  160. true
  161. },
  162. {
  163. ExtensionRelationId,
  164. ExtensionOidIndexId,
  165. -1,
  166. -1,
  167. Anum_pg_extension_extname,
  168. InvalidAttrNumber, /* extension doesn't belong to extnamespace */
  169. Anum_pg_extension_extowner,
  170. InvalidAttrNumber,
  171. ACL_KIND_EXTENSION,
  172. true
  173. },
  174. {
  175. ForeignDataWrapperRelationId,
  176. ForeignDataWrapperOidIndexId,
  177. FOREIGNDATAWRAPPEROID,
  178. FOREIGNDATAWRAPPERNAME,
  179. Anum_pg_foreign_data_wrapper_fdwname,
  180. InvalidAttrNumber,
  181. Anum_pg_foreign_data_wrapper_fdwowner,
  182. Anum_pg_foreign_data_wrapper_fdwacl,
  183. ACL_KIND_FDW,
  184. true
  185. },
  186. {
  187. ForeignServerRelationId,
  188. ForeignServerOidIndexId,
  189. FOREIGNSERVEROID,
  190. FOREIGNSERVERNAME,
  191. Anum_pg_foreign_server_srvname,
  192. InvalidAttrNumber,
  193. Anum_pg_foreign_server_srvowner,
  194. Anum_pg_foreign_server_srvacl,
  195. ACL_KIND_FOREIGN_SERVER,
  196. true
  197. },
  198. {
  199. ProcedureRelationId,
  200. ProcedureOidIndexId,
  201. PROCOID,
  202. -1, /* PROCNAMEARGSNSP also takes argument types */
  203. Anum_pg_proc_proname,
  204. Anum_pg_proc_pronamespace,
  205. Anum_pg_proc_proowner,
  206. Anum_pg_proc_proacl,
  207. ACL_KIND_PROC,
  208. false
  209. },
  210. {
  211. LanguageRelationId,
  212. LanguageOidIndexId,
  213. LANGOID,
  214. LANGNAME,
  215. Anum_pg_language_lanname,
  216. InvalidAttrNumber,
  217. Anum_pg_language_lanowner,
  218. Anum_pg_language_lanacl,
  219. ACL_KIND_LANGUAGE,
  220. true
  221. },
  222. {
  223. LargeObjectMetadataRelationId,
  224. LargeObjectMetadataOidIndexId,
  225. -1,
  226. -1,
  227. InvalidAttrNumber,
  228. InvalidAttrNumber,
  229. Anum_pg_largeobject_metadata_lomowner,
  230. Anum_pg_largeobject_metadata_lomacl,
  231. ACL_KIND_LARGEOBJECT,
  232. false
  233. },
  234. {
  235. OperatorClassRelationId,
  236. OpclassOidIndexId,
  237. CLAOID,
  238. -1, /* CLAAMNAMENSP also takes opcmethod */
  239. Anum_pg_opclass_opcname,
  240. Anum_pg_opclass_opcnamespace,
  241. Anum_pg_opclass_opcowner,
  242. InvalidAttrNumber,
  243. ACL_KIND_OPCLASS,
  244. true
  245. },
  246. {
  247. OperatorRelationId,
  248. OperatorOidIndexId,
  249. OPEROID,
  250. -1, /* OPERNAMENSP also takes left and right type */
  251. Anum_pg_operator_oprname,
  252. Anum_pg_operator_oprnamespace,
  253. Anum_pg_operator_oprowner,
  254. InvalidAttrNumber,
  255. ACL_KIND_OPER,
  256. false
  257. },
  258. {
  259. OperatorFamilyRelationId,
  260. OpfamilyOidIndexId,
  261. OPFAMILYOID,
  262. -1, /* OPFAMILYAMNAMENSP also takes opfmethod */
  263. Anum_pg_opfamily_opfname,
  264. Anum_pg_opfamily_opfnamespace,
  265. Anum_pg_opfamily_opfowner,
  266. InvalidAttrNumber,
  267. ACL_KIND_OPFAMILY,
  268. true
  269. },
  270. {
  271. AuthIdRelationId,
  272. AuthIdOidIndexId,
  273. AUTHOID,
  274. AUTHNAME,
  275. Anum_pg_authid_rolname,
  276. InvalidAttrNumber,
  277. InvalidAttrNumber,
  278. InvalidAttrNumber,
  279. -1,
  280. true
  281. },
  282. {
  283. RewriteRelationId,
  284. RewriteOidIndexId,
  285. -1,
  286. -1,
  287. Anum_pg_rewrite_rulename,
  288. InvalidAttrNumber,
  289. InvalidAttrNumber,
  290. InvalidAttrNumber,
  291. -1,
  292. false
  293. },
  294. {
  295. NamespaceRelationId,
  296. NamespaceOidIndexId,
  297. NAMESPACEOID,
  298. NAMESPACENAME,
  299. Anum_pg_namespace_nspname,
  300. InvalidAttrNumber,
  301. Anum_pg_namespace_nspowner,
  302. Anum_pg_namespace_nspacl,
  303. ACL_KIND_NAMESPACE,
  304. true
  305. },
  306. {
  307. RelationRelationId,
  308. ClassOidIndexId,
  309. RELOID,
  310. RELNAMENSP,
  311. Anum_pg_class_relname,
  312. Anum_pg_class_relnamespace,
  313. Anum_pg_class_relowner,
  314. Anum_pg_class_relacl,
  315. ACL_KIND_CLASS,
  316. true
  317. },
  318. {
  319. TableSpaceRelationId,
  320. TablespaceOidIndexId,
  321. TABLESPACEOID,
  322. -1,
  323. Anum_pg_tablespace_spcname,
  324. InvalidAttrNumber,
  325. Anum_pg_tablespace_spcowner,
  326. Anum_pg_tablespace_spcacl,
  327. ACL_KIND_TABLESPACE,
  328. true
  329. },
  330. {
  331. TriggerRelationId,
  332. TriggerOidIndexId,
  333. -1,
  334. -1,
  335. Anum_pg_trigger_tgname,
  336. InvalidAttrNumber,
  337. InvalidAttrNumber,
  338. InvalidAttrNumber,
  339. -1,
  340. false
  341. },
  342. {
  343. EventTriggerRelationId,
  344. EventTriggerOidIndexId,
  345. EVENTTRIGGEROID,
  346. EVENTTRIGGERNAME,
  347. Anum_pg_event_trigger_evtname,
  348. InvalidAttrNumber,
  349. Anum_pg_event_trigger_evtowner,
  350. InvalidAttrNumber,
  351. ACL_KIND_EVENT_TRIGGER,
  352. true
  353. },
  354. {
  355. TSConfigRelationId,
  356. TSConfigOidIndexId,
  357. TSCONFIGOID,
  358. TSCONFIGNAMENSP,
  359. Anum_pg_ts_config_cfgname,
  360. Anum_pg_ts_config_cfgnamespace,
  361. Anum_pg_ts_config_cfgowner,
  362. InvalidAttrNumber,
  363. ACL_KIND_TSCONFIGURATION,
  364. true
  365. },
  366. {
  367. TSDictionaryRelationId,
  368. TSDictionaryOidIndexId,
  369. TSDICTOID,
  370. TSDICTNAMENSP,
  371. Anum_pg_ts_dict_dictname,
  372. Anum_pg_ts_dict_dictnamespace,
  373. Anum_pg_ts_dict_dictowner,
  374. InvalidAttrNumber,
  375. ACL_KIND_TSDICTIONARY,
  376. true
  377. },
  378. {
  379. TSParserRelationId,
  380. TSParserOidIndexId,
  381. TSPARSEROID,
  382. TSPARSERNAMENSP,
  383. Anum_pg_ts_parser_prsname,
  384. Anum_pg_ts_parser_prsnamespace,
  385. InvalidAttrNumber,
  386. InvalidAttrNumber,
  387. -1,
  388. true
  389. },
  390. {
  391. TSTemplateRelationId,
  392. TSTemplateOidIndexId,
  393. TSTEMPLATEOID,
  394. TSTEMPLATENAMENSP,
  395. Anum_pg_ts_template_tmplname,
  396. Anum_pg_ts_template_tmplnamespace,
  397. InvalidAttrNumber,
  398. InvalidAttrNumber,
  399. -1,
  400. true,
  401. },
  402. {
  403. TypeRelationId,
  404. TypeOidIndexId,
  405. TYPEOID,
  406. TYPENAMENSP,
  407. Anum_pg_type_typname,
  408. Anum_pg_type_typnamespace,
  409. Anum_pg_type_typowner,
  410. Anum_pg_type_typacl,
  411. ACL_KIND_TYPE,
  412. true
  413. }
  414. };
  415. static ObjectAddress get_object_address_unqualified(ObjectType objtype,
  416. List *qualname, bool missing_ok);
  417. static ObjectAddress get_relation_by_qualified_name(ObjectType objtype,
  418. List *objname, Relation *relp,
  419. LOCKMODE lockmode, bool missing_ok);
  420. static ObjectAddress get_object_address_relobject(ObjectType objtype,
  421. List *objname, Relation *relp, bool missing_ok);
  422. static ObjectAddress get_object_address_attribute(ObjectType objtype,
  423. List *objname, Relation *relp,
  424. LOCKMODE lockmode, bool missing_ok);
  425. static ObjectAddress get_object_address_type(ObjectType objtype,
  426. List *objname, bool missing_ok);
  427. static ObjectAddress get_object_address_opcf(ObjectType objtype, List *objname,
  428. List *objargs, bool missing_ok);
  429. static const ObjectPropertyType *get_object_property_data(Oid class_id);
  430. static void getRelationDescription(StringInfo buffer, Oid relid);
  431. static void getOpFamilyDescription(StringInfo buffer, Oid opfid);
  432. static void getRelationTypeDescription(StringInfo buffer, Oid relid,
  433. int32 objectSubId);
  434. static void getProcedureTypeDescription(StringInfo buffer, Oid procid);
  435. static void getConstraintTypeDescription(StringInfo buffer, Oid constroid);
  436. static void getOpFamilyIdentity(StringInfo buffer, Oid opfid);
  437. static void getRelationIdentity(StringInfo buffer, Oid relid);
  438. /*
  439. * Translate an object name and arguments (as passed by the parser) to an
  440. * ObjectAddress.
  441. *
  442. * The returned object will be locked using the specified lockmode. If a
  443. * sub-object is looked up, the parent object will be locked instead.
  444. *
  445. * If the object is a relation or a child object of a relation (e.g. an
  446. * attribute or constraint), the relation is also opened and *relp receives
  447. * the open relcache entry pointer; otherwise, *relp is set to NULL. This
  448. * is a bit grotty but it makes life simpler, since the caller will
  449. * typically need the relcache entry too. Caller must close the relcache
  450. * entry when done with it. The relation is locked with the specified lockmode
  451. * if the target object is the relation itself or an attribute, but for other
  452. * child objects, only AccessShareLock is acquired on the relation.
  453. *
  454. * If the object is not found, an error is thrown, unless missing_ok is
  455. * true. In this case, no lock is acquired, relp is set to NULL, and the
  456. * returned address has objectId set to InvalidOid.
  457. *
  458. * We don't currently provide a function to release the locks acquired here;
  459. * typically, the lock must be held until commit to guard against a concurrent
  460. * drop operation.
  461. *
  462. * Note: If the object is not found, we don't give any indication of the
  463. * reason. (It might have been a missing schema if the name was qualified, or
  464. * an inexistant type name in case of a cast, function or operator; etc).
  465. * Currently there is only one caller that might be interested in such info, so
  466. * we don't spend much effort here. If more callers start to care, it might be
  467. * better to add some support for that in this function.
  468. */
  469. ObjectAddress
  470. get_object_address(ObjectType objtype, List *objname, List *objargs,
  471. Relation *relp, LOCKMODE lockmode, bool missing_ok)
  472. {
  473. ObjectAddress address;
  474. ObjectAddress old_address = {InvalidOid, InvalidOid, 0};
  475. Relation relation = NULL;
  476. uint64 inval_count;
  477. /* Some kind of lock must be taken. */
  478. Assert(lockmode != NoLock);
  479. for (;;)
  480. {
  481. /*
  482. * Remember this value, so that, after looking up the object name and
  483. * locking it, we can check whether any invalidation messages have
  484. * been processed that might require a do-over.
  485. */
  486. inval_count = SharedInvalidMessageCounter;
  487. /* Look up object address. */
  488. switch (objtype)
  489. {
  490. case OBJECT_INDEX:
  491. case OBJECT_SEQUENCE:
  492. case OBJECT_TABLE:
  493. case OBJECT_VIEW:
  494. case OBJECT_MATVIEW:
  495. case OBJECT_FOREIGN_TABLE:
  496. address =
  497. get_relation_by_qualified_name(objtype, objname,
  498. &relation, lockmode,
  499. missing_ok);
  500. break;
  501. case OBJECT_COLUMN:
  502. address =
  503. get_object_address_attribute(objtype, objname,
  504. &relation, lockmode,
  505. missing_ok);
  506. break;
  507. case OBJECT_RULE:
  508. case OBJECT_TRIGGER:
  509. case OBJECT_CONSTRAINT:
  510. address = get_object_address_relobject(objtype, objname,
  511. &relation, missing_ok);
  512. break;
  513. case OBJECT_DATABASE:
  514. case OBJECT_EXTENSION:
  515. case OBJECT_TABLESPACE:
  516. case OBJECT_ROLE:
  517. case OBJECT_SCHEMA:
  518. case OBJECT_LANGUAGE:
  519. case OBJECT_FDW:
  520. case OBJECT_FOREIGN_SERVER:
  521. case OBJECT_EVENT_TRIGGER:
  522. address = get_object_address_unqualified(objtype,
  523. objname, missing_ok);
  524. break;
  525. case OBJECT_TYPE:
  526. case OBJECT_DOMAIN:
  527. address = get_object_address_type(objtype, objname, missing_ok);
  528. break;
  529. case OBJECT_AGGREGATE:
  530. address.classId = ProcedureRelationId;
  531. address.objectId =
  532. LookupAggNameTypeNames(objname, objargs, missing_ok);
  533. address.objectSubId = 0;
  534. break;
  535. case OBJECT_FUNCTION:
  536. address.classId = ProcedureRelationId;
  537. address.objectId =
  538. LookupFuncNameTypeNames(objname, objargs, missing_ok);
  539. address.objectSubId = 0;
  540. break;
  541. case OBJECT_OPERATOR:
  542. Assert(list_length(objargs) == 2);
  543. address.classId = OperatorRelationId;
  544. address.objectId =
  545. LookupOperNameTypeNames(NULL, objname,
  546. (TypeName *) linitial(objargs),
  547. (TypeName *) lsecond(objargs),
  548. missing_ok, -1);
  549. address.objectSubId = 0;
  550. break;
  551. case OBJECT_COLLATION:
  552. address.classId = CollationRelationId;
  553. address.objectId = get_collation_oid(objname, missing_ok);
  554. address.objectSubId = 0;
  555. break;
  556. case OBJECT_CONVERSION:
  557. address.classId = ConversionRelationId;
  558. address.objectId = get_conversion_oid(objname, missing_ok);
  559. address.objectSubId = 0;
  560. break;
  561. case OBJECT_OPCLASS:
  562. case OBJECT_OPFAMILY:
  563. address = get_object_address_opcf(objtype,
  564. objname, objargs, missing_ok);
  565. break;
  566. case OBJECT_LARGEOBJECT:
  567. Assert(list_length(objname) == 1);
  568. address.classId = LargeObjectRelationId;
  569. address.objectId = oidparse(linitial(objname));
  570. address.objectSubId = 0;
  571. if (!LargeObjectExists(address.objectId))
  572. {
  573. if (!missing_ok)
  574. ereport(ERROR,
  575. (errcode(ERRCODE_UNDEFINED_OBJECT),
  576. errmsg("large object %u does not exist",
  577. address.objectId)));
  578. }
  579. break;
  580. case OBJECT_CAST:
  581. {
  582. TypeName *sourcetype = (TypeName *) linitial(objname);
  583. TypeName *targettype = (TypeName *) linitial(objargs);
  584. Oid sourcetypeid;
  585. Oid targettypeid;
  586. sourcetypeid = LookupTypeNameOid(NULL, sourcetype, missing_ok);
  587. targettypeid = LookupTypeNameOid(NULL, targettype, missing_ok);
  588. address.classId = CastRelationId;
  589. address.objectId =
  590. get_cast_oid(sourcetypeid, targettypeid, missing_ok);
  591. address.objectSubId = 0;
  592. }
  593. break;
  594. case OBJECT_TSPARSER:
  595. address.classId = TSParserRelationId;
  596. address.objectId = get_ts_parser_oid(objname, missing_ok);
  597. address.objectSubId = 0;
  598. break;
  599. case OBJECT_TSDICTIONARY:
  600. address.classId = TSDictionaryRelationId;
  601. address.objectId = get_ts_dict_oid(objname, missing_ok);
  602. address.objectSubId = 0;
  603. break;
  604. case OBJECT_TSTEMPLATE:
  605. address.classId = TSTemplateRelationId;
  606. address.objectId = get_ts_template_oid(objname, missing_ok);
  607. address.objectSubId = 0;
  608. break;
  609. case OBJECT_TSCONFIGURATION:
  610. address.classId = TSConfigRelationId;
  611. address.objectId = get_ts_config_oid(objname, missing_ok);
  612. address.objectSubId = 0;
  613. break;
  614. default:
  615. elog(ERROR, "unrecognized objtype: %d", (int) objtype);
  616. /* placate compiler, in case it thinks elog might return */
  617. address.classId = InvalidOid;
  618. address.objectId = InvalidOid;
  619. address.objectSubId = 0;
  620. }
  621. /*
  622. * If we could not find the supplied object, return without locking.
  623. */
  624. if (!OidIsValid(address.objectId))
  625. {
  626. Assert(missing_ok);
  627. return address;
  628. }
  629. /*
  630. * If we're retrying, see if we got the same answer as last time. If
  631. * so, we're done; if not, we locked the wrong thing, so give up our
  632. * lock.
  633. */
  634. if (OidIsValid(old_address.classId))
  635. {
  636. if (old_address.classId == address.classId
  637. && old_address.objectId == address.objectId
  638. && old_address.objectSubId == address.objectSubId)
  639. break;
  640. if (old_address.classId != RelationRelationId)
  641. {
  642. if (IsSharedRelation(old_address.classId))
  643. UnlockSharedObject(old_address.classId,
  644. old_address.objectId,
  645. 0, lockmode);
  646. else
  647. UnlockDatabaseObject(old_address.classId,
  648. old_address.objectId,
  649. 0, lockmode);
  650. }
  651. }
  652. /*
  653. * If we're dealing with a relation or attribute, then the relation is
  654. * already locked. Otherwise, we lock it now.
  655. */
  656. if (address.classId != RelationRelationId)
  657. {
  658. if (IsSharedRelation(address.classId))
  659. LockSharedObject(address.classId, address.objectId, 0,
  660. lockmode);
  661. else
  662. LockDatabaseObject(address.classId, address.objectId, 0,
  663. lockmode);
  664. }
  665. /*
  666. * At this point, we've resolved the name to an OID and locked the
  667. * corresponding database object. However, it's possible that by the
  668. * time we acquire the lock on the object, concurrent DDL has modified
  669. * the database in such a way that the name we originally looked up no
  670. * longer resolves to that OID.
  671. *
  672. * We can be certain that this isn't an issue if (a) no shared
  673. * invalidation messages have been processed or (b) we've locked a
  674. * relation somewhere along the line. All the relation name lookups
  675. * in this module ultimately use RangeVarGetRelid() to acquire a
  676. * relation lock, and that function protects against the same kinds of
  677. * races we're worried about here. Even when operating on a
  678. * constraint, rule, or trigger, we still acquire AccessShareLock on
  679. * the relation, which is enough to freeze out any concurrent DDL.
  680. *
  681. * In all other cases, however, it's possible that the name we looked
  682. * up no longer refers to the object we locked, so we retry the lookup
  683. * and see whether we get the same answer.
  684. */
  685. if (inval_count == SharedInvalidMessageCounter || relation != NULL)
  686. break;
  687. old_address = address;
  688. }
  689. /* Return the object address and the relation. */
  690. *relp = relation;
  691. return address;
  692. }
  693. /*
  694. * Find an ObjectAddress for a type of object that is identified by an
  695. * unqualified name.
  696. */
  697. static ObjectAddress
  698. get_object_address_unqualified(ObjectType objtype,
  699. List *qualname, bool missing_ok)
  700. {
  701. const char *name;
  702. ObjectAddress address;
  703. /*
  704. * The types of names handled by this function are not permitted to be
  705. * schema-qualified or catalog-qualified.
  706. */
  707. if (list_length(qualname) != 1)
  708. {
  709. const char *msg;
  710. switch (objtype)
  711. {
  712. case OBJECT_DATABASE:
  713. msg = gettext_noop("database name cannot be qualified");
  714. break;
  715. case OBJECT_EXTENSION:
  716. msg = gettext_noop("extension name cannot be qualified");
  717. break;
  718. case OBJECT_TABLESPACE:
  719. msg = gettext_noop("tablespace name cannot be qualified");
  720. break;
  721. case OBJECT_ROLE:
  722. msg = gettext_noop("role name cannot be qualified");
  723. break;
  724. case OBJECT_SCHEMA:
  725. msg = gettext_noop("schema name cannot be qualified");
  726. break;
  727. case OBJECT_LANGUAGE:
  728. msg = gettext_noop("language name cannot be qualified");
  729. break;
  730. case OBJECT_FDW:
  731. msg = gettext_noop("foreign-data wrapper name cannot be qualified");
  732. break;
  733. case OBJECT_FOREIGN_SERVER:
  734. msg = gettext_noop("server name cannot be qualified");
  735. break;
  736. case OBJECT_EVENT_TRIGGER:
  737. msg = gettext_noop("event trigger name cannot be qualified");
  738. break;
  739. default:
  740. elog(ERROR, "unrecognized objtype: %d", (int) objtype);
  741. msg = NULL; /* placate compiler */
  742. }
  743. ereport(ERROR,
  744. (errcode(ERRCODE_SYNTAX_ERROR),
  745. errmsg("%s", _(msg))));
  746. }
  747. /* Format is valid, extract the actual name. */
  748. name = strVal(linitial(qualname));
  749. /* Translate name to OID. */
  750. switch (objtype)
  751. {
  752. case OBJECT_DATABASE:
  753. address.classId = DatabaseRelationId;
  754. address.objectId = get_database_oid(name, missing_ok);
  755. address.objectSubId = 0;
  756. break;
  757. case OBJECT_EXTENSION:
  758. address.classId = ExtensionRelationId;
  759. address.objectId = get_extension_oid(name, missing_ok);
  760. address.objectSubId = 0;
  761. break;
  762. case OBJECT_TABLESPACE:
  763. address.classId = TableSpaceRelationId;
  764. address.objectId = get_tablespace_oid(name, missing_ok);
  765. address.objectSubId = 0;
  766. break;
  767. case OBJECT_ROLE:
  768. address.classId = AuthIdRelationId;
  769. address.objectId = get_role_oid(name, missing_ok);
  770. address.objectSubId = 0;
  771. break;
  772. case OBJECT_SCHEMA:
  773. address.classId = NamespaceRelationId;
  774. address.objectId = get_namespace_oid(name, missing_ok);
  775. address.objectSubId = 0;
  776. break;
  777. case OBJECT_LANGUAGE:
  778. address.classId = LanguageRelationId;
  779. address.objectId = get_language_oid(name, missing_ok);
  780. address.objectSubId = 0;
  781. break;
  782. case OBJECT_FDW:
  783. address.classId = ForeignDataWrapperRelationId;
  784. address.objectId = get_foreign_data_wrapper_oid(name, missing_ok);
  785. address.objectSubId = 0;
  786. break;
  787. case OBJECT_FOREIGN_SERVER:
  788. address.classId = ForeignServerRelationId;
  789. address.objectId = get_foreign_server_oid(name, missing_ok);
  790. address.objectSubId = 0;
  791. break;
  792. case OBJECT_EVENT_TRIGGER:
  793. address.classId = EventTriggerRelationId;
  794. address.objectId = get_event_trigger_oid(name, missing_ok);
  795. address.objectSubId = 0;
  796. break;
  797. default:
  798. elog(ERROR, "unrecognized objtype: %d", (int) objtype);
  799. /* placate compiler, which doesn't know elog won't return */
  800. address.classId = InvalidOid;
  801. address.objectId = InvalidOid;
  802. address.objectSubId = 0;
  803. }
  804. return address;
  805. }
  806. /*
  807. * Locate a relation by qualified name.
  808. */
  809. static ObjectAddress
  810. get_relation_by_qualified_name(ObjectType objtype, List *objname,
  811. Relation *relp, LOCKMODE lockmode,
  812. bool missing_ok)
  813. {
  814. Relation relation;
  815. ObjectAddress address;
  816. address.classId = RelationRelationId;
  817. address.objectId = InvalidOid;
  818. address.objectSubId = 0;
  819. relation = relation_openrv_extended(makeRangeVarFromNameList(objname),
  820. lockmode, missing_ok);
  821. if (!relation)
  822. return address;
  823. switch (objtype)
  824. {
  825. case OBJECT_INDEX:
  826. if (relation->rd_rel->relkind != RELKIND_INDEX)
  827. ereport(ERROR,
  828. (errcode(ERRCODE_WRONG_OBJECT_TYPE),
  829. errmsg("\"%s\" is not an index",
  830. RelationGetRelationName(relation))));
  831. break;
  832. case OBJECT_SEQUENCE:
  833. if (relation->rd_rel->relkind != RELKIND_SEQUENCE)
  834. ereport(ERROR,
  835. (errcode(ERRCODE_WRONG_OBJECT_TYPE),
  836. errmsg("\"%s\" is not a sequence",
  837. RelationGetRelationName(relation))));
  838. break;
  839. case OBJECT_TABLE:
  840. if (relation->rd_rel->relkind != RELKIND_RELATION)
  841. ereport(ERROR,
  842. (errcode(ERRCODE_WRONG_OBJECT_TYPE),
  843. errmsg("\"%s\" is not a table",
  844. RelationGetRelationName(relation))));
  845. break;
  846. case OBJECT_VIEW:
  847. if (relation->rd_rel->relkind != RELKIND_VIEW)
  848. ereport(ERROR,
  849. (errcode(ERRCODE_WRONG_OBJECT_TYPE),
  850. errmsg("\"%s\" is not a view",
  851. RelationGetRelationName(relation))));
  852. break;
  853. case OBJECT_MATVIEW:
  854. if (relation->rd_rel->relkind != RELKIND_MATVIEW)
  855. ereport(ERROR,
  856. (errcode(ERRCODE_WRONG_OBJECT_TYPE),
  857. errmsg("\"%s\" is not a materialized view",
  858. RelationGetRelationName(relation))));
  859. break;
  860. case OBJECT_FOREIGN_TABLE:
  861. if (relation->rd_rel->relkind != RELKIND_FOREIGN_TABLE)
  862. ereport(ERROR,
  863. (errcode(ERRCODE_WRONG_OBJECT_TYPE),
  864. errmsg("\"%s\" is not a foreign table",
  865. RelationGetRelationName(relation))));
  866. break;
  867. default:
  868. elog(ERROR, "unrecognized objtype: %d", (int) objtype);
  869. break;
  870. }
  871. /* Done. */
  872. address.objectId = RelationGetRelid(relation);
  873. *relp = relation;
  874. return address;
  875. }
  876. /*
  877. * Find object address for an object that is attached to a relation.
  878. *
  879. * Note that we take only an AccessShareLock on the relation. We need not
  880. * pass down the LOCKMODE from get_object_address(), because that is the lock
  881. * mode for the object itself, not the relation to which it is attached.
  882. */
  883. static ObjectAddress
  884. get_object_address_relobject(ObjectType objtype, List *objname,
  885. Relation *relp, bool missing_ok)
  886. {
  887. ObjectAddress address;
  888. Relation relation = NULL;
  889. int nnames;
  890. const char *depname;
  891. /* Extract name of dependent object. */
  892. depname = strVal(lfirst(list_tail(objname)));
  893. /* Separate relation name from dependent object name. */
  894. nnames = list_length(objname);
  895. if (nnames < 2)
  896. {
  897. Oid reloid;
  898. /*
  899. * For compatibility with very old releases, we sometimes allow users
  900. * to attempt to specify a rule without mentioning the relation name.
  901. * If there's only rule by that name in the entire database, this will
  902. * work. But objects other than rules don't get this special
  903. * treatment.
  904. */
  905. if (objtype != OBJECT_RULE)
  906. elog(ERROR, "must specify relation and object name");
  907. address.classId = RewriteRelationId;
  908. address.objectId =
  909. get_rewrite_oid_without_relid(depname, &reloid, missing_ok);
  910. address.objectSubId = 0;
  911. /*
  912. * Caller is expecting to get back the relation, even though we didn't
  913. * end up using it to find the rule.
  914. */
  915. if (OidIsValid(address.objectId))
  916. relation = heap_open(reloid, AccessShareLock);
  917. }
  918. else
  919. {
  920. List *relname;
  921. Oid reloid;
  922. /* Extract relation name and open relation. */
  923. relname = list_truncate(list_copy(objname), nnames - 1);
  924. relation = heap_openrv_extended(makeRangeVarFromNameList(relname),
  925. AccessShareLock,
  926. missing_ok);
  927. reloid = relation ? RelationGetRelid(relation) : InvalidOid;
  928. switch (objtype)
  929. {
  930. case OBJECT_RULE:
  931. address.classId = RewriteRelationId;
  932. address.objectId = relation ?
  933. get_rewrite_oid(reloid, depname, missing_ok) : InvalidOid;
  934. address.objectSubId = 0;
  935. break;
  936. case OBJECT_TRIGGER:
  937. address.classId = TriggerRelationId;
  938. address.objectId = relation ?
  939. get_trigger_oid(reloid, depname, missing_ok) : InvalidOid;
  940. address.objectSubId = 0;
  941. break;
  942. case OBJECT_CONSTRAINT:
  943. address.classId = ConstraintRelationId;
  944. address.objectId = relation ?
  945. get_relation_constraint_oid(reloid, depname, missing_ok) :
  946. InvalidOid;
  947. address.objectSubId = 0;
  948. break;
  949. default:
  950. elog(ERROR, "unrecognized objtype: %d", (int) objtype);
  951. /* placate compiler, which doesn't know elog won't return */
  952. address.classId = InvalidOid;
  953. address.objectId = InvalidOid;
  954. address.objectSubId = 0;
  955. }
  956. /* Avoid relcache leak when object not found. */
  957. if (!OidIsValid(address.objectId))
  958. {
  959. if (relation != NULL)
  960. heap_close(relation, AccessShareLock);
  961. relation = NULL; /* department of accident prevention */
  962. return address;
  963. }
  964. }
  965. /* Done. */
  966. *relp = relation;
  967. return address;
  968. }
  969. /*
  970. * Find the ObjectAddress for an attribute.
  971. */
  972. static ObjectAddress
  973. get_object_address_attribute(ObjectType objtype, List *objname,
  974. Relation *relp, LOCKMODE lockmode,
  975. bool missing_ok)
  976. {
  977. ObjectAddress address;
  978. List *relname;
  979. Oid reloid;
  980. Relation relation;
  981. const char *attname;
  982. AttrNumber attnum;
  983. /* Extract relation name and open relation. */
  984. if (list_length(objname) < 2)
  985. ereport(ERROR,
  986. (errcode(ERRCODE_SYNTAX_ERROR),
  987. errmsg("column name must be qualified")));
  988. attname = strVal(lfirst(list_tail(objname)));
  989. relname = list_truncate(list_copy(objname), list_length(objname) - 1);
  990. /* XXX no missing_ok support here */
  991. relation = relation_openrv(makeRangeVarFromNameList(relname), lockmode);
  992. reloid = RelationGetRelid(relation);
  993. /* Look up attribute and construct return value. */
  994. attnum = get_attnum(reloid, attname);
  995. if (attnum == InvalidAttrNumber)
  996. {
  997. if (!missing_ok)
  998. ereport(ERROR,
  999. (errcode(ERRCODE_UNDEFINED_COLUMN),
  1000. errmsg("column \"%s\" of relation \"%s\" does not exist",
  1001. attname, NameListToString(relname))));
  1002. address.classId = RelationRelationId;
  1003. address.objectId = InvalidOid;
  1004. address.objectSubId = InvalidAttrNumber;
  1005. relation_close(relation, lockmode);
  1006. return address;
  1007. }
  1008. address.classId = RelationRelationId;
  1009. address.objectId = reloid;
  1010. address.objectSubId = attnum;
  1011. *relp = relation;
  1012. return address;
  1013. }
  1014. /*
  1015. * Find the ObjectAddress for a type or domain
  1016. */
  1017. static ObjectAddress
  1018. get_object_address_type(ObjectType objtype,
  1019. List *objname, bool missing_ok)
  1020. {
  1021. ObjectAddress address;
  1022. TypeName *typename;
  1023. Type tup;
  1024. typename = makeTypeNameFromNameList(objname);
  1025. address.classId = TypeRelationId;
  1026. address.objectId = InvalidOid;
  1027. address.objectSubId = 0;
  1028. tup = LookupTypeName(NULL, typename, NULL, missing_ok);
  1029. if (!HeapTupleIsValid(tup))
  1030. {
  1031. if (!missing_ok)
  1032. ereport(ERROR,
  1033. (errcode(ERRCODE_UNDEFINED_OBJECT),
  1034. errmsg("type \"%s\" does not exist",
  1035. TypeNameToString(typename))));
  1036. return address;
  1037. }
  1038. address.objectId = typeTypeId(tup);
  1039. if (objtype == OBJECT_DOMAIN)
  1040. {
  1041. if (((Form_pg_type) GETSTRUCT(tup))->typtype != TYPTYPE_DOMAIN)
  1042. ereport(ERROR,
  1043. (errcode(ERRCODE_WRONG_OBJECT_TYPE),
  1044. errmsg("\"%s\" is not a domain",
  1045. TypeNameToString(typename))));
  1046. }
  1047. ReleaseSysCache(tup);
  1048. return address;
  1049. }
  1050. /*
  1051. * Find the ObjectAddress for an opclass or opfamily.
  1052. */
  1053. static ObjectAddress
  1054. get_object_address_opcf(ObjectType objtype,
  1055. List *objname, List *objargs, bool missing_ok)
  1056. {
  1057. Oid amoid;
  1058. ObjectAddress address;
  1059. Assert(list_length(objargs) == 1);
  1060. /* XXX no missing_ok support here */
  1061. amoid = get_am_oid(strVal(linitial(objargs)), false);
  1062. switch (objtype)
  1063. {
  1064. case OBJECT_OPCLASS:
  1065. address.classId = OperatorClassRelationId;
  1066. address.objectId = get_opclass_oid(amoid, objname, missing_ok);
  1067. address.objectSubId = 0;
  1068. break;
  1069. case OBJECT_OPFAMILY:
  1070. address.classId = OperatorFamilyRelationId;
  1071. address.objectId = get_opfamily_oid(amoid, objname, missing_ok);
  1072. address.objectSubId = 0;
  1073. break;
  1074. default:
  1075. elog(ERROR, "unrecognized objtype: %d", (int) objtype);
  1076. /* placate compiler, which doesn't know elog won't return */
  1077. address.classId = InvalidOid;
  1078. address.objectId = InvalidOid;
  1079. address.objectSubId = 0;
  1080. }
  1081. return address;
  1082. }
  1083. /*
  1084. * Check ownership of an object previously identified by get_object_address.
  1085. */
  1086. void
  1087. check_object_ownership(Oid roleid, ObjectType objtype, ObjectAddress address,
  1088. List *objname, List *objargs, Relation relation)
  1089. {
  1090. switch (objtype)
  1091. {
  1092. case OBJECT_INDEX:
  1093. case OBJECT_SEQUENCE:
  1094. case OBJECT_TABLE:
  1095. case OBJECT_VIEW:
  1096. case OBJECT_MATVIEW:
  1097. case OBJECT_FOREIGN_TABLE:
  1098. case OBJECT_COLUMN:
  1099. case OBJECT_RULE:
  1100. case OBJECT_TRIGGER:
  1101. case OBJECT_CONSTRAINT:
  1102. if (!pg_class_ownercheck(RelationGetRelid(relation), roleid))
  1103. aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS,
  1104. RelationGetRelationName(relation));
  1105. break;
  1106. case OBJECT_DATABASE:
  1107. if (!pg_database_ownercheck(address.objectId, roleid))
  1108. aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_DATABASE,
  1109. NameListToString(objname));
  1110. break;
  1111. case OBJECT_TYPE:
  1112. case OBJECT_DOMAIN:
  1113. case OBJECT_ATTRIBUTE:
  1114. if (!pg_type_ownercheck(address.objectId, roleid))
  1115. aclcheck_error_type(ACLCHECK_NOT_OWNER, address.objectId);
  1116. break;
  1117. case OBJECT_AGGREGATE:
  1118. case OBJECT_FUNCTION:
  1119. if (!pg_proc_ownercheck(address.objectId, roleid))
  1120. aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_PROC,
  1121. NameListToString(objname));
  1122. break;
  1123. case OBJECT_OPERATOR:
  1124. if (!pg_oper_ownercheck(address.objectId, roleid))
  1125. aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_OPER,
  1126. NameListToString(objname));
  1127. break;
  1128. case OBJECT_SCHEMA:
  1129. if (!pg_namespace_ownercheck(address.objectId, roleid))
  1130. aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_NAMESPACE,
  1131. NameListToString(objname));
  1132. break;
  1133. case OBJECT_COLLATION:
  1134. if (!pg_collation_ownercheck(address.objectId, roleid))
  1135. aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_COLLATION,
  1136. NameListToString(objname));
  1137. break;
  1138. case OBJECT_CONVERSION:
  1139. if (!pg_conversion_ownercheck(address.objectId, roleid))
  1140. aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CONVERSION,
  1141. NameListToString(objname));
  1142. break;
  1143. case OBJECT_EXTENSION:
  1144. if (!pg_extension_ownercheck(address.objectId, roleid))
  1145. aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_EXTENSION,
  1146. NameListToString(objname));
  1147. break;
  1148. case OBJECT_FDW:
  1149. if (!pg_foreign_data_wrapper_ownercheck(address.objectId, roleid))
  1150. aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_FDW,
  1151. NameListToString(objname));
  1152. break;
  1153. case OBJECT_FOREIGN_SERVER:
  1154. if (!pg_foreign_server_ownercheck(address.objectId, roleid))
  1155. aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_FOREIGN_SERVER,
  1156. NameListToString(objname));
  1157. break;
  1158. case OBJECT_EVENT_TRIGGER:
  1159. if (!pg_event_trigger_ownercheck(address.objectId, roleid))
  1160. aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_EVENT_TRIGGER,
  1161. NameListToString(objname));
  1162. break;
  1163. case OBJECT_LANGUAGE:
  1164. if (!pg_language_ownercheck(address.objectId, roleid))
  1165. aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_LANGUAGE,
  1166. NameListToString(objname));
  1167. break;
  1168. case OBJECT_OPCLASS:
  1169. if (!pg_opclass_ownercheck(address.objectId, roleid))
  1170. aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_OPCLASS,
  1171. NameListToString(objname));
  1172. break;
  1173. case OBJECT_OPFAMILY:
  1174. if (!pg_opfamily_ownercheck(address.objectId, roleid))
  1175. aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_OPFAMILY,
  1176. NameListToString(objname));
  1177. break;
  1178. case OBJECT_LARGEOBJECT:
  1179. if (!lo_compat_privileges &&
  1180. !pg_largeobject_ownercheck(address.objectId, roleid))
  1181. ereport(ERROR,
  1182. (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
  1183. errmsg("must be owner of large object %u",
  1184. address.objectId)));
  1185. break;
  1186. case OBJECT_CAST:
  1187. {
  1188. /* We can only check permissions on the source/target types */
  1189. TypeName *sourcetype = (TypeName *) linitial(objname);
  1190. TypeName *targettype = (TypeName *) linitial(objargs);
  1191. Oid sourcetypeid = typenameTypeId(NULL, sourcetype);
  1192. Oid targettypeid = typenameTypeId(NULL, targettype);
  1193. if (!pg_type_ownercheck(sourcetypeid, roleid)
  1194. && !pg_type_ownercheck(targettypeid, roleid))
  1195. ereport(ERROR,
  1196. (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
  1197. errmsg("must be owner of type %s or type %s",
  1198. format_type_be(sourcetypeid),
  1199. format_type_be(targettypeid))));
  1200. }
  1201. break;
  1202. case OBJECT_TABLESPACE:
  1203. if (!pg_tablespace_ownercheck(address.objectId, roleid))
  1204. aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TABLESPACE,
  1205. NameListToString(objname));
  1206. break;
  1207. case OBJECT_TSDICTIONARY:
  1208. if (!pg_ts_dict_ownercheck(address.objectId, roleid))
  1209. aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TSDICTIONARY,
  1210. NameListToString(objname));
  1211. break;
  1212. case OBJECT_TSCONFIGURATION:
  1213. if (!pg_ts_config_ownercheck(address.objectId, roleid))
  1214. aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TSCONFIGURATION,
  1215. NameListToString(objname));
  1216. break;
  1217. case OBJECT_ROLE:
  1218. /*
  1219. * We treat roles as being "owned" by those with CREATEROLE priv,
  1220. * except that superusers are only owned by superusers.
  1221. */
  1222. if (superuser_arg(address.objectId))
  1223. {
  1224. if (!superuser_arg(roleid))
  1225. ereport(ERROR,
  1226. (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
  1227. errmsg("must be superuser")));
  1228. }
  1229. else
  1230. {
  1231. if (!has_createrole_privilege(roleid))
  1232. ereport(ERROR,
  1233. (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
  1234. errmsg("must have CREATEROLE privilege")));
  1235. }
  1236. break;
  1237. case OBJECT_TSPARSER:
  1238. case OBJECT_TSTEMPLATE:
  1239. /* We treat these object types as being owned by superusers */
  1240. if (!superuser_arg(roleid))
  1241. ereport(ERROR,
  1242. (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
  1243. errmsg("must be superuser")));
  1244. break;
  1245. default:
  1246. elog(ERROR, "unrecognized object type: %d",
  1247. (int) objtype);
  1248. }
  1249. }
  1250. /*
  1251. * get_object_namespace
  1252. *
  1253. * Find the schema containing the specified object. For non-schema objects,
  1254. * this function returns InvalidOid.
  1255. */
  1256. Oid
  1257. get_object_namespace(const ObjectAddress *address)
  1258. {
  1259. int cache;
  1260. HeapTuple tuple;
  1261. bool isnull;
  1262. Oid oid;
  1263. const ObjectPropertyType *property;
  1264. /* If not owned by a namespace, just return InvalidOid. */
  1265. property = get_object_property_data(address->classId);
  1266. if (property->attnum_namespace == InvalidAttrNumber)
  1267. return InvalidOid;
  1268. /* Currently, we can only handle object types with system caches. */
  1269. cache = property->oid_catcache_id;
  1270. Assert(cache != -1);
  1271. /* Fetch tuple from syscache and extract namespace attribute. */
  1272. tuple = SearchSysCache1(cache, ObjectIdGetDatum(address->objectId));
  1273. if (!HeapTupleIsValid(tuple))
  1274. elog(ERROR, "cache lookup failed for cache %d oid %u",
  1275. cache, address->objectId);
  1276. oid = DatumGetObjectId(SysCacheGetAttr(cache,
  1277. tuple,
  1278. property->attnum_namespace,
  1279. &isnull));
  1280. Assert(!isnull);
  1281. ReleaseSysCache(tuple);
  1282. return oid;
  1283. }
  1284. /*
  1285. * Interfaces to reference fields of ObjectPropertyType
  1286. */
  1287. Oid
  1288. get_object_oid_index(Oid class_id)
  1289. {
  1290. const ObjectPropertyType *prop = get_object_property_data(class_id);
  1291. return prop->oid_index_oid;
  1292. }
  1293. int
  1294. get_object_catcache_oid(Oid class_id)
  1295. {
  1296. const ObjectPropertyType *prop = get_object_property_data(class_id);
  1297. return prop->oid_catcache_id;
  1298. }
  1299. int
  1300. get_object_catcache_name(Oid class_id)
  1301. {
  1302. const ObjectPropertyType *prop = get_object_property_data(class_id);
  1303. return prop->name_catcache_id;
  1304. }
  1305. AttrNumber
  1306. get_object_attnum_name(Oid class_id)
  1307. {
  1308. const ObjectPropertyType *prop = get_object_property_data(class_id);
  1309. return prop->attnum_name;
  1310. }
  1311. AttrNumber
  1312. get_object_attnum_namespace(Oid class_id)
  1313. {
  1314. const ObjectPropertyType *prop = get_object_property_data(class_id);
  1315. return prop->attnum_namespace;
  1316. }
  1317. AttrNumber
  1318. get_object_attnum_owner(Oid class_id)
  1319. {
  1320. const ObjectPropertyType *prop = get_object_property_data(class_id);
  1321. return prop->attnum_owner;
  1322. }
  1323. AttrNumber
  1324. get_object_attnum_acl(Oid class_id)
  1325. {
  1326. const ObjectPropertyType *prop = get_object_property_data(class_id);
  1327. return prop->attnum_acl;
  1328. }
  1329. AclObjectKind
  1330. get_object_aclkind(Oid class_id)
  1331. {
  1332. const ObjectPropertyType *prop = get_object_property_data(class_id);
  1333. return prop->acl_kind;
  1334. }
  1335. bool
  1336. get_object_namensp_unique(Oid class_id)
  1337. {
  1338. const ObjectPropertyType *prop = get_object_property_data(class_id);
  1339. return prop->is_nsp_name_unique;
  1340. }
  1341. /*
  1342. * Return whether we have useful data for the given object class in the
  1343. * ObjectProperty table.
  1344. */
  1345. bool
  1346. is_objectclass_supported(Oid class_id)
  1347. {
  1348. int index;
  1349. for (index = 0; index < lengthof(ObjectProperty); index++)
  1350. {
  1351. if (ObjectProperty[index].class_oid == class_id)
  1352. return true;
  1353. }
  1354. return false;
  1355. }
  1356. /*
  1357. * Find ObjectProperty structure by class_id.
  1358. */
  1359. static const ObjectPropertyType *
  1360. get_object_property_data(Oid class_id)
  1361. {
  1362. static const ObjectPropertyType *prop_last = NULL;
  1363. int index;
  1364. /*
  1365. * A shortcut to speed up multiple consecutive lookups of a particular
  1366. * object class.
  1367. */
  1368. if (prop_last && prop_last->class_oid == class_id)
  1369. return prop_last;
  1370. for (index = 0; index < lengthof(ObjectProperty); index++)
  1371. {
  1372. if (ObjectProperty[index].class_oid == class_id)
  1373. {
  1374. prop_last = &ObjectProperty[index];
  1375. return &ObjectProperty[index];
  1376. }
  1377. }
  1378. ereport(ERROR,
  1379. (errmsg_internal("unrecognized class id: %u", class_id)));
  1380. return NULL; /* keep MSC compiler happy */
  1381. }
  1382. /*
  1383. * Return a copy of the tuple for the object with the given object OID, from
  1384. * the given catalog (which must have been opened by the caller and suitably
  1385. * locked). NULL is returned if the OID is not found.
  1386. *
  1387. * We try a syscache first, if available.
  1388. */
  1389. HeapTuple
  1390. get_catalog_object_by_oid(Relation catalog, Oid objectId)
  1391. {
  1392. HeapTuple tuple;
  1393. Oid classId = RelationGetRelid(catalog);
  1394. int oidCacheId = get_object_catcache_oid(classId);
  1395. if (oidCacheId > 0)
  1396. {
  1397. tuple = SearchSysCacheCopy1(oidCacheId, ObjectIdGetDatum(objectId));
  1398. if (!HeapTupleIsValid(tuple)) /* should not happen */
  1399. return NULL;
  1400. }
  1401. else
  1402. {
  1403. Oid oidIndexId = get_object_oid_index(classId);
  1404. SysScanDesc scan;
  1405. ScanKeyData skey;
  1406. Assert(OidIsValid(oidIndexId));
  1407. ScanKeyInit(&skey,
  1408. ObjectIdAttributeNumber,
  1409. BTEqualStrategyNumber, F_OIDEQ,
  1410. ObjectIdGetDatum(objectId));
  1411. scan = systable_beginscan(catalog, oidIndexId, true,
  1412. NULL, 1, &skey);
  1413. tuple = systable_getnext(scan);
  1414. if (!HeapTupleIsValid(tuple))
  1415. {
  1416. systable_endscan(scan);
  1417. return NULL;
  1418. }
  1419. tuple = heap_copytuple(tuple);
  1420. systable_endscan(scan);
  1421. }
  1422. return tuple;
  1423. }
  1424. /*
  1425. * getObjectDescription: build an object description for messages
  1426. *
  1427. * The result is a palloc'd string.
  1428. */
  1429. char *
  1430. getObjectDescription(const ObjectAddress *object)
  1431. {
  1432. StringInfoData buffer;
  1433. initStringInfo(&buffer);
  1434. switch (getObjectClass(object))
  1435. {
  1436. case OCLASS_CLASS:
  1437. getRelationDescription(&buffer, object->objectId);
  1438. if (object->objectSubId != 0)
  1439. appendStringInfo(&buffer, _(" column %s"),
  1440. get_relid_attribute_name(object->objectId,
  1441. object->objectSubId));
  1442. break;
  1443. case OCLASS_PROC:
  1444. appendStringInfo(&buffer, _("function %s"),
  1445. format_procedure(object->objectId));
  1446. break;
  1447. case OCLASS_TYPE:
  1448. appendStringInfo(&buffer, _("type %s"),
  1449. format_type_be(object->objectId));
  1450. break;
  1451. case OCLASS_CAST:
  1452. {
  1453. Relation castDesc;
  1454. ScanKeyData skey[1];
  1455. SysScanDesc rcscan;
  1456. HeapTuple tup;
  1457. Form_pg_cast castForm;
  1458. castDesc = heap_open(CastRelationId, AccessShareLock);
  1459. ScanKeyInit(&skey[0],
  1460. ObjectIdAttributeNumber,
  1461. BTEqualStrategyNumber, F_OIDEQ,
  1462. ObjectIdGetDatum(object->objectId));
  1463. rcscan = systable_beginscan(castDesc, CastOidIndexId, true,
  1464. NULL, 1, skey);
  1465. tup = systable_getnext(rcscan);
  1466. if (!HeapTupleIsValid(tup))
  1467. elog(ERROR, "could not find tuple for cast %u",
  1468. object->objectId);
  1469. castForm = (Form_pg_cast) GETSTRUCT(tup);
  1470. appendStringInfo(&buffer, _("cast from %s to %s"),
  1471. format_type_be(castForm->castsource),
  1472. format_type_be(castForm->casttarget));
  1473. systable_endscan(rcscan);
  1474. heap_close(castDesc, AccessShareLock);
  1475. break;
  1476. }
  1477. case OCLASS_COLLATION:
  1478. {
  1479. HeapTuple collTup;
  1480. Form_pg_collation coll;
  1481. collTup = SearchSysCache1(COLLOID,
  1482. ObjectIdGetDatum(object->objectId));
  1483. if (!HeapTupleIsValid(collTup))
  1484. elog(ERROR, "cache lookup failed for collation %u",
  1485. object->objectId);
  1486. coll = (Form_pg_collation) GETSTRUCT(collTup);
  1487. appendStringInfo(&buffer, _("collation %s"),
  1488. NameStr(coll->collname));
  1489. ReleaseSysCache(collTup);
  1490. break;
  1491. }
  1492. case OCLASS_CONSTRAINT:
  1493. {
  1494. HeapTuple conTup;
  1495. Form_pg_constraint con;
  1496. conTup = SearchSysCache1(CONSTROID,
  1497. ObjectIdGetDatum(object->objectId));
  1498. if (!HeapTupleIsValid(conTup))
  1499. elog(ERROR, "cache lookup failed for constraint %u",
  1500. object->objectId);
  1501. con = (Form_pg_constraint) GETSTRUCT(conTup);
  1502. if (OidIsValid(con->conrelid))
  1503. {
  1504. StringInfoData rel;
  1505. initStringInfo(&rel);
  1506. getRelationDescription(&rel, con->conrelid);
  1507. appendStringInfo(&buffer, _("constraint %s on %s"),
  1508. NameStr(con->conname), rel.data);
  1509. pfree(rel.data);
  1510. }
  1511. else
  1512. {
  1513. appendStringInfo(&buffer, _("constraint %s"),
  1514. NameStr(con->conname));
  1515. }
  1516. ReleaseSysCache(conTup);
  1517. break;
  1518. }
  1519. case OCLASS_CONVERSION:
  1520. {
  1521. HeapTuple conTup;
  1522. conTup = SearchSysCache1(CONVOID,
  1523. ObjectIdGetDatum(object->objectId));
  1524. if (!HeapTupleIsValid(conTup))
  1525. elog(ERROR, "cache lookup failed for conversion %u",
  1526. object->objectId);
  1527. appendStringInfo(&buffer, _("conversion %s"),
  1528. NameStr(((Form_pg_conversion) GETSTRUCT(conTup))->conname));
  1529. ReleaseSysCache(conTup);
  1530. break;
  1531. }
  1532. case OCLASS_DEFAULT:
  1533. {
  1534. Relation attrdefDesc;
  1535. ScanKeyData skey[1];
  1536. SysScanDesc adscan;
  1537. HeapTuple tup;
  1538. Form_pg_attrdef attrdef;
  1539. ObjectAddress colobject;
  1540. attrdefDesc = heap_open(AttrDefaultRelationId, AccessShareLock);
  1541. ScanKeyInit(&skey[0],
  1542. ObjectIdAttributeNumber,
  1543. BTEqualStrategyNumber, F_OIDEQ,
  1544. ObjectIdGetDatum(object->objectId));
  1545. adscan = systable_beginscan(attrdefDesc, AttrDefaultOidIndexId,
  1546. true, NULL, 1, skey);
  1547. tup = systable_getnext(adscan);
  1548. if (!HeapTupleIsValid(tup))
  1549. elog(ERROR, "could not find tuple for attrdef %u",
  1550. object->objectId);
  1551. attrdef = (Form_pg_attrdef) GETSTRUCT(tup);
  1552. colobject.classId = RelationRelationId;
  1553. colobject.objectId = attrdef->adrelid;
  1554. colobject.objectSubId = attrdef->adnum;
  1555. appendStringInfo(&buffer, _("default for %s"),
  1556. getObjectDescription(&colobject));
  1557. systable_endscan(adscan);
  1558. heap_close(attrdefDesc, AccessShareLock);
  1559. break;
  1560. }
  1561. case OCLASS_LANGUAGE:
  1562. {
  1563. HeapTuple langTup;
  1564. langTup = SearchSysCache1(LANGOID,
  1565. ObjectIdGetDatum(object->objectId));
  1566. if (!HeapTupleIsValid(langTup))
  1567. elog(ERROR, "cache lookup failed for language %u",
  1568. object->objectId);
  1569. appendStringInfo(&buffer, _("language %s"),
  1570. NameStr(((Form_pg_language) GETSTRUCT(langTup))->lanname));
  1571. ReleaseSysCache(langTup);
  1572. break;
  1573. }
  1574. case OCLASS_LARGEOBJECT:
  1575. appendStringInfo(&buffer, _("large object %u"),
  1576. object->objectId);
  1577. break;
  1578. case OCLASS_OPERATOR:
  1579. appendStringInfo(&buffer, _("operator %s"),
  1580. format_operator(object->objectId));
  1581. break;
  1582. case OCLASS_OPCLASS:
  1583. {
  1584. HeapTuple opcTup;
  1585. Form_pg_opclass opcForm;
  1586. HeapTuple amTup;
  1587. Form_pg_am amForm;
  1588. char *nspname;
  1589. opcTup = SearchSysCache1(CLAOID,
  1590. ObjectIdGetDatum(object->objectId));
  1591. if (!HeapTupleIsValid(opcTup))
  1592. elog(ERROR, "cache lookup failed for opclass %u",
  1593. object->objectId);
  1594. opcForm = (Form_pg_opclass) GETSTRUCT(opcTup);
  1595. amTup = SearchSysCache1(AMOID,
  1596. ObjectIdGetDatum(opcForm->opcmethod));
  1597. if (!HeapTupleIsValid(amTup))
  1598. elog(ERROR, "cache lookup failed for access method %u",
  1599. opcForm->opcmethod);
  1600. amForm = (Form_pg_am) GETSTRUCT(amTup);
  1601. /* Qualify the name if not visible in search path */
  1602. if (OpclassIsVisible(object->objectId))
  1603. nspname = NULL;
  1604. else
  1605. nspname = get_namespace_name(opcForm->opcnamespace);
  1606. appendStringInfo(&buffer, _("operator class %s for access method %s"),
  1607. quote_qualified_identifier(nspname,
  1608. NameStr(opcForm->opcname)),
  1609. NameStr(amForm->amname));
  1610. ReleaseSysCache(amTup);
  1611. ReleaseSysCache(opcTup);
  1612. break;
  1613. }
  1614. case OCLASS_OPFAMILY:
  1615. getOpFamilyDescription(&buffer, object->objectId);
  1616. break;
  1617. case OCLASS_AMOP:
  1618. {
  1619. Relation amopDesc;
  1620. HeapTuple tup;
  1621. ScanKeyData skey[1];
  1622. SysScanDesc amscan;
  1623. Form_pg_amop amopForm;
  1624. StringInfoData opfam;
  1625. amopDesc = heap_open(AccessMethodOperatorRelationId,
  1626. AccessShareLock);
  1627. ScanKeyInit(&skey[0],
  1628. ObjectIdAttributeNumber,
  1629. BTEqualStrategyNumber, F_OIDEQ,
  1630. ObjectIdGetDatum(object->objectId));
  1631. amscan = systable_beginscan(amopDesc, AccessMethodOperatorOidIndexId, true,
  1632. NULL, 1, skey);
  1633. tup = systable_getnext(amscan);
  1634. if (!HeapTupleIsValid(tup))
  1635. elog(ERROR, "could not find tuple for amop entry %u",
  1636. object->objectId);
  1637. amopForm = (Form_pg_amop) GETSTRUCT(tup);
  1638. initStringInfo(&opfam);
  1639. getOpFamilyDescription(&opfam, amopForm->amopfamily);
  1640. /*------
  1641. translator: %d is the operator strategy (a number), the
  1642. first two %s's are data type names, the third %s is the
  1643. description of the operator family, and the last %s is the
  1644. textual form of the operator with arguments. */
  1645. appendStringInfo(&buffer, _("operator %d (%s, %s) of %s: %s"),
  1646. amopForm->amopstrategy,
  1647. format_type_be(amopForm->amoplefttype),
  1648. format_type_be(amopForm->amoprighttype),
  1649. opfam.data,
  1650. format_operator(amopForm->amopopr));
  1651. pfree(opfam.data);
  1652. systable_endscan(amscan);
  1653. heap_close(amopDesc, AccessShareLock);
  1654. break;
  1655. }
  1656. case OCLASS_AMPROC:
  1657. {
  1658. Relation amprocDesc;
  1659. ScanKeyData skey[1];
  1660. SysScanDesc amscan;
  1661. HeapTuple tup;
  1662. Form_pg_amproc amprocForm;
  1663. StringInfoData opfam;
  1664. amprocDesc = heap_open(AccessMethodProcedureRelationId,
  1665. AccessShareLock);
  1666. ScanKeyInit(&skey[0],
  1667. ObjectIdAttributeNumber,
  1668. BTEqualStrategyNumber, F_OIDEQ,
  1669. ObjectIdGetDatum(object->objectId));
  1670. amscan = systable_beginscan(ampro

Large files files are truncated, but you can click here to view the full file