Skip to content

Conversation

@Tishj
Copy link
Contributor

@Tishj Tishj commented Apr 12, 2024

We add a virtual method to SQLStatement (and CreateInfo) called HasToString, used to signify that ToString has been overridden for that type and it can safely be called.
(The default SQLStatement::ToString just throws an InternalException)
Instead of the switch case in the statement verifier path, we now use this method.

The default ToString has been changed to throw a NotImplementedException instead, in places where ToString can be used, we employ try/catch as a boolean to indicate whether ToString was implemented.

This uncovered some issues in existing ToString implementations, which this PR fixes.

LogicalType::ToString problem

One notable change (which we might want to find a better solution for):
the SQLNULL type ToString used to return NULL, now turned into "NULL", because when it appears in a query it has to be quoted.
See test/sql/types/test_null_type.test

Possible Solution

Similar to Value perhaps we need a differentiation between ToString and ToSQLString for LogicalType as well.
Where the SQLString uses the quoting rules, and ToString doesn't

@Tishj Tishj requested a review from Mytherin April 12, 2024 11:01
Copy link
Collaborator

@Mytherin Mytherin left a comment

Choose a reason for hiding this comment

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

Thanks for the PR! Some comments below

@duckdb-draftbot duckdb-draftbot marked this pull request as draft April 13, 2024 12:14
@Tishj Tishj marked this pull request as ready for review April 13, 2024 12:49
@duckdb-draftbot duckdb-draftbot marked this pull request as draft April 14, 2024 18:24
@Tishj Tishj marked this pull request as ready for review April 14, 2024 19:07
@duckdb-draftbot duckdb-draftbot marked this pull request as draft April 15, 2024 08:10
@Tishj Tishj marked this pull request as ready for review April 15, 2024 13:11
@Tishj Tishj requested a review from Mytherin April 16, 2024 16:24
@duckdb-draftbot duckdb-draftbot marked this pull request as draft April 18, 2024 08:36
@Tishj Tishj marked this pull request as ready for review April 19, 2024 08:53
@duckdb-draftbot duckdb-draftbot marked this pull request as draft April 19, 2024 12:08
@Tishj Tishj marked this pull request as ready for review April 19, 2024 12:13
@Mytherin Mytherin merged commit 1a3ed8f into duckdb:main Apr 23, 2024
@Mytherin
Copy link
Collaborator

Thanks!

github-actions bot pushed a commit to duckdb/duckdb-r that referenced this pull request May 5, 2024
Merge pull request duckdb/duckdb#11625 from Tishj/statement_to_string_fixes
Merge pull request duckdb/duckdb#11770 from pdet/mv_test
Merge pull request duckdb/duckdb#11784 from szarnyasg/ci-job-expected-behavior-label
@cpcloud
Copy link
Contributor

cpcloud commented May 27, 2024

The change from the string NULL to the string "NULL" broke a test in Ibis. What was the rationale for this change?

I see

One notable change (which we might want to find a better solution for):
the SQLNULL type ToString used to return NULL, now turned into "NULL", because when it appears in a query it has to be quoted.
See test/sql/types/test_null_type.test

In particular, not 100% following this:

because when it appears in a query it has to be quoted.

Wouldn't that be true for all the other types as well? Why would NULL need to be special cased, the return value of typeof already produces the string with characters NULL.

@Mytherin
Copy link
Collaborator

Quotes are added to other types that need them as well - for example:

D select typeof(null::struct(this_is_an_unquoted_identifier integer)) AS struct_type;
┌────────────────────────────────────────────────┐
│                  struct_type                   │
│                    varchar                     │
├────────────────────────────────────────────────┤
│ STRUCT(this_is_an_unquoted_identifier INTEGER) │
└────────────────────────────────────────────────┘

D select typeof(null::struct("this is a quoted identifier" integer)) AS struct_type;
┌───────────────────────────────────────────────┐
│                  struct_type                  │
│                    varchar                    │
├───────────────────────────────────────────────┤
│ STRUCT("this is a quoted identifier" INTEGER) │
└───────────────────────────────────────────────┘

The main idea here is that LogicalType::ToString can be round-tripped within our parser, i.e. you can take the output of that and use it as a type directly in SQL. This is not particularly important for typeof - but is used elsewhere in the code to turn our logical operators back into SQL strings.

We could strip the quotes from NULL for typeof specifically if it is a big issue?

@Mytherin
Copy link
Collaborator

To add to that - here's the SQL that shows that NULL needs to be quoted to be used as a type, but INT does not:

D select cast(null as int) AS result;
┌────────┐
│ result │
│ int32  │
├────────┤
│   NULL │
└────────┘
D select cast(null as null) AS result;
-- Parser Error: syntax error at or near "null"
-- LINE 1: select cast(null as null) AS result;
--                             ^
D select cast(null as "null") AS result;
┌────────┐
│ result │
│ int32  │
├────────┤
│   NULL │
└────────┘

@cpcloud
Copy link
Contributor

cpcloud commented May 27, 2024

Ah, got it. The double quote wasn't clicking, but now it makes sense: you need them to differentiate betwee NULL-the-value and NULL-the-identifier-that-refers-to-a-type.

@Tishj Tishj deleted the statement_to_string_fixes branch November 7, 2025 16:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants