Re: Question on doc for RETURNING clause

2024-01-11 Thread Russell, John


> On Jan 11, 2024, at 12:43 PM, Tom Lane  wrote:
> 
> "Russell, John"  writes:
>> Hi, I was thinking of suggesting some doc clarifications and additional 
>> examples related to the RETURNING clause. Just a couple of questions first 
>> to see if my understanding is correct.
> 
>> I was trying to figure out what the precise “thing” is that comes back from 
>> a RETURNING clause. A table reference? A result set?
> 
> I'd say it's a result set, just like the output of SELECT.
> 
>> That made me think both a RETURNING clause could work in contexts such as 
>> CTE (yes) and subquery (seems like no).
> 
> We disallow DML in subqueries because there's a lot of squishiness
> around when a subquery is evaluated, whether it's evaluated to
> completion, or indeed whether it's evaluated more than once.
> CTEs have tighter semantics and so it's practical to require
> "exactly once" evaluation for CTEs.  Partly this is a matter of
> historical expectations, but I doubt we'd consider revisiting it.

Makes sense. I don’t mind the limitation, I was just thinking of places to 
document it and examples to add to illustrate usage of RETURNING. If you want 
to rename columns in the result set, use AS clauses for the column names in 
RETURNING. If you want to sort and filter what comes back from RETURNING, use a 
CTE and select from that. My first idea was to try a subquery for all such 
cases; hadn’t thought of how subqueries might get pruned, moved around, or 
repeated.

>>> PostgreSQL allows INSERT, UPDATE, and DELETE to be used as WITH queries. 
>>> This is not found in the SQL standard.
> 
>> Is MERGE allowed in that ^^^ context?
> 
> Not yet, as you'd find out if you tried it.  I think there's a patch
> in the pipeline to allow it.

On the way to trying it, I did see in the doc that MERGE doesn’t have a 
RETURNING clause, which I presume makes the point moot. If there’s a patch that 
adds such support in process, I won’t suggest adding “MERGE not supported” at 
this spot in the doc.

Thanks,
John

Re: Question on doc for RETURNING clause

2024-01-11 Thread Tom Lane
"Russell, John"  writes:
> Hi, I was thinking of suggesting some doc clarifications and additional 
> examples related to the RETURNING clause. Just a couple of questions first to 
> see if my understanding is correct.

> I was trying to figure out what the precise “thing” is that comes back from a 
> RETURNING clause. A table reference? A result set?

I'd say it's a result set, just like the output of SELECT.

> That made me think both a RETURNING clause could work in contexts such as CTE 
> (yes) and subquery (seems like no).

We disallow DML in subqueries because there's a lot of squishiness
around when a subquery is evaluated, whether it's evaluated to
completion, or indeed whether it's evaluated more than once.
CTEs have tighter semantics and so it's practical to require
"exactly once" evaluation for CTEs.  Partly this is a matter of
historical expectations, but I doubt we'd consider revisiting it.

>> PostgreSQL allows INSERT, UPDATE, and DELETE to be used as WITH queries. 
>> This is not found in the SQL standard.

> Is MERGE allowed in that ^^^ context?

Not yet, as you'd find out if you tried it.  I think there's a patch
in the pipeline to allow it.

regards, tom lane




Re: Question on doc for RETURNING clause

2024-01-11 Thread David G. Johnston
On Thu, Jan 11, 2024 at 11:55 AM Russell, John  wrote:

> ```
> postgres=> insert into generatedfields (x) values (0), (10), (100) order
> by 2 desc returning id, x;
> ERROR:  ORDER BY position 2 is not in select list
> LINE 1: ...eratedfields (x) values (0), (10), (100) order by 2 desc ret...
>  ^
> ```
>
> Is the acceptance of ORDER BY documented anywhere?


VALUES, like SELECT, is an SQL Command in its own right.

https://www.postgresql.org/docs/current/sql-values.html

That is what you are ordering, before attempting insertion.  Hence why it
only sees one column.



> I didn’t see that anywhere in the INSERT syntax. Does it have any
> practical effect if there’s no RETURNING clause, e.g. do the rows get
> physically inserted in the ORDER BY order, which could have implications
> for columns like SERIAL?
>

At present, the order of rows presented to the insert does in no way compel
the insert command to act on the provided rows in order; even though in
practice it will seem to do so.

David J.


Question on doc for RETURNING clause

2024-01-11 Thread Russell, John
Hi, I was thinking of suggesting some doc clarifications and additional 
examples related to the RETURNING clause. Just a couple of questions first to 
see if my understanding is correct.

There’s the basic usage of the RETURNING clause, like is shown on the 
https://www.postgresql.org/docs/current/dml-returning.html doc page:

```
postgres=> create table ret (id serial, x int, s varchar);
CREATE TABLE
postgres=> insert into ret (x, s) values (1, 'one'), (2, 'two'), (3, 'three') 
returning id, s;
 id |   s   
+---
  1 | one
  2 | two
  3 | three
```

> The allowed contents of a RETURNING clause are the same as a SELECT command's 
> output list (see Section 7.3). It can contain column names of the command's 
> target table, or value expressions using those columns.

I was trying to figure out what the precise “thing” is that comes back from a 
RETURNING clause. A table reference? A result set? The glossary mentions it in 
the context of result sets:

https://www.postgresql.org/docs/16/glossary.html#GLOSSARY-RESULT-SET

That made me think both a RETURNING clause could work in contexts such as CTE 
(yes) and subquery (seems like no).

A DML statement with a RETURNING clause can be used in a CTE:

```
postgres=> with t1 as (insert into ret (x, s) values (1, 'one'), (2, 'two'), 
(3, 'three') returning id, s) select * from t1 order by id desc;
 id |   s 
+--- 
  6 | three
  5 | two
  4 | one
```

But it can’t be used in a subquery:

```
postgres=> select * from (insert into ret (x, s) values (1, 'one'), (2, 'two'), 
(3, 'three') returning id, s) t1 order by id desc;
ERROR:  syntax error at or near "into"   
LINE 1: select * from (insert into ret (x, s) values (1, 'one'), (2,...
```

I couldn’t tell from the definition of subqueries in 7.2.1.3 if a DML with a 
RETURNING clause should be allowed there or not.

INSERT/UPDATE/DELETE are mentioned in the with_query block of the SELECT 
statement: https://www.postgresql.org/docs/16/sql-select.html

Also on that page:

> PostgreSQL allows INSERT, UPDATE, and DELETE to be used as WITH queries. This 
> is not found in the SQL standard.

Is MERGE allowed in that ^^^ context?

Having a RETURNING clause doesn’t magically make a DML statement recognize 
extra clauses like ORDER BY:

```
postgres=> insert into ret (x, s) values (1, 'one'), (2, 'two'), (3, 'three') 
returning id, s order by id desc;
ERROR:  syntax error at or near "order"
LINE 1: ... 'one'), (2, 'two'), (3, 'three') returning id, s order by i...
 ^
```

Although intriguingly ORDER BY was recognized if I put it before RETURNING:

```
postgres=> insert into ret (x, s) values (1, 'one'), (2, 'two'), (3, 'three') 
order by id desc returning id, s;
ERROR:  column "id" does not exist
LINE 1: ...ues (1, 'one'), (2, 'two'), (3, 'three') order by id desc re...
 ^
HINT:  There is a column named "id" in table "ret", but it cannot be referenced 
from this part of the query.
```

If I didn’t rely on the column name, I could do ORDER BY as part of the INSERT… 
but it seems like only the “real” inserted column is considered. Here the 
ordering is by column 2 of the RETURNING clause, which is column 1 from the 
list of inserted columns:

```
postgres=> insert into generatedfields (x) values (0), (10), (100) order by 1 
desc returning id, x;
 id |  x  
+-
 13 | 100
 14 |  10
 15 |   0  
```

The statement is only aware of 1 column that it can order by, not 2 as in the 
RETURNING clause:

```
postgres=> insert into generatedfields (x) values (0), (10), (100) order by 2 
desc returning id, x;
ERROR:  ORDER BY position 2 is not in select list
LINE 1: ...eratedfields (x) values (0), (10), (100) order by 2 desc ret...
 ^
```

Is the acceptance of ORDER BY documented anywhere? I didn’t see that anywhere 
in the INSERT syntax. Does it have any practical effect if there’s no RETURNING 
clause, e.g. do the rows get physically inserted in the ORDER BY order, which 
could have implications for columns like SERIAL?

Thanks,
John