Repository: sqlc-dev/sqlc (2026-04-17T13:21:52Z)

Issue:
bug if column and param share the same name
### Version

1.30.0

### What happened?

A bug happened!
sql:
```
-- name: GetUserByEmail :one
SELECT email
FROM users
WHERE email = sqlc.arg(email);
```
generated:
```
func (q *Queries) GetUserByEmail(ctx context.Context, email string) (string, error) {
	row := q.db.QueryRow(ctx, getUserByEmail, email)
	err := row.Scan(&email)
	return email, err
}
```

on ErrNoRows, the function GetUserByEmail returns the input email... expected an empty string.
maybe create a separate string var like what is done with other types? after a little testing, this only happens when the names are the same xD


### Relevant log output

```shell

```

### Database schema

```sql

```

### SQL queries

```sql

```

### Configuration

```yaml

```

### Playground URL

_No response_

### What operating system are you using?

Windows

### What database engines are you using?

PostgreSQL

### What type of code are you generating?

Go


Discussion:

Patch:
diff --git a/internal/codegen/golang/result.go b/internal/codegen/golang/result.go
index 0820488f9d..216f5e3372 100644
--- a/internal/codegen/golang/result.go
+++ b/internal/codegen/golang/result.go
@@ -268,8 +268,26 @@ func buildQueries(req *plugin.GenerateRequest, options *opts.Options, structs []
 			c := query.Columns[0]
 			name := columnName(c, 0)
 			name = strings.Replace(name, "$", "_", -1)
+			retName := escape(name)
+			// For :one queries the scan destination lives in the same scope as
+			// the query parameters, so reusing a parameter's name would cause
+			// Scan to overwrite the input and leak it back to the caller on
+			// sql.ErrNoRows (see sqlc-dev/sqlc#4354). Rename the return
+			// variable when it would collide.
+			if query.Cmd == metadata.CmdOne {
+				argNames := map[string]struct{}{}
+				for _, p := range gq.Arg.Pairs() {
+					argNames[p.Name] = struct{}{}
+				}
+				for {
+					if _, conflict := argNames[retName]; !conflict {
+						break
+					}
+					retName += "_2"
+				}
+			}
 			gq.Ret = QueryValue{
-				Name:      escape(name),
+				Name:      retName,
 				DBName:    name,
 				Typ:       goType(req, options, c),
 				SQLDriver: sqlpkg,


Test patch:
diff --git a/internal/endtoend/testdata/single_param_conflict/mysql/go/query.sql.go b/internal/endtoend/testdata/single_param_conflict/mysql/go/query.sql.go
index e3ba139207..44385a7b9d 100644
--- a/internal/endtoend/testdata/single_param_conflict/mysql/go/query.sql.go
+++ b/internal/endtoend/testdata/single_param_conflict/mysql/go/query.sql.go
@@ -32,8 +32,9 @@ LIMIT   1
 
 func (q *Queries) GetAuthorIDByID(ctx context.Context, id int64) (int64, error) {
 	row := q.db.QueryRowContext(ctx, getAuthorIDByID, id)
-	err := row.Scan(&id)
-	return id, err
+	var id_2 int64
+	err := row.Scan(&id_2)
+	return id_2, err
 }
 
 const getUser = `-- name: GetUser :one
@@ -45,6 +46,7 @@ LIMIT   1
 
 func (q *Queries) GetUser(ctx context.Context, sub string) (string, error) {
 	row := q.db.QueryRowContext(ctx, getUser, sub)
-	err := row.Scan(&sub)
-	return sub, err
+	var sub_2 string
+	err := row.Scan(&sub_2)
+	return sub_2, err
 }
diff --git a/internal/endtoend/testdata/single_param_conflict/postgresql/pgx/v4/go/query.sql.go b/internal/endtoend/testdata/single_param_conflict/postgresql/pgx/v4/go/query.sql.go
index 1912659d8b..05f0540e5c 100644
--- a/internal/endtoend/testdata/single_param_conflict/postgresql/pgx/v4/go/query.sql.go
+++ b/internal/endtoend/testdata/single_param_conflict/postgresql/pgx/v4/go/query.sql.go
@@ -34,8 +34,9 @@ LIMIT   1
 
 func (q *Queries) GetAuthorIDByID(ctx context.Context, id int64) (int64, error) {
 	row := q.db.QueryRow(ctx, getAuthorIDByID, id)
-	err := row.Scan(&id)
-	return id, err
+	var id_2 int64
+	err := row.Scan(&id_2)
+	return id_2, err
 }
 
 const getUser = `-- name: GetUser :one
@@ -47,8 +48,9 @@ LIMIT   1
 
 func (q *Queries) GetUser(ctx context.Context, sub uuid.UUID) (uuid.UUID, error) {
 	row := q.db.QueryRow(ctx, getUser, sub)
-	err := row.Scan(&sub)
-	return sub, err
+	var sub_2 uuid.UUID
+	err := row.Scan(&sub_2)
+	return sub_2, err
 }
 
 const setDefaultName = `-- name: SetDefaultName :one
@@ -62,6 +64,7 @@ RETURNING id
 // https://github.com/sqlc-dev/sqlc/issues/1235
 func (q *Queries) SetDefaultName(ctx context.Context, id int64) (int64, error) {
 	row := q.db.QueryRow(ctx, setDefaultName, id)
-	err := row.Scan(&id)
-	return id, err
+	var id_2 int64
+	err := row.Scan(&id_2)
+	return id_2, err
 }
diff --git a/internal/endtoend/testdata/single_param_conflict/postgresql/pgx/v5/go/query.sql.go b/internal/endtoend/testdata/single_param_conflict/postgresql/pgx/v5/go/query.sql.go
index daa903d8c2..6db0c091dd 100644
--- a/internal/endtoend/testdata/single_param_conflict/postgresql/pgx/v5/go/query.sql.go
+++ b/internal/endtoend/testdata/single_param_conflict/postgresql/pgx/v5/go/query.sql.go
@@ -34,8 +34,9 @@ LIMIT   1
 
 func (q *Queries) GetAuthorIDByID(ctx context.Context, id int64) (int64, error) {
 	row := q.db.QueryRow(ctx, getAuthorIDByID, id)
-	err := row.Scan(&id)
-	return id, err
+	var id_2 int64
+	err := row.Scan(&id_2)
+	return id_2, err
 }
 
 const getUser = `-- name: GetUser :one
@@ -47,8 +48,9 @@ LIMIT   1
 
 func (q *Queries) GetUser(ctx context.Context, sub pgtype.UUID) (pgtype.UUID, error) {
 	row := q.db.QueryRow(ctx, getUser, sub)
-	err := row.Scan(&sub)
-	return sub, err
+	var sub_2 pgtype.UUID
+	err := row.Scan(&sub_2)
+	return sub_2, err
 }
 
 const setDefaultName = `-- name: SetDefaultName :one
@@ -62,6 +64,7 @@ RETURNING id
 // https://github.com/sqlc-dev/sqlc/issues/1235
 func (q *Queries) SetDefaultName(ctx context.Context, id int64) (int64, error) {
 	row := q.db.QueryRow(ctx, setDefaultName, id)
-	err := row.Scan(&id)
-	return id, err
+	var id_2 int64
+	err := row.Scan(&id_2)
+	return id_2, err
 }
diff --git a/internal/endtoend/testdata/single_param_conflict/postgresql/stdlib/go/query.sql.go b/internal/endtoend/testdata/single_param_conflict/postgresql/stdlib/go/query.sql.go
index 0b99078536..4f4bd175be 100644
--- a/internal/endtoend/testdata/single_param_conflict/postgresql/stdlib/go/query.sql.go
+++ b/internal/endtoend/testdata/single_param_conflict/postgresql/stdlib/go/query.sql.go
@@ -34,8 +34,9 @@ LIMIT   1
 
 func (q *Queries) GetAuthorIDByID(ctx context.Context, id int64) (int64, error) {
 	row := q.db.QueryRowContext(ctx, getAuthorIDByID, id)
-	err := row.Scan(&id)
-	return id, err
+	var id_2 int64
+	err := row.Scan(&id_2)
+	return id_2, err
 }
 
 const getUser = `-- name: GetUser :one
@@ -47,8 +48,9 @@ LIMIT   1
 
 func (q *Queries) GetUser(ctx context.Context, sub uuid.UUID) (uuid.UUID, error) {
 	row := q.db.QueryRowContext(ctx, getUser, sub)
-	err := row.Scan(&sub)
-	return sub, err
+	var sub_2 uuid.UUID
+	err := row.Scan(&sub_2)
+	return sub_2, err
 }
 
 const setDefaultName = `-- name: SetDefaultName :one
@@ -62,6 +64,7 @@ RETURNING id
 // https://github.com/sqlc-dev/sqlc/issues/1235
 func (q *Queries) SetDefaultName(ctx context.Context, id int64) (int64, error) {
 	row := q.db.QueryRowContext(ctx, setDefaultName, id)
-	err := row.Scan(&id)
-	return id, err
+	var id_2 int64
+	err := row.Scan(&id_2)
+	return id_2, err
 }
diff --git a/internal/endtoend/testdata/single_param_conflict/sqlite/go/query.sql.go b/internal/endtoend/testdata/single_param_conflict/sqlite/go/query.sql.go
index e3ba139207..44385a7b9d 100644
--- a/internal/endtoend/testdata/single_param_conflict/sqlite/go/query.sql.go
+++ b/internal/endtoend/testdata/single_param_conflict/sqlite/go/query.sql.go
@@ -32,8 +32,9 @@ LIMIT   1
 
 func (q *Queries) GetAuthorIDByID(ctx context.Context, id int64) (int64, error) {
 	row := q.db.QueryRowContext(ctx, getAuthorIDByID, id)
-	err := row.Scan(&id)
-	return id, err
+	var id_2 int64
+	err := row.Scan(&id_2)
+	return id_2, err
 }
 
 const getUser = `-- name: GetUser :one
@@ -45,6 +46,7 @@ LIMIT   1
 
 func (q *Queries) GetUser(ctx context.Context, sub string) (string, error) {
 	row := q.db.QueryRowContext(ctx, getUser, sub)
-	err := row.Scan(&sub)
-	return sub, err
+	var sub_2 string
+	err := row.Scan(&sub_2)
+	return sub_2, err
 }
diff --git a/internal/endtoend/testdata/vet_explain/mysql/db/query.sql.go b/internal/endtoend/testdata/vet_explain/mysql/db/query.sql.go
index cef6fbff90..9a11dd5328 100644
--- a/internal/endtoend/testdata/vet_explain/mysql/db/query.sql.go
+++ b/internal/endtoend/testdata/vet_explain/mysql/db/query.sql.go
@@ -438,6 +438,7 @@ WHERE id = ? LIMIT 1
 
 func (q *Queries) SelectById(ctx context.Context, id int64) (int64, error) {
 	row := q.db.QueryRowContext(ctx, selectById, id)
-	err := row.Scan(&id)
-	return id, err
+	var id_2 int64
+	err := row.Scan(&id_2)
+	return id_2, err
 }