1414 | 1404 | int numattrs;
| 1415 | 1405 | int *attrnos;
|
1416 | 1406 |
|
| 1407 | + /* Steps below are not sensible for non-INSERT queries */ |
| 1408 | + Assert(parsetree->commandType == CMD_INSERT); |
| 1409 | + Assert(rte->rtekind == RTE_VALUES); |
| 1410 | + |
1417 | 1411 | /*
|
1418 | 1412 | * Rebuilding all the lists is a pretty expensive proposition in a big
|
1419 | 1413 | * VALUES list, and it's a waste of time if there aren't any DEFAULT
|
1420 | 1414 | * placeholders. So first scan to see if there are any.
|
1421 |
| - * |
1422 |
| - * We skip this check if force_nulls is true, because we know that there |
1423 |
| - * are DEFAULT items present in that case. |
1424 | 1415 | */
|
1425 |
| - if (!force_nulls && !searchForDefault(rte)) |
| 1416 | + if (!searchForDefault(rte)) |
1426 | 1417 | return true; /* nothing to do */
|
1427 | 1418 |
|
1428 | 1419 | /*
|
@@ -1456,12 +1447,10 @@ rewriteValuesRTE(Query *parsetree, RangeTblEntry *rte, int rti,
|
1456 | 1447 | /*
|
1457 | 1448 | * Check if the target relation is an auto-updatable view, in which case
|
1458 | 1449 | * unresolved defaults will be left untouched rather than being set to
|
1459 |
| - * NULL. If force_nulls is true, we always set DEFAULT items to NULL, so |
1460 |
| - * skip this check in that case --- it isn't an auto-updatable view. |
| 1450 | + * NULL. |
1461 | 1451 | */
|
1462 | 1452 | isAutoUpdatableView = false;
|
1463 |
| - if (!force_nulls && |
1464 |
| - target_relation->rd_rel->relkind == RELKIND_VIEW && |
| 1453 | + if (target_relation->rd_rel->relkind == RELKIND_VIEW && |
1465 | 1454 | !view_has_instead_trigger(target_relation, CMD_INSERT))
|
1466 | 1455 | {
|
1467 | 1456 | List *locks;
|
@@ -1535,9 +1524,10 @@ rewriteValuesRTE(Query *parsetree, RangeTblEntry *rte, int rti,
|
1535 | 1524 |
|
1536 | 1525 | if (attrno == 0)
|
1537 | 1526 | elog(ERROR, "cannot set value in column %d to DEFAULT", i);
|
| 1527 | + Assert(attrno > 0 && attrno <= target_relation->rd_att->natts); |
1538 | 1528 | att_tup = TupleDescAttr(target_relation->rd_att, attrno - 1);
|
1539 | 1529 |
|
1540 |
| - if (!force_nulls && !att_tup->attisdropped) |
| 1530 | + if (!att_tup->attisdropped) |
1541 | 1531 | new_expr = build_column_default(target_relation, attrno);
|
1542 | 1532 | else
|
1543 | 1533 | new_expr = NULL; /* force a NULL if dropped */
|
@@ -1587,6 +1577,50 @@ rewriteValuesRTE(Query *parsetree, RangeTblEntry *rte, int rti,
|
1587 | 1577 | return allReplaced;
|
1588 | 1578 | }
|
1589 | 1579 |
|
| 1580 | +/* |
| 1581 | + * Mop up any remaining DEFAULT items in the given VALUES RTE by |
| 1582 | + * replacing them with NULL constants. |
| 1583 | + * |
| 1584 | + * This is used for the product queries generated by DO ALSO rules attached to |
| 1585 | + * an auto-updatable view. The action can't depend on the "target relation" |
| 1586 | + * since the product query might not have one (it needn't be an INSERT). |
| 1587 | + * Essentially, such queries are treated as being attached to a rule-updatable |
| 1588 | + * view. |
| 1589 | + */ |
| 1590 | +static void |
| 1591 | +rewriteValuesRTEToNulls(Query *parsetree, RangeTblEntry *rte) |
| 1592 | +{ |
| 1593 | + List *newValues; |
| 1594 | + ListCell *lc; |
| 1595 | + |
| 1596 | + Assert(rte->rtekind == RTE_VALUES); |
| 1597 | + newValues = NIL; |
| 1598 | + foreach(lc, rte->values_lists) |
| 1599 | + { |
| 1600 | + List *sublist = (List *) lfirst(lc); |
| 1601 | + List *newList = NIL; |
| 1602 | + ListCell *lc2; |
| 1603 | + |
| 1604 | + foreach(lc2, sublist) |
| 1605 | + { |
| 1606 | + Node *col = (Node *) lfirst(lc2); |
| 1607 | + |
| 1608 | + if (IsA(col, SetToDefault)) |
| 1609 | + { |
| 1610 | + SetToDefault *def = (SetToDefault *) col; |
| 1611 | + |
| 1612 | + newList = lappend(newList, makeNullConst(def->typeId, |
| 1613 | + def->typeMod, |
| 1614 | + def->collation)); |
| 1615 | + } |
| 1616 | + else |
| 1617 | + newList = lappend(newList, col); |
| 1618 | + } |
| 1619 | + newValues = lappend(newValues, newList); |
| 1620 | + } |
| 1621 | + rte->values_lists = newValues; |
| 1622 | +} |
| 1623 | + |
1590 | 1624 |
|
1591 | 1625 | /*
|
1592 | 1626 | * Record in target_rte->extraUpdatedCols the indexes of any generated columns
|
@@ -3746,7 +3780,7 @@ RewriteQuery(Query *parsetree, List *rewrite_events)
|
3746 | 3780 | &unused_values_attrnos);
|
3747 | 3781 | /* ... and the VALUES expression lists */
|
3748 | 3782 | if (!rewriteValuesRTE(parsetree, values_rte, values_rte_index,
|
3749 |
| - rt_entry_relation, false, |
| 3783 | + rt_entry_relation, |
3750 | 3784 | unused_values_attrnos))
|
3751 | 3785 | defaults_remaining = true;
|
3752 | 3786 | }
|
@@ -3860,10 +3894,7 @@ RewriteQuery(Query *parsetree, List *rewrite_events)
|
3860 | 3894 | RangeTblEntry *values_rte = rt_fetch(values_rte_index,
|
3861 | 3895 | pt->rtable);
|
3862 | 3896 |
|
3863 |
| - rewriteValuesRTE(pt, values_rte, values_rte_index, |
3864 |
| - rt_entry_relation, |
3865 |
| - true, /* Force remaining defaults to NULL */ |
3866 |
| - NULL); |
| 3897 | + rewriteValuesRTEToNulls(pt, values_rte); |
3867 | 3898 | }
|
3868 | 3899 | }
|
3869 | 3900 |
|
|
0 commit comments