Re: Order of rows in simple "select r from table_fn()"

From: Bryn Llewellyn <bryn(at)yugabyte(dot)com>
To: "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, pavel(dot)stehule(at)gmail(dot)com
Cc: pgsql-general list <pgsql-general(at)lists(dot)postgresql(dot)org>
Subject: Re: Order of rows in simple "select r from table_fn()"
Date: 2023-02-15 05:01:20
Message-ID: D25756FE-1F2B-4B45-9603-637712D35413@yugabyte.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-general

> david(dot)g(dot)johnston(at)gmail(dot)com wrote:
>
>> bryn(at)yugabyte(dot)com wrote:
>>
>> I've found that a table function with "returns table(r text)" provides a convenient way to write a nicely formatted report using psql that can be easily directed to a file with the "\o" metacommand. In general, for cases like this, I can't write a useful "order by r" because the values of "r" interleave, for example, rule-offs between sections of the report, various sub-headings, and actual query results. The required order is exactly the order in which my code produces the rows.
>
> Seems safe enough to rely upon if the query is indeed: SELECT * FROM fn(); The system has to consume the output of the function call in its serial order and has no reason to then reorder things prior to producing the final result set. Though I'd probably still consider adding a "report line number" column to the output for end-user usability or if they want to sort the report and then return to the physical order.
>
> I am curious whether a user-defined set-returning function is allowed to specify "WITH ORDINALITY" like the built-in UNNEST function does to produce the output row numbers external to the function body and signature.

Thanks, David. Thanks, too, to pavel(dot)stehule(at)gmail(dot)com for your separate reply that also says that I can rely on seeing the order in which I produce the rows in the function's implementation. And yes, I realize that Postgres table functions are not pipelined in the way that they can be, if you choose this, in Oracle Database.

Given that the order is pre-calculated, it seems that "with ordinality" can add line numbering "after the fact" reliably and with minimum clutter when it's needed. I tried these two variants:

create function f1()
returns setof text
language sql
as $body$
values ('skiing'), ('cycling'), ('running');
$body$;
and:

create function f2()
returns table(r text)
language plpgsql
as $body$
begin
r := 'skiing'; return next;
r := 'cycling'; return next;
r := 'running'; return next;
end;
$body$;

select t.line_no, t.report_text
from f1() with ordinality as t(report_text, line_no);

Each supports this same query

select t.line_no, t.report_text
from fN() with ordinality as t(report_text, line_no);

and gets this same result:

line_no | report_text
---------+-------------
1 | skiing
2 | cycling
3 | running

In response to

Browse pgsql-general by date

  From Date Subject
Next Message Amit Kapila 2023-02-15 05:57:04 Re: Support logical replication of DDLs
Previous Message Pavel Stehule 2023-02-15 04:34:43 Re: Order of rows in simple "select r from table_fn()"