Skip to content

Commit c62736c

Browse files
committed
Add SQL Standard WITH ORDINALITY support for UNNEST (and any other SRF)
Author: Andrew Gierth, David Fetter Reviewers: Dean Rasheed, Jeevan Chalke, Stephen Frost
1 parent 55cbfa5 commit c62736c

File tree

22 files changed

+1499
-336
lines changed

22 files changed

+1499
-336
lines changed

doc/src/sgml/func.sgml

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13278,14 +13278,56 @@ select $1[i][j]
1327813278
generate_subscripts($1,2) g2(j);
1327913279
$$ LANGUAGE sql IMMUTABLE;
1328013280
CREATE FUNCTION
13281-
postgres=# SELECT * FROM unnest2(ARRAY[[1,2],[3,4]]);
13281+
SELECT * FROM unnest2(ARRAY[[1,2],[3,4]]);
1328213282
unnest2
1328313283
---------
1328413284
1
1328513285
2
1328613286
3
1328713287
4
1328813288
(4 rows)
13289+
</programlisting>
13290+
</para>
13291+
13292+
<indexterm>
13293+
<primary>ordinality</primary>
13294+
</indexterm>
13295+
13296+
<para>
13297+
When a function in the <literal>FROM</literal> clause is suffixed by
13298+
<literal>WITH ORDINALITY</literal>, a <type>bigint</type> column is appended
13299+
to the output which starts from 1 and increments by 1 for each row of the
13300+
function's output. This is most useful in the case of set returning functions
13301+
such as UNNEST(). This functionality is available for functions returning
13302+
composite types or using <literal>OUT</literal> parameters, but not when using
13303+
a function returning <literal>RECORD</literal> with an explicit column
13304+
definition list.
13305+
13306+
<programlisting>
13307+
-- set returning function WITH ORDINALITY
13308+
SELECT * FROM pg_ls_dir('.') WITH ORDINALITY AS t(ls,n);
13309+
ls | n
13310+
-----------------+----
13311+
pg_serial | 1
13312+
pg_twophase | 2
13313+
postmaster.opts | 3
13314+
pg_notify | 4
13315+
postgresql.conf | 5
13316+
pg_tblspc | 6
13317+
logfile | 7
13318+
base | 8
13319+
postmaster.pid | 9
13320+
pg_ident.conf | 10
13321+
global | 11
13322+
pg_clog | 12
13323+
pg_snapshots | 13
13324+
pg_multixact | 14
13325+
PG_VERSION | 15
13326+
pg_xlog | 16
13327+
pg_hba.conf | 17
13328+
pg_stat_tmp | 18
13329+
pg_subtrans | 19
13330+
(19 rows)
1328913331
</programlisting>
1329013332
</para>
1329113333

doc/src/sgml/ref/select.sgml

Lines changed: 35 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,8 @@ SELECT [ ALL | DISTINCT [ ON ( <replaceable class="parameter">expression</replac
5252
[ ONLY ] <replaceable class="parameter">table_name</replaceable> [ * ] [ [ AS ] <replaceable class="parameter">alias</replaceable> [ ( <replaceable class="parameter">column_alias</replaceable> [, ...] ) ] ]
5353
[ LATERAL ] ( <replaceable class="parameter">select</replaceable> ) [ AS ] <replaceable class="parameter">alias</replaceable> [ ( <replaceable class="parameter">column_alias</replaceable> [, ...] ) ]
5454
<replaceable class="parameter">with_query_name</replaceable> [ [ AS ] <replaceable class="parameter">alias</replaceable> [ ( <replaceable class="parameter">column_alias</replaceable> [, ...] ) ] ]
55-
[ LATERAL ] <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> [, ...] ) ]
55+
[ LATERAL ] <replaceable class="parameter">function_name</replaceable> ( [ <replaceable class="parameter">argument</replaceable> [, ...] ] ) [ WITH ORDINALITY ] [ [ AS ] <replaceable class="parameter">alias</replaceable> [ ( <replaceable class="parameter">column_alias</replaceable> [, ...] ) ] ]
56+
[ LATERAL ] <replaceable class="parameter">function_name</replaceable> ( [ <replaceable class="parameter">argument</replaceable> [, ...] ] ) [ AS ] <replaceable class="parameter">alias</replaceable> ( <replaceable class="parameter">column_definition</replaceable> [, ...] )
5657
[ LATERAL ] <replaceable class="parameter">function_name</replaceable> ( [ <replaceable class="parameter">argument</replaceable> [, ...] ] ) AS ( <replaceable class="parameter">column_definition</replaceable> [, ...] )
5758
<replaceable class="parameter">from_item</replaceable> [ NATURAL ] <replaceable class="parameter">join_type</replaceable> <replaceable class="parameter">from_item</replaceable> [ ON <replaceable class="parameter">join_condition</replaceable> | USING ( <replaceable class="parameter">join_column</replaceable> [, ...] ) ]
5859

@@ -368,18 +369,40 @@ TABLE [ ONLY ] <replaceable class="parameter">table_name</replaceable> [ * ]
368369
clause. (This is especially useful for functions that return
369370
result sets, but any function can be used.) This acts as
370371
though its output were created as a temporary table for the
371-
duration of this single <command>SELECT</command> command. An
372-
alias can also be used. If an alias is written, a column alias
373-
list can also be written to provide substitute names for one
374-
or more attributes of the function's composite return type. If
375-
the function has been defined as returning the <type>record</>
376-
data type, then an alias or the key word <literal>AS</> must
377-
be present, followed by a column definition list in the form
378-
<literal>( <replaceable
372+
duration of this single <command>SELECT</command> command.
373+
When the optional <command>WITH ORDINALITY</command> is
374+
appended to the function call, a new column is appended after
375+
all the function call's columns with numbering for each row.
376+
For example:
377+
<programlisting>
378+
SELECT * FROM unnest(ARRAY['a','b','c','d','e','f']) WITH ORDINALITY;
379+
unnest | ordinality
380+
--------+----------
381+
a | 1
382+
b | 2
383+
c | 3
384+
d | 4
385+
e | 5
386+
f | 6
387+
(6 rows)
388+
</programlisting>
389+
An alias can also be used. If an alias is written, a column
390+
alias list can also be written to provide substitute names for
391+
one or more attributes of the function's composite return
392+
type, including the column added by <literal>ORDINALITY</literal>
393+
if present.
394+
</para>
395+
396+
<para>
397+
If the function has been defined as returning the
398+
<type>record</> data type, then an alias or the key word
399+
<literal>AS</> must be present, followed by a column
400+
definition list in the form <literal>( <replaceable
379401
class="parameter">column_name</replaceable> <replaceable
380-
class="parameter">data_type</replaceable> <optional>, ... </>
381-
)</literal>. The column definition list must match the actual
382-
number and types of columns returned by the function.
402+
class="parameter">data_type</replaceable> <optional>, ...
403+
</>)</literal>. The column definition list must match the
404+
actual number and types of columns returned by the function.
405+
<literal>ORDINALITY</literal> does not work in this case.
383406
</para>
384407
</listitem>
385408
</varlistentry>

src/backend/access/common/tupdesc.c

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,40 @@ CreateTupleDescCopy(TupleDesc tupdesc)
157157
return desc;
158158
}
159159

160+
/*
161+
* CreateTupleDescCopyExtend
162+
* This function creates a new TupleDesc by copying from an existing
163+
* TupleDesc, but adding space for more columns. The new tupdesc is
164+
* not regarded as the same record type as the old one (and therefore
165+
* does not inherit its typeid/typmod, which instead are left as an
166+
* anonymous record type).
167+
*
168+
* The additional column slots are not initialized in any way;
169+
* callers must do their own TupleDescInitEntry on each.
170+
*
171+
* !!! Constraints and defaults are not copied !!!
172+
*/
173+
TupleDesc
174+
CreateTupleDescCopyExtend(TupleDesc tupdesc, int moreatts)
175+
{
176+
TupleDesc desc;
177+
int i;
178+
int src_natts = tupdesc->natts;
179+
180+
Assert(moreatts >= 0);
181+
182+
desc = CreateTemplateTupleDesc(src_natts + moreatts, tupdesc->tdhasoid);
183+
184+
for (i = 0; i < src_natts; i++)
185+
{
186+
memcpy(desc->attrs[i], tupdesc->attrs[i], ATTRIBUTE_FIXED_PART_SIZE);
187+
desc->attrs[i]->attnotnull = false;
188+
desc->attrs[i]->atthasdef = false;
189+
}
190+
191+
return desc;
192+
}
193+
160194
/*
161195
* CreateTupleDescCopyConstr
162196
* This function creates a new TupleDesc by copying from an existing

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy