@@ -2099,6 +2099,39 @@ func TestQueryWithDuplicateNamedParameter(t *testing.T) {
20992099 }
21002100}
21012101
2102+ func TestQueryWithDuplicateNamedParameterStartingWithUnderscore (t * testing.T ) {
2103+ t .Parallel ()
2104+
2105+ db , server , teardown := setupTestDBConnection (t )
2106+ defer teardown ()
2107+
2108+ // database/sql does not allow named arguments to start with an underscore.
2109+ // The Spanner database/sql driver allows a workaround for this by specifying those named arguments with a
2110+ // SpannerNamedArg.
2111+ s := "insert into users (id, name) values (@__name, @__name)"
2112+ _ = server .TestSpanner .PutStatementResult (s , & testutil.StatementResult {
2113+ Type : testutil .StatementResultUpdateCount ,
2114+ UpdateCount : 1 ,
2115+ })
2116+ _ , err := db .Exec (s , sql .Named ("p__name" , SpannerNamedArg {NameInQuery : "__name" , Value : "foo" }), sql .Named ("p__name" , SpannerNamedArg {NameInQuery : "__name" , Value : "bar" }))
2117+ if err != nil {
2118+ t .Fatal (err )
2119+ }
2120+ // Verify that 'bar' is used for both instances of the parameter @__name.
2121+ requests := drainRequestsFromServer (server .TestSpanner )
2122+ sqlRequests := requestsOfType (requests , reflect .TypeOf (& sppb.ExecuteSqlRequest {}))
2123+ if len (sqlRequests ) != 1 {
2124+ t .Fatalf ("sql requests count mismatch\n Got: %v\n Want: %v" , len (sqlRequests ), 1 )
2125+ }
2126+ req := sqlRequests [0 ].(* sppb.ExecuteSqlRequest )
2127+ if g , w := len (req .Params .Fields ), 1 ; g != w {
2128+ t .Fatalf ("params count mismatch\n Got: %v\n Want: %v" , g , w )
2129+ }
2130+ if g , w := req .Params .Fields ["__name" ].GetStringValue (), "bar" ; g != w {
2131+ t .Fatalf ("param value mismatch\n Got: %v\n Want: %v" , g , w )
2132+ }
2133+ }
2134+
21022135func TestQueryWithReusedNamedParameter (t * testing.T ) {
21032136 t .Parallel ()
21042137
@@ -2129,6 +2162,36 @@ func TestQueryWithReusedNamedParameter(t *testing.T) {
21292162 }
21302163}
21312164
2165+ func TestQueryWithReusedNamedParameterStartingWithUnderscore (t * testing.T ) {
2166+ t .Parallel ()
2167+
2168+ db , server , teardown := setupTestDBConnection (t )
2169+ defer teardown ()
2170+
2171+ s := "insert into users (id, name) values (@__name, @__name)"
2172+ _ = server .TestSpanner .PutStatementResult (s , & testutil.StatementResult {
2173+ Type : testutil .StatementResultUpdateCount ,
2174+ UpdateCount : 1 ,
2175+ })
2176+ _ , err := db .Exec (s , sql .Named ("p__name" , SpannerNamedArg {NameInQuery : "__name" , Value : "foo" }))
2177+ if err != nil {
2178+ t .Fatal (err )
2179+ }
2180+ // Verify that 'foo' is used for both instances of the parameter @__name.
2181+ requests := drainRequestsFromServer (server .TestSpanner )
2182+ sqlRequests := requestsOfType (requests , reflect .TypeOf (& sppb.ExecuteSqlRequest {}))
2183+ if len (sqlRequests ) != 1 {
2184+ t .Fatalf ("sql requests count mismatch\n Got: %v\n Want: %v" , len (sqlRequests ), 1 )
2185+ }
2186+ req := sqlRequests [0 ].(* sppb.ExecuteSqlRequest )
2187+ if g , w := len (req .Params .Fields ), 1 ; g != w {
2188+ t .Fatalf ("params count mismatch\n Got: %v\n Want: %v" , g , w )
2189+ }
2190+ if g , w := req .Params .Fields ["__name" ].GetStringValue (), "foo" ; g != w {
2191+ t .Fatalf ("param value mismatch\n Got: %v\n Want: %v" , g , w )
2192+ }
2193+ }
2194+
21322195func TestQueryWithReusedPositionalParameter (t * testing.T ) {
21332196 t .Parallel ()
21342197
0 commit comments