-
Notifications
You must be signed in to change notification settings - Fork 71
Description
With conditionals in particular, it appears SuperDB is not currently promoting the return type to the common type of arguments in the same way Postgres does. Here's three such examples:
$ super -version
Version: 03130efdf
$ super -c "SELECT NULLIF(53, 80.0) / -71;"
{"NULLIF(53, 80.0)/-71":0}
$ super -c "SELECT COALESCE(19, 104.0) / 74;"
{"COALESCE(19, 104.0)/74":0}
$ super -c "SELECT CASE WHEN 1=1 THEN 19 ELSE 104.0 END / 74;"
{"case when 1=1 then 19 else 104.0 end/74":0}
Details
Repro is with super commit 03130ef. These queries are simplifications of sqllogictests such as random/expr/slt_good_0/q7944 and random/expr/slt_good_2/q10793.
Here's Postgres and DuckDB each giving similar results as each other for these, which differ from the ones super gave.
$ psql postgres
psql (17.7 (Homebrew))
Type "help" for help.
postgres=# SELECT NULLIF(53, 80.0) / -71;
?column?
-------------------------
-0.74647887323943661972
(1 row)
postgres=# SELECT COALESCE(19, 104.0) / 74;
?column?
------------------------
0.25675675675675675676
(1 row)
postgres=# SELECT CASE WHEN 1=1 THEN 19 ELSE 104.0 END / 74;
?column?
------------------------
0.25675675675675675676
(1 row)
$ duckdb
DuckDB v1.4.3 (Andium) d1dc88f950
Enter ".help" for usage hints.
Connected to a transient in-memory database.
Use ".open FILENAME" to reopen on a persistent database.
D SELECT NULLIF(53, 80.0) / -71;
┌────────────────────────────┐
│ ("nullif"(53, 80.0) / -71) │
│ double │
├────────────────────────────┤
│ -0.7464788732394366 │
└────────────────────────────┘
D SELECT COALESCE(19, 104.0) / 74;
┌────────────────────────────┐
│ (COALESCE(19, 104.0) / 74) │
│ double │
├────────────────────────────┤
│ 0.25675675675675674 │
└────────────────────────────┘
D SELECT CASE WHEN 1=1 THEN 19 ELSE 104.0 END / 74;
┌──────────────────────────────────────────────────────┐
│ (CASE WHEN ((1 = 1)) THEN (19) ELSE 104.0 END / 74) │
│ double │
├──────────────────────────────────────────────────────┤
│ 0.25675675675675674 │
└──────────────────────────────────────────────────────┘
There's admittedly some variation in how different SQL implementations behave here. For instance, SQLite returns what super does.
$ sqlite3
SQLite version 3.51.1 2025-11-28 17:28:25
Enter ".help" for usage hints.
Connected to a transient in-memory database.
Use ".open FILENAME" to reopen on a persistent database.
sqlite> SELECT NULLIF(53, 80.0) / -71;
0
sqlite> SELECT COALESCE(19, 104.0) / 74;
0
sqlite> SELECT CASE WHEN 1=1 THEN 19 ELSE 104.0 END / 74;
0
In Postgres, all of these functions happen to be documented at the same Conditional Expressions page, and it looks like the effect is explained by the "conversion to a common data type" that apparently happens with multiple arguments to these functions. So as I understand it, in NULLIF(53, 80.0), even though 53 is the value to be returned by the function and starts life as an INTEGER type, the fact the second argument is NUMERIC means both arguments are promoted to type NUMERIC and that becomes the return type. And the return value 53 being NUMERIC has the follow-on effect of a fractional result when dividing by an INTEGER.
postgres=# SELECT NULLIF(53, 80.0),pg_typeof(NULLIF(53, 80.0)),pg_typeof(53),pg_typeof(80.0),pg_typeof(NULLIF(53, 80));
nullif | pg_typeof | pg_typeof | pg_typeof | pg_typeof
--------+-----------+-----------+-----------+-----------
53 | numeric | integer | numeric | integer
(1 row)