I noticed that the PostgreSQL entry in a pan-database feature matrix by
Modern SQL was not reflecting the reality of our features.[1]
It turns out that test case used by the author produced an error which
the tool took to mean the feature was not implemented. I don't have the
actual test, but here is a simulation of it:
postgres=# SELECT LAG(n, 1, -99) OVER (ORDER BY n)
postgres-# FROM (VALUES (1.1), (2.2), (3.3)) AS v (n)
postgres-# ORDER BY n;
ERROR: function lag(numeric, integer, integer) does not exist
LINE 1: SELECT LAG(n, 1, -99) OVER (ORDER BY n)
^
HINT: No function matches the given name and argument types. You
might need to add explicit type casts.
Attached is a patch that fixes this issue using the new anycompatible
pseudotype. I am hoping this can be slipped into 13 even though it
requires a catversion bump after BETA1.
I looked for other functions with a similar issue but didn't find any.
[1] https://twitter.com/pg_xocolatl/status/1266694496194093057
--
Vik Fearing
diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml
index 7c06afd3ea..f1b6f6392e 100644
--- a/doc/src/sgml/func.sgml
+++ b/doc/src/sgml/func.sgml
@@ -19577,17 +19577,17 @@ SELECT count(*) FROM sometable;
<indexterm>
<primary>lag</primary>
</indexterm>
- <function>lag</function> ( <parameter>value</parameter> <type>anyelement</type>
+ <function>lag</function> ( <parameter>value</parameter> <type>anycompatible</type>
<optional>, <parameter>offset</parameter> <type>integer</type>
- <optional>, <parameter>default</parameter> <type>anyelement</type> </optional></optional> )
- <returnvalue>anyelement</returnvalue>
+ <optional>, <parameter>default</parameter> <type>anycompatible</type> </optional></optional> )
+ <returnvalue>anycompatible</returnvalue>
</para>
<para>
Returns <parameter>value</parameter> evaluated at
the row that is <parameter>offset</parameter>
rows before the current row within the partition; if there is no such
row, instead returns <parameter>default</parameter>
- (which must be of the same type as
+ (which must be of a compatible type as
<parameter>value</parameter>).
Both <parameter>offset</parameter> and
<parameter>default</parameter> are evaluated
@@ -19602,17 +19602,17 @@ SELECT count(*) FROM sometable;
<indexterm>
<primary>lead</primary>
</indexterm>
- <function>lead</function> ( <parameter>value</parameter> <type>anyelement</type>
+ <function>lead</function> ( <parameter>value</parameter> <type>anycompatible</type>
<optional>, <parameter>offset</parameter> <type>integer</type>
- <optional>, <parameter>default</parameter> <type>anyelement</type> </optional></optional> )
- <returnvalue>anyelement</returnvalue>
+ <optional>, <parameter>default</parameter> <type>anycompatible</type> </optional></optional> )
+ <returnvalue>anycompatible</returnvalue>
</para>
<para>
Returns <parameter>value</parameter> evaluated at
the row that is <parameter>offset</parameter>
rows after the current row within the partition; if there is no such
row, instead returns <parameter>default</parameter>
- (which must be of the same type as
+ (which must be of a compatible type as
<parameter>value</parameter>).
Both <parameter>offset</parameter> and
<parameter>default</parameter> are evaluated
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 61f2c2f5b4..4b2d5f6ee6 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -9689,8 +9689,8 @@
proname => 'lag', prokind => 'w', prorettype => 'anyelement',
proargtypes => 'anyelement int4', prosrc => 'window_lag_with_offset' },
{ oid => '3108', descr => 'fetch the Nth preceding row value with default',
- proname => 'lag', prokind => 'w', prorettype => 'anyelement',
- proargtypes => 'anyelement int4 anyelement',
+ proname => 'lag', prokind => 'w', prorettype => 'anycompatible',
+ proargtypes => 'anycompatible int4 anycompatible',
prosrc => 'window_lag_with_offset_and_default' },
{ oid => '3109', descr => 'fetch the following row value',
proname => 'lead', prokind => 'w', prorettype => 'anyelement',
@@ -9699,8 +9699,8 @@
proname => 'lead', prokind => 'w', prorettype => 'anyelement',
proargtypes => 'anyelement int4', prosrc => 'window_lead_with_offset' },
{ oid => '3111', descr => 'fetch the Nth following row value with default',
- proname => 'lead', prokind => 'w', prorettype => 'anyelement',
- proargtypes => 'anyelement int4 anyelement',
+ proname => 'lead', prokind => 'w', prorettype => 'anycompatible',
+ proargtypes => 'anycompatible int4 anycompatible',
prosrc => 'window_lead_with_offset_and_default' },
{ oid => '3112', descr => 'fetch the first row value',
proname => 'first_value', prokind => 'w', prorettype => 'anyelement',
diff --git a/src/test/regress/expected/window.out b/src/test/regress/expected/window.out
index d5fd4045f9..b064cd0c97 100644
--- a/src/test/regress/expected/window.out
+++ b/src/test/regress/expected/window.out
@@ -300,6 +300,21 @@ SELECT lag(ten, four, 0) OVER (PARTITION BY four ORDER BY ten), ten, four FROM t
0 | 3 | 3
(10 rows)
+SELECT lag(ten, four, 0.7) OVER (PARTITION BY four ORDER BY ten), ten, four FROM tenk1 WHERE unique2 < 10 ORDER BY four, ten;
+ lag | ten | four
+-----+-----+------
+ 0 | 0 | 0
+ 0 | 0 | 0
+ 4 | 4 | 0
+ 0.7 | 1 | 1
+ 1 | 1 | 1
+ 1 | 7 | 1
+ 7 | 9 | 1
+ 0.7 | 0 | 2
+ 0.7 | 1 | 3
+ 0.7 | 3 | 3
+(10 rows)
+
SELECT lead(ten) OVER (PARTITION BY four ORDER BY ten), ten, four FROM tenk1 WHERE unique2 < 10;
lead | ten | four
------+-----+------
@@ -345,6 +360,21 @@ SELECT lead(ten * 2, 1, -1) OVER (PARTITION BY four ORDER BY ten), ten, four FRO
-1 | 3 | 3
(10 rows)
+SELECT lead(ten * 2, 1, -1.4) OVER (PARTITION BY four ORDER BY ten), ten, four FROM tenk1 WHERE unique2 < 10 ORDER BY four, ten;
+ lead | ten | four
+------+-----+------
+ 0 | 0 | 0
+ 8 | 0 | 0
+ -1.4 | 4 | 0
+ 2 | 1 | 1
+ 14 | 1 | 1
+ 18 | 7 | 1
+ -1.4 | 9 | 1
+ -1.4 | 0 | 2
+ 6 | 1 | 3
+ -1.4 | 3 | 3
+(10 rows)
+
SELECT first_value(ten) OVER (PARTITION BY four ORDER BY ten), ten, four FROM tenk1 WHERE unique2 < 10;
first_value | ten | four
-------------+-----+------
diff --git a/src/test/regress/sql/window.sql b/src/test/regress/sql/window.sql
index fe273aa31e..49570458be 100644
--- a/src/test/regress/sql/window.sql
+++ b/src/test/regress/sql/window.sql
@@ -63,12 +63,14 @@ SELECT lag(ten) OVER (PARTITION BY four ORDER BY ten), ten, four FROM tenk1 WHER
SELECT lag(ten, four) OVER (PARTITION BY four ORDER BY ten), ten, four FROM tenk1 WHERE unique2 < 10;
SELECT lag(ten, four, 0) OVER (PARTITION BY four ORDER BY ten), ten, four FROM tenk1 WHERE unique2 < 10;
+SELECT lag(ten, four, 0.7) OVER (PARTITION BY four ORDER BY ten), ten, four FROM tenk1 WHERE unique2 < 10 ORDER BY four, ten;
SELECT lead(ten) OVER (PARTITION BY four ORDER BY ten), ten, four FROM tenk1 WHERE unique2 < 10;
SELECT lead(ten * 2, 1) OVER (PARTITION BY four ORDER BY ten), ten, four FROM tenk1 WHERE unique2 < 10;
SELECT lead(ten * 2, 1, -1) OVER (PARTITION BY four ORDER BY ten), ten, four FROM tenk1 WHERE unique2 < 10;
+SELECT lead(ten * 2, 1, -1.4) OVER (PARTITION BY four ORDER BY ten), ten, four FROM tenk1 WHERE unique2 < 10 ORDER BY four, ten;
SELECT first_value(ten) OVER (PARTITION BY four ORDER BY ten), ten, four FROM tenk1 WHERE unique2 < 10;