From 82d68a530eb55d1f5c164caf27b7147207d51be8 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 17 Apr 2026 13:44:25 +0000 Subject: [PATCH 1/2] Coerce SQLite JSONB output regardless of type casing The sqliteSelector was doing a case-sensitive comparison against "jsonb", so columns declared with capitalized variants like JSONB or JsonB were not wrapped in json(col) on SELECT/RETURNING. Use strings.EqualFold to match the type name case-insensitively. fixes #4337 --- internal/compiler/selector.go | 4 +++- internal/compiler/selector_test.go | 2 ++ .../testdata/jsonb/sqlite/go/models.go | 4 ++++ .../testdata/jsonb/sqlite/go/query.sql.go | 24 +++++++++++++++---- .../endtoend/testdata/jsonb/sqlite/query.sql | 12 ++++++++-- .../endtoend/testdata/jsonb/sqlite/schema.sql | 6 ++++- 6 files changed, 44 insertions(+), 8 deletions(-) diff --git a/internal/compiler/selector.go b/internal/compiler/selector.go index 04d118ff9c..115c9eb835 100644 --- a/internal/compiler/selector.go +++ b/internal/compiler/selector.go @@ -1,5 +1,7 @@ package compiler +import "strings" + // selector is an interface used by a compiler for generating expressions for // output columns in a `SELECT ...` or `RETURNING ...` statement. // @@ -39,7 +41,7 @@ func (s *sqliteSelector) ColumnExpr(name string, column *Column) string { // outside of the database itself. For jsonb columns in SQLite, wrap values // in `json(col)` to coerce the internal binary format to JSON parsable by // the user-space application. - if column.DataType == "jsonb" { + if strings.EqualFold(column.DataType, "jsonb") { return "json(" + name + ")" } return name diff --git a/internal/compiler/selector_test.go b/internal/compiler/selector_test.go index e460dd281c..a17cc4268d 100644 --- a/internal/compiler/selector_test.go +++ b/internal/compiler/selector_test.go @@ -30,6 +30,8 @@ func TestSelector(t *testing.T) { selectorExpectColumnExpr(t, selector, "my_column", "my_column", &Column{DataType: "integer"}) selectorExpectColumnExpr(t, selector, "my_column", "my_column", &Column{DataType: "json"}) selectorExpectColumnExpr(t, selector, "json(my_column)", "my_column", &Column{DataType: "jsonb"}) + selectorExpectColumnExpr(t, selector, "json(my_column)", "my_column", &Column{DataType: "JSONB"}) + selectorExpectColumnExpr(t, selector, "json(my_column)", "my_column", &Column{DataType: "JsonB"}) selectorExpectColumnExpr(t, selector, "my_column", "my_column", &Column{DataType: "text"}) }) } diff --git a/internal/endtoend/testdata/jsonb/sqlite/go/models.go b/internal/endtoend/testdata/jsonb/sqlite/go/models.go index 3980b20cad..d8e9fa20bc 100644 --- a/internal/endtoend/testdata/jsonb/sqlite/go/models.go +++ b/internal/endtoend/testdata/jsonb/sqlite/go/models.go @@ -13,4 +13,8 @@ type Foo struct { B json.RawMessage C json.RawMessage D json.RawMessage + E json.RawMessage + F json.RawMessage + G json.RawMessage + H json.RawMessage } diff --git a/internal/endtoend/testdata/jsonb/sqlite/go/query.sql.go b/internal/endtoend/testdata/jsonb/sqlite/go/query.sql.go index 448182e3dd..c073069515 100644 --- a/internal/endtoend/testdata/jsonb/sqlite/go/query.sql.go +++ b/internal/endtoend/testdata/jsonb/sqlite/go/query.sql.go @@ -15,13 +15,21 @@ INSERT INTO foo ( a, b, c, - d + d, + e, + f, + g, + h ) VALUES ( ?1, ?2, ?3, - ?4 -) RETURNING a, json(b), c, json(d) + ?4, + ?5, + ?6, + ?7, + ?8 +) RETURNING a, json(b), c, json(d), e, json(f), g, json(h) ` type InsertFooParams struct { @@ -29,6 +37,10 @@ type InsertFooParams struct { B json.RawMessage C json.RawMessage D json.RawMessage + E json.RawMessage + F json.RawMessage + G json.RawMessage + H json.RawMessage } func (q *Queries) InsertFoo(ctx context.Context, arg InsertFooParams) error { @@ -37,12 +49,16 @@ func (q *Queries) InsertFoo(ctx context.Context, arg InsertFooParams) error { arg.B, arg.C, arg.D, + arg.E, + arg.F, + arg.G, + arg.H, ) return err } const selectFoo = `-- name: SelectFoo :exec -SELECT a, json(b), c, json(d) FROM foo +SELECT a, json(b), c, json(d), e, json(f), g, json(h) FROM foo ` func (q *Queries) SelectFoo(ctx context.Context) error { diff --git a/internal/endtoend/testdata/jsonb/sqlite/query.sql b/internal/endtoend/testdata/jsonb/sqlite/query.sql index 6959bd1a70..baca24c120 100644 --- a/internal/endtoend/testdata/jsonb/sqlite/query.sql +++ b/internal/endtoend/testdata/jsonb/sqlite/query.sql @@ -3,12 +3,20 @@ INSERT INTO foo ( a, b, c, - d + d, + e, + f, + g, + h ) VALUES ( @a, @b, @c, - @d + @d, + @e, + @f, + @g, + @h ) RETURNING *; -- name: SelectFoo :exec diff --git a/internal/endtoend/testdata/jsonb/sqlite/schema.sql b/internal/endtoend/testdata/jsonb/sqlite/schema.sql index 6b4a1bb0fd..cc237ce009 100644 --- a/internal/endtoend/testdata/jsonb/sqlite/schema.sql +++ b/internal/endtoend/testdata/jsonb/sqlite/schema.sql @@ -2,6 +2,10 @@ CREATE TABLE foo ( a json not null, b jsonb not null, c json, - d jsonb + d jsonb, + e JSON not null, + f JSONB not null, + g JSON, + h JSONB ); From 0272689ebdd1fc5974c3cf7da3f2b1a4fc4e9e97 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 17 Apr 2026 13:46:43 +0000 Subject: [PATCH 2/2] Drop unit test additions; rely on end-to-end coverage The capitalized JSONB case is already exercised by the internal/endtoend/testdata/jsonb/sqlite fixture. --- internal/compiler/selector_test.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/internal/compiler/selector_test.go b/internal/compiler/selector_test.go index a17cc4268d..e460dd281c 100644 --- a/internal/compiler/selector_test.go +++ b/internal/compiler/selector_test.go @@ -30,8 +30,6 @@ func TestSelector(t *testing.T) { selectorExpectColumnExpr(t, selector, "my_column", "my_column", &Column{DataType: "integer"}) selectorExpectColumnExpr(t, selector, "my_column", "my_column", &Column{DataType: "json"}) selectorExpectColumnExpr(t, selector, "json(my_column)", "my_column", &Column{DataType: "jsonb"}) - selectorExpectColumnExpr(t, selector, "json(my_column)", "my_column", &Column{DataType: "JSONB"}) - selectorExpectColumnExpr(t, selector, "json(my_column)", "my_column", &Column{DataType: "JsonB"}) selectorExpectColumnExpr(t, selector, "my_column", "my_column", &Column{DataType: "text"}) }) }