> david.g.johns...@gmail.com wrote:
> 
>> b...@yugabyte.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.steh...@gmail.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

Reply via email to