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); }
        ;