Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit091fe03

Browse files
committed
Code review for UPDATE SET (columnlist) patch. Make it handle as much
of the syntax as this fundamentally dead-end approach can, in particularcombinations of single and multi column assignments. Improve ratherinadequate documentation and provide some regression tests.
1 parent676d1b4 commit091fe03

File tree

4 files changed

+195
-141
lines changed

4 files changed

+195
-141
lines changed

‎doc/src/sgml/ref/update.sgml

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<!--
2-
$PostgreSQL: pgsql/doc/src/sgml/ref/update.sgml,v 1.39 2006/09/02 20:34:47 momjian Exp $
2+
$PostgreSQL: pgsql/doc/src/sgml/ref/update.sgml,v 1.40 2006/09/03 22:37:05 tgl Exp $
33
PostgreSQL documentation
44
-->
55

@@ -21,8 +21,8 @@ PostgreSQL documentation
2121
<refsynopsisdiv>
2222
<synopsis>
2323
UPDATE [ ONLY ] <replaceable class="PARAMETER">table</replaceable> [ [ AS ] <replaceable class="parameter">alias</replaceable> ]
24-
[SET <replaceable class="PARAMETER">column</replaceable> = { <replaceable class="PARAMETER">expression</replaceable> | DEFAULT } [, ...] |
25-
SET( <replaceable class="PARAMETER">column</replaceable> [, ...] ) = ( { <replaceable class="PARAMETER">expression</replaceable> | DEFAULT } [, ...] ) [, ...]]
24+
SET{<replaceable class="PARAMETER">column</replaceable> = { <replaceable class="PARAMETER">expression</replaceable> | DEFAULT } |
25+
( <replaceable class="PARAMETER">column</replaceable> [, ...] ) = ( { <replaceable class="PARAMETER">expression</replaceable> | DEFAULT } [, ...] )}[, ...]
2626
[ FROM <replaceable class="PARAMETER">fromlist</replaceable> ]
2727
[ WHERE <replaceable class="PARAMETER">condition</replaceable> ]
2828
[ RETURNING * | <replaceable class="parameter">output_expression</replaceable> [ AS <replaceable class="parameter">output_name</replaceable> ] [, ...] ]
@@ -251,10 +251,6 @@ UPDATE films SET kind = 'Dramatic' WHERE kind = 'Drama';
251251
<programlisting>
252252
UPDATE weather SET temp_lo = temp_lo+1, temp_hi = temp_lo+15, prcp = DEFAULT
253253
WHERE city = 'San Francisco' AND date = '2003-07-03';
254-
</programlisting>
255-
<programlisting>
256-
UPDATE weather SET (temp_lo, temp_hi, prcp) = (temp_lo+1, temp_lo+15, DEFAULT)
257-
WHERE city = 'San Francisco' AND date = '2003-07-03';
258254
</programlisting>
259255
</para>
260256

@@ -268,6 +264,14 @@ UPDATE weather SET temp_lo = temp_lo+1, temp_hi = temp_lo+15, prcp = DEFAULT
268264
</programlisting>
269265
</para>
270266

267+
<para>
268+
Use the alternative column-list syntax to do the same update:
269+
<programlisting>
270+
UPDATE weather SET (temp_lo, temp_hi, prcp) = (temp_lo+1, temp_lo+15, DEFAULT)
271+
WHERE city = 'San Francisco' AND date = '2003-07-03';
272+
</programlisting>
273+
</para>
274+
271275
<para>
272276
Increment the sales count of the salesperson who manages the
273277
account for Acme Corporation, using the <literal>FROM</literal>
@@ -316,6 +320,19 @@ COMMIT;
316320
are <productname>PostgreSQL</productname> extensions.
317321
</para>
318322

323+
<para>
324+
According to the standard, the column-list syntax should allow a list
325+
of columns to be assigned from a single row-valued expression, such
326+
as a sub-select:
327+
<programlisting>
328+
UPDATE accounts SET (contact_last_name, contact_first_name) =
329+
(SELECT last_name, first_name FROM salesmen
330+
WHERE salesmen.id = accounts.sales_id);
331+
</programlisting>
332+
This is not currently implemented &mdash; the source must be a list
333+
of independent expressions.
334+
</para>
335+
319336
<para>
320337
Some other database systems offer a <literal>FROM</> option in which
321338
the target table is supposed to be listed again within <literal>FROM</>.

‎src/backend/parser/gram.y

Lines changed: 96 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
*
1212
*
1313
* IDENTIFICATION
14-
* $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.564 2006/09/0303:19:44 momjian Exp $
14+
* $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.565 2006/09/0322:37:05 tgl Exp $
1515
*
1616
* HISTORY
1717
* AUTHORDATEMAJOR EVENT
@@ -236,9 +236,9 @@ static void doNegateFloat(Value *v);
236236
name_listfrom_clausefrom_listopt_array_bounds
237237
qualified_name_listany_nameany_name_list
238238
any_operatorexpr_listattrs
239-
target_listupdate_col_listupdate_target_list
240-
update_value_listset_optinsert_column_list
241-
values_listdef_listindirectionopt_indirection
239+
target_listinsert_column_listset_target_list
240+
set_clause_listset_clausemultiple_set_clause
241+
ctext_expr_listctext_rowdef_listindirectionopt_indirection
242242
group_clauseTriggerFuncArgsselect_limit
243243
opt_select_limitopclass_item_list
244244
transaction_mode_list_or_empty
@@ -299,7 +299,7 @@ static void doNegateFloat(Value *v);
299299
%type<list>when_clause_list
300300
%type<ival>sub_type
301301
%type<list>OptCreateAsCreateAsList
302-
%type<node>CreateAsElementvalues_item
302+
%type<node>CreateAsElementctext_expr
303303
%type<value>NumericOnlyFloatOnlyIntegerOnly
304304
%type<alias>alias_clause
305305
%type<sortby>sortby
@@ -308,8 +308,7 @@ static void doNegateFloat(Value *v);
308308
%type<jexpr>joined_table
309309
%type<range>relation_expr
310310
%type<range>relation_expr_opt_alias
311-
%type<target>target_elupdate_target_elupdate_col_list_elinsert_column_item
312-
%type<list>update_target_lists_listupdate_target_lists_el
311+
%type<target>target_elsingle_set_clauseset_targetinsert_column_item
313312

314313
%type<typnam>TypenameSimpleTypenameConstTypename
315314
GenericTypeNumericopt_float
@@ -5488,7 +5487,7 @@ opt_nowait:NOWAIT{ $$ = TRUE; }
54885487
*****************************************************************************/
54895488

54905489
UpdateStmt: UPDATE relation_expr_opt_alias
5491-
SETset_opt
5490+
SETset_clause_list
54925491
from_clause
54935492
where_clause
54945493
returning_clause
@@ -5503,9 +5502,65 @@ UpdateStmt: UPDATE relation_expr_opt_alias
55035502
}
55045503
;
55055504

5506-
set_opt:
5507-
update_target_list{$$ =$1; }
5508-
| update_target_lists_list{$$ =$1; }
5505+
set_clause_list:
5506+
set_clause{$$ =$1; }
5507+
| set_clause_list',' set_clause{$$ = list_concat($1,$3); }
5508+
;
5509+
5510+
set_clause:
5511+
single_set_clause{$$ = list_make1($1); }
5512+
| multiple_set_clause{$$ =$1; }
5513+
;
5514+
5515+
single_set_clause:
5516+
set_target'=' ctext_expr
5517+
{
5518+
$$ =$1;
5519+
$$->val = (Node *)$3;
5520+
}
5521+
;
5522+
5523+
multiple_set_clause:
5524+
'(' set_target_list')''=' ctext_row
5525+
{
5526+
ListCell *col_cell;
5527+
ListCell *val_cell;
5528+
5529+
/*
5530+
* Break the ctext_row apart, merge individual expressions
5531+
* into the destination ResTargets. XXX this approach
5532+
* cannot work for general row expressions as sources.
5533+
*/
5534+
if (list_length($2) != list_length($5))
5535+
ereport(ERROR,
5536+
(errcode(ERRCODE_SYNTAX_ERROR),
5537+
errmsg("number of columns does not match number of values")));
5538+
forboth(col_cell, $2, val_cell, $5)
5539+
{
5540+
ResTarget *res_col = (ResTarget *)lfirst(col_cell);
5541+
Node *res_val = (Node *)lfirst(val_cell);
5542+
5543+
res_col->val = res_val;
5544+
}
5545+
5546+
$$ =$2;
5547+
}
5548+
;
5549+
5550+
set_target:
5551+
ColId opt_indirection
5552+
{
5553+
$$ = makeNode(ResTarget);
5554+
$$->name =$1;
5555+
$$->indirection =$2;
5556+
$$->val =NULL;/* upper production sets this*/
5557+
$$->location =@1;
5558+
}
5559+
;
5560+
5561+
set_target_list:
5562+
set_target{$$ = list_make1($1); }
5563+
| set_target_list',' set_target{$$ = lappend($1,$3); }
55095564
;
55105565

55115566

@@ -5887,83 +5942,20 @@ locked_rels_list:
58875942

58885943

58895944
values_clause:
5890-
VALUES'(' values_list')'
5945+
VALUESctext_row
58915946
{
58925947
SelectStmt *n = makeNode(SelectStmt);
5893-
n->valuesLists = list_make1($3);
5948+
n->valuesLists = list_make1($2);
58945949
$$ = (Node *) n;
58955950
}
5896-
| values_clause',''(' values_list')'
5951+
| values_clause','ctext_row
58975952
{
58985953
SelectStmt *n = (SelectStmt *)$1;
5899-
n->valuesLists = lappend(n->valuesLists,$4);
5954+
n->valuesLists = lappend(n->valuesLists,$3);
59005955
$$ = (Node *) n;
59015956
}
59025957
;
59035958

5904-
values_list: values_item{$$ = list_make1($1); }
5905-
| values_list',' values_item{$$ = lappend($1,$3); }
5906-
;
5907-
5908-
values_item:
5909-
a_expr{$$ = (Node *)$1; }
5910-
| DEFAULT{$$ = (Node *) makeNode(SetToDefault); }
5911-
;
5912-
5913-
update_target_lists_list:
5914-
update_target_lists_el {$$ =$1; }
5915-
| update_target_lists_list',' update_target_lists_el {$$ = list_concat($1,$3); }
5916-
;
5917-
5918-
update_target_lists_el:
5919-
'(' update_col_list')''=''(' update_value_list')'
5920-
{
5921-
ListCell *col_cell;
5922-
ListCell *val_cell;
5923-
5924-
if (list_length($2) != list_length($6))
5925-
{
5926-
ereport(ERROR,
5927-
(errcode(ERRCODE_SYNTAX_ERROR),
5928-
errmsg("number of columns does not match to number of values")));
5929-
}
5930-
5931-
for (col_cell = list_head($2), val_cell = list_head($6);
5932-
col_cell !=NULL && val_cell !=NULL;
5933-
col_cell = lnext(col_cell), val_cell = lnext(val_cell))
5934-
{
5935-
/* merge update_value_list with update_col_list*/
5936-
ResTarget *res_col = (ResTarget *) lfirst(col_cell);
5937-
Node *res_val = (Node *) lfirst(val_cell);
5938-
5939-
res_col->val = res_val;
5940-
}
5941-
5942-
$$ =$2;
5943-
}
5944-
;
5945-
5946-
update_col_list:
5947-
update_col_list_el {$$ = list_make1($1); }
5948-
| update_col_list',' update_col_list_el {$$ = lappend($1,$3); }
5949-
;
5950-
5951-
update_col_list_el:
5952-
ColId opt_indirection
5953-
{
5954-
$$ = makeNode(ResTarget);
5955-
$$->name =$1;
5956-
$$->indirection =$2;
5957-
$$->val =NULL;
5958-
$$->location =@1;
5959-
}
5960-
;
5961-
5962-
update_value_list:
5963-
values_item {$$ = list_make1($1); }
5964-
| update_value_list',' values_item {$$ = lappend($1,$3); }
5965-
;
5966-
59675959

59685960
/*****************************************************************************
59695961
*
@@ -8232,10 +8224,35 @@ opt_asymmetric: ASYMMETRIC
82328224
|/*EMPTY*/
82338225
;
82348226

8227+
/*
8228+
* The SQL spec defines "contextually typed value expressions" and
8229+
* "contextually typed row value constructors", which for our purposes
8230+
* are the same as "a_expr" and "row" except that DEFAULT can appear at
8231+
* the top level.
8232+
*/
8233+
8234+
ctext_expr:
8235+
a_expr{$$ = (Node *)$1; }
8236+
| DEFAULT{$$ = (Node *) makeNode(SetToDefault); }
8237+
;
8238+
8239+
ctext_expr_list:
8240+
ctext_expr{$$ = list_make1($1); }
8241+
| ctext_expr_list',' ctext_expr{$$ = lappend($1,$3); }
8242+
;
8243+
8244+
/*
8245+
* We should allow ROW '(' ctext_expr_list ')' too, but that seems to require
8246+
* making VALUES a fully reserved word, which will probably break more apps
8247+
* than allowing the noise-word is worth.
8248+
*/
8249+
ctext_row:'(' ctext_expr_list')'{$$ =$2; }
8250+
;
8251+
82358252

82368253
/*****************************************************************************
82378254
*
8238-
*targetlists for SELECT, UPDATE, INSERT
8255+
*targetlist for SELECT
82398256
*
82408257
*****************************************************************************/
82418258

@@ -8275,31 +8292,6 @@ target_el:a_expr AS ColLabel
82758292
}
82768293
;
82778294

8278-
update_target_list:
8279-
update_target_el {$$ = list_make1($1); }
8280-
| update_target_list',' update_target_el {$$ = lappend($1,$3); }
8281-
;
8282-
8283-
update_target_el:
8284-
ColId opt_indirection'=' a_expr
8285-
{
8286-
$$ = makeNode(ResTarget);
8287-
$$->name =$1;
8288-
$$->indirection =$2;
8289-
$$->val = (Node *)$4;
8290-
$$->location =@1;
8291-
}
8292-
| ColId opt_indirection'=' DEFAULT
8293-
{
8294-
$$ = makeNode(ResTarget);
8295-
$$->name =$1;
8296-
$$->indirection =$2;
8297-
$$->val = (Node *) makeNode(SetToDefault);
8298-
$$->location =@1;
8299-
}
8300-
8301-
;
8302-
83038295

83048296
/*****************************************************************************
83058297
*

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp