PostgreSQL Source Code git master
Loading...
Searching...
No Matches
pg_depend.c
Go to the documentation of this file.
1/*-------------------------------------------------------------------------
2 *
3 * pg_depend.c
4 * routines to support manipulation of the pg_depend relation
5 *
6 * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
8 *
9 *
10 * IDENTIFICATION
11 * src/backend/catalog/pg_depend.c
12 *
13 *-------------------------------------------------------------------------
14 */
15#include "postgres.h"
16
17#include "access/genam.h"
18#include "access/htup_details.h"
19#include "access/table.h"
20#include "catalog/catalog.h"
21#include "catalog/dependency.h"
22#include "catalog/indexing.h"
24#include "catalog/pg_depend.h"
26#include "catalog/pg_type.h"
27#include "catalog/partition.h"
28#include "commands/extension.h"
29#include "miscadmin.h"
30#include "utils/fmgroids.h"
31#include "utils/lsyscache.h"
32#include "utils/rel.h"
33#include "utils/syscache.h"
34
35
36static bool isObjectPinned(const ObjectAddress *object);
37
38
39/*
40 * Record a dependency between 2 objects via their respective ObjectAddress.
41 * The first argument is the dependent object, the second the one it
42 * references.
43 *
44 * This simply creates an entry in pg_depend, without any other processing.
45 */
46void
53
54/*
55 * Record multiple dependencies (of the same kind) for a single dependent
56 * object. This has a little less overhead than recording each separately.
57 */
58void
61 int nreferenced,
62 DependencyType behavior)
63{
66 TupleTableSlot **slot;
67 int i,
71
72 if (nreferenced <= 0)
73 return; /* nothing to do */
74
75 /*
76 * During bootstrap, do nothing since pg_depend may not exist yet.
77 *
78 * Objects created during bootstrap are most likely pinned, and the few
79 * that are not do not have dependencies on each other, so that there
80 * would be no need to make a pg_depend entry anyway.
81 */
83 return;
84
86
87 /*
88 * Allocate the slots to use, but delay costly initialization until we
89 * know that they will be used.
90 */
94
95 /* Don't open indexes unless we need to make an update */
96 indstate = NULL;
97
98 /* number of slots currently storing tuples */
100 /* number of slots currently initialized */
101 slot_init_count = 0;
102 for (i = 0; i < nreferenced; i++, referenced++)
103 {
104 /*
105 * If the referenced object is pinned by the system, there's no real
106 * need to record dependencies on it. This saves lots of space in
107 * pg_depend, so it's worth the time taken to check.
108 */
110 continue;
111
113 {
117 }
118
120
121 /*
122 * Record the dependency. Note we don't bother to check for duplicate
123 * dependencies; there's no harm in them.
124 */
132
133 memset(slot[slot_stored_count]->tts_isnull, false,
134 slot[slot_stored_count]->tts_tupleDescriptor->natts * sizeof(bool));
135
138
139 /* If slots are full, insert a batch of tuples */
141 {
142 /* fetch index info only when we know we need it */
143 if (indstate == NULL)
145
147 indstate);
149 }
150 }
151
152 /* Insert any tuples left in the buffer */
153 if (slot_stored_count > 0)
154 {
155 /* fetch index info only when we know we need it */
156 if (indstate == NULL)
158
160 indstate);
161 }
162
163 if (indstate != NULL)
165
167
168 /* Drop only the number of slots used */
169 for (i = 0; i < slot_init_count; i++)
171 pfree(slot);
172}
173
174/*
175 * If we are executing a CREATE EXTENSION operation, mark the given object
176 * as being a member of the extension, or check that it already is one.
177 * Otherwise, do nothing.
178 *
179 * This must be called during creation of any user-definable object type
180 * that could be a member of an extension.
181 *
182 * isReplace must be true if the object already existed, and false if it is
183 * newly created. In the former case we insist that it already be a member
184 * of the current extension. In the latter case we can skip checking whether
185 * it is already a member of any extension.
186 *
187 * Note: isReplace = true is typically used when updating an object in
188 * CREATE OR REPLACE and similar commands. We used to allow the target
189 * object to not already be an extension member, instead silently absorbing
190 * it into the current extension. However, this was both error-prone
191 * (extensions might accidentally overwrite free-standing objects) and
192 * a security hazard (since the object would retain its previous ownership).
193 */
194void
196 bool isReplace)
197{
198 /* Only whole objects can be extension members */
199 Assert(object->objectSubId == 0);
200
202 {
204
205 /* Only need to check for existing membership if isReplace */
206 if (isReplace)
207 {
208 Oid oldext;
209
210 /*
211 * Side note: these catalog lookups are safe only because the
212 * object is a pre-existing one. In the not-isReplace case, the
213 * caller has most likely not yet done a CommandCounterIncrement
214 * that would make the new object visible.
215 */
216 oldext = getExtensionOfObject(object->classId, object->objectId);
217 if (OidIsValid(oldext))
218 {
219 /* If already a member of this extension, nothing to do */
221 return;
222 /* Already a member of some other extension, so reject */
225 errmsg("%s is already a member of extension \"%s\"",
226 getObjectDescription(object, false),
228 }
229 /* It's a free-standing object, so reject */
232 errmsg("%s is not a member of extension \"%s\"",
233 getObjectDescription(object, false),
235 errdetail("An extension is not allowed to replace an object that it does not own.")));
236 }
237
238 /* OK, record it as a member of CurrentExtensionObject */
241 extension.objectSubId = 0;
242
244 }
245}
246
247/*
248 * If we are executing a CREATE EXTENSION operation, check that the given
249 * object is a member of the extension, and throw an error if it isn't.
250 * Otherwise, do nothing.
251 *
252 * This must be called whenever a CREATE IF NOT EXISTS operation (for an
253 * object type that can be an extension member) has found that an object of
254 * the desired name already exists. It is insecure for an extension to use
255 * IF NOT EXISTS except when the conflicting object is already an extension
256 * member; otherwise a hostile user could substitute an object with arbitrary
257 * properties.
258 */
259void
261{
262 /*
263 * This is actually the same condition tested in
264 * recordDependencyOnCurrentExtension; but we want to issue a
265 * differently-worded error, and anyway it would be pretty confusing to
266 * call recordDependencyOnCurrentExtension in these circumstances.
267 */
268
269 /* Only whole objects can be extension members */
270 Assert(object->objectSubId == 0);
271
273 {
274 Oid oldext;
275
276 oldext = getExtensionOfObject(object->classId, object->objectId);
277 /* If already a member of this extension, OK */
279 return;
280 /* Else complain */
283 errmsg("%s is not a member of extension \"%s\"",
284 getObjectDescription(object, false),
286 errdetail("An extension may only use CREATE ... IF NOT EXISTS to skip object creation if the conflicting object is one that it already owns.")));
287 }
288}
289
290/*
291 * deleteDependencyRecordsFor -- delete all records with given depender
292 * classId/objectId. Returns the number of records deleted.
293 *
294 * This is used when redefining an existing object. Links leading to the
295 * object do not change, and links leading from it will be recreated
296 * (possibly with some differences from before).
297 *
298 * If skipExtensionDeps is true, we do not delete any dependencies that
299 * show that the given object is a member of an extension. This avoids
300 * needing a lot of extra logic to fetch and recreate that dependency.
301 */
302long
305{
306 long count = 0;
308 ScanKeyData key[2];
309 SysScanDesc scan;
311
313
314 ScanKeyInit(&key[0],
317 ObjectIdGetDatum(classId));
318 ScanKeyInit(&key[1],
321 ObjectIdGetDatum(objectId));
322
324 NULL, 2, key);
325
326 while (HeapTupleIsValid(tup = systable_getnext(scan)))
327 {
328 if (skipExtensionDeps &&
330 continue;
331
332 CatalogTupleDelete(depRel, &tup->t_self);
333 count++;
334 }
335
336 systable_endscan(scan);
337
339
340 return count;
341}
342
343/*
344 * deleteDependencyRecordsForClass -- delete all records with given depender
345 * classId/objectId, dependee classId, and deptype.
346 * Returns the number of records deleted.
347 *
348 * This is a variant of deleteDependencyRecordsFor, useful when revoking
349 * an object property that is expressed by a dependency record (such as
350 * extension membership).
351 */
352long
354 Oid refclassId, char deptype)
355{
356 long count = 0;
358 ScanKeyData key[2];
359 SysScanDesc scan;
361
363
364 ScanKeyInit(&key[0],
367 ObjectIdGetDatum(classId));
368 ScanKeyInit(&key[1],
371 ObjectIdGetDatum(objectId));
372
374 NULL, 2, key);
375
376 while (HeapTupleIsValid(tup = systable_getnext(scan)))
377 {
379
380 if (depform->refclassid == refclassId && depform->deptype == deptype)
381 {
382 CatalogTupleDelete(depRel, &tup->t_self);
383 count++;
384 }
385 }
386
387 systable_endscan(scan);
388
390
391 return count;
392}
393
394/*
395 * deleteDependencyRecordsForSpecific -- delete all records with given depender
396 * classId/objectId, dependee classId/objectId, of the given deptype.
397 * Returns the number of records deleted.
398 */
399long
400deleteDependencyRecordsForSpecific(Oid classId, Oid objectId, char deptype,
402{
403 long count = 0;
405 ScanKeyData key[2];
406 SysScanDesc scan;
408
410
411 ScanKeyInit(&key[0],
414 ObjectIdGetDatum(classId));
415 ScanKeyInit(&key[1],
418 ObjectIdGetDatum(objectId));
419
421 NULL, 2, key);
422
423 while (HeapTupleIsValid(tup = systable_getnext(scan)))
424 {
426
427 if (depform->refclassid == refclassId &&
428 depform->refobjid == refobjectId &&
429 depform->deptype == deptype)
430 {
431 CatalogTupleDelete(depRel, &tup->t_self);
432 count++;
433 }
434 }
435
436 systable_endscan(scan);
437
439
440 return count;
441}
442
443/*
444 * Adjust dependency record(s) to point to a different object of the same type
445 *
446 * classId/objectId specify the referencing object.
447 * refClassId/oldRefObjectId specify the old referenced object.
448 * newRefObjectId is the new referenced object (must be of class refClassId).
449 *
450 * Note the lack of objsubid parameters. If there are subobject references
451 * they will all be readjusted. Also, there is an expectation that we are
452 * dealing with NORMAL dependencies: if we have to replace an (implicit)
453 * dependency on a pinned object with an explicit dependency on an unpinned
454 * one, the new one will be NORMAL.
455 *
456 * Returns the number of records updated -- zero indicates a problem.
457 */
458long
459changeDependencyFor(Oid classId, Oid objectId,
462{
463 long count = 0;
465 ScanKeyData key[2];
466 SysScanDesc scan;
470 bool oldIsPinned;
471 bool newIsPinned;
472
473 /*
474 * Check to see if either oldRefObjectId or newRefObjectId is pinned.
475 * Pinned objects should not have any dependency entries pointing to them,
476 * so in these cases we should add or remove a pg_depend entry, or do
477 * nothing at all, rather than update an entry as in the normal case.
478 */
480 objAddr.objectId = oldRefObjectId;
481 objAddr.objectSubId = 0;
482
484
485 objAddr.objectId = newRefObjectId;
486
488
489 if (oldIsPinned)
490 {
491 /*
492 * If both are pinned, we need do nothing. However, return 1 not 0,
493 * else callers will think this is an error case.
494 */
495 if (newIsPinned)
496 return 1;
497
498 /*
499 * There is no old dependency record, but we should insert a new one.
500 * Assume a normal dependency is wanted.
501 */
502 depAddr.classId = classId;
503 depAddr.objectId = objectId;
504 depAddr.objectSubId = 0;
506
507 return 1;
508 }
509
511
512 /* There should be existing dependency record(s), so search. */
513 ScanKeyInit(&key[0],
516 ObjectIdGetDatum(classId));
517 ScanKeyInit(&key[1],
520 ObjectIdGetDatum(objectId));
521
523 NULL, 2, key);
524
525 while (HeapTupleIsValid((tup = systable_getnext(scan))))
526 {
528
529 if (depform->refclassid == refClassId &&
530 depform->refobjid == oldRefObjectId)
531 {
532 if (newIsPinned)
533 CatalogTupleDelete(depRel, &tup->t_self);
534 else
535 {
536 /* make a modifiable copy */
539
540 depform->refobjid = newRefObjectId;
541
542 CatalogTupleUpdate(depRel, &tup->t_self, tup);
543
545 }
546
547 count++;
548 }
549 }
550
551 systable_endscan(scan);
552
554
555 return count;
556}
557
558/*
559 * Adjust all dependency records to come from a different object of the same type
560 *
561 * classId/oldObjectId specify the old referencing object.
562 * newObjectId is the new referencing object (must be of class classId).
563 *
564 * Returns the number of records updated.
565 */
566long
569{
570 long count = 0;
572 ScanKeyData key[2];
573 SysScanDesc scan;
575
577
578 ScanKeyInit(&key[0],
581 ObjectIdGetDatum(classId));
582 ScanKeyInit(&key[1],
586
588 NULL, 2, key);
589
590 while (HeapTupleIsValid((tup = systable_getnext(scan))))
591 {
593
594 /* make a modifiable copy */
597
598 depform->objid = newObjectId;
599
600 CatalogTupleUpdate(depRel, &tup->t_self, tup);
601
603
604 count++;
605 }
606
607 systable_endscan(scan);
608
610
611 return count;
612}
613
614/*
615 * Adjust all dependency records to point to a different object of the same type
616 *
617 * refClassId/oldRefObjectId specify the old referenced object.
618 * newRefObjectId is the new referenced object (must be of class refClassId).
619 *
620 * Returns the number of records updated.
621 */
622long
625{
626 long count = 0;
628 ScanKeyData key[2];
629 SysScanDesc scan;
632 bool newIsPinned;
633
635
636 /*
637 * If oldRefObjectId is pinned, there won't be any dependency entries on
638 * it --- we can't cope in that case. (This isn't really worth expending
639 * code to fix, in current usage; it just means you can't rename stuff out
640 * of pg_catalog, which would likely be a bad move anyway.)
641 */
642 objAddr.classId = refClassId;
643 objAddr.objectId = oldRefObjectId;
644 objAddr.objectSubId = 0;
645
649 errmsg("cannot remove dependency on %s because it is a system object",
650 getObjectDescription(&objAddr, false))));
651
652 /*
653 * We can handle adding a dependency on something pinned, though, since
654 * that just means deleting the dependency entry.
655 */
656 objAddr.objectId = newRefObjectId;
657
659
660 /* Now search for dependency records */
661 ScanKeyInit(&key[0],
665 ScanKeyInit(&key[1],
669
671 NULL, 2, key);
672
673 while (HeapTupleIsValid((tup = systable_getnext(scan))))
674 {
675 if (newIsPinned)
676 CatalogTupleDelete(depRel, &tup->t_self);
677 else
678 {
680
681 /* make a modifiable copy */
684
685 depform->refobjid = newRefObjectId;
686
687 CatalogTupleUpdate(depRel, &tup->t_self, tup);
688
690 }
691
692 count++;
693 }
694
695 systable_endscan(scan);
696
698
699 return count;
700}
701
702/*
703 * isObjectPinned()
704 *
705 * Test if an object is required for basic database functionality.
706 *
707 * The passed subId, if any, is ignored; we assume that only whole objects
708 * are pinned (and that this implies pinning their components).
709 */
710static bool
712{
713 return IsPinnedObject(object->classId, object->objectId);
714}
715
716
717/*
718 * Various special-purpose lookups and manipulations of pg_depend.
719 */
720
721
722/*
723 * Find the extension containing the specified object, if any
724 *
725 * Returns the OID of the extension, or InvalidOid if the object does not
726 * belong to any extension.
727 *
728 * Extension membership is marked by an EXTENSION dependency from the object
729 * to the extension. Note that the result will be indeterminate if pg_depend
730 * contains links from this object to more than one extension ... but that
731 * should never happen.
732 */
733Oid
734getExtensionOfObject(Oid classId, Oid objectId)
735{
736 Oid result = InvalidOid;
738 ScanKeyData key[2];
739 SysScanDesc scan;
741
743
744 ScanKeyInit(&key[0],
747 ObjectIdGetDatum(classId));
748 ScanKeyInit(&key[1],
751 ObjectIdGetDatum(objectId));
752
754 NULL, 2, key);
755
756 while (HeapTupleIsValid((tup = systable_getnext(scan))))
757 {
759
760 if (depform->refclassid == ExtensionRelationId &&
761 depform->deptype == DEPENDENCY_EXTENSION)
762 {
763 result = depform->refobjid;
764 break; /* no need to keep scanning */
765 }
766 }
767
768 systable_endscan(scan);
769
771
772 return result;
773}
774
775/*
776 * Return (possibly NIL) list of extensions that the given object depends on
777 * in DEPENDENCY_AUTO_EXTENSION mode.
778 */
779List *
781{
782 List *result = NIL;
784 ScanKeyData key[2];
785 SysScanDesc scan;
787
789
790 ScanKeyInit(&key[0],
793 ObjectIdGetDatum(classId));
794 ScanKeyInit(&key[1],
797 ObjectIdGetDatum(objectId));
798
800 NULL, 2, key);
801
802 while (HeapTupleIsValid((tup = systable_getnext(scan))))
803 {
805
806 if (depform->refclassid == ExtensionRelationId &&
808 result = lappend_oid(result, depform->refobjid);
809 }
810
811 systable_endscan(scan);
812
814
815 return result;
816}
817
818/*
819 * Look up a type belonging to an extension.
820 *
821 * Returns the type's OID, or InvalidOid if not found.
822 *
823 * Notice that the type is specified by name only, without a schema.
824 * That's because this will typically be used by relocatable extensions
825 * which can't make a-priori assumptions about which schema their objects
826 * are in. As long as the extension only defines one type of this name,
827 * the answer is unique anyway.
828 *
829 * We might later add the ability to look up functions, operators, etc.
830 */
831Oid
833{
834 Oid result = InvalidOid;
836 ScanKeyData key[3];
837 SysScanDesc scan;
839
841
842 ScanKeyInit(&key[0],
846 ScanKeyInit(&key[1],
850 ScanKeyInit(&key[2],
853 Int32GetDatum(0));
854
856 NULL, 3, key);
857
858 while (HeapTupleIsValid(tup = systable_getnext(scan)))
859 {
861
862 if (depform->classid == TypeRelationId &&
863 depform->deptype == DEPENDENCY_EXTENSION)
864 {
865 Oid typoid = depform->objid;
867
870 continue; /* should we throw an error? */
872 typname) == 0)
873 {
874 result = typoid;
876 break; /* no need to keep searching */
877 }
879 }
880 }
881
882 systable_endscan(scan);
883
885
886 return result;
887}
888
889/*
890 * Detect whether a sequence is marked as "owned" by a column
891 *
892 * An ownership marker is an AUTO or INTERNAL dependency from the sequence to the
893 * column. If we find one, store the identity of the owning column
894 * into *tableId and *colId and return true; else return false.
895 *
896 * Note: if there's more than one such pg_depend entry then you get
897 * a random one of them returned into the out parameters. This should
898 * not happen, though.
899 */
900bool
902{
903 bool ret = false;
905 ScanKeyData key[2];
906 SysScanDesc scan;
908
910
911 ScanKeyInit(&key[0],
915 ScanKeyInit(&key[1],
919
921 NULL, 2, key);
922
923 while (HeapTupleIsValid((tup = systable_getnext(scan))))
924 {
926
927 if (depform->refclassid == RelationRelationId &&
928 depform->deptype == deptype)
929 {
930 *tableId = depform->refobjid;
931 *colId = depform->refobjsubid;
932 ret = true;
933 break; /* no need to keep scanning */
934 }
935 }
936
937 systable_endscan(scan);
938
940
941 return ret;
942}
943
944/*
945 * Collect a list of OIDs of all sequences owned by the specified relation,
946 * and column if specified. If deptype is not zero, then only find sequences
947 * with the specified dependency type.
948 */
949static List *
951{
952 List *result = NIL;
954 ScanKeyData key[3];
955 SysScanDesc scan;
957
959
960 ScanKeyInit(&key[0],
964 ScanKeyInit(&key[1],
967 ObjectIdGetDatum(relid));
968 if (attnum)
969 ScanKeyInit(&key[2],
973
975 NULL, attnum ? 3 : 2, key);
976
977 while (HeapTupleIsValid(tup = systable_getnext(scan)))
978 {
980
981 /*
982 * We assume any auto or internal dependency of a sequence on a column
983 * must be what we are looking for. (We need the relkind test because
984 * indexes can also have auto dependencies on columns.)
985 */
986 if (deprec->classid == RelationRelationId &&
987 deprec->objsubid == 0 &&
988 deprec->refobjsubid != 0 &&
989 (deprec->deptype == DEPENDENCY_AUTO || deprec->deptype == DEPENDENCY_INTERNAL) &&
991 {
992 if (!deptype || deprec->deptype == deptype)
993 result = lappend_oid(result, deprec->objid);
994 }
995 }
996
997 systable_endscan(scan);
998
1000
1001 return result;
1002}
1003
1004/*
1005 * Collect a list of OIDs of all sequences owned (identity or serial) by the
1006 * specified relation.
1007 */
1008List *
1010{
1011 return getOwnedSequences_internal(relid, 0, 0);
1012}
1013
1014/*
1015 * Get owned identity sequence, error if not exactly one.
1016 */
1017Oid
1019{
1020 Oid relid = RelationGetRelid(rel);
1021 List *seqlist;
1022
1023 /*
1024 * The identity sequence is associated with the topmost partitioned table,
1025 * which might have column order different than the given partition.
1026 */
1028 {
1029 List *ancestors = get_partition_ancestors(relid);
1030 const char *attname = get_attname(relid, attnum, false);
1031
1032 relid = llast_oid(ancestors);
1033 attnum = get_attnum(relid, attname);
1035 elog(ERROR, "cache lookup failed for attribute \"%s\" of relation %u",
1036 attname, relid);
1037 list_free(ancestors);
1038 }
1039
1041 if (list_length(seqlist) > 1)
1042 elog(ERROR, "more than one owned sequence found");
1043 else if (seqlist == NIL)
1044 {
1045 if (missing_ok)
1046 return InvalidOid;
1047 else
1048 elog(ERROR, "no owned sequence found");
1049 }
1050
1051 return linitial_oid(seqlist);
1052}
1053
1054/*
1055 * get_index_constraint
1056 * Given the OID of an index, return the OID of the owning unique,
1057 * primary-key, or exclusion constraint, or InvalidOid if there
1058 * is no owning constraint.
1059 */
1060Oid
1062{
1065 ScanKeyData key[3];
1066 SysScanDesc scan;
1067 HeapTuple tup;
1068
1069 /* Search the dependency table for the index */
1071
1072 ScanKeyInit(&key[0],
1076 ScanKeyInit(&key[1],
1080 ScanKeyInit(&key[2],
1083 Int32GetDatum(0));
1084
1086 NULL, 3, key);
1087
1088 while (HeapTupleIsValid(tup = systable_getnext(scan)))
1089 {
1091
1092 /*
1093 * We assume any internal dependency on a constraint must be what we
1094 * are looking for.
1095 */
1096 if (deprec->refclassid == ConstraintRelationId &&
1097 deprec->refobjsubid == 0 &&
1098 deprec->deptype == DEPENDENCY_INTERNAL)
1099 {
1100 constraintId = deprec->refobjid;
1101 break;
1102 }
1103 }
1104
1105 systable_endscan(scan);
1107
1108 return constraintId;
1109}
1110
1111/*
1112 * get_index_ref_constraints
1113 * Given the OID of an index, return the OID of all foreign key
1114 * constraints which reference the index.
1115 */
1116List *
1118{
1119 List *result = NIL;
1121 ScanKeyData key[3];
1122 SysScanDesc scan;
1123 HeapTuple tup;
1124
1125 /* Search the dependency table for the index */
1127
1128 ScanKeyInit(&key[0],
1132 ScanKeyInit(&key[1],
1136 ScanKeyInit(&key[2],
1139 Int32GetDatum(0));
1140
1142 NULL, 3, key);
1143
1144 while (HeapTupleIsValid(tup = systable_getnext(scan)))
1145 {
1147
1148 /*
1149 * We assume any normal dependency from a constraint must be what we
1150 * are looking for.
1151 */
1152 if (deprec->classid == ConstraintRelationId &&
1153 deprec->objsubid == 0 &&
1154 deprec->deptype == DEPENDENCY_NORMAL)
1155 {
1156 result = lappend_oid(result, deprec->objid);
1157 }
1158 }
1159
1160 systable_endscan(scan);
1162
1163 return result;
1164}
int16 AttrNumber
Definition attnum.h:21
#define InvalidAttrNumber
Definition attnum.h:23
#define NameStr(name)
Definition c.h:777
#define Min(x, y)
Definition c.h:1019
#define Assert(condition)
Definition c.h:885
int32_t int32
Definition c.h:554
#define OidIsValid(objectId)
Definition c.h:800
bool IsPinnedObject(Oid classId, Oid objectId)
Definition catalog.c:370
DependencyType
Definition dependency.h:32
@ DEPENDENCY_AUTO
Definition dependency.h:34
@ DEPENDENCY_AUTO_EXTENSION
Definition dependency.h:39
@ DEPENDENCY_INTERNAL
Definition dependency.h:35
@ DEPENDENCY_EXTENSION
Definition dependency.h:38
@ DEPENDENCY_NORMAL
Definition dependency.h:33
int errcode(int sqlerrcode)
Definition elog.c:874
int errmsg(const char *fmt,...)
Definition elog.c:1093
int errdetail(const char *fmt,...) pg_attribute_printf(1
#define ERROR
Definition elog.h:39
#define elog(elevel,...)
Definition elog.h:226
#define ereport(elevel,...)
Definition elog.h:150
TupleTableSlot * MakeSingleTupleTableSlot(TupleDesc tupdesc, const TupleTableSlotOps *tts_ops)
void ExecDropSingleTupleTableSlot(TupleTableSlot *slot)
TupleTableSlot * ExecStoreVirtualTuple(TupleTableSlot *slot)
const TupleTableSlotOps TTSOpsHeapTuple
Definition execTuples.c:85
bool creating_extension
Definition extension.c:79
Oid CurrentExtensionObject
Definition extension.c:80
char * get_extension_name(Oid ext_oid)
Definition extension.c:250
#define palloc_array(type, count)
Definition fe_memutils.h:76
void systable_endscan(SysScanDesc sysscan)
Definition genam.c:603
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition genam.c:514
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition genam.c:388
HeapTuple heap_copytuple(HeapTuple tuple)
Definition heaptuple.c:778
void heap_freetuple(HeapTuple htup)
Definition heaptuple.c:1435
#define HeapTupleIsValid(tuple)
Definition htup.h:78
static void * GETSTRUCT(const HeapTupleData *tuple)
void CatalogTuplesMultiInsertWithInfo(Relation heapRel, TupleTableSlot **slot, int ntuples, CatalogIndexState indstate)
Definition indexing.c:273
void CatalogTupleUpdate(Relation heapRel, const ItemPointerData *otid, HeapTuple tup)
Definition indexing.c:313
void CatalogCloseIndexes(CatalogIndexState indstate)
Definition indexing.c:61
CatalogIndexState CatalogOpenIndexes(Relation heapRel)
Definition indexing.c:43
void CatalogTupleDelete(Relation heapRel, const ItemPointerData *tid)
Definition indexing.c:365
#define MAX_CATALOG_MULTI_INSERT_BYTES
Definition indexing.h:33
int i
Definition isn.c:77
List * lappend_oid(List *list, Oid datum)
Definition list.c:375
void list_free(List *list)
Definition list.c:1546
#define AccessShareLock
Definition lockdefs.h:36
#define RowExclusiveLock
Definition lockdefs.h:38
AttrNumber get_attnum(Oid relid, const char *attname)
Definition lsyscache.c:934
char get_rel_relkind(Oid relid)
Definition lsyscache.c:2153
char * get_attname(Oid relid, AttrNumber attnum, bool missing_ok)
Definition lsyscache.c:903
void pfree(void *pointer)
Definition mcxt.c:1616
#define IsBootstrapProcessingMode()
Definition miscadmin.h:477
char * getObjectDescription(const ObjectAddress *object, bool missing_ok)
List * get_partition_ancestors(Oid relid)
Definition partition.c:134
NameData attname
int16 attnum
void checkMembershipInCurrentExtension(const ObjectAddress *object)
Definition pg_depend.c:260
Oid getExtensionType(Oid extensionOid, const char *typname)
Definition pg_depend.c:832
void recordMultipleDependencies(const ObjectAddress *depender, const ObjectAddress *referenced, int nreferenced, DependencyType behavior)
Definition pg_depend.c:59
void recordDependencyOn(const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior)
Definition pg_depend.c:47
long changeDependencyFor(Oid classId, Oid objectId, Oid refClassId, Oid oldRefObjectId, Oid newRefObjectId)
Definition pg_depend.c:459
static bool isObjectPinned(const ObjectAddress *object)
Definition pg_depend.c:711
long deleteDependencyRecordsForClass(Oid classId, Oid objectId, Oid refclassId, char deptype)
Definition pg_depend.c:353
Oid getExtensionOfObject(Oid classId, Oid objectId)
Definition pg_depend.c:734
long changeDependenciesOf(Oid classId, Oid oldObjectId, Oid newObjectId)
Definition pg_depend.c:567
List * get_index_ref_constraints(Oid indexId)
Definition pg_depend.c:1117
List * getOwnedSequences(Oid relid)
Definition pg_depend.c:1009
long deleteDependencyRecordsFor(Oid classId, Oid objectId, bool skipExtensionDeps)
Definition pg_depend.c:303
long deleteDependencyRecordsForSpecific(Oid classId, Oid objectId, char deptype, Oid refclassId, Oid refobjectId)
Definition pg_depend.c:400
long changeDependenciesOn(Oid refClassId, Oid oldRefObjectId, Oid newRefObjectId)
Definition pg_depend.c:623
static List * getOwnedSequences_internal(Oid relid, AttrNumber attnum, char deptype)
Definition pg_depend.c:950
Oid getIdentitySequence(Relation rel, AttrNumber attnum, bool missing_ok)
Definition pg_depend.c:1018
Oid get_index_constraint(Oid indexId)
Definition pg_depend.c:1061
void recordDependencyOnCurrentExtension(const ObjectAddress *object, bool isReplace)
Definition pg_depend.c:195
bool sequenceIsOwned(Oid seqId, char deptype, Oid *tableId, int32 *colId)
Definition pg_depend.c:901
List * getAutoExtensionsOfObject(Oid classId, Oid objectId)
Definition pg_depend.c:780
FormData_pg_depend
Definition pg_depend.h:67
END_CATALOG_STRUCT typedef FormData_pg_depend * Form_pg_depend
Definition pg_depend.h:76
static int list_length(const List *l)
Definition pg_list.h:152
#define NIL
Definition pg_list.h:68
#define llast_oid(l)
Definition pg_list.h:200
#define linitial_oid(l)
Definition pg_list.h:180
END_CATALOG_STRUCT typedef FormData_pg_type * Form_pg_type
Definition pg_type.h:265
NameData typname
Definition pg_type.h:43
static Datum ObjectIdGetDatum(Oid X)
Definition postgres.h:262
static Datum Int32GetDatum(int32 X)
Definition postgres.h:222
static Datum CharGetDatum(char X)
Definition postgres.h:132
#define InvalidOid
unsigned int Oid
static int fb(int x)
#define RelationGetForm(relation)
Definition rel.h:508
#define RelationGetRelid(relation)
Definition rel.h:514
#define RelationGetDescr(relation)
Definition rel.h:540
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition scankey.c:76
#define BTEqualStrategyNumber
Definition stratnum.h:31
Definition pg_list.h:54
Datum * tts_values
Definition tuptable.h:124
void ReleaseSysCache(HeapTuple tuple)
Definition syscache.c:264
HeapTuple SearchSysCache1(SysCacheIdentifier cacheId, Datum key1)
Definition syscache.c:220
void table_close(Relation relation, LOCKMODE lockmode)
Definition table.c:126
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition table.c:40
static TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition tuptable.h:457