sql: resolve table names as tuples #26719
Labels
A-sql-name-resolution
SQL name resolution rules and CTEs.
A-sql-pgcompat
Semantic compatibility with PostgreSQL
C-enhancement
Solution expected to add code/behavior + preserve backward-compat (pg compat issues are exception)
This is a postgres oddity that was reported in #24866 but not actually fixed by #26628:
The syntax
(E).C
requiresE
to have tuple type. The namet
inside the parentheses refers to a table, not a column. In a sane world the query should fail with "t
is not a column in this FROM context". Instead, pg accepts the syntax and resolvest
as a table name and treats(t).a
as equivalent tot.a
.So the query above fails in CockroachDB (currently) and succeeds in pg. This is the problem to solve.
The caveat emptor is that this special logic kicks in after regular name resolution. Consider the following query:
In this context we have in the FROM clause:
t
t
t
So the expression on the left
(t).t
can refer either to:t
in the tuple contained in columnt
(column name resolution has priority over table name resolution), ort
in tablet
(table name resolution has priority over column name resolution).Which one is it? To reveal the behavior in postgres, which does not support on-the-fly label tuples, we have to make an equivalent query using a pre-defined record type:
And the result is... The field
word
in the tuple column. So column name resolution has priority.(Which CockroachDB currently gets right because there is no other form of name resolution)
cc @rytaft
Noted in Postgres docs: https://www.postgresql.org/docs/12/rowtypes.html#ROWTYPES-USAGE
There are various special syntax rules and behaviors associated with composite types in queries. These rules provide useful shortcuts, but can be confusing if you don't know the logic behind them.
In PostgreSQL, a reference to a table name (or alias) in a query is effectively a reference to the composite value of the table's current row. For example, if we had a table inventory_item as shown above, we could write:
This query produces a single composite-valued column, so we might get output like:
Note however that simple names are matched to column names before table names, so this example works only because there is no column named c in the query's tables.
The text was updated successfully, but these errors were encountered: