Hi,

here is a patch that extends update syntax following the sql standard.
The patch includes sgml documentation, too.

For example:

UPDATE table SET (col1, col2, ...) = (val1, val2, ...), 
(colm, coln, ...) = (valm, valn, ...), ...;

Susanne

Index: doc/src/sgml/ref/update.sgml
===================================================================
RCS file: /projects/cvsroot/pgsql/doc/src/sgml/ref/update.sgml,v
retrieving revision 1.37
diff -u -3 -p -c -r1.37 update.sgml
*** doc/src/sgml/ref/update.sgml	8 Mar 2006 22:59:09 -0000	1.37
--- doc/src/sgml/ref/update.sgml	19 Jul 2006 13:01:48 -0000
*************** UPDATE [ ONLY ] <replaceable class="PARA
*** 25,30 ****
--- 25,36 ----
      [ FROM <replaceable class="PARAMETER">fromlist</replaceable> ]
      [ WHERE <replaceable class="PARAMETER">condition</replaceable> ]
  </synopsis>
+ <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 } [, ...] ) [, ...]
+     [ FROM <replaceable class="PARAMETER">fromlist</replaceable> ]
+     [ WHERE <replaceable class="PARAMETER">condition</replaceable> ]
+ </synopsis>
   </refsynopsisdiv>
  
   <refsect1>
*************** UPDATE films SET kind = 'Dramatic' WHERE
*** 210,215 ****
--- 216,225 ----
  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>
Index: src/backend/parser/gram.y
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/parser/gram.y,v
retrieving revision 2.551
diff -u -3 -p -c -r2.551 gram.y
*** src/backend/parser/gram.y	3 Jul 2006 22:45:39 -0000	2.551
--- src/backend/parser/gram.y	19 Jul 2006 13:01:55 -0000
*************** static void doNegateFloat(Value *v);
*** 237,243 ****
  				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
  				insert_target_list def_list indirection opt_indirection
  				group_clause TriggerFuncArgs select_limit
  				opt_select_limit opclass_item_list
--- 237,244 ----
  				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_col_list update_target_list
!                                 update_value_list insert_column_list
  				insert_target_list def_list indirection opt_indirection
  				group_clause TriggerFuncArgs select_limit
  				opt_select_limit opclass_item_list
*************** static void doNegateFloat(Value *v);
*** 308,314 ****
  %type <jexpr>	joined_table
  %type <range>	relation_expr
  %type <range>	relation_expr_opt_alias
! %type <target>	target_el insert_target_el update_target_el insert_column_item
  
  %type <typnam>	Typename SimpleTypename ConstTypename
  				GenericType Numeric opt_float
--- 309,317 ----
  %type <jexpr>	joined_table
  %type <range>	relation_expr
  %type <range>	relation_expr_opt_alias
! %type <target>	target_el insert_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
*************** UpdateStmt: UPDATE relation_expr_opt_ali
*** 5477,5482 ****
--- 5480,5497 ----
  					n->whereClause = $6;
  					$$ = (Node *)n;
  				}
+             | UPDATE relation_expr_opt_alias
+ 			SET update_target_lists_list
+ 			from_clause
+ 			where_clause
+ 				{
+ 					UpdateStmt *n = makeNode(UpdateStmt);
+ 					n->relation = $2;
+ 					n->targetList = $4;
+ 					n->fromClause = $5;
+ 					n->whereClause = $6;
+ 					$$ = (Node *)n;
+ 				}
  		;
  
  
*************** target_el:	a_expr AS ColLabel
*** 8165,8171 ****
  		;
  
  update_target_list:
! 			update_target_el						{ $$ = list_make1($1); }
  			| update_target_list ',' update_target_el { $$ = lappend($1,$3); }
  		;
  
--- 8180,8186 ----
  		;
  
  update_target_list:
! 			update_target_el			  { $$ = list_make1($1); }
  			| update_target_list ',' update_target_el { $$ = lappend($1,$3); }
  		;
  
*************** update_target_el:
*** 8186,8192 ****
--- 8201,8261 ----
  					$$->val = (Node *) makeNode(SetToDefault);
  					$$->location = @1;
  				}
+ 		;
+ 
+ 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 = NULL;
+ 				    ListCell *val_cell = NULL;
+ 
+ 					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->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:
+ 			insert_target_el { $$ = list_make1($1); }
+ 			| update_value_list ',' insert_target_el { $$ = lappend($1, $3); }
  		;
  
  insert_target_list:

Attachment: signature.asc
Description: This is a digitally signed message part

Reply via email to