Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 1795897

Browse files
committed
Allow a multi-row INSERT to specify DEFAULTs for a generated column.
One can say "INSERT INTO tab(generated_col) VALUES (DEFAULT)" and not draw an error. But the equivalent case for a multi-row VALUES list always threw an error, even if one properly said DEFAULT in each row. Fix that. While here, improve the test cases for nearby logic about OVERRIDING SYSTEM/USER values. Dean Rasheed Discussion: https://postgr.es/m/9q0sgcr416t.fsf@gmx.us
1 parent 9fe649e commit 1795897

File tree

5 files changed

+357
-32
lines changed

5 files changed

+357
-32
lines changed

src/backend/rewrite/rewriteHandler.c

+215-27
Original file line numberDiff line numberDiff line change
@@ -69,13 +69,18 @@ static List *rewriteTargetListIU(List *targetList,
6969
CmdType commandType,
7070
OverridingKind override,
7171
Relation target_relation,
72-
int result_rti);
72+
int result_rti,
73+
RangeTblEntry *values_rte,
74+
int values_rte_index,
75+
Bitmapset **unused_values_attrnos);
7376
static TargetEntry *process_matched_tle(TargetEntry *src_tle,
7477
TargetEntry *prior_tle,
7578
const char *attrName);
7679
static Node *get_assignment_input(Node *node);
80+
static Bitmapset *findDefaultOnlyColumns(RangeTblEntry *rte);
7781
static bool rewriteValuesRTE(Query *parsetree, RangeTblEntry *rte, int rti,
78-
Relation target_relation, bool force_nulls);
82+
Relation target_relation, bool force_nulls,
83+
Bitmapset *unused_cols);
7984
static void markQueryForLocking(Query *qry, Node *jtnode,
8085
LockClauseStrength strength, LockWaitPolicy waitPolicy,
8186
bool pushedDown);
@@ -708,13 +713,25 @@ adjustJoinTreeList(Query *parsetree, bool removert, int rt_index)
708713
* is incorrect by this light, since child relations might have different
709714
* column ordering, but the planner will fix things by re-sorting the tlist
710715
* for each child.)
716+
*
717+
* If values_rte is non-NULL (i.e., we are doing a multi-row INSERT using
718+
* values from a VALUES RTE), we populate *unused_values_attrnos with the
719+
* attribute numbers of any unused columns from the VALUES RTE. This can
720+
* happen for identity and generated columns whose targetlist entries are
721+
* replaced with generated expressions (if INSERT ... OVERRIDING USER VALUE is
722+
* used, or all the values to be inserted are DEFAULT). This information is
723+
* required by rewriteValuesRTE() to handle any DEFAULT items in the unused
724+
* columns. The caller must have initialized *unused_values_attrnos to NULL.
711725
*/
712726
static List *
713727
rewriteTargetListIU(List *targetList,
714728
CmdType commandType,
715729
OverridingKind override,
716730
Relation target_relation,
717-
int result_rti)
731+
int result_rti,
732+
RangeTblEntry *values_rte,
733+
int values_rte_index,
734+
Bitmapset **unused_values_attrnos)
718735
{
719736
TargetEntry **new_tles;
720737
List *new_tlist = NIL;
@@ -724,6 +741,7 @@ rewriteTargetListIU(List *targetList,
724741
next_junk_attrno,
725742
numattrs;
726743
ListCell *temp;
744+
Bitmapset *default_only_cols = NULL;
727745

728746
/*
729747
* We process the normal (non-junk) attributes by scanning the input tlist
@@ -803,30 +821,106 @@ rewriteTargetListIU(List *targetList,
803821

804822
if (commandType == CMD_INSERT)
805823
{
824+
int values_attrno = 0;
825+
826+
/* Source attribute number for values that come from a VALUES RTE */
827+
if (values_rte && new_tle && IsA(new_tle->expr, Var))
828+
{
829+
Var *var = (Var *) new_tle->expr;
830+
831+
if (var->varno == values_rte_index)
832+
values_attrno = var->varattno;
833+
}
834+
835+
/*
836+
* Can only insert DEFAULT into GENERATED ALWAYS identity columns,
837+
* unless either OVERRIDING USER VALUE or OVERRIDING SYSTEM VALUE
838+
* is specified.
839+
*/
806840
if (att_tup->attidentity == ATTRIBUTE_IDENTITY_ALWAYS && !apply_default)
807841
{
808842
if (override == OVERRIDING_USER_VALUE)
809843
apply_default = true;
810844
else if (override != OVERRIDING_SYSTEM_VALUE)
811-
ereport(ERROR,
812-
(errcode(ERRCODE_GENERATED_ALWAYS),
813-
errmsg("cannot insert into column \"%s\"", NameStr(att_tup->attname)),
814-
errdetail("Column \"%s\" is an identity column defined as GENERATED ALWAYS.",
815-
NameStr(att_tup->attname)),
816-
errhint("Use OVERRIDING SYSTEM VALUE to override.")));
845+
{
846+
/*
847+
* If this column's values come from a VALUES RTE, test
848+
* whether it contains only SetToDefault items. Since the
849+
* VALUES list might be quite large, we arrange to only
850+
* scan it once.
851+
*/
852+
if (values_attrno != 0)
853+
{
854+
if (default_only_cols == NULL)
855+
default_only_cols = findDefaultOnlyColumns(values_rte);
856+
857+
if (bms_is_member(values_attrno, default_only_cols))
858+
apply_default = true;
859+
}
860+
861+
if (!apply_default)
862+
ereport(ERROR,
863+
(errcode(ERRCODE_GENERATED_ALWAYS),
864+
errmsg("cannot insert into column \"%s\"",
865+
NameStr(att_tup->attname)),
866+
errdetail("Column \"%s\" is an identity column defined as GENERATED ALWAYS.",
867+
NameStr(att_tup->attname)),
868+
errhint("Use OVERRIDING SYSTEM VALUE to override.")));
869+
}
817870
}
818871

819-
if (att_tup->attidentity == ATTRIBUTE_IDENTITY_BY_DEFAULT && override == OVERRIDING_USER_VALUE)
872+
/*
873+
* Although inserting into a GENERATED BY DEFAULT identity column
874+
* is allowed, apply the default if OVERRIDING USER VALUE is
875+
* specified.
876+
*/
877+
if (att_tup->attidentity == ATTRIBUTE_IDENTITY_BY_DEFAULT &&
878+
override == OVERRIDING_USER_VALUE)
820879
apply_default = true;
821880

881+
/*
882+
* Can only insert DEFAULT into generated columns, regardless of
883+
* any OVERRIDING clauses.
884+
*/
822885
if (att_tup->attgenerated && !apply_default)
823-
ereport(ERROR,
824-
(errcode(ERRCODE_SYNTAX_ERROR),
825-
errmsg("cannot insert into column \"%s\"", NameStr(att_tup->attname)),
826-
errdetail("Column \"%s\" is a generated column.",
827-
NameStr(att_tup->attname))));
886+
{
887+
/*
888+
* If this column's values come from a VALUES RTE, test
889+
* whether it contains only SetToDefault items, as above.
890+
*/
891+
if (values_attrno != 0)
892+
{
893+
if (default_only_cols == NULL)
894+
default_only_cols = findDefaultOnlyColumns(values_rte);
895+
896+
if (bms_is_member(values_attrno, default_only_cols))
897+
apply_default = true;
898+
}
899+
900+
if (!apply_default)
901+
ereport(ERROR,
902+
(errcode(ERRCODE_SYNTAX_ERROR),
903+
errmsg("cannot insert into column \"%s\"",
904+
NameStr(att_tup->attname)),
905+
errdetail("Column \"%s\" is a generated column.",
906+
NameStr(att_tup->attname))));
907+
}
908+
909+
/*
910+
* For an INSERT from a VALUES RTE, return the attribute numbers
911+
* of any VALUES columns that will no longer be used (due to the
912+
* targetlist entry being replaced by a default expression).
913+
*/
914+
if (values_attrno != 0 && apply_default && unused_values_attrnos)
915+
*unused_values_attrnos = bms_add_member(*unused_values_attrnos,
916+
values_attrno);
828917
}
829918

919+
/*
920+
* Updates to identity and generated columns follow the same rules as
921+
* above, except that UPDATE doesn't admit OVERRIDING clauses. Also,
922+
* the source can't be a VALUES RTE, so we needn't consider that.
923+
*/
830924
if (commandType == CMD_UPDATE)
831925
{
832926
if (att_tup->attidentity == ATTRIBUTE_IDENTITY_ALWAYS && new_tle && !apply_default)
@@ -1219,6 +1313,62 @@ searchForDefault(RangeTblEntry *rte)
12191313
return false;
12201314
}
12211315

1316+
1317+
/*
1318+
* Search a VALUES RTE for columns that contain only SetToDefault items,
1319+
* returning a Bitmapset containing the attribute numbers of any such columns.
1320+
*/
1321+
static Bitmapset *
1322+
findDefaultOnlyColumns(RangeTblEntry *rte)
1323+
{
1324+
Bitmapset *default_only_cols = NULL;
1325+
ListCell *lc;
1326+
1327+
foreach(lc, rte->values_lists)
1328+
{
1329+
List *sublist = (List *) lfirst(lc);
1330+
ListCell *lc2;
1331+
int i;
1332+
1333+
if (default_only_cols == NULL)
1334+
{
1335+
/* Populate the initial result bitmap from the first row */
1336+
i = 0;
1337+
foreach(lc2, sublist)
1338+
{
1339+
Node *col = (Node *) lfirst(lc2);
1340+
1341+
i++;
1342+
if (IsA(col, SetToDefault))
1343+
default_only_cols = bms_add_member(default_only_cols, i);
1344+
}
1345+
}
1346+
else
1347+
{
1348+
/* Update the result bitmap from this next row */
1349+
i = 0;
1350+
foreach(lc2, sublist)
1351+
{
1352+
Node *col = (Node *) lfirst(lc2);
1353+
1354+
i++;
1355+
if (!IsA(col, SetToDefault))
1356+
default_only_cols = bms_del_member(default_only_cols, i);
1357+
}
1358+
}
1359+
1360+
/*
1361+
* If no column in the rows read so far contains only DEFAULT items,
1362+
* we are done.
1363+
*/
1364+
if (bms_is_empty(default_only_cols))
1365+
break;
1366+
}
1367+
1368+
return default_only_cols;
1369+
}
1370+
1371+
12221372
/*
12231373
* When processing INSERT ... VALUES with a VALUES RTE (ie, multiple VALUES
12241374
* lists), we have to replace any DEFAULT items in the VALUES lists with
@@ -1246,19 +1396,31 @@ searchForDefault(RangeTblEntry *rte)
12461396
* an insert into an auto-updatable view, and the product queries are inserts
12471397
* into a rule-updatable view.
12481398
*
1399+
* Finally, if a DEFAULT item is found in a column mentioned in unused_cols,
1400+
* it is explicitly set to NULL. This happens for columns in the VALUES RTE
1401+
* whose corresponding targetlist entries have already been replaced with the
1402+
* relation's default expressions, so that any values in those columns of the
1403+
* VALUES RTE are no longer used. This can happen for identity and generated
1404+
* columns (if INSERT ... OVERRIDING USER VALUE is used, or all the values to
1405+
* be inserted are DEFAULT). In principle we could replace all entries in
1406+
* such a column with NULL, whether DEFAULT or not; but it doesn't seem worth
1407+
* the trouble.
1408+
*
12491409
* Note that we may have subscripted or field assignment targetlist entries,
12501410
* as well as more complex expressions from already-replaced DEFAULT items if
12511411
* we have recursed to here for an auto-updatable view. However, it ought to
1252-
* be impossible for such entries to have DEFAULTs assigned to them --- we
1253-
* should only have to replace DEFAULT items for targetlist entries that
1254-
* contain simple Vars referencing the VALUES RTE.
1412+
* be impossible for such entries to have DEFAULTs assigned to them, except
1413+
* for unused columns, as described above --- we should only have to replace
1414+
* DEFAULT items for targetlist entries that contain simple Vars referencing
1415+
* the VALUES RTE, or which are no longer referred to by the targetlist.
12551416
*
12561417
* Returns true if all DEFAULT items were replaced, and false if some were
12571418
* left untouched.
12581419
*/
12591420
static bool
12601421
rewriteValuesRTE(Query *parsetree, RangeTblEntry *rte, int rti,
1261-
Relation target_relation, bool force_nulls)
1422+
Relation target_relation, bool force_nulls,
1423+
Bitmapset *unused_cols)
12621424
{
12631425
List *newValues;
12641426
ListCell *lc;
@@ -1282,8 +1444,8 @@ rewriteValuesRTE(Query *parsetree, RangeTblEntry *rte, int rti,
12821444
* Scan the targetlist for entries referring to the VALUES RTE, and note
12831445
* the target attributes. As noted above, we should only need to do this
12841446
* for targetlist entries containing simple Vars --- nothing else in the
1285-
* VALUES RTE should contain DEFAULT items, and we complain if such a
1286-
* thing does occur.
1447+
* VALUES RTE should contain DEFAULT items (except possibly for unused
1448+
* columns), and we complain if such a thing does occur.
12871449
*/
12881450
numattrs = list_length(linitial(rte->values_lists));
12891451
attrnos = (int *) palloc0(numattrs * sizeof(int));
@@ -1370,6 +1532,22 @@ rewriteValuesRTE(Query *parsetree, RangeTblEntry *rte, int rti,
13701532
Form_pg_attribute att_tup;
13711533
Node *new_expr;
13721534

1535+
/*
1536+
* If this column isn't used, just replace the DEFAULT with
1537+
* NULL (attrno will be 0 in this case because the targetlist
1538+
* entry will have been replaced by the default expression).
1539+
*/
1540+
if (bms_is_member(i, unused_cols))
1541+
{
1542+
SetToDefault *def = (SetToDefault *) col;
1543+
1544+
newList = lappend(newList,
1545+
makeNullConst(def->typeId,
1546+
def->typeMod,
1547+
def->collation));
1548+
continue;
1549+
}
1550+
13731551
if (attrno == 0)
13741552
elog(ERROR, "cannot set value in column %d to DEFAULT", i);
13751553
att_tup = TupleDescAttr(target_relation->rd_att, attrno - 1);
@@ -3614,15 +3792,21 @@ RewriteQuery(Query *parsetree, List *rewrite_events)
36143792

36153793
if (values_rte)
36163794
{
3795+
Bitmapset *unused_values_attrnos = NULL;
3796+
36173797
/* Process the main targetlist ... */
36183798
parsetree->targetList = rewriteTargetListIU(parsetree->targetList,
36193799
parsetree->commandType,
36203800
parsetree->override,
36213801
rt_entry_relation,
3622-
parsetree->resultRelation);
3802+
parsetree->resultRelation,
3803+
values_rte,
3804+
values_rte_index,
3805+
&unused_values_attrnos);
36233806
/* ... and the VALUES expression lists */
36243807
if (!rewriteValuesRTE(parsetree, values_rte, values_rte_index,
3625-
rt_entry_relation, false))
3808+
rt_entry_relation, false,
3809+
unused_values_attrnos))
36263810
defaults_remaining = true;
36273811
}
36283812
else
@@ -3633,7 +3817,8 @@ RewriteQuery(Query *parsetree, List *rewrite_events)
36333817
parsetree->commandType,
36343818
parsetree->override,
36353819
rt_entry_relation,
3636-
parsetree->resultRelation);
3820+
parsetree->resultRelation,
3821+
NULL, 0, NULL);
36373822
}
36383823

36393824
if (parsetree->onConflict &&
@@ -3644,7 +3829,8 @@ RewriteQuery(Query *parsetree, List *rewrite_events)
36443829
CMD_UPDATE,
36453830
parsetree->override,
36463831
rt_entry_relation,
3647-
parsetree->resultRelation);
3832+
parsetree->resultRelation,
3833+
NULL, 0, NULL);
36483834
}
36493835
}
36503836
else if (event == CMD_UPDATE)
@@ -3654,7 +3840,8 @@ RewriteQuery(Query *parsetree, List *rewrite_events)
36543840
parsetree->commandType,
36553841
parsetree->override,
36563842
rt_entry_relation,
3657-
parsetree->resultRelation);
3843+
parsetree->resultRelation,
3844+
NULL, 0, NULL);
36583845

36593846
/* Also populate extraUpdatedCols (for generated columns) */
36603847
fill_extraUpdatedCols(rt_entry, rt_entry_relation);
@@ -3704,7 +3891,8 @@ RewriteQuery(Query *parsetree, List *rewrite_events)
37043891

37053892
rewriteValuesRTE(pt, values_rte, values_rte_index,
37063893
rt_entry_relation,
3707-
true); /* Force remaining defaults to NULL */
3894+
true, /* Force remaining defaults to NULL */
3895+
NULL);
37083896
}
37093897
}
37103898

0 commit comments

Comments
 (0)