Docs and regression tests attached.

One slightly annoying thing is this:

---
regression=# declare foo cursor with hold for VALUES(1,2), (3, 4);
DECLARE CURSOR
regression=# declare foo2 cursor with hold for (VALUES(1,2), (3, 4)) as
foo(i, j);
ERROR:  syntax error at or near "as"
LINE 1: ...e foo2 cursor with hold for (VALUES(1,2), (3, 4)) as foo(i, ...
---

Now, we can just rewrite the second query as:

---
declare foo2 cursor with hold for select * from (VALUES(1,2), (3, 4)) as
foo(i, j);
---

but it's not immediately obvious. Not worth busting up the grammar for it,
though. And, it's not spec.

Gavin
Index: doc/src/sgml/ref/declare.sgml
===================================================================
RCS file: /usr/local/cvsroot/pgsql/doc/src/sgml/ref/declare.sgml,v
retrieving revision 1.37
diff -c -p -r1.37 declare.sgml
*** doc/src/sgml/ref/declare.sgml       26 Feb 2006 03:20:46 -0000      1.37
--- doc/src/sgml/ref/declare.sgml       3 Aug 2006 04:18:28 -0000
*************** DECLARE liahona CURSOR FOR SELECT * FROM
*** 275,280 ****
--- 275,288 ----
     See <xref linkend="sql-fetch" endterm="sql-fetch-title"> for more
     examples of cursor usage.
    </para>
+ 
+   <para>
+    The cursor <replaceable class="parameter">query</> clause can also
+    be a <literal>VALUES</> list:
+ <programlisting>
+ DECLARE cols CURSOR FOR VALUES(1,2), (3,4);
+ </programlisting>
+   </para>
   </refsect1>
  
   <refsect1>
Index: doc/src/sgml/ref/delete.sgml
===================================================================
RCS file: /usr/local/cvsroot/pgsql/doc/src/sgml/ref/delete.sgml,v
retrieving revision 1.26
diff -c -p -r1.26 delete.sgml
*** doc/src/sgml/ref/delete.sgml        22 Jan 2006 05:20:33 -0000      1.26
--- doc/src/sgml/ref/delete.sgml        3 Aug 2006 03:26:58 -0000
*************** DELETE FROM [ ONLY ] <replaceable class=
*** 117,122 ****
--- 117,128 ----
        in the <replaceable class="PARAMETER">usinglist</replaceable>,
        unless you wish to set up a self-join.
       </para>
+ 
+      <para>
+       The <replaceable class="PARAMETER">usinglist</> may also contain a
+       <literal>VALUES</> list, evaluating to one or more rows. These
+       rows may also be referenced in the <literal>WHERE</> clause.
+        </para>
      </listitem>
     </varlistentry>
  
*************** DELETE FROM films WHERE kind &lt;&gt; 'M
*** 191,196 ****
--- 197,213 ----
  DELETE FROM films;
  </programlisting>      
    </para>
+ 
+   <para>
+    Delete films made after 1990 which are 'Horror' and films made
+    after 2000 which are 'Crime'. To do this, we use a <literal>VALUES</>
+    list in the <literal>USING</> clause.
+ <programlisting>
+ DELETE FROM films USING (VALUES('1990-01-01, 'Horror'), ('2000-01-01', 
'Crime))
+     AS det (year, kind) WHERE films.date_prod >= det.year AND
+     films.kind = det.kind;
+ </programlisting>
+   </para>
   </refsect1>
  
   <refsect1>
Index: doc/src/sgml/ref/insert.sgml
===================================================================
RCS file: /usr/local/cvsroot/pgsql/doc/src/sgml/ref/insert.sgml,v
retrieving revision 1.30
diff -c -p -r1.30 insert.sgml
*** doc/src/sgml/ref/insert.sgml        17 Nov 2005 22:14:51 -0000      1.30
--- doc/src/sgml/ref/insert.sgml        2 Aug 2006 22:40:14 -0000
*************** PostgreSQL documentation
*** 21,27 ****
   <refsynopsisdiv>
  <synopsis>
  INSERT INTO <replaceable class="PARAMETER">table</replaceable> [ ( 
<replaceable class="PARAMETER">column</replaceable> [, ...] ) ]
!     { DEFAULT VALUES | VALUES ( { <replaceable 
class="PARAMETER">expression</replaceable> | DEFAULT } [, ...] ) | <replaceable 
class="PARAMETER">query</replaceable> }
  </synopsis>
   </refsynopsisdiv>
  
--- 21,27 ----
   <refsynopsisdiv>
  <synopsis>
  INSERT INTO <replaceable class="PARAMETER">table</replaceable> [ ( 
<replaceable class="PARAMETER">column</replaceable> [, ...] ) ]
!     { DEFAULT VALUES | VALUES ( { <replaceable 
class="PARAMETER">expression</replaceable> | DEFAULT } [, ...] ) [, ( ... ) ] | 
<replaceable class="PARAMETER">query</replaceable> }
  </synopsis>
   </refsynopsisdiv>
  
*************** INSERT INTO <replaceable class="PARAMETE
*** 30,37 ****
  
    <para>
     <command>INSERT</command> inserts new rows into a table.
!    One can insert a single row specified by value expressions,
!    or several rows as a result of a query.
    </para>
  
    <para>
--- 30,37 ----
  
    <para>
     <command>INSERT</command> inserts new rows into a table.
!    One can insert one or more rows specified by value expressions,
!    or zero or more rows resulting from a query.
    </para>
  
    <para>
*************** INSERT INTO films VALUES
*** 162,167 ****
--- 162,177 ----
    </para>
  
    <para>
+    Insert multiple rows into a table <literal>films</>:
+ 
+ <programlisting>
+ INSERT INTO films VALUES
+       ('B6717', 'Tampopo', 110, '1985-02-10', 'Comedy'),
+       ('HG120', 'The Dinner Game', 140, '1998-10-12', 'Comedy');
+ </programlisting>
+   </para>
+ 
+   <para>
     In this example, the <literal>len</literal> column is
     omitted and therefore it will have the default value:
  
Index: doc/src/sgml/ref/select.sgml
===================================================================
RCS file: /usr/local/cvsroot/pgsql/doc/src/sgml/ref/select.sgml,v
retrieving revision 1.91
diff -c -p -r1.91 select.sgml
*** doc/src/sgml/ref/select.sgml        30 Apr 2006 18:30:38 -0000      1.91
--- doc/src/sgml/ref/select.sgml        2 Aug 2006 22:40:12 -0000
*************** SELECT [ ALL | DISTINCT [ ON ( <replacea
*** 35,40 ****
--- 35,41 ----
  where <replaceable class="parameter">from_item</replaceable> can be one of:
  
      [ ONLY ] <replaceable class="parameter">table_name</replaceable> [ * ] [ 
[ AS ] <replaceable class="parameter">alias</replaceable> [ ( <replaceable 
class="parameter">column_alias</replaceable> [, ...] ) ] ]
+     ( VALUES ( <replaceable class="parameter">expression</replaceable> [, ... 
] ) [, ( ... ) ] [ AS ] <replaceable class="parameter">alias</replaceable> [ ( 
<replaceable class="parameter">column_alias</replaceable> [, ...] ) ]
      ( <replaceable class="parameter">select</replaceable> ) [ AS ] 
<replaceable class="parameter">alias</replaceable> [ ( <replaceable 
class="parameter">column_alias</replaceable> [, ...] ) ]
      <replaceable class="parameter">function_name</replaceable> ( [ 
<replaceable class="parameter">argument</replaceable> [, ...] ] ) [ AS ] 
<replaceable class="parameter">alias</replaceable> [ ( <replaceable 
class="parameter">column_alias</replaceable> [, ...] | <replaceable 
class="parameter">column_definition</replaceable> [, ...] ) ]
      <replaceable class="parameter">function_name</replaceable> ( [ 
<replaceable class="parameter">argument</replaceable> [, ...] ] ) AS ( 
<replaceable class="parameter">column_definition</replaceable> [, ...] )
*************** where <replaceable class="parameter">fro
*** 197,202 ****
--- 198,214 ----
         </para>
        </listitem>
       </varlistentry>
+ 
+      <varlistentry>
+       <term><literal>VALUES(<replaceable 
class="parameter">expression</replaceable> [, ...]) [, ...]</literal></term>
+       <listitem>
+        <para>
+         One or more rows may be constructed in the from clause. Each
+         <replaceable class="parameter">expression</> will be evaluated and
+         assigned to the corresponding column.
+        </para>
+       </listitem>
+      </varlistentry>
       
       <varlistentry>
        <term><replaceable class="parameter">alias</replaceable></term>
*************** SELECT f.title, f.did, d.name, f.date_pr
*** 916,921 ****
--- 928,947 ----
    </para>
  
    <para>
+    To join the table <literal>films</> with a <literal>VALUES</> list:
+ <programlisting>
+ SELECT f.title, f.did, f.date_prod, f.kind
+     FROM films f, (VALUES('Horror'), ('Sci-Fi')) as k (kind)
+     WHERE f.kind = k.kind;
+             title             | did | date_prod  |  kind
+ ------------------------------+-----+------------+--------
+  The Texas Chain Saw Massacre | 190 | 1974-06-11 | Horror
+  2001: A Space Odyssey        | 210 | 1968-08-24 | Sci-Fi
+  ...
+ </programlisting>
+   </para>
+ 
+   <para>
     To sum the column <literal>len</literal> of all films and group
     the results by <literal>kind</literal>:
  
Index: doc/src/sgml/ref/update.sgml
===================================================================
RCS file: /usr/local/cvsroot/pgsql/doc/src/sgml/ref/update.sgml,v
retrieving revision 1.37
diff -c -p -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        3 Aug 2006 03:27:07 -0000
*************** UPDATE [ ONLY ] <replaceable class="PARA
*** 134,139 ****
--- 134,145 ----
        <replaceable>fromlist</>, unless you intend a self-join (in which
        case it must appear with an alias in the <replaceable>fromlist</>).
       </para>
+ 
+        <para>
+         The <replaceable class="PARAMETER">from_list</> may also contain a
+         <literal>VALUES</> list, evaluating to one or more rows. These
+         rows may also be referenced in the <literal>WHERE</> clause.
+      </para>
      </listitem>
     </varlistentry>
  
*************** UPDATE employees SET sales_count = sales
*** 233,238 ****
--- 239,255 ----
    </para>
  
    <para>
+    Perform an update on <literal>employees</> with a join against a 
+    <literal>VALUES</> list:
+ <programlisting>
+ UPDATE employees SET salary = salary * increase
+    FROM (VALUES(1, 200000, 1.2), (2, 400000, 1.4)) 
+    as prof (depno, target, increase)
+    WHERE employees.sales &gt;= prof.target and employees.depno = prof.depno;
+ </programlisting>
+   </para>
+ 
+   <para>
     Attempt to insert a new stock item along with the quantity of stock. If
     the item already exists, instead update the stock count of the existing
     item. To do this without failing the entire transaction, use savepoints.
Index: src/test/regress/sql/insert.sql
===================================================================
RCS file: /usr/local/cvsroot/pgsql/src/test/regress/sql/insert.sql,v
retrieving revision 1.2
diff -c -p -r1.2 insert.sql
*** src/test/regress/sql/insert.sql     24 Apr 2002 02:22:54 -0000      1.2
--- src/test/regress/sql/insert.sql     3 Aug 2006 05:13:57 -0000
*************** insert into inserttest (col1, col2, col3
*** 18,22 ****
--- 18,29 ----
  insert into inserttest (col1) values (1, 2);
  insert into inserttest (col1) values (DEFAULT, DEFAULT);
  
+ --
+ -- VALUES test
+ --
+ 
+ insert into inserttest values(10, 20, '40'), (-1, 2, DEFAULT),
+       ((select 2), (select i from (values(3)) as foo (i)), 'values are fun!');
+ 
  select * from inserttest;
  drop table inserttest;
Index: src/test/regress/sql/select.sql
===================================================================
RCS file: /usr/local/cvsroot/pgsql/src/test/regress/sql/select.sql,v
retrieving revision 1.10
diff -c -p -r1.10 select.sql
*** src/test/regress/sql/select.sql     14 Dec 2005 16:28:32 -0000      1.10
--- src/test/regress/sql/select.sql     3 Aug 2006 05:04:15 -0000
*************** SELECT p.name, p.age FROM person* p ORDE
*** 110,112 ****
--- 110,125 ----
  select foo from (select 1) as foo;
  select foo from (select null) as foo;
  select foo from (select 'xyzzy',1,null) as foo;
+ 
+ --
+ -- Test VALUES lists
+ --
+ select * from onek, (values(147, 'RFAAAA'), (931, 'VJAAAA')) as v (i, j) WHERE
+       onek.unique1 = v.i and onek.stringu1 = v.j;
+ 
+ -- a more complex case
+ -- looks like we're coding lisp :-)
+ select * from onek, (values((select i from 
+       (values(10000), (2), (389), (1000), (2000), ((select 10029))) as foo(i)
+       order by i asc limit 1))) bar (i)
+       where onek.unique1 = bar.i;
Index: src/test/regress/sql/update.sql
===================================================================
RCS file: /usr/local/cvsroot/pgsql/src/test/regress/sql/update.sql,v
retrieving revision 1.3
diff -c -p -r1.3 update.sql
*** src/test/regress/sql/update.sql     22 Jan 2006 05:20:35 -0000      1.3
--- src/test/regress/sql/update.sql     3 Aug 2006 04:32:03 -0000
*************** SELECT * FROM update_test;
*** 23,28 ****
--- 23,35 ----
  
  UPDATE update_test t SET b = t.b + 10 WHERE t.a = 10;
  
+ --
+ -- Test VALUES in FROM
+ --
+ 
+ UPDATE update_test SET a=v.i FROM (VALUES(100, 20)) AS v(i, j)
+       WHERE update_test.b = v.j;
+ 
  SELECT * FROM update_test;
  
  -- if an alias for the target table is specified, don't allow references
*************** SET LOCAL add_missing_from = false;
*** 32,35 ****
--- 39,43 ----
  UPDATE update_test AS t SET b = update_test.b + 10 WHERE t.a = 10;
  ROLLBACK;
  
+ 
  DROP TABLE update_test;
Index: src/test/regress/expected/insert.out
===================================================================
RCS file: /usr/local/cvsroot/pgsql/src/test/regress/expected/insert.out,v
retrieving revision 1.7
diff -c -p -r1.7 insert.out
*** src/test/regress/expected/insert.out        25 Sep 2003 06:58:06 -0000      
1.7
--- src/test/regress/expected/insert.out        3 Aug 2006 05:19:01 -0000
*************** insert into inserttest (col1) values (1,
*** 28,40 ****
  ERROR:  INSERT has more expressions than target columns
  insert into inserttest (col1) values (DEFAULT, DEFAULT);
  ERROR:  INSERT has more expressions than target columns
  select * from inserttest;
   col1 | col2 |  col3   
! ------+------+---------
        |    3 | testing
        |    5 | testing
        |    5 | test
        |    7 | testing
! (4 rows)
  
  drop table inserttest;
--- 28,48 ----
  ERROR:  INSERT has more expressions than target columns
  insert into inserttest (col1) values (DEFAULT, DEFAULT);
  ERROR:  INSERT has more expressions than target columns
+ --
+ -- VALUES test
+ --
+ insert into inserttest values(10, 20, '40'), (-1, 2, DEFAULT),
+       ((select 2), (select i from (values(3)) as foo (i)), 'values are fun!');
  select * from inserttest;
   col1 | col2 |  col3   
! ------+------+-----------------
        |    3 | testing
        |    5 | testing
        |    5 | test
        |    7 | testing
!    10 |   20 | 40
!    -1 |    2 | testing
!     2 |    3 | values are fun!
! (7 rows)
  
  drop table inserttest;
Index: src/test/regress/expected/select.out
===================================================================
RCS file: /usr/local/cvsroot/pgsql/src/test/regress/expected/select.out,v
retrieving revision 1.14
diff -c -p -r1.14 select.out
*** src/test/regress/expected/select.out        14 Dec 2005 16:28:32 -0000      
1.14
--- src/test/regress/expected/select.out        3 Aug 2006 04:50:36 -0000
*************** select foo from (select 'xyzzy',1,null) 
*** 452,454 ****
--- 452,476 ----
   (xyzzy,1,)
  (1 row)
  
+ --
+ -- Test VALUES lists
+ --
+ select * from onek, (values(147, 'RFAAAA'), (931, 'VJAAAA')) as v (i, j) WHERE
+       onek.unique1 = v.i and onek.stringu1 = v.j;
+  unique1 | unique2 | two | four | ten | twenty | hundred | thousand | 
twothousand | fivethous | tenthous | odd | even | stringu1 | stringu2 | string4 
|  i  |   j    
+ 
---------+---------+-----+------+-----+--------+---------+----------+-------------+-----------+----------+-----+------+----------+----------+---------+-----+--------
+      147 |       0 |   1 |    3 |   7 |      7 |       7 |       47 |         
147 |       147 |      147 |  14 |   15 | RFAAAA   | AAAAAA   | AAAAxx  | 147 | 
RFAAAA
+      931 |       1 |   1 |    3 |   1 |     11 |       1 |       31 |         
131 |       431 |      931 |   2 |    3 | VJAAAA   | BAAAAA   | HHHHxx  | 931 | 
VJAAAA
+ (2 rows)
+ 
+ -- a more complex case
+ -- looks like we're coding lisp :-)
+ select * from onek, (values((select i from 
+       (values(10000), (2), (389), (1000), (2000), ((select 10029))) as foo(i)
+       order by i asc limit 1))) bar (i)
+       where onek.unique1 = bar.i;
+  unique1 | unique2 | two | four | ten | twenty | hundred | thousand | 
twothousand | fivethous | tenthous | odd | even | stringu1 | stringu2 | string4 
| i 
+ 
---------+---------+-----+------+-----+--------+---------+----------+-------------+-----------+----------+-----+------+----------+----------+---------+---
+        2 |     326 |   0 |    2 |   2 |      2 |       2 |        2 |         
  2 |         2 |        2 |   4 |    5 | CAAAAA   | OMAAAA   | OOOOxx  | 2
+ (1 row)
+ 
Index: src/test/regress/expected/update.out
===================================================================
RCS file: /usr/local/cvsroot/pgsql/src/test/regress/expected/update.out,v
retrieving revision 1.3
diff -c -p -r1.3 update.out
*** src/test/regress/expected/update.out        14 Mar 2006 22:48:25 -0000      
1.3
--- src/test/regress/expected/update.out        3 Aug 2006 04:50:48 -0000
*************** SELECT * FROM update_test;
*** 32,42 ****
  (2 rows)
  
  UPDATE update_test t SET b = t.b + 10 WHERE t.a = 10;
  SELECT * FROM update_test;
   a  | b  
! ----+----
!  10 | 20
!  10 | 20
  (2 rows)
  
  -- if an alias for the target table is specified, don't allow references
--- 32,47 ----
  (2 rows)
  
  UPDATE update_test t SET b = t.b + 10 WHERE t.a = 10;
+ --
+ -- Test VALUES in FROM
+ --
+ UPDATE update_test SET a=v.i FROM (VALUES(100, 20)) AS v(i, j)
+       WHERE update_test.b = v.j;
  SELECT * FROM update_test;
   a  | b  
! -----+----
!  100 | 20
!  100 | 20
  (2 rows)
  
  -- if an alias for the target table is specified, don't allow references
---------------------------(end of broadcast)---------------------------
TIP 3: Have you checked our extensive FAQ?

               http://www.postgresql.org/docs/faq

Reply via email to