mirror of
https://git.postgresql.org/git/postgresql.git
synced 2024-09-01 03:47:24 +02:00
Further fixing for multi-row VALUES lists for updatable views.
Previously, rewriteTargetListIU() generated a list of attribute numbers from the targetlist, which were passed to rewriteValuesRTE(), which expected them to contain the same number of entries as there are columns in the VALUES RTE, and to be in the same order. That was fine when the target relation was a table, but for an updatable view it could be broken in at least three different ways --- rewriteTargetListIU() could insert additional targetlist entries for view columns with defaults, the view columns could be in a different order from the columns of the underlying base relation, and targetlist entries could be merged together when assigning to elements of an array or composite type. As a result, when recursing to the base relation, the list of attribute numbers generated from the rewritten targetlist could no longer be relied upon to match the columns of the VALUES RTE. We got away with that prior to41531e42d3
because it used to always be the case that rewriteValuesRTE() did nothing for the underlying base relation, since all DEFAULTS had already been replaced when it was initially invoked for the view, but that was incorrect because it failed to apply defaults from the base relation. Fix this by examining the targetlist entries more carefully and picking out just those that are simple Vars referencing the VALUES RTE. That's sufficient for the purposes of rewriteValuesRTE(), which is only responsible for dealing with DEFAULT items in the VALUES RTE. Any DEFAULT item in the VALUES RTE that doesn't have a matching simple-Var-assignment in the targetlist is an error which we complain about, but in theory that ought to be impossible. Additionally, move this code into rewriteValuesRTE() to give a clearer separation of concerns between the 2 functions. There is no need for rewriteTargetListIU() to know about the details of the VALUES RTE. While at it, fix the comment for rewriteValuesRTE() which claimed that it doesn't support array element and field assignments --- that hasn't been true sincea3c7a993d5
(9.6 and later). Back-patch to all supported versions, with minor differences for the pre-9.6 branches, which don't support array element and field assignments to the same column in multi-row VALUES lists. Reviewed by Amit Langote. Discussion: https://postgr.es/m/15623-5d67a46788ec8b7f@postgresql.org
This commit is contained in:
parent
0bf7f56cfe
commit
6ccb973373
@ -65,14 +65,13 @@ static List *rewriteTargetListIU(List *targetList,
|
|||||||
CmdType commandType,
|
CmdType commandType,
|
||||||
OverridingKind override,
|
OverridingKind override,
|
||||||
Relation target_relation,
|
Relation target_relation,
|
||||||
int result_rti,
|
int result_rti);
|
||||||
List **attrno_list);
|
|
||||||
static TargetEntry *process_matched_tle(TargetEntry *src_tle,
|
static TargetEntry *process_matched_tle(TargetEntry *src_tle,
|
||||||
TargetEntry *prior_tle,
|
TargetEntry *prior_tle,
|
||||||
const char *attrName);
|
const char *attrName);
|
||||||
static Node *get_assignment_input(Node *node);
|
static Node *get_assignment_input(Node *node);
|
||||||
static bool rewriteValuesRTE(Query *parsetree, RangeTblEntry *rte,
|
static bool rewriteValuesRTE(Query *parsetree, RangeTblEntry *rte, int rti,
|
||||||
Relation target_relation, List *attrnos, bool force_nulls);
|
Relation target_relation, bool force_nulls);
|
||||||
static void markQueryForLocking(Query *qry, Node *jtnode,
|
static void markQueryForLocking(Query *qry, Node *jtnode,
|
||||||
LockClauseStrength strength, LockWaitPolicy waitPolicy,
|
LockClauseStrength strength, LockWaitPolicy waitPolicy,
|
||||||
bool pushedDown);
|
bool pushedDown);
|
||||||
@ -701,11 +700,6 @@ adjustJoinTreeList(Query *parsetree, bool removert, int rt_index)
|
|||||||
* is not needed for rewriting, but will be needed by the planner, and we
|
* is not needed for rewriting, but will be needed by the planner, and we
|
||||||
* can do it essentially for free while handling the other items.
|
* can do it essentially for free while handling the other items.
|
||||||
*
|
*
|
||||||
* If attrno_list isn't NULL, we return an additional output besides the
|
|
||||||
* rewritten targetlist: an integer list of the assigned-to attnums, in
|
|
||||||
* order of the original tlist's non-junk entries. This is needed for
|
|
||||||
* processing VALUES RTEs.
|
|
||||||
*
|
|
||||||
* Note that for an inheritable UPDATE, this processing is only done once,
|
* Note that for an inheritable UPDATE, this processing is only done once,
|
||||||
* using the parent relation as reference. It must not do anything that
|
* using the parent relation as reference. It must not do anything that
|
||||||
* will not be correct when transposed to the child relation(s). (Step 4
|
* will not be correct when transposed to the child relation(s). (Step 4
|
||||||
@ -718,8 +712,7 @@ rewriteTargetListIU(List *targetList,
|
|||||||
CmdType commandType,
|
CmdType commandType,
|
||||||
OverridingKind override,
|
OverridingKind override,
|
||||||
Relation target_relation,
|
Relation target_relation,
|
||||||
int result_rti,
|
int result_rti)
|
||||||
List **attrno_list)
|
|
||||||
{
|
{
|
||||||
TargetEntry **new_tles;
|
TargetEntry **new_tles;
|
||||||
List *new_tlist = NIL;
|
List *new_tlist = NIL;
|
||||||
@ -730,9 +723,6 @@ rewriteTargetListIU(List *targetList,
|
|||||||
numattrs;
|
numattrs;
|
||||||
ListCell *temp;
|
ListCell *temp;
|
||||||
|
|
||||||
if (attrno_list) /* initialize optional result list */
|
|
||||||
*attrno_list = NIL;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We process the normal (non-junk) attributes by scanning the input tlist
|
* We process the normal (non-junk) attributes by scanning the input tlist
|
||||||
* once and transferring TLEs into an array, then scanning the array to
|
* once and transferring TLEs into an array, then scanning the array to
|
||||||
@ -758,10 +748,6 @@ rewriteTargetListIU(List *targetList,
|
|||||||
elog(ERROR, "bogus resno %d in targetlist", attrno);
|
elog(ERROR, "bogus resno %d in targetlist", attrno);
|
||||||
att_tup = TupleDescAttr(target_relation->rd_att, attrno - 1);
|
att_tup = TupleDescAttr(target_relation->rd_att, attrno - 1);
|
||||||
|
|
||||||
/* put attrno into attrno_list even if it's dropped */
|
|
||||||
if (attrno_list)
|
|
||||||
*attrno_list = lappend_int(*attrno_list, attrno);
|
|
||||||
|
|
||||||
/* We can (and must) ignore deleted attributes */
|
/* We can (and must) ignore deleted attributes */
|
||||||
if (att_tup->attisdropped)
|
if (att_tup->attisdropped)
|
||||||
continue;
|
continue;
|
||||||
@ -1234,22 +1220,26 @@ searchForDefault(RangeTblEntry *rte)
|
|||||||
* an insert into an auto-updatable view, and the product queries are inserts
|
* an insert into an auto-updatable view, and the product queries are inserts
|
||||||
* into a rule-updatable view.
|
* into a rule-updatable view.
|
||||||
*
|
*
|
||||||
* Note that we currently can't support subscripted or field assignment
|
* Note that we may have subscripted or field assignment targetlist entries,
|
||||||
* in the multi-VALUES case. The targetlist will contain simple Vars
|
* as well as more complex expressions from already-replaced DEFAULT items if
|
||||||
* referencing the VALUES RTE, and therefore process_matched_tle() will
|
* we have recursed to here for an auto-updatable view. However, it ought to
|
||||||
* reject any such attempt with "multiple assignments to same column".
|
* be impossible for such entries to have DEFAULTs assigned to them --- we
|
||||||
|
* should only have to replace DEFAULT items for targetlist entries that
|
||||||
|
* contain simple Vars referencing the VALUES RTE.
|
||||||
*
|
*
|
||||||
* Returns true if all DEFAULT items were replaced, and false if some were
|
* Returns true if all DEFAULT items were replaced, and false if some were
|
||||||
* left untouched.
|
* left untouched.
|
||||||
*/
|
*/
|
||||||
static bool
|
static bool
|
||||||
rewriteValuesRTE(Query *parsetree, RangeTblEntry *rte,
|
rewriteValuesRTE(Query *parsetree, RangeTblEntry *rte, int rti,
|
||||||
Relation target_relation, List *attrnos, bool force_nulls)
|
Relation target_relation, bool force_nulls)
|
||||||
{
|
{
|
||||||
List *newValues;
|
List *newValues;
|
||||||
ListCell *lc;
|
ListCell *lc;
|
||||||
bool isAutoUpdatableView;
|
bool isAutoUpdatableView;
|
||||||
bool allReplaced;
|
bool allReplaced;
|
||||||
|
int numattrs;
|
||||||
|
int *attrnos;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Rebuilding all the lists is a pretty expensive proposition in a big
|
* Rebuilding all the lists is a pretty expensive proposition in a big
|
||||||
@ -1262,8 +1252,33 @@ rewriteValuesRTE(Query *parsetree, RangeTblEntry *rte,
|
|||||||
if (!force_nulls && !searchForDefault(rte))
|
if (!force_nulls && !searchForDefault(rte))
|
||||||
return true; /* nothing to do */
|
return true; /* nothing to do */
|
||||||
|
|
||||||
/* Check list lengths (we can assume all the VALUES sublists are alike) */
|
/*
|
||||||
Assert(list_length(attrnos) == list_length(linitial(rte->values_lists)));
|
* Scan the targetlist for entries referring to the VALUES RTE, and note
|
||||||
|
* the target attributes. As noted above, we should only need to do this
|
||||||
|
* for targetlist entries containing simple Vars --- nothing else in the
|
||||||
|
* VALUES RTE should contain DEFAULT items, and we complain if such a
|
||||||
|
* thing does occur.
|
||||||
|
*/
|
||||||
|
numattrs = list_length(linitial(rte->values_lists));
|
||||||
|
attrnos = (int *) palloc0(numattrs * sizeof(int));
|
||||||
|
|
||||||
|
foreach(lc, parsetree->targetList)
|
||||||
|
{
|
||||||
|
TargetEntry *tle = (TargetEntry *) lfirst(lc);
|
||||||
|
|
||||||
|
if (IsA(tle->expr, Var))
|
||||||
|
{
|
||||||
|
Var *var = (Var *) tle->expr;
|
||||||
|
|
||||||
|
if (var->varno == rti)
|
||||||
|
{
|
||||||
|
int attrno = var->varattno;
|
||||||
|
|
||||||
|
Assert(attrno >= 1 && attrno <= numattrs);
|
||||||
|
attrnos[attrno - 1] = tle->resno;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check if the target relation is an auto-updatable view, in which case
|
* Check if the target relation is an auto-updatable view, in which case
|
||||||
@ -1314,18 +1329,23 @@ rewriteValuesRTE(Query *parsetree, RangeTblEntry *rte,
|
|||||||
List *sublist = (List *) lfirst(lc);
|
List *sublist = (List *) lfirst(lc);
|
||||||
List *newList = NIL;
|
List *newList = NIL;
|
||||||
ListCell *lc2;
|
ListCell *lc2;
|
||||||
ListCell *lc3;
|
int i;
|
||||||
|
|
||||||
forboth(lc2, sublist, lc3, attrnos)
|
Assert(list_length(sublist) == numattrs);
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
foreach(lc2, sublist)
|
||||||
{
|
{
|
||||||
Node *col = (Node *) lfirst(lc2);
|
Node *col = (Node *) lfirst(lc2);
|
||||||
int attrno = lfirst_int(lc3);
|
int attrno = attrnos[i++];
|
||||||
|
|
||||||
if (IsA(col, SetToDefault))
|
if (IsA(col, SetToDefault))
|
||||||
{
|
{
|
||||||
Form_pg_attribute att_tup;
|
Form_pg_attribute att_tup;
|
||||||
Node *new_expr;
|
Node *new_expr;
|
||||||
|
|
||||||
|
if (attrno == 0)
|
||||||
|
elog(ERROR, "cannot set value in column %d to DEFAULT", i);
|
||||||
att_tup = TupleDescAttr(target_relation->rd_att, attrno - 1);
|
att_tup = TupleDescAttr(target_relation->rd_att, attrno - 1);
|
||||||
|
|
||||||
if (!force_nulls && !att_tup->attisdropped)
|
if (!force_nulls && !att_tup->attisdropped)
|
||||||
@ -1373,6 +1393,8 @@ rewriteValuesRTE(Query *parsetree, RangeTblEntry *rte,
|
|||||||
}
|
}
|
||||||
rte->values_lists = newValues;
|
rte->values_lists = newValues;
|
||||||
|
|
||||||
|
pfree(attrnos);
|
||||||
|
|
||||||
return allReplaced;
|
return allReplaced;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3451,7 +3473,6 @@ RewriteQuery(Query *parsetree, List *rewrite_events)
|
|||||||
List *locks;
|
List *locks;
|
||||||
List *product_queries;
|
List *product_queries;
|
||||||
bool hasUpdate = false;
|
bool hasUpdate = false;
|
||||||
List *attrnos = NIL;
|
|
||||||
int values_rte_index = 0;
|
int values_rte_index = 0;
|
||||||
bool defaults_remaining = false;
|
bool defaults_remaining = false;
|
||||||
|
|
||||||
@ -3501,11 +3522,10 @@ RewriteQuery(Query *parsetree, List *rewrite_events)
|
|||||||
parsetree->commandType,
|
parsetree->commandType,
|
||||||
parsetree->override,
|
parsetree->override,
|
||||||
rt_entry_relation,
|
rt_entry_relation,
|
||||||
parsetree->resultRelation,
|
parsetree->resultRelation);
|
||||||
&attrnos);
|
|
||||||
/* ... and the VALUES expression lists */
|
/* ... and the VALUES expression lists */
|
||||||
if (!rewriteValuesRTE(parsetree, values_rte,
|
if (!rewriteValuesRTE(parsetree, values_rte, values_rte_index,
|
||||||
rt_entry_relation, attrnos, false))
|
rt_entry_relation, false))
|
||||||
defaults_remaining = true;
|
defaults_remaining = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -3516,7 +3536,7 @@ RewriteQuery(Query *parsetree, List *rewrite_events)
|
|||||||
parsetree->commandType,
|
parsetree->commandType,
|
||||||
parsetree->override,
|
parsetree->override,
|
||||||
rt_entry_relation,
|
rt_entry_relation,
|
||||||
parsetree->resultRelation, NULL);
|
parsetree->resultRelation);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parsetree->onConflict &&
|
if (parsetree->onConflict &&
|
||||||
@ -3527,8 +3547,7 @@ RewriteQuery(Query *parsetree, List *rewrite_events)
|
|||||||
CMD_UPDATE,
|
CMD_UPDATE,
|
||||||
parsetree->override,
|
parsetree->override,
|
||||||
rt_entry_relation,
|
rt_entry_relation,
|
||||||
parsetree->resultRelation,
|
parsetree->resultRelation);
|
||||||
NULL);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (event == CMD_UPDATE)
|
else if (event == CMD_UPDATE)
|
||||||
@ -3538,7 +3557,7 @@ RewriteQuery(Query *parsetree, List *rewrite_events)
|
|||||||
parsetree->commandType,
|
parsetree->commandType,
|
||||||
parsetree->override,
|
parsetree->override,
|
||||||
rt_entry_relation,
|
rt_entry_relation,
|
||||||
parsetree->resultRelation, NULL);
|
parsetree->resultRelation);
|
||||||
}
|
}
|
||||||
else if (event == CMD_DELETE)
|
else if (event == CMD_DELETE)
|
||||||
{
|
{
|
||||||
@ -3583,7 +3602,8 @@ RewriteQuery(Query *parsetree, List *rewrite_events)
|
|||||||
RangeTblEntry *values_rte = rt_fetch(values_rte_index,
|
RangeTblEntry *values_rte = rt_fetch(values_rte_index,
|
||||||
pt->rtable);
|
pt->rtable);
|
||||||
|
|
||||||
rewriteValuesRTE(pt, values_rte, rt_entry_relation, attrnos,
|
rewriteValuesRTE(pt, values_rte, values_rte_index,
|
||||||
|
rt_entry_relation,
|
||||||
true); /* Force remaining defaults to NULL */
|
true); /* Force remaining defaults to NULL */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2789,6 +2789,7 @@ insert into base_tab_def_view values (12), (13);
|
|||||||
insert into base_tab_def_view values (14, default, default, default, default);
|
insert into base_tab_def_view values (14, default, default, default, default);
|
||||||
insert into base_tab_def_view values (15, default, default, default, default),
|
insert into base_tab_def_view values (15, default, default, default, default),
|
||||||
(16, default, default, default, default);
|
(16, default, default, default, default);
|
||||||
|
insert into base_tab_def_view values (17), (default);
|
||||||
select * from base_tab_def order by a;
|
select * from base_tab_def order by a;
|
||||||
a | b | c | d | e
|
a | b | c | d | e
|
||||||
----+---------------+---------------+--------------+---
|
----+---------------+---------------+--------------+---
|
||||||
@ -2804,7 +2805,9 @@ select * from base_tab_def order by a;
|
|||||||
14 | View default | Table default | View default |
|
14 | View default | Table default | View default |
|
||||||
15 | View default | Table default | View default |
|
15 | View default | Table default | View default |
|
||||||
16 | View default | Table default | View default |
|
16 | View default | Table default | View default |
|
||||||
(12 rows)
|
17 | View default | Table default | View default |
|
||||||
|
| View default | Table default | View default |
|
||||||
|
(14 rows)
|
||||||
|
|
||||||
-- Adding an INSTEAD OF trigger should cause NULLs to be inserted instead of
|
-- Adding an INSTEAD OF trigger should cause NULLs to be inserted instead of
|
||||||
-- table defaults, where there are no view defaults.
|
-- table defaults, where there are no view defaults.
|
||||||
@ -2830,6 +2833,7 @@ insert into base_tab_def_view values (12), (13);
|
|||||||
insert into base_tab_def_view values (14, default, default, default, default);
|
insert into base_tab_def_view values (14, default, default, default, default);
|
||||||
insert into base_tab_def_view values (15, default, default, default, default),
|
insert into base_tab_def_view values (15, default, default, default, default),
|
||||||
(16, default, default, default, default);
|
(16, default, default, default, default);
|
||||||
|
insert into base_tab_def_view values (17), (default);
|
||||||
select * from base_tab_def order by a;
|
select * from base_tab_def order by a;
|
||||||
a | b | c | d | e
|
a | b | c | d | e
|
||||||
----+---------------+---------------+--------------+---
|
----+---------------+---------------+--------------+---
|
||||||
@ -2845,7 +2849,9 @@ select * from base_tab_def order by a;
|
|||||||
14 | View default | | View default |
|
14 | View default | | View default |
|
||||||
15 | View default | | View default |
|
15 | View default | | View default |
|
||||||
16 | View default | | View default |
|
16 | View default | | View default |
|
||||||
(12 rows)
|
17 | View default | | View default |
|
||||||
|
| View default | | View default |
|
||||||
|
(14 rows)
|
||||||
|
|
||||||
-- Using an unconditional DO INSTEAD rule should also cause NULLs to be
|
-- Using an unconditional DO INSTEAD rule should also cause NULLs to be
|
||||||
-- inserted where there are no view defaults.
|
-- inserted where there are no view defaults.
|
||||||
@ -2864,6 +2870,7 @@ insert into base_tab_def_view values (12), (13);
|
|||||||
insert into base_tab_def_view values (14, default, default, default, default);
|
insert into base_tab_def_view values (14, default, default, default, default);
|
||||||
insert into base_tab_def_view values (15, default, default, default, default),
|
insert into base_tab_def_view values (15, default, default, default, default),
|
||||||
(16, default, default, default, default);
|
(16, default, default, default, default);
|
||||||
|
insert into base_tab_def_view values (17), (default);
|
||||||
select * from base_tab_def order by a;
|
select * from base_tab_def order by a;
|
||||||
a | b | c | d | e
|
a | b | c | d | e
|
||||||
----+---------------+---------------+--------------+---
|
----+---------------+---------------+--------------+---
|
||||||
@ -2879,7 +2886,9 @@ select * from base_tab_def order by a;
|
|||||||
14 | View default | | View default |
|
14 | View default | | View default |
|
||||||
15 | View default | | View default |
|
15 | View default | | View default |
|
||||||
16 | View default | | View default |
|
16 | View default | | View default |
|
||||||
(12 rows)
|
17 | View default | | View default |
|
||||||
|
| View default | | View default |
|
||||||
|
(14 rows)
|
||||||
|
|
||||||
-- A DO ALSO rule should cause each row to be inserted twice. The first
|
-- A DO ALSO rule should cause each row to be inserted twice. The first
|
||||||
-- insert should behave the same as an auto-updatable view (using table
|
-- insert should behave the same as an auto-updatable view (using table
|
||||||
@ -2900,6 +2909,7 @@ insert into base_tab_def_view values (12), (13);
|
|||||||
insert into base_tab_def_view values (14, default, default, default, default);
|
insert into base_tab_def_view values (14, default, default, default, default);
|
||||||
insert into base_tab_def_view values (15, default, default, default, default),
|
insert into base_tab_def_view values (15, default, default, default, default),
|
||||||
(16, default, default, default, default);
|
(16, default, default, default, default);
|
||||||
|
insert into base_tab_def_view values (17), (default);
|
||||||
select * from base_tab_def order by a, c NULLS LAST;
|
select * from base_tab_def order by a, c NULLS LAST;
|
||||||
a | b | c | d | e
|
a | b | c | d | e
|
||||||
----+---------------+---------------+--------------+---
|
----+---------------+---------------+--------------+---
|
||||||
@ -2921,7 +2931,26 @@ select * from base_tab_def order by a, c NULLS LAST;
|
|||||||
15 | View default | | View default |
|
15 | View default | | View default |
|
||||||
16 | View default | Table default | View default |
|
16 | View default | Table default | View default |
|
||||||
16 | View default | | View default |
|
16 | View default | | View default |
|
||||||
(18 rows)
|
17 | View default | Table default | View default |
|
||||||
|
17 | View default | | View default |
|
||||||
|
| View default | Table default | View default |
|
||||||
|
| View default | | View default |
|
||||||
|
(22 rows)
|
||||||
|
|
||||||
drop view base_tab_def_view;
|
drop view base_tab_def_view;
|
||||||
drop table base_tab_def;
|
drop table base_tab_def;
|
||||||
|
-- Test defaults with array assignments
|
||||||
|
create table base_tab (a serial, b int[], c text, d text default 'Table default');
|
||||||
|
create view base_tab_view as select c, a, b from base_tab;
|
||||||
|
alter view base_tab_view alter column c set default 'View default';
|
||||||
|
insert into base_tab_view (b[1], b[2], c, b[5], b[4], a, b[3])
|
||||||
|
values (1, 2, default, 5, 4, default, 3), (10, 11, 'C value', 14, 13, 100, 12);
|
||||||
|
select * from base_tab order by a;
|
||||||
|
a | b | c | d
|
||||||
|
-----+------------------+--------------+---------------
|
||||||
|
1 | {1,2,3,4,5} | View default | Table default
|
||||||
|
100 | {10,11,12,13,14} | C value | Table default
|
||||||
|
(2 rows)
|
||||||
|
|
||||||
|
drop view base_tab_view;
|
||||||
|
drop table base_tab;
|
||||||
|
@ -1397,6 +1397,7 @@ insert into base_tab_def_view values (12), (13);
|
|||||||
insert into base_tab_def_view values (14, default, default, default, default);
|
insert into base_tab_def_view values (14, default, default, default, default);
|
||||||
insert into base_tab_def_view values (15, default, default, default, default),
|
insert into base_tab_def_view values (15, default, default, default, default),
|
||||||
(16, default, default, default, default);
|
(16, default, default, default, default);
|
||||||
|
insert into base_tab_def_view values (17), (default);
|
||||||
select * from base_tab_def order by a;
|
select * from base_tab_def order by a;
|
||||||
|
|
||||||
-- Adding an INSTEAD OF trigger should cause NULLs to be inserted instead of
|
-- Adding an INSTEAD OF trigger should cause NULLs to be inserted instead of
|
||||||
@ -1423,6 +1424,7 @@ insert into base_tab_def_view values (12), (13);
|
|||||||
insert into base_tab_def_view values (14, default, default, default, default);
|
insert into base_tab_def_view values (14, default, default, default, default);
|
||||||
insert into base_tab_def_view values (15, default, default, default, default),
|
insert into base_tab_def_view values (15, default, default, default, default),
|
||||||
(16, default, default, default, default);
|
(16, default, default, default, default);
|
||||||
|
insert into base_tab_def_view values (17), (default);
|
||||||
select * from base_tab_def order by a;
|
select * from base_tab_def order by a;
|
||||||
|
|
||||||
-- Using an unconditional DO INSTEAD rule should also cause NULLs to be
|
-- Using an unconditional DO INSTEAD rule should also cause NULLs to be
|
||||||
@ -1442,6 +1444,7 @@ insert into base_tab_def_view values (12), (13);
|
|||||||
insert into base_tab_def_view values (14, default, default, default, default);
|
insert into base_tab_def_view values (14, default, default, default, default);
|
||||||
insert into base_tab_def_view values (15, default, default, default, default),
|
insert into base_tab_def_view values (15, default, default, default, default),
|
||||||
(16, default, default, default, default);
|
(16, default, default, default, default);
|
||||||
|
insert into base_tab_def_view values (17), (default);
|
||||||
select * from base_tab_def order by a;
|
select * from base_tab_def order by a;
|
||||||
|
|
||||||
-- A DO ALSO rule should cause each row to be inserted twice. The first
|
-- A DO ALSO rule should cause each row to be inserted twice. The first
|
||||||
@ -1463,7 +1466,18 @@ insert into base_tab_def_view values (12), (13);
|
|||||||
insert into base_tab_def_view values (14, default, default, default, default);
|
insert into base_tab_def_view values (14, default, default, default, default);
|
||||||
insert into base_tab_def_view values (15, default, default, default, default),
|
insert into base_tab_def_view values (15, default, default, default, default),
|
||||||
(16, default, default, default, default);
|
(16, default, default, default, default);
|
||||||
|
insert into base_tab_def_view values (17), (default);
|
||||||
select * from base_tab_def order by a, c NULLS LAST;
|
select * from base_tab_def order by a, c NULLS LAST;
|
||||||
|
|
||||||
drop view base_tab_def_view;
|
drop view base_tab_def_view;
|
||||||
drop table base_tab_def;
|
drop table base_tab_def;
|
||||||
|
|
||||||
|
-- Test defaults with array assignments
|
||||||
|
create table base_tab (a serial, b int[], c text, d text default 'Table default');
|
||||||
|
create view base_tab_view as select c, a, b from base_tab;
|
||||||
|
alter view base_tab_view alter column c set default 'View default';
|
||||||
|
insert into base_tab_view (b[1], b[2], c, b[5], b[4], a, b[3])
|
||||||
|
values (1, 2, default, 5, 4, default, 3), (10, 11, 'C value', 14, 13, 100, 12);
|
||||||
|
select * from base_tab order by a;
|
||||||
|
drop view base_tab_view;
|
||||||
|
drop table base_tab;
|
||||||
|
Loading…
Reference in New Issue
Block a user