diff options
author | Bruce Momjian <bruce@momjian.us> | 2006-09-02 20:34:47 +0000 |
---|---|---|
committer | Bruce Momjian <bruce@momjian.us> | 2006-09-02 20:34:47 +0000 |
commit | 6e8596a146c9b16f2c053ea8c6e361a114c0b65c (patch) | |
tree | ff705971cafc03f720747aaea46ebc1923f45151 | |
parent | 9e522d0816a93c6b574109b9b5251371ff6bcd64 (diff) | |
download | postgresql-6e8596a146c9b16f2c053ea8c6e361a114c0b65c.tar.gz postgresql-6e8596a146c9b16f2c053ea8c6e361a114c0b65c.zip |
Add UPDATE tab SET ROW (col, ...) = (val, ...) for updating
multiple columns
Susanne Ebrecht
-rw-r--r-- | doc/src/sgml/ref/update.sgml | 9 | ||||
-rw-r--r-- | src/backend/parser/gram.y | 78 |
2 files changed, 81 insertions, 6 deletions
diff --git a/doc/src/sgml/ref/update.sgml b/doc/src/sgml/ref/update.sgml index 5d1265e945f..7b5d17a1fc8 100644 --- a/doc/src/sgml/ref/update.sgml +++ b/doc/src/sgml/ref/update.sgml @@ -1,5 +1,5 @@ <!-- -$PostgreSQL: pgsql/doc/src/sgml/ref/update.sgml,v 1.38 2006/08/12 02:52:03 tgl Exp $ +$PostgreSQL: pgsql/doc/src/sgml/ref/update.sgml,v 1.39 2006/09/02 20:34:47 momjian Exp $ PostgreSQL documentation --> @@ -21,7 +21,8 @@ PostgreSQL documentation <refsynopsisdiv> <synopsis> UPDATE [ ONLY ] <replaceable class="PARAMETER">table</replaceable> [ [ AS ] <replaceable class="parameter">alias</replaceable> ] - SET <replaceable class="PARAMETER">column</replaceable> = { <replaceable class="PARAMETER">expression</replaceable> | DEFAULT } [, ...] + [ SET <replaceable class="PARAMETER">column</replaceable> = { <replaceable class="PARAMETER">expression</replaceable> | DEFAULT } [, ...] | + SET ( <replaceable class="PARAMETER">column</replaceable> [, ...] ) = ( { <replaceable class="PARAMETER">expression</replaceable> | DEFAULT } [, ...] ) [, ...] ] [ FROM <replaceable class="PARAMETER">fromlist</replaceable> ] [ WHERE <replaceable class="PARAMETER">condition</replaceable> ] [ RETURNING * | <replaceable class="parameter">output_expression</replaceable> [ AS <replaceable class="parameter">output_name</replaceable> ] [, ...] ] @@ -251,6 +252,10 @@ UPDATE films SET kind = 'Dramatic' WHERE kind = 'Drama'; UPDATE weather SET temp_lo = temp_lo+1, temp_hi = temp_lo+15, prcp = DEFAULT WHERE city = 'San Francisco' AND date = '2003-07-03'; </programlisting> +<programlisting> +UPDATE weather SET (temp_lo, temp_hi, prcp) = (temp_lo+1, temp_lo+15, DEFAULT) + WHERE city = 'San Francisco' AND date = '2003-07-03'; +</programlisting> </para> <para> diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index f53ba9ce60d..eab360bc774 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -11,7 +11,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.560 2006/09/02 18:17:17 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.561 2006/09/02 20:34:47 momjian Exp $ * * HISTORY * AUTHOR DATE MAJOR EVENT @@ -237,7 +237,8 @@ static void doNegateFloat(Value *v); name_list from_clause from_list opt_array_bounds qualified_name_list any_name any_name_list any_operator expr_list attrs - target_list update_target_list insert_column_list + target_list update_col_list update_target_list + update_value_list insert_column_list values_list def_list indirection opt_indirection group_clause TriggerFuncArgs select_limit opt_select_limit opclass_item_list @@ -308,7 +309,8 @@ static void doNegateFloat(Value *v); %type <jexpr> joined_table %type <range> relation_expr %type <range> relation_expr_opt_alias -%type <target> target_el update_target_el insert_column_item +%type <target> target_el update_target_el update_col_list_el insert_column_item +%type <list> update_target_lists_list update_target_lists_el %type <typnam> Typename SimpleTypename ConstTypename GenericType Numeric opt_float @@ -5537,6 +5539,20 @@ UpdateStmt: UPDATE relation_expr_opt_alias n->returningList = $7; $$ = (Node *)n; } + | UPDATE relation_expr_opt_alias + SET update_target_lists_list + from_clause + where_clause + returning_clause + { + UpdateStmt *n = makeNode(UpdateStmt); + n->relation = $2; + n->targetList = $4; + n->fromClause = $5; + n->whereClause = $6; + n->returningList = $7; + $$ = (Node *)n; + } ; @@ -5941,6 +5957,60 @@ values_item: | DEFAULT { $$ = (Node *) makeNode(SetToDefault); } ; +update_target_lists_list: + update_target_lists_el { $$ = $1; } + | update_target_lists_list ',' update_target_lists_el { $$ = list_concat($1, $3); } + ; + +update_target_lists_el: + '(' update_col_list ')' '=' '(' update_value_list ')' + { + ListCell *col_cell; + ListCell *val_cell; + + if (list_length($2) != list_length($6)) + { + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("number of columns does not match to number of values"))); + } + + for (col_cell = list_head($2), val_cell = list_head($6); + col_cell != NULL && val_cell != NULL; + col_cell = lnext(col_cell), val_cell = lnext(val_cell)) + { + /* merge update_value_list with update_col_list */ + ResTarget *res_col = (ResTarget *) lfirst(col_cell); + ResTarget *res_val = (ResTarget *) lfirst(val_cell); + + res_col->val = (Node *)copyObject(res_val); + } + + $$ = $2; + } + ; + +update_col_list: + update_col_list_el { $$ = list_make1($1); } + | update_col_list ',' update_col_list_el { $$ = lappend($1, $3); } + ; + +update_col_list_el: + ColId opt_indirection + { + $$ = makeNode(ResTarget); + $$->name = $1; + $$->indirection = $2; + $$->val = NULL; + $$->location = @1; + } + ; + +update_value_list: + values_item { $$ = list_make1($1); } + | update_value_list ',' values_item { $$ = lappend($1, $3); } + ; + /***************************************************************************** * @@ -8253,7 +8323,7 @@ target_el: a_expr AS ColLabel ; update_target_list: - update_target_el { $$ = list_make1($1); } + update_target_el { $$ = list_make1($1); } | update_target_list ',' update_target_el { $$ = lappend($1,$3); } ; |