PostgreSQL Source Code: src/backend/catalog/pg_constraint.c Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
16
34#include "utils/fmgroids.h"
38
39
40
41
42
43
44
45
46
47
48
49
59 Oid relId,
83 bool is_internal)
84{
98 int i;
102
103
106
108
110
113
114
115
116
118 {
120
125 }
126 else
128
130 {
133
147
149 {
153 }
154 else
156 }
157 else
158 {
164 }
165
167 {
169
174 }
175 else
177
178
180 {
181 nulls[i] = false;
183 }
184
207
210 else
212
215 else
217
220 else
222
225 else
227
230 else
232
235 else
237
240 else
242
245 else
247
249
251
253
255
256
258
260 {
261
262
263
264
266
268 {
270 {
274 }
275 }
276 else
277 {
280 }
281 }
282
284 {
285
286
287
289
292 }
293
297
298
300
302 {
303
304
305
306
308
310 {
312 {
316 }
317 }
318 else
319 {
322 }
323 }
324
326 {
327
328
329
330
331
332
334
337 }
338
340 {
341
342
343
344
345
346
348
351
353 {
357 {
360 }
362 {
365 }
366 }
367 }
368
372
373
374
375
376
377
378
379
380
382 {
383
384
385
386
390 }
391
392
394 is_internal);
395
397}
398
399
400
401
402
403
404
405
406
407
408
409
410
411bool
413 const char *conname)
414{
415 bool found;
419
421
436
439
440
442
445
446 return found;
447}
448
449
450
451
452
453
454
455
456bool
458{
459 bool found;
463
465
470
475
478
480
483
484 return found;
485}
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512char *
516{
517 int pass = 0;
518 char *conname = NULL;
523 bool found;
525
527
528
529 if (label[0] != '\0')
531 else
533
534 for (;;)
535 {
537
538 found = false;
539
541 {
542 if (strcmp((char *) lfirst(l), conname) == 0)
543 {
544 found = true;
545 break;
546 }
547 }
548
549 if (!found)
550 {
555
560
563
565
567 }
568
569 if (!found)
570 break;
571
572
575 }
576
578
579 return conname;
580}
581
582
583
584
585
586
587
588
589
590
593{
596 retval = NULL;
599
606 true, NULL, 1, &key);
607
609 {
612
613
614
615
616
618 continue;
619
622 continue;
623
624
626 break;
627 }
628
631
632 return retval;
633}
634
635
636
637
638
639
640
652
653
654
655
656
659{
662 retval = NULL;
665
672 true, NULL, 1, &key);
673
675 {
677
678
679
680
682 continue;
683 if (!con->convalidated)
684 continue;
685
686
688 break;
689 }
690
693
694 return retval;
695}
696
697
698
699
700
703{
706
707
709
717 elog(ERROR, "conkey is not a 1-D smallint array");
718
719
720
722}
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741bool
743 bool is_local, bool is_no_inherit, bool is_notvalid)
744{
746
749 {
753
756
757
758
759
760
761 if (is_no_inherit != conform->connoinherit)
764 errmsg("cannot change NO INHERIT status of NOT NULL constraint \"%s\" on relation \"%s\"",
766 errhint("You might need to make the existing constraint inheritable using %s.",
767 "ALTER TABLE ... ALTER CONSTRAINT ... INHERIT"));
768
769
770
771
772
776 errmsg("incompatible NOT VALID constraint \"%s\" on relation \"%s\"",
778 errhint("You might need to validate it using %s.",
779 "ALTER TABLE ... VALIDATE CONSTRAINT"));
780
781
782
783
784
785
786
787
792 errmsg("cannot create not-null constraint \"%s\" on column \"%s\" of table \"%s\"",
794 errdetail("A not-null constraint named \"%s\" already exists for this column.",
796
797 if (!is_local)
798 {
803 errmsg("too many inheritance parents"));
805 }
806 else if (->conislocal)
807 {
808 conform->conislocal = true;
810 }
811
814
816
817 return true;
818 }
819
820 return false;
821}
822
823
824
825
826
827
828
829
830
831
832
835{
841
849
851 {
854
856 continue;
858 continue;
859
861
863 {
865
867
871 cooked->attnum = colnum;
873 cooked->is_enforced = true;
874 cooked->skip_validation = ->convalidated;
875 cooked->is_local = true;
876 cooked->inhcount = 0;
878
880 }
881 else
882 {
884
892 false)));
897 notnulls = lappend(notnulls, constr);
898 }
899 }
900
903
904 return notnulls;
905}
906
907
908
909
910
911void
913{
917
919
922 elog(ERROR, "cache lookup failed for constraint %u", conId);
924
925
926
927
929 {
931
932
933
934
935
937
938
939
940
941
942
944 {
948
953 elog(ERROR, "cache lookup failed for relation %u",
954 con->conrelid);
956
959 else
960
961 elog(WARNING, "relation \"%s\" has relchecks = %d",
963
965
967
969 }
970
971
973 }
975 {
976
977
978
979
980
981
982 }
983 else
984 elog(ERROR, "constraint %u is not of a known type", conId);
985
986
988
989
992}
993
994
995
996
997
998
999
1000
1001
1002
1003
1004void
1006{
1010
1012
1015 elog(ERROR, "cache lookup failed for constraint %u", conId);
1017
1018
1019
1020
1023 con->conrelid,
1024 newname))
1027 errmsg("constraint \"%s\" for relation \"%s\" already exists",
1031 con->contypid,
1032 newname))
1035 errmsg("constraint \"%s\" for domain %s already exists",
1037
1038
1039 namestrcpy(&(con->conname), newname);
1040
1042
1044
1047}
1048
1049
1050
1051
1052
1053
1054
1055
1056void
1059{
1064
1066
1075
1077 NULL, 2, key);
1078
1080 {
1083
1085
1087 continue;
1088
1089
1091 {
1094
1096
1098
1099
1100
1101
1102
1103
1104 }
1105
1107
1109 }
1110
1112
1114}
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125void
1129{
1136
1144 {
1145
1148 elog(ERROR, "constraint %u already has a parent constraint",
1150
1156 errmsg("too many inheritance parents"));
1157
1159
1161
1163
1166
1169 }
1170 else
1171 {
1175
1176
1178
1180
1187 }
1188
1191}
1192
1193
1194
1195
1196
1197
1198
1201{
1207
1209
1222
1225
1226
1229
1231
1232
1236 errmsg("constraint \"%s\" for table \"%s\" does not exist",
1238
1240
1242}
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1259{
1265
1266
1268
1270
1283
1286
1287
1289 {
1291 bool isNull;
1292
1294
1295
1298 if (!isNull)
1299 {
1303 int i;
1304
1311 elog(ERROR, "conkey is not a 1-D smallint array");
1313
1314
1316 {
1319 }
1320 }
1321 }
1322
1324
1325
1329 errmsg("constraint \"%s\" for table \"%s\" does not exist",
1331
1333
1335}
1336
1337
1338
1339
1340
1341
1342
1343
1344
1347{
1353
1355
1362 true, NULL, 1, &key);
1364 {
1366
1368
1369
1373 continue;
1374
1376 {
1378 break;
1379 }
1380 }
1382
1385}
1386
1387
1388
1389
1390
1391
1394{
1400
1402
1415
1418
1419
1422
1424
1425
1429 errmsg("constraint \"%s\" for domain %s does not exist",
1431
1433
1435}
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1453{
1459
1460
1462
1463
1465
1470
1473
1475 {
1478 bool isNull;
1481 int numkeys;
1482 int i;
1483
1484
1486 continue;
1487
1488
1489
1490
1491
1492
1494 break;
1495
1496
1499 if (isNull)
1500 elog(ERROR, "null conkey for constraint %u",
1505 numkeys < 0 ||
1508 elog(ERROR, "conkey is not a 1-D smallint array");
1510
1511
1512 for (i = 0; i < numkeys; i++)
1513 {
1516 }
1518
1519
1520 break;
1521 }
1522
1524
1526
1528}
1529
1530
1531
1532
1533
1534
1535
1536
1537void
1540 Oid *pf_eq_oprs, Oid *pp_eq_oprs, Oid *ff_eq_oprs,
1542{
1544 bool isNull;
1546 int numkeys;
1547
1548
1549
1550
1551
1552
1559 elog(ERROR, "conkey is not a 1-D smallint array");
1562 elog(ERROR, "foreign key constraint cannot have %d columns", numkeys);
1565 pfree(arr);
1566
1571 ARR_DIMS(arr)[0] != numkeys ||
1574 elog(ERROR, "confkey is not a 1-D smallint array");
1577 pfree(arr);
1578
1579 if (pf_eq_oprs)
1580 {
1584
1586 ARR_DIMS(arr)[0] != numkeys ||
1589 elog(ERROR, "conpfeqop is not a 1-D Oid array");
1592 pfree(arr);
1593 }
1594
1595 if (pp_eq_oprs)
1596 {
1601 ARR_DIMS(arr)[0] != numkeys ||
1604 elog(ERROR, "conppeqop is not a 1-D Oid array");
1607 pfree(arr);
1608 }
1609
1610 if (ff_eq_oprs)
1611 {
1616 ARR_DIMS(arr)[0] != numkeys ||
1619 elog(ERROR, "conffeqop is not a 1-D Oid array");
1622 pfree(arr);
1623 }
1624
1625 if (fk_del_set_cols)
1626 {
1629 if (isNull)
1630 {
1632 }
1633 else
1634 {
1636
1641 elog(ERROR, "confdelsetcols is not a 1-D smallint array");
1645 pfree(arr);
1646
1648 }
1649 }
1650
1652}
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667void
1672{
1676
1677
1679 {
1683 errmsg("invalid type for PERIOD part of foreign key"),
1684 errdetail("Only range and multirange are supported."));
1685
1686 }
1687 else
1688 elog(ERROR, "cache lookup failed for opclass %u", opclass);
1689
1690
1691
1692
1693
1694
1695
1701
1702
1703
1704
1705
1706
1712
1713 switch (opcintype)
1714 {
1717 break;
1720 break;
1721 default:
1722 elog(ERROR, "unexpected opcintype: %u", opcintype);
1723 }
1724}
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741bool
1746{
1751
1752
1755 return false;
1756
1757
1760 {
1762
1764 gvar->varno == varno &&
1765 gvar->varlevelsup == varlevelsup)
1768 }
1769
1771 {
1772
1774 return true;
1775 }
1776
1777 return false;
1778}
#define DatumGetArrayTypeP(X)
ArrayType * construct_array_builtin(Datum *elems, int nelems, Oid elmtype)
#define InvalidAttrNumber
bool bms_is_subset(const Bitmapset *a, const Bitmapset *b)
Bitmapset * bms_add_member(Bitmapset *a, int x)
static Datum values[MAXATTR]
#define CStringGetTextDatum(s)
#define Assert(condition)
#define OidIsValid(objectId)
Oid GetNewOidWithIndex(Relation relation, Oid indexId, AttrNumber oidcolumn)
void record_object_address_dependencies(const ObjectAddress *depender, ObjectAddresses *referenced, DependencyType behavior)
void recordDependencyOnSingleRelExpr(const ObjectAddress *depender, Node *expr, Oid relId, DependencyType behavior, DependencyType self_behavior, bool reverse_self)
bool object_address_present(const ObjectAddress *object, const ObjectAddresses *addrs)
void add_exact_object_address(const ObjectAddress *object, ObjectAddresses *addrs)
ObjectAddresses * new_object_addresses(void)
void free_object_addresses(ObjectAddresses *addrs)
@ DEPENDENCY_PARTITION_PRI
@ DEPENDENCY_PARTITION_SEC
int errcode(int sqlerrcode)
int errhint(const char *fmt,...) pg_attribute_printf(1
int errdetail(const char *fmt,...) pg_attribute_printf(1
#define ereport(elevel,...)
#define palloc_object(type)
char * format_type_be(Oid type_oid)
void systable_endscan(SysScanDesc sysscan)
HeapTuple systable_getnext(SysScanDesc sysscan)
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
HeapTuple heap_copytuple(HeapTuple tuple)
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, const Datum *values, const bool *isnull)
void heap_freetuple(HeapTuple htup)
#define HeapTupleIsValid(tuple)
static Datum heap_getattr(HeapTuple tup, int attnum, TupleDesc tupleDesc, bool *isnull)
static void * GETSTRUCT(const HeapTupleData *tuple)
char * makeObjectName(const char *name1, const char *name2, const char *label)
void GetOperatorFromCompareType(Oid opclass, Oid rhstype, CompareType cmptype, Oid *opid, StrategyNumber *strat)
void CatalogTupleUpdate(Relation heapRel, const ItemPointerData *otid, HeapTuple tup)
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
void CatalogTupleDelete(Relation heapRel, const ItemPointerData *tid)
static bool pg_add_s16_overflow(int16 a, int16 b, int16 *result)
List * lappend(List *list, void *datum)
List * lappend_oid(List *list, Oid datum)
#define AccessExclusiveLock
char * get_rel_name(Oid relid)
AttrNumber get_attnum(Oid relid, const char *attname)
bool get_opclass_opfamily_and_input_type(Oid opclass, Oid *opfamily, Oid *opcintype)
char * get_attname(Oid relid, AttrNumber attnum, bool missing_ok)
char * pstrdup(const char *in)
void pfree(void *pointer)
void namestrcpy(Name name, const char *str)
#define IsA(nodeptr, _type_)
#define InvokeObjectPostAlterHook(classId, objectId, subId)
#define InvokeObjectPostCreateHookArg(classId, objectId, subId, is_internal)
#define ObjectAddressSet(addr, class_id, object_id)
#define ObjectAddressSubSet(addr, class_id, object_id, object_sub_id)
FormData_pg_class * Form_pg_class
Oid CreateConstraintEntry(const char *constraintName, Oid constraintNamespace, char constraintType, bool isDeferrable, bool isDeferred, bool isEnforced, bool isValidated, Oid parentConstrId, Oid relId, const int16 *constraintKey, int constraintNKeys, int constraintNTotalKeys, Oid domainId, Oid indexRelId, Oid foreignRelId, const int16 *foreignKey, const Oid *pfEqOp, const Oid *ppEqOp, const Oid *ffEqOp, int foreignNKeys, char foreignUpdateType, char foreignDeleteType, const int16 *fkDeleteSetCols, int numFkDeleteSetCols, char foreignMatchType, const Oid *exclOp, Node *conExpr, const char *conBin, bool conIsLocal, int16 conInhCount, bool conNoInherit, bool conPeriod, bool is_internal)
HeapTuple findNotNullConstraint(Oid relid, const char *colname)
bool ConstraintNameIsUsed(ConstraintCategory conCat, Oid objId, const char *conname)
void RemoveConstraintById(Oid conId)
bool AdjustNotNullInheritance(Oid relid, AttrNumber attnum, const char *new_conname, bool is_local, bool is_no_inherit, bool is_notvalid)
void FindFKPeriodOpers(Oid opclass, Oid *containedbyoperoid, Oid *aggedcontainedbyoperoid, Oid *intersectoperoid)
void RenameConstraintById(Oid conId, const char *newname)
Oid get_relation_idx_constraint_oid(Oid relationId, Oid indexId)
void ConstraintSetParentConstraint(Oid childConstrId, Oid parentConstrId, Oid childTableId)
Bitmapset * get_primary_key_attnos(Oid relid, bool deferrableOk, Oid *constraintOid)
HeapTuple findDomainNotNullConstraint(Oid typid)
void DeconstructFkConstraintRow(HeapTuple tuple, int *numfks, AttrNumber *conkey, AttrNumber *confkey, Oid *pf_eq_oprs, Oid *pp_eq_oprs, Oid *ff_eq_oprs, int *num_fk_del_set_cols, AttrNumber *fk_del_set_cols)
HeapTuple findNotNullConstraintAttnum(Oid relid, AttrNumber attnum)
void AlterConstraintNamespaces(Oid ownerId, Oid oldNspId, Oid newNspId, bool isType, ObjectAddresses *objsMoved)
List * RelationGetNotNullConstraints(Oid relid, bool cooked, bool include_noinh)
bool ConstraintNameExists(const char *conname, Oid namespaceid)
char * ChooseConstraintName(const char *name1, const char *name2, const char *label, Oid namespaceid, List *others)
bool check_functional_grouping(Oid relid, Index varno, Index varlevelsup, List *grouping_columns, List **constraintDeps)
Bitmapset * get_relation_constraint_attnos(Oid relid, const char *conname, bool missing_ok, Oid *constraintOid)
Oid get_relation_constraint_oid(Oid relid, const char *conname, bool missing_ok)
AttrNumber extractNotNullColumn(HeapTuple constrTup)
Oid get_domain_constraint_oid(Oid typid, const char *conname, bool missing_ok)
END_CATALOG_STRUCT typedef FormData_pg_constraint * Form_pg_constraint
void recordDependencyOn(const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior)
long deleteDependencyRecordsForClass(Oid classId, Oid objectId, Oid refclassId, char deptype)
size_t strlcpy(char *dst, const char *src, size_t siz)
static Datum PointerGetDatum(const void *X)
static Datum Int16GetDatum(int16 X)
static Datum BoolGetDatum(bool X)
static Datum ObjectIdGetDatum(Oid X)
static Datum NameGetDatum(const NameData *X)
static Pointer DatumGetPointer(Datum X)
static Datum CStringGetDatum(const char *X)
static Datum CharGetDatum(char X)
#define RelationGetDescr(relation)
#define RelationGetRelationName(relation)
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
#define BTEqualStrategyNumber
#define ERRCODE_DUPLICATE_OBJECT
#define FirstLowInvalidHeapAttributeNumber
void ReleaseSysCache(HeapTuple tuple)
Datum SysCacheGetAttrNotNull(SysCacheIdentifier cacheId, HeapTuple tup, AttrNumber attributeNumber)
HeapTuple SearchSysCache1(SysCacheIdentifier cacheId, Datum key1)
Datum SysCacheGetAttr(SysCacheIdentifier cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
#define SearchSysCacheCopy1(cacheId, key1)
void table_close(Relation relation, LOCKMODE lockmode)
Relation table_open(Oid relationId, LOCKMODE lockmode)
String * makeString(char *str)