Repository: sqlc-dev/sqlc
Pull request #2962 (2023-11-09 07:22:59)

fix: Return an error instead of generating duplicate Go names
Resolves https://github.com/sqlc-dev/sqlc/issues/588


Patch:
diff --git a/internal/codegen/golang/gen.go b/internal/codegen/golang/gen.go
index 5b8289d44..54b742763 100644
--- a/internal/codegen/golang/gen.go
+++ b/internal/codegen/golang/gen.go
@@ -124,9 +124,40 @@ func Generate(ctx context.Context, req *plugin.GenerateRequest) (*plugin.Generat
 		enums, structs = filterUnusedStructs(enums, structs, queries)
 	}
 
+	if err := validate(options, enums, structs, queries); err != nil {
+		return nil, err
+	}
+
 	return generate(req, options, enums, structs, queries)
 }
 
+func validate(options *opts.Options, enums []Enum, structs []Struct, queries []Query) error {
+	enumNames := make(map[string]struct{})
+	for _, enum := range enums {
+		enumNames[enum.Name] = struct{}{}
+		enumNames["Null"+enum.Name] = struct{}{}
+	}
+	structNames := make(map[string]struct{})
+	for _, struckt := range structs {
+		if _, ok := enumNames[struckt.Name]; ok {
+			return fmt.Errorf("struct name conflicts with enum name: %s", struckt.Name)
+		}
+		structNames[struckt.Name] = struct{}{}
+	}
+	if !options.EmitExportedQueries {
+		return nil
+	}
+	for _, query := range queries {
+		if _, ok := enumNames[query.ConstantName]; ok {
+			return fmt.Errorf("query constant name conflicts with enum name: %s", query.ConstantName)
+		}
+		if _, ok := structNames[query.ConstantName]; ok {
+			return fmt.Errorf("query constant name conflicts with struct name: %s", query.ConstantName)
+		}
+	}
+	return nil
+}
+
 func generate(req *plugin.GenerateRequest, options *opts.Options, enums []Enum, structs []Struct, queries []Query) (*plugin.GenerateResponse, error) {
 	i := &importer{
 		Options: options,


Test patch:
diff --git a/internal/endtoend/testdata/duplicate_go_names/enum/query.sql b/internal/endtoend/testdata/duplicate_go_names/enum/query.sql
new file mode 100644
index 000000000..760e82582
--- /dev/null
+++ b/internal/endtoend/testdata/duplicate_go_names/enum/query.sql
@@ -0,0 +1,2 @@
+-- name: GetFoos :many
+SELECT * FROM foos;
\ No newline at end of file
diff --git a/internal/endtoend/testdata/duplicate_go_names/enum/schema.sql b/internal/endtoend/testdata/duplicate_go_names/enum/schema.sql
new file mode 100644
index 000000000..d0ac445ab
--- /dev/null
+++ b/internal/endtoend/testdata/duplicate_go_names/enum/schema.sql
@@ -0,0 +1,3 @@
+CREATE TYPE foo AS ENUM ();
+
+CREATE TABLE foos ();
\ No newline at end of file
diff --git a/internal/endtoend/testdata/duplicate_go_names/enum/sqlc.yaml b/internal/endtoend/testdata/duplicate_go_names/enum/sqlc.yaml
new file mode 100644
index 000000000..48946b027
--- /dev/null
+++ b/internal/endtoend/testdata/duplicate_go_names/enum/sqlc.yaml
@@ -0,0 +1,8 @@
+version: "2"
+sql:
+- schema: "schema.sql"
+  queries: "query.sql"
+  engine: "postgresql"
+  gen:
+    go:
+      out: "db"
diff --git a/internal/endtoend/testdata/duplicate_go_names/enum/stderr.txt b/internal/endtoend/testdata/duplicate_go_names/enum/stderr.txt
new file mode 100644
index 000000000..e6d206bda
--- /dev/null
+++ b/internal/endtoend/testdata/duplicate_go_names/enum/stderr.txt
@@ -0,0 +1,2 @@
+# package 
+error generating code: struct name conflicts with enum name: Foo
diff --git a/internal/endtoend/testdata/duplicate_go_names/null_enum/query.sql b/internal/endtoend/testdata/duplicate_go_names/null_enum/query.sql
new file mode 100644
index 000000000..fcb2e7592
--- /dev/null
+++ b/internal/endtoend/testdata/duplicate_go_names/null_enum/query.sql
@@ -0,0 +1,2 @@
+-- name: GetFoos :many
+SELECT * FROM null_foos;
\ No newline at end of file
diff --git a/internal/endtoend/testdata/duplicate_go_names/null_enum/schema.sql b/internal/endtoend/testdata/duplicate_go_names/null_enum/schema.sql
new file mode 100644
index 000000000..46fe734fe
--- /dev/null
+++ b/internal/endtoend/testdata/duplicate_go_names/null_enum/schema.sql
@@ -0,0 +1,3 @@
+CREATE TYPE foo AS ENUM ();
+
+CREATE TABLE null_foos ();
\ No newline at end of file
diff --git a/internal/endtoend/testdata/duplicate_go_names/null_enum/sqlc.yaml b/internal/endtoend/testdata/duplicate_go_names/null_enum/sqlc.yaml
new file mode 100644
index 000000000..48946b027
--- /dev/null
+++ b/internal/endtoend/testdata/duplicate_go_names/null_enum/sqlc.yaml
@@ -0,0 +1,8 @@
+version: "2"
+sql:
+- schema: "schema.sql"
+  queries: "query.sql"
+  engine: "postgresql"
+  gen:
+    go:
+      out: "db"
diff --git a/internal/endtoend/testdata/duplicate_go_names/null_enum/stderr.txt b/internal/endtoend/testdata/duplicate_go_names/null_enum/stderr.txt
new file mode 100644
index 000000000..16321a008
--- /dev/null
+++ b/internal/endtoend/testdata/duplicate_go_names/null_enum/stderr.txt
@@ -0,0 +1,2 @@
+# package 
+error generating code: struct name conflicts with enum name: NullFoo
diff --git a/internal/endtoend/testdata/duplicate_go_names/query_constant/query.sql b/internal/endtoend/testdata/duplicate_go_names/query_constant/query.sql
new file mode 100644
index 000000000..fc3436d4c
--- /dev/null
+++ b/internal/endtoend/testdata/duplicate_go_names/query_constant/query.sql
@@ -0,0 +1,2 @@
+-- name: Foo :one
+SELECT 1;
\ No newline at end of file
diff --git a/internal/endtoend/testdata/duplicate_go_names/query_constant/schema.sql b/internal/endtoend/testdata/duplicate_go_names/query_constant/schema.sql
new file mode 100644
index 000000000..a0ed9c3ab
--- /dev/null
+++ b/internal/endtoend/testdata/duplicate_go_names/query_constant/schema.sql
@@ -0,0 +1,1 @@
+CREATE TYPE foo AS ENUM ();
diff --git a/internal/endtoend/testdata/duplicate_go_names/query_constant/sqlc.yaml b/internal/endtoend/testdata/duplicate_go_names/query_constant/sqlc.yaml
new file mode 100644
index 000000000..e6314287c
--- /dev/null
+++ b/internal/endtoend/testdata/duplicate_go_names/query_constant/sqlc.yaml
@@ -0,0 +1,9 @@
+version: "2"
+sql:
+- schema: "schema.sql"
+  queries: "query.sql"
+  engine: "postgresql"
+  gen:
+    go:
+      out: "db"
+      emit_exported_queries: true
diff --git a/internal/endtoend/testdata/duplicate_go_names/query_constant/stderr.txt b/internal/endtoend/testdata/duplicate_go_names/query_constant/stderr.txt
new file mode 100644
index 000000000..1a9b5f80b
--- /dev/null
+++ b/internal/endtoend/testdata/duplicate_go_names/query_constant/stderr.txt
@@ -0,0 +1,2 @@
+# package 
+error generating code: query constant name conflicts with enum name: Foo