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 (equal(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 (IsA(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 (rewriteValuesRTE(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