Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

MySQL Enum redeclarations #502

Unanswered
oderwat asked this question in Issue Triage
May 16, 2020 · 3 comments · 1 reply
Discussion options

I am evaluating sqlc for one of our future projects. Currently, I am using sqlc to write a small migration tool for converting a legacy MySQL database to PostgreSQL.

At the very first step I ran into a problem with the generated code for this schema fragment:

CREATE TABLE `users` (
 `id` int(14) unsigned NOT NULL AUTO_INCREMENT,
 `status` enum('active','inactive','blocked') NOT NULL DEFAULT 'active',
 `testuser` enum('N','Y') NOT NULL DEFAULT 'N',
 `readonly` enum('N',Y') NOT NULL DEFAULT 'N',
...

The problem is that those enums cause redeclaration errors as it creates constants with the raw Enum name.

type TestuserType string
const (
	N TestuserType = "N"
	Y TestuserType = "Y"
)
type ReadonlyType string
const (
	N ReadonlyType = "N"
	Y ReadonlyType = "Y"
)

The real users schema includes 12 enums of the type enum('N','Y') and a lot of the other tables share the same enum names too.

I wonder that it seems that I can not use enums with the same names in different columns or even different tables.

Is this because MySQL support is being experimental or am I doing something wrong here and there is a way to solve this problem?

You must be logged in to vote

Replies: 3 comments 1 reply

Comment options

I wonder that it seems that I can not use enums with the same names in different columns or even different tables.

Right now sqlc will generate a new type for every column with an enum.

Is this because MySQL support is being experimental or am I doing something wrong here and there is a way to solve this problem?

You aren't doing anything wrong; MySQL support is experimental and this is one (of many) edge cases.

I won't be fixing any MySQL bugs in the short term; I'm working on a major architecture change that unifies the SQL processing for all database engines. It should land by the next release.

You must be logged in to vote
0 replies
Comment options

The documentation for enums clearly shows that the variable names for the values get the same name as the enum type as a prefix. So I guess that this edge case is not really an edge case but a wrong implementation of what is supposed to happen for Enums?

I guess this can easily be fixed by changing
https://github.com/kyleconroy/sqlc/blob/fd329cbd13f1cfa31623b888e356960db5cbec8e/internal/mysql/gen.go#L39

I think I am going to do this in a dev version just to be able to continue with what I wanted to do. Would you accept a PR for this or is the new version really close anyway?

You must be logged in to vote
0 replies
Comment options

@oderwat Sorry that discussion of this dropped off. As I said in a previous comment, the MySQL package has been deprecated and replaced. The new package, code-named Dolphin, now has enum support (#676). However, that implementation has a different strategy for enum naming.

Given your MySQL table:

CREATE TABLE `users` (
 `id` int(14) unsigned NOT NULL AUTO_INCREMENT,
 `status` enum('active','inactive','blocked') NOT NULL DEFAULT 'active',
 `testuser` enum('N','Y') NOT NULL DEFAULT 'N',
 `readonly` enum('N','Y') NOT NULL DEFAULT 'N',
)

The old MySQL package generated the following Go:

type TestuserType string
const (
	N TestuserType = "N"
	Y TestuserType = "Y"
)
type ReadonlyType string
const (
	N ReadonlyType = "N"
	Y ReadonlyType = "Y"
)

This was obviously wrong, as N and Y were declared multiple times, causing compilation to fail.

The new MySQL package generates the following:

type Readonly string
const (
	ReadonlyN Readonly = "N"
	ReadonlyY Readonly = "Y"
)
type Status string
const (
	StatusActive Status = "active"
	StatusInactive Status = "inactive"
	StatusBlocked Status = "blocked"
)
type Testuser string
const (
	TestuserN Testuser = "N"
	TestuserY Testuser = "Y"
)

This will compile, but using the column name as the type name may cause conflicts if the name is reused elsewhere.

You must be logged in to vote
1 reply
Comment options

I am very pleased about your coming back to this!

The new way seems to be pretty nice. Just a thought: Wouldn't it possible to bring this into a kind of "enum" package? That way it would be enum.Status and enum.StatusActive and make it impossible to clash with something in the "db" package.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Converted from issue

This discussion was converted from issue #502 on August 25, 2020 19:58.

AltStyle によって変換されたページ (->オリジナル) /