Skip to content

Conversation

@RadhiFadlillah
Copy link
Contributor

This is duplicate of #2020, which become closed because I accidentally deleted its source repository. Since I'm unable to recover the deleted repo, I decided to just recreate the PR.

What is this

As the title said, this PR wants to add support for CAST function in MySQL.

This PR is based from PR by @ryanpbrewsterhere (which unfortunately he didn't send here, and only exist in his repository).

Why is this PR created

Currently sqlc unable to infer the correct type from SQL function like MAX, MIN, SUM, etc. For those function, sqlc will return its value as interface{}. This behavior can be seen in this playground.

As workaround, it advised to use CAST function to explicitly tell what is the type for that column, as mentioned in #1574.

Unfortunately, currently sqlc only support CAST function in PostgreSQL and not in MySQL. Thanks to this, right now MySQL users have to parse the interface{} manually, which is not really desirable.

What does this PR do?

  • Implement convertFuncCast function for MySQL.
  • Add better nil pointer check in some functions that related to convertFuncCast.

I haven't write any test because I'm not sure how and where to put it. However, as far as I know the code that handle ast.TypeCast for PostgreSQL also don't have any test, so I guess it's fine 🤷‍♂️

Related issues

@andrewmbenton
Copy link
Collaborator

andrewmbenton commented Jul 18, 2023

Hi and thanks! I haven't looked at this closely yet but regarding the testing question I think the best thing would be to create a new endtoend test in either internal/endtoend/testdata/func_call_cast or internal/endtoend/testdata/select_column_cast. You can put the current contents of either directory into a postgresql subdirectory, and then create a mysql subdirectory for your test. The names of the directories don't matter, it's just our convention.

To generate the expected test output (from your patch) you'll naturally need a dev build of sqlc with your patch in it. You can build using make sqlc-dev for convenience.

You can run all the endtoend tests with go test ./internal/endtoend/... or just your test with go test -run TestReplay/testdata/func_call_cast/mysql -v ./internal/endtoend/.

@RadhiFadlillah
Copy link
ContributorAuthor

I've added the test, however I'm not really sure if I did it right:

  • I haven't added the postgresql directory because there is already pgx directory. Should I add it as well?
  • For func_call_cast in MySQL, I don't use UUID like in pgx directory because MySQL doesn't have UUID type like Postgres, and sqlc already return MySQL's UUID as string. So, I just use GREATEST function in MySQL which currently generated as interface{} by sqlc.

@andrewmbenton
Copy link
Collaborator

The tests look great, thanks! You don't need to add the postgresql directory, I can do it later. When we have multi-engine tests we would typically have both the stdlib and pgx directories within a postgresql directory alongside the mysql directory since there are two access methods supported for postgres. But all the tests will run in any case.

Regarding the actual code, I think there is a subtle change in behavior introduced by removing the switch statement in internal/compiler/compat.go. The default error (unexpected node type) will get returned in cases now where the node type is actually expected but the node pointer happens to be nil. I'm not sure exactly what the right thing to do is, but my suggestion for now is to leave the switch statement in place and return a new error in each case where the pointer can be nil, before operating on the value.

I think we can get this merged for the next release though, so I'm adding it to the 1.20 milestone.

@andrewmbentonandrewmbenton added this to the v1.20.0 milestone Jul 27, 2023
@RadhiFadlillah
Copy link
ContributorAuthor

Done, I've reverted the if with type assertion back to switch. I also added the nil check in each switch case.

@andrewmbenton
Copy link
Collaborator

I think this looks good. @kyleconroy if you agree feel free to merge or comment if not.

@kyleconroykyleconroy changed the title Implement cast function parser for MySQLfeat(mysql): Implement cast function parserJul 30, 2023
@kyleconroykyleconroy merged commit 39f16cc into sqlc-dev:mainJul 30, 2023
andrewmbenton added a commit that referenced this pull request Jul 31, 2023
kyleconroy pushed a commit that referenced this pull request Jul 31, 2023
@RadhiFadlillahRadhiFadlillah deleted the mysql-cast branch August 17, 2023 12:19
alfonsodev pushed a commit to ExponentiaTeam/sqlc that referenced this pull request Oct 13, 2025
What is this As the title said, this PR wants to add support for CAST function in MySQL. This PR is based from PR by @ryanpbrewster here (which unfortunately he didn't send here, and only exist in his repository). Why is this PR created Currently sqlc unable to infer the correct type from SQL function like MAX, MIN, SUM, etc. For those function, sqlc will return its value as interface{}. This behavior can be seen in this playground. As workaround, it advised to use CAST function to explicitly tell what is the type for that column, as mentioned in sqlc-dev#1574. Unfortunately, currently sqlc only support CAST function in PostgreSQL and not in MySQL. Thanks to this, right now MySQL users have to parse the interface{} manually, which is not really desirable. What does this PR do? Implement convertFuncCast function for MySQL. Add better nil pointer check in some functions that related to convertFuncCast. I haven't write any test because I'm not sure how and where to put it. However, as far as I know the code that handle ast.TypeCast for PostgreSQL also don't have any test, so I guess it's fine 🤷‍♂️ Related issues Support CAST ... AS sqlc-dev#687, which currently is the oldest MySQL issue that still opened. Using MYSQL functions ( CONVERT and CAST) result in removing column from struct sqlc-dev#1622 Unable to Type Alias sqlc-dev#1866 sum in select result in model field type interface{} sqlc-dev#1901 MIN() returns an interface{} sqlc-dev#1965
alfonsodev pushed a commit to ExponentiaTeam/sqlc that referenced this pull request Oct 13, 2025
Sign up for freeto 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.

3 participants

@RadhiFadlillah@andrewmbenton@kyleconroy