PostgreSQL Source Code: src/backend/rewrite/rewriteHandler.c Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
22
47
48
49
51{
55
57{
58 bool for_execute;
60
62{
66
70 Query *rule_action,
71 Node *rule_qual,
72 int rt_index,
74 bool *returning_flag);
81 int values_rte_index,
82 Bitmapset **unused_values_attrnos);
85 const char *attrName);
94 bool pushedDown);
96 int varno, Query *parsetree, bool *hasUpdate);
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147void
149 bool forExecute,
150 bool forUpdatePushedDown)
151{
153 int rt_index;
155
157
158
159
160
161 rt_index = 0;
162 foreach(l, parsetree->rtable)
163 {
167 List *newaliasvars;
168 Index curinputvarno;
171
172 ++rt_index;
174 {
176
177
178
179
180
181
182
183
184
185
186 if (!forExecute)
188 else if (forUpdatePushedDown)
189 {
190
193 lockmode = rte->rellockmode;
194 }
195 else
196 lockmode = rte->rellockmode;
197
198 rel = table_open(rte->relid, lockmode);
199
200
201
202
203
204 rte->relkind = rel->rd_rel->relkind;
205
207 break;
208
210
211
212
213
214
215
216
217
218
219
220 newaliasvars = NIL;
221 curinputvarno = 0;
222 curinputrte = NULL;
223 foreach(ll, rte->joinaliasvars)
224 {
226 Var *aliasvar = aliasitem;
227
228
230
231
232
233
234
235
236
237
238 if (aliasvar && IsA(aliasvar, Var))
239 {
240
241
242
243
244
245
246
247
248
250 if (aliasvar->varno != curinputvarno)
251 {
252 curinputvarno = aliasvar->varno;
253 if (curinputvarno >= rt_index)
254 elog(ERROR, "unexpected varno %d in JOIN RTE %d",
255 curinputvarno, rt_index);
256 curinputrte = rt_fetch(curinputvarno,
258 }
261 {
262
263 aliasitem = NULL;
264 }
265 }
266 newaliasvars = lappend(newaliasvars, aliasitem);
267 }
268 rte->joinaliasvars = newaliasvars;
269 break;
270
272
273
274
275
276
278 forExecute,
279 (forUpdatePushedDown ||
281 break;
282
283 default:
284
285 break;
286 }
287 }
288
289
290 foreach(l, parsetree->cteList)
291 {
293
295 }
296
297
298
299
300
301 if (parsetree->hasSubLinks)
304}
305
306
307
308
309static bool
311{
312 if (node == NULL)
313 return false;
315 {
317
318
321 false);
322
323 }
324
325
326
327
328
330}
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
352 Query *rule_action,
353 Node *rule_qual,
354 int rt_index,
356 bool *returning_flag)
357{
358 int current_varno,
359 new_varno;
360 int rt_length;
361 Query *sub_action;
362 Query **sub_action_ptr;
365
367
368
369
370
371
372 rule_action = copyObject(rule_action);
374
375
376
377
380
381 current_varno = rt_index;
384
385
386
387
388
389
390
391
392
394
397
402
403
404
405
406
407
408
409
410
411 foreach(lc, sub_action->rtable)
412 {
414
417 rte->lateral = true;
418 }
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447 {
448 List *rtable_tail = sub_action->rtable;
449 List *perminfos_tail = sub_action->rteperminfos;
450
451
452
453
454
455
457 sub_action->rteperminfos = copyObject(parsetree->rteperminfos);
459 rtable_tail, perminfos_tail);
460 }
461
462
463
464
465
466 if (parsetree->hasSubLinks && !sub_action->hasSubLinks)
467 {
468 foreach(lc, parsetree->rtable)
469 {
471
473 {
475 sub_action->hasSubLinks =
477 break;
479 sub_action->hasSubLinks =
481 break;
483 sub_action->hasSubLinks =
485 break;
487 sub_action->hasSubLinks =
489 break;
490 default:
491
492 break;
493 }
494 sub_action->hasSubLinks |=
496 if (sub_action->hasSubLinks)
497 break;
498 }
499 }
500
501
502
503
504
505
506
507
508 sub_action->hasRowSecurity |= parsetree->hasRowSecurity;
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
525 {
526 bool keeporig;
527 List *newjointree;
528
531 rt_index, 0)) &&
535 if (newjointree != NIL)
536 {
537
538
539
540
541
542
545 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
546 errmsg("conditional UNION/INTERSECT/EXCEPT statements are not implemented")));
547
550
551
552
553
554
555 if (parsetree->hasSubLinks && !sub_action->hasSubLinks)
556 sub_action->hasSubLinks =
558 }
559 }
560
561
562
563
564
566 {
567
568
569
570
571
572
573
574
575
576
577
578 foreach(lc, parsetree->cteList)
579 {
582
583 foreach(lc2, sub_action->cteList)
584 {
586
589 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
590 errmsg("WITH query name \"%s\" appears in both a rule action and the query being rewritten",
592 }
593 }
594
595
598
599 sub_action->hasRecursive |= parsetree->hasRecursive;
600 sub_action->hasModifyingCTE |= parsetree->hasModifyingCTE;
601
602
603
604
605
606
607
608
609
610
611
612
613
614 if (sub_action->hasModifyingCTE && rule_action != sub_action)
616 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
617 errmsg("INSERT ... SELECT rule actions are not supported for queries having data-modifying statements in WITH")));
618 }
619
620
621
622
623
624
625 AddQual(sub_action, rule_qual);
626
628
629
630
631
632
633
634
635
636
639 {
640 sub_action = (Query *)
642 new_varno,
643 0,
646 sub_action->resultRelation,
650 current_varno,
651 NULL);
652 if (sub_action_ptr)
653 *sub_action_ptr = sub_action;
654 else
655 rule_action = sub_action;
656 }
657
658
659
660
661
662
663
667 {
668 if (*returning_flag)
670 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
671 errmsg("cannot have RETURNING lists in multiple rules")));
672 *returning_flag = true;
675 parsetree->resultRelation,
676 0,
677 rt_fetch(parsetree->resultRelation,
680 rule_action->resultRelation,
682 0,
683 &rule_action->hasSubLinks);
684
685
686 rule_action->returningOldAlias = parsetree->returningOldAlias;
687 rule_action->returningNewAlias = parsetree->returningNewAlias;
688
689
690
691
692
693 if (parsetree->hasSubLinks && !rule_action->hasSubLinks)
694 rule_action->hasSubLinks =
696 }
697
698 return rule_action;
699}
700
701
702
703
704
705
706
707
708
711{
714
715 if (removert)
716 {
717 foreach(l, newjointree)
718 {
720
722 rtr->rtindex == rt_index)
723 {
725 break;
726 }
727 }
728 }
729 return newjointree;
730}
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
777 int values_rte_index,
778 Bitmapset **unused_values_attrnos)
779{
784 int attrno,
785 next_junk_attrno,
786 numattrs;
788 Bitmapset *default_only_cols = NULL;
789
790
791
792
793
794
795
796
797
798
801 next_junk_attrno = numattrs + 1;
802
803 foreach(temp, targetList)
804 {
806
807 if (!old_tle->resjunk)
808 {
809
810 attrno = old_tle->resno;
811 if (attrno < 1 || attrno > numattrs)
812 elog(ERROR, "bogus resno %d in targetlist", attrno);
814
815
816 if (att_tup->attisdropped)
817 continue;
818
819
820 new_tles[attrno - 1] =
822 new_tles[attrno - 1],
823 NameStr(att_tup->attname));
824 }
825 else
826 {
827
828
829
830
831
832
833
834
835
836
837 if (old_tle->resno != next_junk_attrno)
838 {
840 old_tle->resno = next_junk_attrno;
841 }
842 junk_tlist = lappend(junk_tlist, old_tle);
843 next_junk_attrno++;
844 }
845 }
846
847 for (attrno = 1; attrno <= numattrs; attrno++)
848 {
849 TargetEntry *new_tle = new_tles[attrno - 1];
850 bool apply_default;
851
853
854
855 if (att_tup->attisdropped)
856 continue;
857
858
859
860
861
862
863 apply_default = ((new_tle == NULL && commandType == CMD_INSERT) ||
865
867 {
868 int values_attrno = 0;
869
870
871 if (values_rte && new_tle && IsA(new_tle->expr, Var))
872 {
874
875 if (var->varno == values_rte_index)
876 values_attrno = var->varattno;
877 }
878
879
880
881
882
883
884 if (att_tup->attidentity == ATTRIBUTE_IDENTITY_ALWAYS && !apply_default)
885 {
887 apply_default = true;
889 {
890
891
892
893
894
895
896 if (values_attrno != 0)
897 {
898 if (default_only_cols == NULL)
900
901 if (bms_is_member(values_attrno, default_only_cols))
902 apply_default = true;
903 }
904
905 if (!apply_default)
907 (errcode(ERRCODE_GENERATED_ALWAYS),
908 errmsg("cannot insert a non-DEFAULT value into column \"%s\"",
909 NameStr(att_tup->attname)),
910 errdetail("Column \"%s\" is an identity column defined as GENERATED ALWAYS.",
911 NameStr(att_tup->attname)),
912 errhint("Use OVERRIDING SYSTEM VALUE to override.")));
913 }
914 }
915
916
917
918
919
920
921 if (att_tup->attidentity == ATTRIBUTE_IDENTITY_BY_DEFAULT &&
923 apply_default = true;
924
925
926
927
928
929 if (att_tup->attgenerated && !apply_default)
930 {
931
932
933
934
935 if (values_attrno != 0)
936 {
937 if (default_only_cols == NULL)
939
940 if (bms_is_member(values_attrno, default_only_cols))
941 apply_default = true;
942 }
943
944 if (!apply_default)
946 (errcode(ERRCODE_GENERATED_ALWAYS),
947 errmsg("cannot insert a non-DEFAULT value into column \"%s\"",
948 NameStr(att_tup->attname)),
949 errdetail("Column \"%s\" is a generated column.",
950 NameStr(att_tup->attname))));
951 }
952
953
954
955
956
957
958 if (values_attrno != 0 && apply_default && unused_values_attrnos)
959 *unused_values_attrnos = bms_add_member(*unused_values_attrnos,
960 values_attrno);
961 }
962
963
964
965
966
967
969 {
970 if (att_tup->attidentity == ATTRIBUTE_IDENTITY_ALWAYS &&
971 new_tle && !apply_default)
973 (errcode(ERRCODE_GENERATED_ALWAYS),
974 errmsg("column \"%s\" can only be updated to DEFAULT",
975 NameStr(att_tup->attname)),
976 errdetail("Column \"%s\" is an identity column defined as GENERATED ALWAYS.",
977 NameStr(att_tup->attname))));
978
979 if (att_tup->attgenerated && new_tle && !apply_default)
981 (errcode(ERRCODE_GENERATED_ALWAYS),
982 errmsg("column \"%s\" can only be updated to DEFAULT",
983 NameStr(att_tup->attname)),
984 errdetail("Column \"%s\" is a generated column.",
985 NameStr(att_tup->attname))));
986 }
987
988 if (att_tup->attgenerated)
989 {
990
991
992
993
994 new_tle = NULL;
995 }
996 else if (apply_default)
997 {
998 Node *new_expr;
999
1001
1002
1003
1004
1005
1006
1007
1008
1009 if (!new_expr)
1010 {
1012 new_tle = NULL;
1013 else
1015 att_tup->atttypmod,
1016 att_tup->attcollation,
1017 att_tup->attlen,
1018 att_tup->attbyval);
1019 }
1020
1021 if (new_expr)
1023 attrno,
1025 false);
1026 }
1027
1028 if (new_tle)
1029 new_tlist = lappend(new_tlist, new_tle);
1030 }
1031
1032 pfree(new_tles);
1033
1034 return list_concat(new_tlist, junk_tlist);
1035}
1036
1037
1038
1039
1040
1041
1042
1043
1047 const char *attrName)
1048{
1051 Node *src_expr;
1052 Node *prior_expr;
1053 Node *src_input;
1054 Node *prior_input;
1055 Node *priorbottom;
1056 Node *newexpr;
1057
1058 if (prior_tle == NULL)
1059 {
1060
1061
1062
1063 return src_tle;
1064 }
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097 src_expr = (Node *) src_tle->expr;
1098 prior_expr = (Node *) prior_tle->expr;
1099
1104 {
1105
1109 }
1110
1113 if (src_input == NULL ||
1114 prior_input == NULL ||
1117 (errcode(ERRCODE_SYNTAX_ERROR),
1118 errmsg("multiple assignments to same column \"%s\"",
1119 attrName)));
1120
1121
1122
1123
1124 priorbottom = prior_input;
1125 for (;;)
1126 {
1128
1129 if (newbottom == NULL)
1130 break;
1131 priorbottom = newbottom;
1132 }
1133 if ((priorbottom, src_input))
1135 (errcode(ERRCODE_SYNTAX_ERROR),
1136 errmsg("multiple assignments to same column \"%s\"",
1137 attrName)));
1138
1139
1140
1141
1143 {
1145
1147 {
1148
1149 memcpy(fstore, prior_expr, sizeof(FieldStore));
1152 ((FieldStore *) src_expr)->newvals);
1153 fstore->fieldnums =
1155 ((FieldStore *) src_expr)->fieldnums);
1156 }
1157 else
1158 {
1159
1160 memcpy(fstore, src_expr, sizeof(FieldStore));
1161 fstore->arg = (Expr *) prior_expr;
1162 }
1163 newexpr = (Node *) fstore;
1164 }
1166 {
1168
1171 newexpr = (Node *) sbsref;
1172 }
1173 else
1174 {
1176 newexpr = NULL;
1177 }
1178
1179 if (coerce_expr)
1180 {
1181
1183
1184 memcpy(newcoerce, coerce_expr, sizeof(CoerceToDomain));
1185 newcoerce->arg = (Expr *) newexpr;
1186 newexpr = (Node *) newcoerce;
1187 }
1188
1190 result->expr = (Expr *) newexpr;
1191 return result;
1192}
1193
1194
1195
1196
1197static Node *
1199{
1200 if (node == NULL)
1201 return NULL;
1203 {
1205
1206 return (Node *) fstore->arg;
1207 }
1209 {
1211
1213 return NULL;
1214
1216 }
1217
1218 return NULL;
1219}
1220
1221
1222
1223
1224
1225
1228{
1231 Oid atttype = att_tup->atttypid;
1232 int32 atttypmod = att_tup->atttypmod;
1233 Node *expr = NULL;
1234 Oid exprtype;
1235
1236 if (att_tup->attidentity)
1237 {
1239
1241 nve->typeId = att_tup->atttypid;
1242
1243 return (Node *) nve;
1244 }
1245
1246
1247
1248
1249 if (att_tup->atthasdef)
1250 {
1252 if (expr == NULL)
1253 elog(ERROR, "default expression not found for attribute %d of relation \"%s\"",
1255 }
1256
1257
1258
1259
1260
1261 if (expr == NULL && !att_tup->attgenerated)
1263
1264 if (expr == NULL)
1265 return NULL;
1266
1267
1268
1269
1270
1271
1272
1273
1275
1277 expr, exprtype,
1278 atttype, atttypmod,
1281 -1);
1282 if (expr == NULL)
1284 (errcode(ERRCODE_DATATYPE_MISMATCH),
1285 errmsg("column \"%s\" is of type %s"
1286 " but default expression is of type %s",
1287 NameStr(att_tup->attname),
1290 errhint("You will need to rewrite or cast the expression.")));
1291
1292 return expr;
1293}
1294
1295
1296
1297static bool
1299{
1301
1303 {
1306
1307 foreach(lc2, sublist)
1308 {
1310
1312 return true;
1313 }
1314 }
1315 return false;
1316}
1317
1318
1319
1320
1321
1322
1325{
1326 Bitmapset *default_only_cols = NULL;
1328
1330 {
1333 int i;
1334
1335 if (default_only_cols == NULL)
1336 {
1337
1338 i = 0;
1339 foreach(lc2, sublist)
1340 {
1342
1343 i++;
1345 default_only_cols = bms_add_member(default_only_cols, i);
1346 }
1347 }
1348 else
1349 {
1350
1351 i = 0;
1352 foreach(lc2, sublist)
1353 {
1355
1356 i++;
1358 default_only_cols = bms_del_member(default_only_cols, i);
1359 }
1360 }
1361
1362
1363
1364
1365
1367 break;
1368 }
1369
1370 return default_only_cols;
1371}
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411static bool
1415{
1416 List *newValues;
1418 bool isAutoUpdatableView;
1419 bool allReplaced;
1420 int numattrs;
1421 int *attrnos;
1422
1423
1426
1427
1428
1429
1430
1431
1433 return true;
1434
1435
1436
1437
1438
1439
1440
1441
1443 attrnos = (int *) palloc0(numattrs * sizeof(int));
1444
1446 {
1448
1450 {
1452
1454 {
1456
1457 Assert(attrno >= 1 && attrno <= numattrs);
1458 attrnos[attrno - 1] = tle->resno;
1459 }
1460 }
1461 }
1462
1463
1464
1465
1466
1467
1468 isAutoUpdatableView = false;
1469 if (target_relation->rd_rel->relkind == RELKIND_VIEW &&
1471 {
1472 List *locks;
1473 bool hasUpdate;
1474 bool found;
1476
1477
1479 parsetree->resultRelation, parsetree, &hasUpdate);
1480
1481 found = false;
1482 foreach(l, locks)
1483 {
1485
1487 rule_lock->qual == NULL)
1488 {
1489 found = true;
1490 break;
1491 }
1492 }
1493
1494
1495
1496
1497
1498
1499 if (!found)
1500 isAutoUpdatableView = true;
1501 }
1502
1503 newValues = NIL;
1504 allReplaced = true;
1506 {
1510 int i;
1511
1513
1514 i = 0;
1515 foreach(lc2, sublist)
1516 {
1518 int attrno = attrnos[i++];
1519
1521 {
1523 Node *new_expr;
1524
1525
1526
1527
1528
1529
1531 {
1533
1534 newList = lappend(newList,
1536 def->typeMod,
1537 def->collation));
1538 continue;
1539 }
1540
1541 if (attrno == 0)
1542 elog(ERROR, "cannot set value in column %d to DEFAULT", i);
1543 Assert(attrno > 0 && attrno <= target_relation->rd_att->natts);
1545
1546 if (!att_tup->attisdropped)
1548 else
1549 new_expr = NULL;
1550
1551
1552
1553
1554
1555
1556 if (!new_expr)
1557 {
1558 if (isAutoUpdatableView)
1559 {
1560
1561 newList = lappend(newList, col);
1562 allReplaced = false;
1563 continue;
1564 }
1565
1567 att_tup->atttypmod,
1568 att_tup->attcollation,
1569 att_tup->attlen,
1570 att_tup->attbyval);
1571 }
1572 newList = lappend(newList, new_expr);
1573 }
1574 else
1575 newList = lappend(newList, col);
1576 }
1577 newValues = lappend(newValues, newList);
1578 }
1580
1582
1583 return allReplaced;
1584}
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596static void
1598{
1599 List *newValues;
1601
1602 newValues = NIL;
1604 {
1608
1609 foreach(lc2, sublist)
1610 {
1612
1614 {
1616
1618 def->typeMod,
1619 def->collation));
1620 }
1621 else
1622 newList = lappend(newList, col);
1623 }
1624 newValues = lappend(newValues, newList);
1625 }
1627}
1628
1629
1630
1631
1632
1633
1634static List *
1637 int varno,
1638 Query *parsetree,
1639 bool *hasUpdate)
1640{
1642 List *matching_locks = NIL;
1643 int nlocks;
1644 int i;
1645
1646 if (rulelocks == NULL)
1647 return NIL;
1648
1650 {
1651 if (parsetree->resultRelation != varno)
1652 return NIL;
1653 }
1654
1655 nlocks = rulelocks->numLocks;
1656
1657 for (i = 0; i < nlocks; i++)
1658 {
1660
1662 *hasUpdate = true;
1663
1664
1665
1666
1667
1668
1669
1671 {
1673 {
1676 continue;
1677 }
1678 else
1679 {
1682 continue;
1683 }
1684
1685
1688 errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1689 errmsg("cannot execute MERGE on relation \"%s\"",
1691 errdetail("MERGE is not supported for relations with rules."));
1692 }
1693
1694 if (oneLock->event == event)
1695 {
1698 matching_locks = lappend(matching_locks, oneLock);
1699 }
1700 }
1701
1702 return matching_locks;
1703}
1704
1705
1706
1707
1708
1712 int rt_index,
1714 List *activeRIRs)
1715{
1716 Query *rule_action;
1719 int numCols;
1720
1722 elog(ERROR, "expected just one rule action");
1723 if (rule->qual != NULL)
1724 elog(ERROR, "cannot handle qualified ON SELECT rule");
1725
1726
1730 (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1731 errmsg("access to non-system view \"%s\" is restricted",
1733
1734 if (rt_index == parsetree->resultRelation)
1735 {
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1754 return parsetree;
1758 {
1760 Var *var;
1762
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1780 parsetree->resultRelation, 0);
1781
1782
1783
1784
1785
1786
1787
1792 true);
1793
1795
1796
1797 }
1798 else
1799 elog(ERROR, "unrecognized commandType: %d",
1801 }
1802
1803
1804
1805
1806
1807
1808
1809
1811
1812
1813
1814
1815
1816
1818
1820
1821
1822
1823
1824
1825
1826 if (rc != NULL)
1829
1830
1831
1832
1833 rule_action = fireRIRrules(rule_action, activeRIRs);
1834
1835
1836
1837
1838
1839 parsetree->hasRowSecurity |= rule_action->hasRowSecurity;
1840
1841
1842
1843
1844
1846
1848 rte->subquery = rule_action;
1850
1851
1852
1853
1854
1855
1856
1858 rte->inh = false;
1859
1860
1861
1862
1863
1864
1865
1866
1868 while (list_length(rte->eref->colnames) < numCols)
1869 {
1870 rte->eref->colnames = lappend(rte->eref->colnames,
1872 }
1873
1874 return parsetree;
1875}
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889static void
1892 bool pushedDown)
1893{
1894 if (jtnode == NULL)
1895 return;
1897 {
1898 int rti = ((RangeTblRef *) jtnode)->rtindex;
1900
1902 {
1904
1906
1909 }
1911 {
1913
1915 strength, waitPolicy, true);
1916 }
1917
1918 }
1920 {
1923
1926 }
1928 {
1930
1933 }
1934 else
1935 elog(ERROR, "unrecognized node type: %d",
1937}
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953static bool
1955{
1956 if (node == NULL)
1957 return false;
1959 {
1961
1962
1965
1966
1967
1968
1970
1971
1972 }
1973
1974
1975
1976
1977
1979}
1980
1981
1982
1983
1984
1985
1986
1987
1988
1991{
1992 int origResultRelation = parsetree->resultRelation;
1993 int rt_index;
1995
1996
1997
1998
1999
2000
2001
2002 foreach(lc, parsetree->cteList)
2003 {
2005
2006 if (cte->search_clause || cte->cycle_clause)
2007 {
2010 }
2011 }
2012
2013
2014
2015
2016
2017 rt_index = 0;
2019 {
2022 List *locks;
2025 int i;
2026
2027 ++rt_index;
2028
2030
2031
2032
2033
2034
2035
2037 {
2039
2040
2041
2042
2043
2044 parsetree->hasRowSecurity |= rte->subquery->hasRowSecurity;
2045
2046 continue;
2047 }
2048
2049
2050
2051
2053 continue;
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065 if (rte->relkind == RELKIND_MATVIEW)
2066 continue;
2067
2068
2069
2070
2071
2072
2073
2074
2077 continue;
2078
2079
2080
2081
2082
2083
2084
2085
2086 if (rt_index != parsetree->resultRelation &&
2088 continue;
2089
2090
2091
2092
2093
2094 if (rt_index == parsetree->resultRelation &&
2095 rt_index != origResultRelation)
2096 continue;
2097
2098
2099
2100
2101
2103
2104
2105
2106
2108 if (rules != NULL)
2109 {
2110 locks = NIL;
2111 for (i = 0; i < rules->numLocks; i++)
2112 {
2115 continue;
2116
2118 }
2119
2120
2121
2122
2123 if (locks != NIL)
2124 {
2126
2129 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
2130 errmsg("infinite recursion detected in rules for relation \"%s\"",
2133
2134 foreach(l, locks)
2135 {
2137
2140 rt_index,
2141 rel,
2142 activeRIRs);
2143 }
2144
2146 }
2147 }
2148
2150 }
2151
2152
2153 foreach(lc, parsetree->cteList)
2154 {
2156
2159
2160
2161
2162
2163
2164 parsetree->hasRowSecurity |= ((Query *) cte->ctequery)->hasRowSecurity;
2165 }
2166
2167
2168
2169
2170
2171 if (parsetree->hasSubLinks)
2172 {
2174
2177
2180
2181
2182
2183
2184
2185 parsetree->hasRowSecurity |= context.hasRowSecurity;
2186 }
2187
2188
2189
2190
2191
2192
2193
2194 rt_index = 0;
2195 foreach(lc, parsetree->rtable)
2196 {
2199 List *securityQuals;
2200 List *withCheckOptions;
2201 bool hasRowSecurity;
2202 bool hasSubLinks;
2203
2204 ++rt_index;
2205
2206
2208 (rte->relkind != RELKIND_RELATION &&
2209 rte->relkind != RELKIND_PARTITIONED_TABLE))
2210 continue;
2211
2213
2214
2215
2216
2218 &securityQuals, &withCheckOptions,
2219 &hasRowSecurity, &hasSubLinks);
2220
2221 if (securityQuals != NIL || withCheckOptions != NIL)
2222 {
2223 if (hasSubLinks)
2224 {
2227
2228
2229
2230
2231
2234 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
2235 errmsg("infinite recursion detected in policy for relation \"%s\"",
2237
2239
2240
2241
2242
2243
2244
2245
2246
2247
2251 &context);
2252
2253
2254
2255
2256
2257 fire_context.activeRIRs = activeRIRs;
2259
2262
2265
2266
2267
2268
2269
2270
2271 Assert(hasRowSecurity);
2272
2274 }
2275
2276
2277
2278
2279
2280
2281
2282 rte->securityQuals = list_concat(securityQuals,
2283 rte->securityQuals);
2284
2285 parsetree->withCheckOptions = list_concat(withCheckOptions,
2286 parsetree->withCheckOptions);
2287 }
2288
2289
2290
2291
2292
2293 if (hasRowSecurity)
2294 parsetree->hasRowSecurity = true;
2295 if (hasSubLinks)
2296 parsetree->hasSubLinks = true;
2297
2299 }
2300
2301 return parsetree;
2302}
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2320 Node *rule_qual,
2321 int rt_index,
2323{
2324
2327
2329
2330
2331
2332
2333
2334
2335
2337
2338
2340
2344 0,
2348 parsetree->resultRelation,
2352 rt_index,
2353 &parsetree->hasSubLinks);
2354
2356
2357 return parsetree;
2358}
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389static List *
2391 int rt_index,
2393 List *locks,
2394 bool *instead_flag,
2395 bool *returning_flag,
2396 Query **qual_product)
2397{
2400
2401 foreach(l, locks)
2402 {
2404 Node *event_qual = rule_lock->qual;
2408
2409
2411 {
2412 if (event_qual != NULL)
2414 else
2415 {
2417 *instead_flag = true;
2418 }
2419 }
2420 else
2422
2424 {
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437 if (!*instead_flag)
2438 {
2439 if (*qual_product == NULL)
2440 *qual_product = copyObject(parsetree);
2442 event_qual,
2443 rt_index,
2444 event);
2445 }
2446 }
2447
2448
2449 foreach(r, actions)
2450 {
2452
2454 continue;
2455
2457 event_qual, rt_index, event,
2458 returning_flag);
2459
2460 rule_action->querySource = qsrc;
2461 rule_action->canSetTag = false;
2462
2463 results = lappend(results, rule_action);
2464 }
2465 }
2466
2467 return results;
2468}
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2482{
2483 int i;
2484
2485 Assert(view->rd_rel->relkind == RELKIND_VIEW);
2486
2488 {
2490
2492 {
2493
2495 elog(ERROR, "invalid _RETURN rule action specification");
2496
2498 }
2499 }
2500
2501 elog(ERROR, "failed to find _RETURN rule for view");
2502 return NULL;
2503}
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519bool
2521{
2523
2524 switch (event)
2525 {
2528 return true;
2529 break;
2532 return true;
2533 break;
2536 return true;
2537 break;
2540 {
2541 switch (action->commandType)
2542 {
2545 return false;
2546 break;
2549 return false;
2550 break;
2553 return false;
2554 break;
2556
2557 break;
2558 default:
2559 elog(ERROR, "unrecognized commandType: %d", action->commandType);
2560 break;
2561 }
2562 }
2563 return true;
2564 default:
2565 elog(ERROR, "unrecognized CmdType: %d", (int) event);
2566 break;
2567 }
2568 return false;
2569}
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583static const char *
2585{
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597 if (tle->resjunk)
2598 return gettext_noop("Junk view columns are not updatable.");
2599
2600 if ((var, Var) ||
2603 return gettext_noop("View columns that are not columns of their base relation are not updatable.");
2604
2606 return gettext_noop("View columns that refer to system columns are not updatable.");
2607
2609 return gettext_noop("View columns that return whole-row references are not updatable.");
2610
2611 return NULL;
2612}
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631const char *
2633{
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2670 return gettext_noop("Views containing DISTINCT are not automatically updatable.");
2671
2673 return gettext_noop("Views containing GROUP BY are not automatically updatable.");
2674
2676 return gettext_noop("Views containing HAVING are not automatically updatable.");
2677
2679 return gettext_noop("Views containing UNION, INTERSECT, or EXCEPT are not automatically updatable.");
2680
2682 return gettext_noop("Views containing WITH are not automatically updatable.");
2683
2685 return gettext_noop("Views containing LIMIT or OFFSET are not automatically updatable.");
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696 if (viewquery->hasAggs)
2697 return gettext_noop("Views that return aggregate functions are not automatically updatable.");
2698
2699 if (viewquery->hasWindowFuncs)
2700 return gettext_noop("Views that return window functions are not automatically updatable.");
2701
2702 if (viewquery->hasTargetSRFs)
2703 return gettext_noop("Views that return set-returning functions are not automatically updatable.");
2704
2705
2706
2707
2708
2710 return gettext_noop("Views that do not select from a single table or view are not automatically updatable.");
2711
2714 return gettext_noop("Views that do not select from a single table or view are not automatically updatable.");
2715
2718 (base_rte->relkind != RELKIND_RELATION &&
2719 base_rte->relkind != RELKIND_FOREIGN_TABLE &&
2720 base_rte->relkind != RELKIND_VIEW &&
2721 base_rte->relkind != RELKIND_PARTITIONED_TABLE))
2722 return gettext_noop("Views that do not select from a single table or view are not automatically updatable.");
2723
2725 return gettext_noop("Views containing TABLESAMPLE are not automatically updatable.");
2726
2727
2728
2729
2730
2731 if (check_cols)
2732 {
2734 bool found;
2735
2736 found = false;
2737 foreach(cell, viewquery->targetList)
2738 {
2740
2742 {
2743 found = true;
2744 break;
2745 }
2746 }
2747
2748 if (!found)
2749 return gettext_noop("Views that have no updatable columns are not automatically updatable.");
2750 }
2751
2752 return NULL;
2753}
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779static const char *
2783 char **non_updatable_col)
2784{
2788
2789
2790
2791
2792
2795
2796
2797 if (updatable_cols != NULL)
2798 *updatable_cols = NULL;
2799 if (non_updatable_col != NULL)
2800 *non_updatable_col = NULL;
2801
2802
2804 foreach(cell, viewquery->targetList)
2805 {
2807 const char *col_update_detail;
2808
2809 col++;
2811
2812 if (col_update_detail == NULL)
2813 {
2814
2815 if (updatable_cols != NULL)
2816 *updatable_cols = bms_add_member(*updatable_cols, col);
2817 }
2819 {
2820
2821 if (non_updatable_col != NULL)
2822 *non_updatable_col = tle->resname;
2823 return col_update_detail;
2824 }
2825 }
2826
2827 return NULL;
2828}
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862int
2864 List *outer_reloids,
2865 bool include_triggers,
2867{
2868 int events = 0;
2871
2872#define ALL_EVENTS ((1 << CMD_INSERT) | (1 << CMD_UPDATE) | (1 << CMD_DELETE))
2873
2874
2876
2878
2879
2880
2881
2882
2883
2884
2885 if (rel == NULL)
2886 return 0;
2887
2888
2890 {
2892 return 0;
2893 }
2894
2895
2896 if (rel->rd_rel->relkind == RELKIND_RELATION ||
2897 rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
2898 {
2901 }
2902
2903
2905 if (rulelocks != NULL)
2906 {
2907 int i;
2908
2909 for (i = 0; i < rulelocks->numLocks; i++)
2910 {
2913 {
2915 }
2916 }
2917
2918
2920 {
2922 return events;
2923 }
2924 }
2925
2926
2927 if (include_triggers)
2928 {
2930
2931 if (trigDesc)
2932 {
2939
2940
2942 {
2944 return events;
2945 }
2946 }
2947 }
2948
2949
2950 if (rel->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
2951 {
2953
2956 else
2957 {
2958
2965 }
2966
2968 return events;
2969 }
2970
2971
2972 if (rel->rd_rel->relkind == RELKIND_VIEW)
2973 {
2975
2977 {
2979 int auto_events;
2982 Oid baseoid;
2983
2984
2985
2986
2987
2988
2989
2991 &updatable_cols, NULL);
2992
2993 if (include_cols != NULL)
2994 updatable_cols = bms_int_members(updatable_cols, include_cols);
2995
2997 auto_events = (1 << CMD_DELETE);
2998 else
2999 auto_events = ALL_EVENTS;
3000
3001
3002
3003
3004
3005
3006
3010
3011 if (base_rte->relkind != RELKIND_RELATION &&
3012 base_rte->relkind != RELKIND_PARTITIONED_TABLE)
3013 {
3014 baseoid = base_rte->relid;
3015 outer_reloids = lappend_oid(outer_reloids,
3020 outer_reloids,
3021 include_triggers,
3022 include_cols);
3024 }
3025 events |= auto_events;
3026 }
3027 }
3028
3029
3031 return events;
3032}
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3045{
3047 int col;
3048
3049 col = -1;
3051 {
3052
3054
3056 {
3057
3058
3059
3060
3061
3062
3063
3065
3066 foreach(lc, targetlist)
3067 {
3069 Var *var;
3070
3071 if (tle->resjunk)
3072 continue;
3076 }
3077 }
3078 else
3079 {
3080
3081
3082
3083
3084
3086
3087 if (tle != NULL && !tle->resjunk && IsA(tle->expr, Var))
3088 {
3090
3093 }
3094 else
3095 elog(ERROR, "attribute number %d not found in view targetlist",
3096 attno);
3097 }
3098 }
3099
3100 return result;
3101}
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117void
3120 List *mergeActionList,
3121 const char *detail)
3122{
3124
3125 switch (command)
3126 {
3129 errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
3130 errmsg("cannot insert into view \"%s\"",
3133 errhint("To enable inserting into the view, provide an INSTEAD OF INSERT trigger or an unconditional ON INSERT DO INSTEAD rule."));
3134 break;
3137 errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
3138 errmsg("cannot update view \"%s\"",
3141 errhint("To enable updating the view, provide an INSTEAD OF UPDATE trigger or an unconditional ON UPDATE DO INSTEAD rule."));
3142 break;
3145 errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
3146 errmsg("cannot delete from view \"%s\"",
3149 errhint("To enable deleting from the view, provide an INSTEAD OF DELETE trigger or an unconditional ON DELETE DO INSTEAD rule."));
3150 break;
3152
3153
3154
3155
3156
3158 {
3159 switch (action->commandType)
3160 {
3164 errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
3165 errmsg("cannot insert into view \"%s\"",
3168 errhint("To enable inserting into the view using MERGE, provide an INSTEAD OF INSERT trigger."));
3169 break;
3173 errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
3174 errmsg("cannot update view \"%s\"",
3177 errhint("To enable updating the view using MERGE, provide an INSTEAD OF UPDATE trigger."));
3178 break;
3182 errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
3183 errmsg("cannot delete from view \"%s\"",
3186 errhint("To enable deleting from the view using MERGE, provide an INSTEAD OF DELETE trigger."));
3187 break;
3189 break;
3190 default:
3191 elog(ERROR, "unrecognized commandType: %d", action->commandType);
3192 break;
3193 }
3194 }
3195 break;
3196 default:
3197 elog(ERROR, "unrecognized CmdType: %d", (int) command);
3198 break;
3199 }
3200}
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3214{
3215 Query *viewquery;
3216 bool insert_or_update;
3217 const char *auto_update_detail;
3219 int base_rt_index;
3220 int new_rt_index;
3228 List *view_targetlist;
3230
3231
3232
3233
3234
3235
3236
3237
3239
3240
3241 view_rte = rt_fetch(parsetree->resultRelation, parsetree->rtable);
3243
3244
3245
3246
3247
3248
3249 insert_or_update =
3252
3254 {
3256 {
3259 {
3260 insert_or_update = true;
3261 break;
3262 }
3263 }
3264 }
3265
3266
3270 (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
3271 errmsg("access to non-system view \"%s\" is restricted",
3273
3274
3275
3276
3277
3278
3279
3280 auto_update_detail =
3282
3283 if (auto_update_detail)
3287 auto_update_detail);
3288
3289
3290
3291
3292
3293 if (insert_or_update)
3294 {
3296 char *non_updatable_col;
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3310
3312 {
3314
3315 if (!tle->resjunk)
3318 }
3319
3321 {
3323 {
3325
3326 if (!tle->resjunk)
3329 }
3330 }
3331
3333 {
3336 {
3338 {
3339 if (!tle->resjunk)
3342 }
3343 }
3344 }
3345
3347 modified_cols,
3348 NULL,
3349 &non_updatable_col);
3350 if (auto_update_detail)
3351 {
3352
3353
3354
3355
3357 {
3360 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3361 errmsg("cannot insert into column \"%s\" of view \"%s\"",
3362 non_updatable_col,
3365 break;
3368 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3369 errmsg("cannot update column \"%s\" of view \"%s\"",
3370 non_updatable_col,
3373 break;
3376 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3377 errmsg("cannot merge into column \"%s\" of view \"%s\"",
3378 non_updatable_col,
3381 break;
3382 default:
3383 elog(ERROR, "unrecognized CmdType: %d",
3385 break;
3386 }
3387 }
3388 }
3389
3390
3391
3392
3393
3394
3395
3396
3398 {
3400 {
3404 errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3405 errmsg("cannot merge into view \"%s\"",
3407 errdetail("MERGE is not supported for views with INSTEAD OF triggers for some actions but not all."),
3408 errhint("To enable merging into the view, either provide a full set of INSTEAD OF triggers or drop the existing INSTEAD OF triggers."));
3409 }
3410 }
3411
3412
3413
3414
3415
3418
3419 base_rt_index = rtr->rtindex;
3420 base_rte = rt_fetch(base_rt_index, viewquery->rtable);
3423
3424
3425
3426
3427
3428
3429
3430
3432
3433
3434
3435
3436
3437 base_rte->relkind = base_rel->rd_rel->relkind;
3438
3439
3440
3441
3442
3443
3444
3445 if (viewquery->hasSubLinks)
3446 {
3448
3452 }
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465 new_rte = base_rte;
3467
3470
3471
3472
3473
3474
3476 new_rte->inh = false;
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486 view_targetlist = viewquery->targetList;
3487
3489 base_rt_index,
3490 new_rt_index,
3491 0);
3492
3493
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512 new_rte->perminfoindex = 0;
3516 else
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3546
3548
3551
3554
3555
3556
3557
3558
3559
3560 new_rte->securityQuals = view_rte->securityQuals;
3561 view_rte->securityQuals = NIL;
3562
3563
3564
3565
3566
3567 parsetree = (Query *)
3569 parsetree->resultRelation,
3570 0,
3571 view_rte,
3572 view_targetlist,
3573 new_rt_index,
3575 0,
3576 NULL);
3577
3578
3579
3580
3581
3582
3583
3585 parsetree->resultRelation,
3586 new_rt_index,
3587 0);
3588 Assert(parsetree->resultRelation == new_rt_index);
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3601 {
3603 {
3606
3607 if (tle->resjunk)
3608 continue;
3609
3611 if (view_tle != NULL && !view_tle->resjunk && IsA(view_tle->expr, Var))
3612 tle->resno = ((Var *) view_tle->expr)->varattno;
3613 else
3614 elog(ERROR, "attribute number %d not found in view targetlist",
3616 }
3617
3619 {
3622 {
3624 {
3626
3627 if (tle->resjunk)
3628 continue;
3629
3631 if (view_tle != NULL && !view_tle->resjunk && IsA(view_tle->expr, Var))
3632 tle->resno = ((Var *) view_tle->expr)->varattno;
3633 else
3634 elog(ERROR, "attribute number %d not found in view targetlist",
3635 tle->resno);
3636 }
3637 }
3638 }
3639 }
3640
3641
3642
3643
3644
3647 {
3648 Index old_exclRelIndex,
3649 new_exclRelIndex;
3652 List *tmp_tlist;
3653
3654
3655
3656
3657
3658
3660 {
3663
3664 if (tle->resjunk)
3665 continue;
3666
3668 if (view_tle != NULL && !view_tle->resjunk && IsA(view_tle->expr, Var))
3669 tle->resno = ((Var *) view_tle->expr)->varattno;
3670 else
3671 elog(ERROR, "attribute number %d not found in view targetlist",
3673 }
3674
3675
3676
3677
3678
3679
3680
3681
3682
3684
3686 base_rel,
3689 false, false);
3690 new_exclRte = new_exclNSItem->p_rte;
3691 new_exclRte->relkind = RELKIND_COMPOSITE_TYPE;
3692
3693 new_exclRte->perminfoindex = 0;
3694
3698
3699
3700
3701
3702
3705
3706
3707
3708
3709
3710
3711
3712
3713
3714 tmp_tlist = copyObject(view_targetlist);
3715
3717 new_exclRelIndex, 0);
3718
3721 old_exclRelIndex,
3722 0,
3723 view_rte,
3724 tmp_tlist,
3725 new_rt_index,
3727 0,
3728 &parsetree->hasSubLinks);
3729 }
3730
3731
3732
3733
3734
3735
3736
3737
3738
3739
3740
3741
3742
3745 {
3747
3748
3749
3750
3751
3752
3754
3755 ChangeVarNodes(viewqual, base_rt_index, new_rt_index, 0);
3756
3758 {
3759
3760
3761
3762
3763
3764
3765
3766
3767 new_rte = rt_fetch(new_rt_index, parsetree->rtable);
3768 new_rte->securityQuals = lcons(viewqual, new_rte->securityQuals);
3769
3770
3771
3772
3773
3774
3775
3776
3777
3778
3779 if (!parsetree->hasSubLinks)
3781 }
3782 else
3784 }
3785
3786
3787
3788
3789
3790
3791
3792 if (insert_or_update)
3793 {
3796
3797
3798
3799
3800
3801
3802
3803
3804
3805 if (parsetree->withCheckOptions != NIL)
3806 {
3809
3811 {
3812 has_wco = true;
3813 cascaded = true;
3814 }
3815 }
3816
3817
3818
3819
3820
3821
3822
3823
3824
3825
3826 if (has_wco && (cascaded || viewquery->jointree->quals != NULL))
3827 {
3829
3834 wco->qual = NULL;
3836
3837 parsetree->withCheckOptions = lcons(wco,
3838 parsetree->withCheckOptions);
3839
3841 {
3844
3845
3846
3847
3848
3849
3850
3851 if (!parsetree->hasSubLinks &&
3854 }
3855 }
3856 }
3857
3859
3860 return parsetree;
3861}
3862
3863
3864
3865
3866
3867
3868
3869
3870
3871
3872
3873
3874
3875static List *
3877{
3879 bool instead = false;
3880 bool returning = false;
3881 bool updatableview = false;
3882 Query *qual_product = NULL;
3885
3886
3887
3888
3889
3890
3891 foreach(lc1, parsetree->cteList)
3892 {
3895 List *newstuff;
3896
3898 continue;
3899
3900 newstuff = RewriteQuery(ctequery, rewrite_events, 0);
3901
3902
3903
3904
3905
3906
3908 {
3909
3916 {
3917
3918
3919
3920
3922 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3923 errmsg("DO INSTEAD NOTIFY rules are not supported for data-modifying statements in WITH")));
3924 }
3925
3926 Assert(!ctequery->canSetTag);
3927
3929 }
3930 else if (newstuff == NIL)
3931 {
3933 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3934 errmsg("DO INSTEAD NOTHING rules are not supported for data-modifying statements in WITH")));
3935 }
3936 else
3937 {
3939
3940
3941 foreach(lc2, newstuff)
3942 {
3944
3947 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3948 errmsg("conditional DO INSTEAD rules are not supported for data-modifying statements in WITH")));
3951 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3952 errmsg("DO ALSO rules are not supported for data-modifying statements in WITH")));
3953 }
3954
3956 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3957 errmsg("multi-statement DO INSTEAD rules are not supported for data-modifying statements in WITH")));
3958 }
3959 }
3960
3961
3962
3963
3964
3965
3966
3967
3968
3970 {
3971 int result_relation;
3974 List *locks;
3975 int product_orig_rt_length;
3976 List *product_queries;
3977 bool hasUpdate = false;
3978 int values_rte_index = 0;
3979 bool defaults_remaining = false;
3980
3981 result_relation = parsetree->resultRelation;
3982 Assert(result_relation != 0);
3983 rt_entry = rt_fetch(result_relation, parsetree->rtable);
3985
3986
3987
3988
3989
3991
3992
3993
3994
3996 {
3999
4000
4001
4002
4003
4004
4005
4007 {
4009
4011 {
4014
4016 {
4017
4018 if (values_rte != NULL)
4019 elog(ERROR, "more than one VALUES RTE found");
4020
4021 values_rte = rte;
4022 values_rte_index = rtr->rtindex;
4023 }
4024 }
4025 }
4026
4027 if (values_rte)
4028 {
4029 Bitmapset *unused_values_attrnos = NULL;
4030
4031
4034 parsetree->override,
4035 rt_entry_relation,
4036 values_rte,
4037 values_rte_index,
4038 &unused_values_attrnos);
4039
4040 if ((parsetree, values_rte, values_rte_index,
4041 rt_entry_relation,
4042 unused_values_attrnos))
4043 defaults_remaining = true;
4044 }
4045 else
4046 {
4047
4051 parsetree->override,
4052 rt_entry_relation,
4053 NULL, 0, NULL);
4054 }
4055
4058 {
4062 parsetree->override,
4063 rt_entry_relation,
4064 NULL, 0, NULL);
4065 }
4066 }
4068 {
4073 parsetree->override,
4074 rt_entry_relation,
4075 NULL, 0, NULL);
4076 }
4078 {
4080
4081
4082
4083
4085 {
4087
4088 switch (action->commandType)
4089 {
4091 case CMD_DELETE:
4092 break;
4095
4096
4097
4098
4099
4100 action->targetList =
4102 action->commandType,
4104 rt_entry_relation,
4105 NULL, 0, NULL);
4106 break;
4107 default:
4108 elog(ERROR, "unrecognized commandType: %d", action->commandType);
4109 break;
4110 }
4111 }
4112 }
4114 {
4115
4116 }
4117 else
4118 elog(ERROR, "unrecognized commandType: %d", (int) event);
4119
4120
4121
4122
4123 locks = matchLocks(event, rt_entry_relation,
4124 result_relation, parsetree, &hasUpdate);
4125
4127 product_queries = fireRules(parsetree,
4128 result_relation,
4129 event,
4130 locks,
4131 &instead,
4132 &returning,
4133 &qual_product);
4134
4135
4136
4137
4138
4139
4140
4141
4142
4143 if (defaults_remaining && product_queries != NIL)
4144 {
4146
4147
4148
4149
4150
4151
4152
4153
4154
4155
4156 foreach(n, product_queries)
4157 {
4160
4164 {
4166
4168 {
4169 int rtindex = ((RangeTblRef *) jtnode)->rtindex;
4171
4177 }
4178 }
4179
4180 values_rte = rt_fetch(values_rte_index, pt->rtable);
4182 elog(ERROR, "failed to find VALUES RTE in product query");
4183
4185 }
4186 }
4187
4188
4189
4190
4191
4192
4193
4194
4195
4196
4197
4198
4199
4200
4201
4202
4203 if (!instead &&
4204 rt_entry_relation->rd_rel->relkind == RELKIND_VIEW &&
4207 {
4208
4209
4210
4211
4212
4213 if (qual_product != NULL)
4217 gettext_noop("Views with conditional DO INSTEAD rules are not automatically updatable."));
4218
4219
4220
4221
4222
4223
4225
4226
4227
4228
4229
4230
4231
4233 product_queries = lcons(parsetree, product_queries);
4234 else
4235 product_queries = lappend(product_queries, parsetree);
4236
4237
4238
4239
4240
4241
4242
4243
4244 instead = true;
4245 returning = true;
4246 updatableview = true;
4247 }
4248
4249
4250
4251
4252
4253 if (product_queries != NIL)
4254 {
4257
4258 foreach(n, rewrite_events)
4259 {
4262 rev->event == event)
4264 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
4265 errmsg("infinite recursion detected in rules for relation \"%s\"",
4267 }
4268
4271 rev->event = event;
4272 rewrite_events = lappend(rewrite_events, rev);
4273
4274 foreach(n, product_queries)
4275 {
4277 List *newstuff;
4278
4279
4280
4281
4282
4283
4284
4285
4286
4287
4289 pt == parsetree ?
4290 orig_rt_length :
4291 product_orig_rt_length);
4292 rewritten = list_concat(rewritten, newstuff);
4293 }
4294
4296 }
4297
4298
4299
4300
4301
4302
4303
4304
4305 if ((instead || qual_product != NULL) &&
4307 !returning)
4308 {
4309 switch (event)
4310 {
4313 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4314 errmsg("cannot perform INSERT RETURNING on relation \"%s\"",
4316 errhint("You need an unconditional ON INSERT DO INSTEAD rule with a RETURNING clause.")));
4317 break;
4320 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4321 errmsg("cannot perform UPDATE RETURNING on relation \"%s\"",
4323 errhint("You need an unconditional ON UPDATE DO INSTEAD rule with a RETURNING clause.")));
4324 break;
4327 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4328 errmsg("cannot perform DELETE RETURNING on relation \"%s\"",
4330 errhint("You need an unconditional ON DELETE DO INSTEAD rule with a RETURNING clause.")));
4331 break;
4332 default:
4333 elog(ERROR, "unrecognized commandType: %d",
4334 (int) event);
4335 break;
4336 }
4337 }
4338
4339
4340
4341
4342
4344 (product_queries != NIL || hasUpdate) &&
4345 !updatableview)
4347 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4348 errmsg("INSERT with ON CONFLICT clause cannot be used with table that has INSERT or UPDATE rules")));
4349
4351 }
4352
4353
4354
4355
4356
4357
4358
4359
4360
4361
4362
4363
4364
4365 if (!instead)
4366 {
4368 {
4369 if (qual_product != NULL)
4370 rewritten = lcons(qual_product, rewritten);
4371 else
4372 rewritten = lcons(parsetree, rewritten);
4373 }
4374 else
4375 {
4376 if (qual_product != NULL)
4377 rewritten = lappend(rewritten, qual_product);
4378 else
4379 rewritten = lappend(rewritten, parsetree);
4380 }
4381 }
4382
4383
4384
4385
4386
4387
4388
4389
4390
4392 {
4393 int qcount = 0;
4394
4395 foreach(lc1, rewritten)
4396 {
4398
4400 qcount++;
4401 }
4402 if (qcount > 1)
4404 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4405 errmsg("WITH cannot be used in a query that is rewritten by rules into multiple queries")));
4406 }
4407
4408 return rewritten;
4409}
4410
4411
4412
4413
4414
4415
4416
4417
4418
4419
4420
4421
4422
4423
4424
4425
4426
4427static Node *
4430{
4432
4435 {
4437
4438 for (int i = 0; i < tupdesc->natts; i++)
4439 {
4441
4442 if (attr->attgenerated == ATTRIBUTE_GENERATED_VIRTUAL)
4443 {
4444 Node *defexpr;
4446
4449
4451 tlist = lappend(tlist, te);
4452 }
4453 }
4454
4456
4458 result_relation,
4460 NULL);
4461 }
4462
4463 return node;
4464}
4465
4466
4467
4468
4469
4470
4471
4474{
4476
4478 {
4480
4482
4486
4488 }
4489
4490 return node;
4491}
4492
4493
4494
4495
4496
4497
4500{
4503 Node *defexpr;
4504 Oid attcollid;
4505
4507 Assert(att_tup->attgenerated == ATTRIBUTE_GENERATED_VIRTUAL);
4508
4510 if (defexpr == NULL)
4511 elog(ERROR, "no generation expression found for column number %d of table \"%s\"",
4513
4514
4515
4516
4517
4518
4519 attcollid = att_tup->attcollation;
4520 if (attcollid && attcollid != exprCollation(defexpr))
4521 {
4523
4524 ce->arg = (Expr *) defexpr;
4525 ce->collOid = attcollid;
4527
4528 defexpr = (Node *) ce;
4529 }
4530
4531 return defexpr;
4532}
4533
4534
4535
4536
4537
4538
4539
4540
4541
4542
4543
4546{
4547 uint64 input_query_id = parsetree->queryId;
4548 List *querylist;
4549 List *results;
4552 bool foundOriginalQuery;
4553 Query *lastInstead;
4554
4555
4556
4557
4559 Assert(parsetree->canSetTag);
4560
4561
4562
4563
4564
4565
4567
4568
4569
4570
4571
4572
4573
4574
4575 results = NIL;
4576 foreach(l, querylist)
4577 {
4579
4581
4582 query->queryId = input_query_id;
4583
4584 results = lappend(results, query);
4585 }
4586
4587
4588
4589
4590
4591
4592
4593
4594
4595
4596
4597
4598
4599
4600
4601
4602
4604 foundOriginalQuery = false;
4605 lastInstead = NULL;
4606
4607 foreach(l, results)
4608 {
4610
4612 {
4613 Assert(query->canSetTag);
4614 Assert(!foundOriginalQuery);
4615 foundOriginalQuery = true;
4616#ifndef USE_ASSERT_CHECKING
4617 break;
4618#endif
4619 }
4620 else
4621 {
4622 Assert(!query->canSetTag);
4623 if (query->commandType == origCmdType &&
4626 lastInstead = query;
4627 }
4628 }
4629
4630 if (!foundOriginalQuery && lastInstead != NULL)
4631 lastInstead->canSetTag = true;
4632
4633 return results;
4634}
#define InvalidAttrNumber
Bitmapset * bms_int_members(Bitmapset *a, const Bitmapset *b)
int bms_next_member(const Bitmapset *a, int prevbit)
Bitmapset * bms_del_member(Bitmapset *a, int x)
bool bms_is_member(int x, const Bitmapset *a)
Bitmapset * bms_add_member(Bitmapset *a, int x)
Bitmapset * bms_union(const Bitmapset *a, const Bitmapset *b)
int errdetail_internal(const char *fmt,...)
int errdetail(const char *fmt,...)
int errhint(const char *fmt,...)
int errcode(int sqlerrcode)
int errmsg(const char *fmt,...)
#define ereport(elevel,...)
bool equal(const void *a, const void *b)
int ExecCleanTargetListLength(List *targetlist)
FdwRoutine * GetFdwRoutineForRelation(Relation relation, bool makecopy)
char * format_type_be(Oid type_oid)
Assert(PointerIsAligned(start, uint64))
if(TABLE==NULL||TABLE_index==NULL)
List * lappend(List *list, void *datum)
List * list_concat(List *list1, const List *list2)
List * list_concat_copy(const List *list1, const List *list2)
List * lappend_oid(List *list, Oid datum)
List * lcons(void *datum, List *list)
List * list_delete_last(List *list)
bool list_member_oid(const List *list, Oid datum)
Node * get_typdefault(Oid typid)
Alias * makeAlias(const char *aliasname, List *colnames)
Const * makeNullConst(Oid consttype, int32 consttypmod, Oid constcollid)
Var * makeWholeRowVar(RangeTblEntry *rte, int varno, Index varlevelsup, bool allowScalar)
TargetEntry * makeTargetEntry(Expr *expr, AttrNumber resno, char *resname, bool resjunk)
TargetEntry * flatCopyTargetEntry(TargetEntry *src_tle)
char * pstrdup(const char *in)
void pfree(void *pointer)
void * palloc0(Size size)
Oid exprType(const Node *expr)
Oid exprCollation(const Node *expr)
Node * strip_implicit_coercions(Node *node)
#define query_tree_walker(q, w, c, f)
#define expression_tree_walker(n, w, c)
#define QTW_IGNORE_RC_SUBQUERIES
#define IsA(nodeptr, _type_)
#define castNode(_type_, nodeptr)
Node * coerce_null_to_domain(Oid typid, int32 typmod, Oid collation, int typlen, bool typbyval)
Node * coerce_to_target_type(ParseState *pstate, Node *expr, Oid exprtype, Oid targettype, int32 targettypmod, CoercionContext ccontext, CoercionForm cformat, int location)
ParseState * make_parsestate(ParseState *parentParseState)
ParseNamespaceItem * addRangeTableEntryForRelation(ParseState *pstate, Relation rel, int lockmode, Alias *alias, bool inh, bool inFromCl)
RTEPermissionInfo * getRTEPermissionInfo(List *rteperminfos, RangeTblEntry *rte)
RowMarkClause * get_parse_rowmark(Query *qry, Index rtindex)
TargetEntry * get_tle_by_resno(List *tlist, AttrNumber resno)
bool get_rte_attribute_is_dropped(RangeTblEntry *rte, AttrNumber attnum)
RTEPermissionInfo * addRTEPermissionInfo(List **rteperminfos, RangeTblEntry *rte)
#define ACL_SELECT_FOR_UPDATE
void applyLockingClause(Query *qry, Index rtindex, LockClauseStrength strength, LockWaitPolicy waitPolicy, bool pushedDown)
List * BuildOnConflictExcludedTargetlist(Relation targetrel, Index exclRelIndex)
#define rt_fetch(rangetable_index, rangetable)
FormData_pg_attribute * Form_pg_attribute
Oid getIdentitySequence(Relation rel, AttrNumber attnum, bool missing_ok)
#define lfirst_node(type, lc)
static int list_length(const List *l)
#define linitial_node(type, l)
#define foreach_delete_current(lst, var_or_cell)
#define foreach_node(type, var, lst)
int restrict_nonsystem_relation_kind
@ OVERRIDING_SYSTEM_VALUE
#define RelationGetRelid(relation)
#define RelationHasCheckOption(relation)
#define RelationHasSecurityInvoker(relation)
#define RelationGetDescr(relation)
#define RelationGetNumberOfAttributes(relation)
#define RelationGetRelationName(relation)
#define RelationHasCascadedCheckOption(relation)
#define RelationIsSecurityView(relation)
#define RULE_FIRES_ON_ORIGIN
#define RULE_FIRES_ON_REPLICA
static void markQueryForLocking(Query *qry, Node *jtnode, LockClauseStrength strength, LockWaitPolicy waitPolicy, bool pushedDown)
static Query * ApplyRetrieveRule(Query *parsetree, RewriteRule *rule, int rt_index, Relation relation, List *activeRIRs)
static Query * rewriteRuleAction(Query *parsetree, Query *rule_action, Node *rule_qual, int rt_index, CmdType event, bool *returning_flag)
static TargetEntry * process_matched_tle(TargetEntry *src_tle, TargetEntry *prior_tle, const char *attrName)
static bool fireRIRonSubLink(Node *node, fireRIRonSubLink_context *context)
static List * adjustJoinTreeList(Query *parsetree, bool removert, int rt_index)
void AcquireRewriteLocks(Query *parsetree, bool forExecute, bool forUpdatePushedDown)
bool view_has_instead_trigger(Relation view, CmdType event, List *mergeActionList)
static const char * view_cols_are_auto_updatable(Query *viewquery, Bitmapset *required_cols, Bitmapset **updatable_cols, char **non_updatable_col)
struct fireRIRonSubLink_context fireRIRonSubLink_context
static List * fireRules(Query *parsetree, int rt_index, CmdType event, List *locks, bool *instead_flag, bool *returning_flag, Query **qual_product)
static Query * CopyAndAddInvertedQual(Query *parsetree, Node *rule_qual, int rt_index, CmdType event)
int relation_is_updatable(Oid reloid, List *outer_reloids, bool include_triggers, Bitmapset *include_cols)
Query * get_view_query(Relation view)
static bool acquireLocksOnSubLinks(Node *node, acquireLocksOnSubLinks_context *context)
static bool rewriteValuesRTE(Query *parsetree, RangeTblEntry *rte, int rti, Relation target_relation, Bitmapset *unused_cols)
static Node * get_assignment_input(Node *node)
static List * RewriteQuery(Query *parsetree, List *rewrite_events, int orig_rt_length)
static Bitmapset * adjust_view_column_set(Bitmapset *cols, List *targetlist)
const char * view_query_is_auto_updatable(Query *viewquery, bool check_cols)
struct acquireLocksOnSubLinks_context acquireLocksOnSubLinks_context
static const char * view_col_is_auto_updatable(RangeTblRef *rtr, TargetEntry *tle)
static bool searchForDefault(RangeTblEntry *rte)
struct rewrite_event rewrite_event
static Query * fireRIRrules(Query *parsetree, List *activeRIRs)
static Query * rewriteTargetView(Query *parsetree, Relation view)
List * QueryRewrite(Query *parsetree)
static Node * expand_generated_columns_internal(Node *node, Relation rel, int rt_index, RangeTblEntry *rte, int result_relation)
static Bitmapset * findDefaultOnlyColumns(RangeTblEntry *rte)
static void rewriteValuesRTEToNulls(Query *parsetree, RangeTblEntry *rte)
Node * build_generation_expression(Relation rel, int attrno)
static List * matchLocks(CmdType event, Relation relation, int varno, Query *parsetree, bool *hasUpdate)
void error_view_not_updatable(Relation view, CmdType command, List *mergeActionList, const char *detail)
Node * build_column_default(Relation rel, int attrno)
static List * rewriteTargetListIU(List *targetList, CmdType commandType, OverridingKind override, Relation target_relation, RangeTblEntry *values_rte, int values_rte_index, Bitmapset **unused_values_attrnos)
Node * expand_generated_columns_in_expr(Node *node, Relation rel, int rt_index)
void ChangeVarNodes(Node *node, int rt_index, int new_index, int sublevels_up)
void OffsetVarNodes(Node *node, int offset, int sublevels_up)
bool checkExprHasSubLink(Node *node)
void CombineRangeTables(List **dst_rtable, List **dst_perminfos, List *src_rtable, List *src_perminfos)
void AddQual(Query *parsetree, Node *qual)
bool rangeTableEntry_used(Node *node, int rt_index, int sublevels_up)
Query * getInsertSelectQuery(Query *parsetree, Query ***subquery_ptr)
void AddInvertedQual(Query *parsetree, Node *qual)
Node * ReplaceVarsFromTargetList(Node *node, int target_varno, int sublevels_up, RangeTblEntry *target_rte, List *targetlist, int result_relation, ReplaceVarsNoMatchOption nomatch_option, int nomatch_varno, bool *outer_hasSubLinks)
@ REPLACEVARS_SUBSTITUTE_NULL
@ REPLACEVARS_CHANGE_VARNO
@ REPLACEVARS_REPORT_ERROR
CommonTableExpr * rewriteSearchAndCycle(CommonTableExpr *cte)
void get_row_security_policies(Query *root, RangeTblEntry *rte, int rt_index, List **securityQuals, List **withCheckOptions, bool *hasRowSecurity, bool *hasSubLinks)
void relation_close(Relation relation, LOCKMODE lockmode)
Relation try_relation_open(Oid relationId, LOCKMODE lockmode)
void check_stack_depth(void)
ExecForeignInsert_function ExecForeignInsert
ExecForeignUpdate_function ExecForeignUpdate
ExecForeignDelete_function ExecForeignDelete
IsForeignRelUpdatable_function IsForeignRelUpdatable
OnConflictExpr * onConflict
struct TableSampleClause * tablesample
LockClauseStrength strength
LockWaitPolicy waitPolicy
bool trig_update_instead_row
bool trig_delete_instead_row
bool trig_insert_instead_row
bool has_generated_virtual
#define FirstLowInvalidHeapAttributeNumber
void table_close(Relation relation, LOCKMODE lockmode)
Relation table_open(Oid relationId, LOCKMODE lockmode)
#define RESTRICT_RELKIND_VIEW
#define FirstNormalObjectId
int SessionReplicationRole
#define SESSION_REPLICATION_ROLE_REPLICA
Node * TupleDescGetDefault(TupleDesc tupdesc, AttrNumber attnum)
static FormData_pg_attribute * TupleDescAttr(TupleDesc tupdesc, int i)
String * makeString(char *str)
bool contain_vars_of_level(Node *node, int levelsup)
static struct rule * rules