Skip to content

fix(postgres)!: Preserve quoting for user defined types#5216

Merged
VaggelisD merged 1 commit intomainfrom
vaggelisd/udt_quoting
Jun 12, 2025
Merged

fix(postgres)!: Preserve quoting for user defined types#5216
VaggelisD merged 1 commit intomainfrom
vaggelisd/udt_quoting

Conversation

@VaggelisD
Copy link
Collaborator

Fixes #5212

I went ahead and fixed this for Postgres only; It seems to be one of the few dialects that supports user defined types and the identifier resolution is respected:

postgres> CREATE TYPE "fOo";
CREATE TYPE

postgres> SELECT CAST(1 AS foo);
ERROR:  type "foo" does not exist
LINE 1: SELECT CAST(1 AS foo);
                         ^
postgres> SELECT CAST(1 AS "fOo");
ERROR:  type "fOo" is only a shell
LINE 1: SELECT CAST(1 AS "fOo");

DuckDB also supports UDTs but quoting doesn't seem to make a difference:

duckdb> CREATE TYPE "fOo" AS INTEGER;

duckdb>  SELECT CAST (1 AS foo);
┌────────────────┐
│ CAST(1 AS foo) │
│     int32      │
├────────────────┤
│       1        │
└────────────────┘

duckdb>  SELECT CAST (1 AS "Foo");
┌────────────────┐
│ CAST(1 AS Foo) │
│     int32      │
├────────────────┤
│       1        │
└────────────────┘

Lastly, T-SQL also allows UDTs, but the approach of this PR wouldn't work because T-SQL also supports such statements (notice the builtin quoted type)

CREATE TABLE [mytable]([email] [varchar](255) NOT NULL)

Which would be transpiled as the identifier "VARCHAR" to other dialects.

@georgesittas
Copy link
Collaborator

DuckDB also supports UDTs but quoting doesn't seem to make a difference: [...]

What if you include unsafe characters though that need to be delimited? E.g. "foo bar".

Copy link
Collaborator

@georgesittas georgesittas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@VaggelisD this fails in duckdb now:

>>> import sqlglot
>>> sqlglot.parse_one('cast(x as "foo bar")', 'duckdb')
Cast(
  this=Column(
    this=Identifier(this=x, quoted=False)),
  to=DataType(this=Type.USERDEFINED, kind=foo bar))
>>> sqlglot.parse_one('cast(x as "foo bar")', 'duckdb').sql('duckdb')
'CAST(x AS foo bar)'

@VaggelisD VaggelisD merged commit 02afa2a into main Jun 12, 2025
7 checks passed
@VaggelisD VaggelisD deleted the vaggelisd/udt_quoting branch June 12, 2025 12:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Quotations on USERDEFINED datatypes don't roundtrip

2 participants