From 5513d9ab0d24e433e2e49a9658a5a33f1c661aee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Thu, 11 Jun 2026 14:34:49 +0200 Subject: [PATCH 1/2] feat(driver): support case-insensitive query parameter matching --- stmt.go | 21 +++++++++++++++++++++ stmt_with_mockserver_test.go | 26 ++++++++++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/stmt.go b/stmt.go index df7b990a..423322d6 100644 --- a/stmt.go +++ b/stmt.go @@ -19,6 +19,7 @@ import ( "database/sql/driver" "fmt" "strconv" + "strings" "cloud.google.com/go/spanner" "github.com/googleapis/go-sql-spanner/connectionstate" @@ -107,6 +108,26 @@ func prepareSpannerStmt(state *connectionstate.ConnectionState, parser *parser.S name = sa.NameInQuery value = sa.Value } + if name != "" { + found := false + if len(namesToIndex) > 0 { + for queryName := range namesToIndex { + if strings.EqualFold(queryName, name) { + name = queryName + found = true + break + } + } + } + if !found { + for _, queryName := range names { + if strings.EqualFold(queryName, name) { + name = queryName + break + } + } + } + } if name == "" && len(names) > i { name = names[i] } else if index, ok := namesToIndex[name]; ok { diff --git a/stmt_with_mockserver_test.go b/stmt_with_mockserver_test.go index d9ade319..ab1e5711 100644 --- a/stmt_with_mockserver_test.go +++ b/stmt_with_mockserver_test.go @@ -534,6 +534,18 @@ func TestNamedParametersWithGoogleSQL(t *testing.T) { input: "insert into my_table (id, initial_value, current_value, generation) values (@id, @value, @value, @id)", wantParams: map[string]string{"id": "1", "value": "One"}, }, + { + name: "case_insensitive", + params: []any{sql.Named("ID", 1), sql.Named("Value", "One")}, + input: "insert into my_table (id, value) values (@id, @value)", + wantParams: map[string]string{"id": "1", "value": "One"}, + }, + { + name: "case_insensitive_2", + params: []any{sql.Named("id", 1), sql.Named("value", "One")}, + input: "insert into my_table (id, value) values (@ID, @VALUE)", + wantParams: map[string]string{"ID": "1", "VALUE": "One"}, + }, { name: "input_out_of_order", params: []any{sql.Named("value", "One"), sql.Named("id", 1)}, @@ -738,6 +750,20 @@ func TestNamedParametersWithPG(t *testing.T) { wantSQL: "insert into my_table (id, initial_value, current_value, generation) values ($1, $2, $2, $1)", wantParams: map[string]string{"p1": "1", "p2": "One"}, }, + { + name: "case_insensitive", + params: []any{sql.Named("ID", 1), sql.Named("Value", "One")}, + input: "insert into my_table (id, value) values (@id, @value)", + wantSQL: "insert into my_table (id, value) values ($1, $2)", + wantParams: map[string]string{"p1": "1", "p2": "One"}, + }, + { + name: "case_insensitive_2", + params: []any{sql.Named("id", 1), sql.Named("value", "One")}, + input: "insert into my_table (id, value) values (@ID, @VALUE)", + wantSQL: "insert into my_table (id, value) values ($1, $2)", + wantParams: map[string]string{"p1": "1", "p2": "One"}, + }, { name: "input_out_of_order", params: []any{sql.Named("value", "One"), sql.Named("id", 1)}, From 0bc8092f88e633a6c9f53747a34afad0e6e292f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Fri, 12 Jun 2026 15:14:48 +0200 Subject: [PATCH 2/2] chore: address review comments --- stmt.go | 13 ++++++++++++- stmt_with_mockserver_test.go | 6 ++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/stmt.go b/stmt.go index 423322d6..82fed337 100644 --- a/stmt.go +++ b/stmt.go @@ -110,7 +110,18 @@ func prepareSpannerStmt(state *connectionstate.ConnectionState, parser *parser.S } if name != "" { found := false - if len(namesToIndex) > 0 { + if _, ok := namesToIndex[name]; ok { + found = true + } + if !found { + for _, queryName := range names { + if queryName == name { + found = true + break + } + } + } + if !found && len(namesToIndex) > 0 { for queryName := range namesToIndex { if strings.EqualFold(queryName, name) { name = queryName diff --git a/stmt_with_mockserver_test.go b/stmt_with_mockserver_test.go index ab1e5711..37827b75 100644 --- a/stmt_with_mockserver_test.go +++ b/stmt_with_mockserver_test.go @@ -546,6 +546,12 @@ func TestNamedParametersWithGoogleSQL(t *testing.T) { input: "insert into my_table (id, value) values (@ID, @VALUE)", wantParams: map[string]string{"ID": "1", "VALUE": "One"}, }, + { + name: "case_insensitive_exact_match_priority", + params: []any{sql.Named("id", 1), sql.Named("ID", 2)}, + input: "insert into my_table (id, value) values (@id, @ID)", + wantParams: map[string]string{"id": "1", "ID": "2"}, + }, { name: "input_out_of_order", params: []any{sql.Named("value", "One"), sql.Named("id", 1)},