]> granicus.if.org Git - postgresql/commitdiff
Add UPDATE tab SET ROW (col, ...) = (val, ...) for updating
authorBruce Momjian <bruce@momjian.us>
Sat, 2 Sep 2006 20:34:47 +0000 (20:34 +0000)
committerBruce Momjian <bruce@momjian.us>
Sat, 2 Sep 2006 20:34:47 +0000 (20:34 +0000)
multiple columns

Susanne Ebrecht

doc/src/sgml/ref/update.sgml
src/backend/parser/gram.y

index 5d1265e945f7ad4e578d5b1635a1ba3a10448307..7b5d17a1fc89dcb4c89f1b87940dfa8080ffbda1 100644 (file)
@@ -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> ] [, ...] ]
@@ -250,6 +251,10 @@ UPDATE films SET kind = 'Dramatic' WHERE kind = 'Drama';
 <programlisting>
 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>
 
index f53ba9ce60d21c1f355366cc14cfeedf481b44dd..eab360bc7748feb8679c404b1ba5b0d885606d89 100644 (file)
@@ -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); }
                ;