From ab3a265a5ccbba133b6fef3d6915043f55bc5ee0 Mon Sep 17 00:00:00 2001 From: arthurvaverko Date: Mon, 9 Feb 2026 06:06:50 +0200 Subject: [PATCH 1/3] Add support for `json.RawMessage` type and update dependencies. --- go.mod | 4 +- go.sum | 4 ++ qrm/utill.go | 11 +++-- tests/postgres/json_test.go | 96 +++++++++++++++++++++++++++++++++++++ 4 files changed, 109 insertions(+), 6 deletions(-) create mode 100644 tests/postgres/json_test.go diff --git a/go.mod b/go.mod index bb2e376..3566f6f 100644 --- a/go.mod +++ b/go.mod @@ -15,7 +15,7 @@ require ( // used in tests require ( - github.com/bytedance/sonic v1.13.3 + github.com/bytedance/sonic v1.14.0 github.com/google/go-cmp v0.7.0 github.com/pkg/profile v1.7.0 github.com/shopspring/decimal v1.4.0 @@ -26,7 +26,7 @@ require ( require ( filippo.io/edwards25519 v1.1.0 // indirect - github.com/bytedance/sonic/loader v0.2.4 // indirect + github.com/bytedance/sonic/loader v0.3.0 // indirect github.com/cloudwego/base64x v0.1.5 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/felixge/fgprof v0.9.3 // indirect diff --git a/go.sum b/go.sum index e044ce1..9e73e3d 100644 --- a/go.sum +++ b/go.sum @@ -5,9 +5,13 @@ github.com/Masterminds/semver/v3 v3.1.1 h1:hLg3sBzpNErnxhQtUy/mmLR2I9foDujNK030I github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= github.com/bytedance/sonic v1.13.3 h1:MS8gmaH16Gtirygw7jV91pDCN33NyMrPbN7qiYhEsF0= github.com/bytedance/sonic v1.13.3/go.mod h1:o68xyaF9u2gvVBuGHPlUVCy+ZfmNNO5ETf1+KgkJhz4= +github.com/bytedance/sonic v1.14.0 h1:/OfKt8HFw0kh2rj8N0F6C/qPGRESq0BbaNZgcNXXzQQ= +github.com/bytedance/sonic v1.14.0/go.mod h1:WoEbx8WTcFJfzCe0hbmyTGrfjt8PzNEBdxlNUO24NhA= github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU= github.com/bytedance/sonic/loader v0.2.4 h1:ZWCw4stuXUsn1/+zQDqeE7JKP+QO47tz7QCNan80NzY= github.com/bytedance/sonic/loader v0.2.4/go.mod h1:N8A3vUdtUebEY2/VQC0MyhYeKUFosQU6FxH2JmUe6VI= +github.com/bytedance/sonic/loader v0.3.0 h1:dskwH8edlzNMctoruo8FPTJDF3vLtDT0sXZwvZJyqeA= +github.com/bytedance/sonic/loader v0.3.0/go.mod h1:N8A3vUdtUebEY2/VQC0MyhYeKUFosQU6FxH2JmUe6VI= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= diff --git a/qrm/utill.go b/qrm/utill.go index 1775fda..84f4ee8 100644 --- a/qrm/utill.go +++ b/qrm/utill.go @@ -2,14 +2,16 @@ package qrm import ( "database/sql" + "encoding/json" "fmt" + "reflect" + "strings" + "time" + "github.com/go-jet/jet/v2/internal/utils/must" "github.com/go-jet/jet/v2/internal/utils/strslice" "github.com/go-jet/jet/v2/qrm/internal" "github.com/google/uuid" - "reflect" - "strings" - "time" ) var scannerInterfaceType = reflect.TypeOf((*sql.Scanner)(nil)).Elem() @@ -148,6 +150,7 @@ func initializeValueIfNilPtr(value reflect.Value) { var timeType = reflect.TypeOf(time.Now()) var uuidType = reflect.TypeOf(uuid.New()) var byteArrayType = reflect.TypeOf([]byte("")) +var jsonRawMessageType = reflect.TypeOf(json.RawMessage{}) func isSimpleModelType(objType reflect.Type) bool { objType = indirectType(objType) @@ -161,7 +164,7 @@ func isSimpleModelType(objType reflect.Type) bool { return true } - return objType == timeType || objType == uuidType || objType == byteArrayType + return objType == timeType || objType == uuidType || objType == byteArrayType || objType == jsonRawMessageType } // source can't be pointer diff --git a/tests/postgres/json_test.go b/tests/postgres/json_test.go new file mode 100644 index 0000000..eaa37a2 --- /dev/null +++ b/tests/postgres/json_test.go @@ -0,0 +1,96 @@ +package postgres + +import ( + "encoding/json" + "testing" + "time" + + "github.com/go-jet/jet/v2/tests/.gentestdata/jetdb/test_sample/model" + "github.com/google/uuid" + "github.com/lib/pq" + "github.com/stretchr/testify/require" + + . "github.com/go-jet/jet/v2/postgres" + . "github.com/go-jet/jet/v2/tests/.gentestdata/jetdb/test_sample/table" +) + +type AllTypesJsonRawMessageResult struct { + SmallIntPtr *int16 `alias:"all_types.small_int_ptr"` + SmallInt int16 `alias:"all_types.small_int"` + IntegerPtr *int32 `alias:"all_types.integer_ptr"` + Integer int32 `alias:"all_types.integer"` + BigIntPtr *int64 `alias:"all_types.big_int_ptr"` + BigInt int64 `alias:"all_types.big_int"` + DecimalPtr *float64 `alias:"all_types.decimal_ptr"` + Decimal float64 `alias:"all_types.decimal"` + NumericPtr *float64 `alias:"all_types.numeric_ptr"` + Numeric float64 `alias:"all_types.numeric"` + RealPtr *float32 `alias:"all_types.real_ptr"` + Real float32 `alias:"all_types.real"` + DoublePrecisionPtr *float64 `alias:"all_types.double_precision_ptr"` + DoublePrecision float64 `alias:"all_types.double_precision"` + Smallserial int64 `alias:"all_types.smallserial"` + Serial int64 `sql:"primary_key" alias:"all_types.serial"` + Bigserial int64 `alias:"all_types.bigserial"` + VarCharPtr *string `alias:"all_types.var_char_ptr"` + VarChar string `alias:"all_types.var_char"` + CharPtr *string `alias:"all_types.char_ptr"` + Char string `alias:"all_types.char"` + TextPtr *string `alias:"all_types.text_ptr"` + Text string `alias:"all_types.text"` + ByteaPtr *[]byte `alias:"all_types.bytea_ptr"` + Bytea []byte `alias:"all_types.bytea"` + TimestampzPtr *time.Time `alias:"all_types.timestampz_ptr"` + Timestampz time.Time `alias:"all_types.timestampz"` + TimestampPtr *time.Time `alias:"all_types.timestamp_ptr"` + Timestamp time.Time `alias:"all_types.timestamp"` + DatePtr *time.Time `alias:"all_types.date_ptr"` + Date time.Time `alias:"all_types.date"` + TimezPtr *time.Time `alias:"all_types.timez_ptr"` + Timez time.Time `alias:"all_types.timez"` + TimePtr *time.Time `alias:"all_types.time_ptr"` + Time time.Time `alias:"all_types.time"` + IntervalPtr *string `alias:"all_types.interval_ptr"` + Interval string `alias:"all_types.interval"` + BooleanPtr *bool `alias:"all_types.boolean_ptr"` + Boolean bool `alias:"all_types.boolean"` + PointPtr *string `alias:"all_types.point_ptr"` + BitPtr *string `alias:"all_types.bit_ptr"` + Bit string `alias:"all_types.bit"` + BitVaryingPtr *string `alias:"all_types.bit_varying_ptr"` + BitVarying string `alias:"all_types.bit_varying"` + TsvectorPtr *string `alias:"all_types.tsvector_ptr"` + Tsvector string `alias:"all_types.tsvector"` + UUIDPtr *uuid.UUID `alias:"all_types.uuid_ptr"` + UUID uuid.UUID `alias:"all_types.uuid"` + XMLPtr *string `alias:"all_types.xml_ptr"` + XML string `alias:"all_types.xml"` + JSONPtr *string `alias:"all_types.json_ptr"` + JSON string `alias:"all_types.json"` + JsonbPtr *json.RawMessage `alias:"all_types.jsonb_ptr"` + Jsonb json.RawMessage `alias:"all_types.jsonb"` + IntegerArrayPtr *pq.Int32Array `alias:"all_types.integer_array_ptr"` + IntegerArray pq.Int32Array `alias:"all_types.integer_array"` + TextArrayPtr *pq.StringArray `alias:"all_types.text_array_ptr"` + TextArray pq.StringArray `alias:"all_types.text_array"` + JsonbArray pq.StringArray `alias:"all_types.jsonb_array"` + TextMultiDimArrayPtr *string `alias:"all_types.text_multi_dim_array_ptr"` + TextMultiDimArray string `alias:"all_types.text_multi_dim_array"` + MoodPtr *model.Mood `alias:"all_types.mood_ptr"` + Mood model.Mood `alias:"all_types.mood"` +} + +func TestJsonRawMessage(t *testing.T) { + var dest []AllTypesJsonRawMessageResult + + err := SELECT(AllTypes.AllColumns). + FROM(AllTypes). + LIMIT(2). + QueryContext(ctx, db, &dest) + + require.NoError(t, err) + + for _, row := range dest { + t.Logf("%+v", string(row.Jsonb)) + } +} From d42fc975f997e386b46979f7b84b29c2ff7b7112 Mon Sep 17 00:00:00 2001 From: Danny Gueta Date: Fri, 13 Feb 2026 09:50:55 +0200 Subject: [PATCH 2/3] Refactor JSON handling in AllTypesJsonRawMessageResult struct by removing unused fields and updating test cases to validate JSON and Jsonb data retrieval. --- tests/postgres/json_test.go | 86 +++++++------------------------------ 1 file changed, 15 insertions(+), 71 deletions(-) diff --git a/tests/postgres/json_test.go b/tests/postgres/json_test.go index eaa37a2..4b05a8b 100644 --- a/tests/postgres/json_test.go +++ b/tests/postgres/json_test.go @@ -3,11 +3,7 @@ package postgres import ( "encoding/json" "testing" - "time" - "github.com/go-jet/jet/v2/tests/.gentestdata/jetdb/test_sample/model" - "github.com/google/uuid" - "github.com/lib/pq" "github.com/stretchr/testify/require" . "github.com/go-jet/jet/v2/postgres" @@ -15,82 +11,30 @@ import ( ) type AllTypesJsonRawMessageResult struct { - SmallIntPtr *int16 `alias:"all_types.small_int_ptr"` - SmallInt int16 `alias:"all_types.small_int"` - IntegerPtr *int32 `alias:"all_types.integer_ptr"` - Integer int32 `alias:"all_types.integer"` - BigIntPtr *int64 `alias:"all_types.big_int_ptr"` - BigInt int64 `alias:"all_types.big_int"` - DecimalPtr *float64 `alias:"all_types.decimal_ptr"` - Decimal float64 `alias:"all_types.decimal"` - NumericPtr *float64 `alias:"all_types.numeric_ptr"` - Numeric float64 `alias:"all_types.numeric"` - RealPtr *float32 `alias:"all_types.real_ptr"` - Real float32 `alias:"all_types.real"` - DoublePrecisionPtr *float64 `alias:"all_types.double_precision_ptr"` - DoublePrecision float64 `alias:"all_types.double_precision"` - Smallserial int64 `alias:"all_types.smallserial"` - Serial int64 `sql:"primary_key" alias:"all_types.serial"` - Bigserial int64 `alias:"all_types.bigserial"` - VarCharPtr *string `alias:"all_types.var_char_ptr"` - VarChar string `alias:"all_types.var_char"` - CharPtr *string `alias:"all_types.char_ptr"` - Char string `alias:"all_types.char"` - TextPtr *string `alias:"all_types.text_ptr"` - Text string `alias:"all_types.text"` - ByteaPtr *[]byte `alias:"all_types.bytea_ptr"` - Bytea []byte `alias:"all_types.bytea"` - TimestampzPtr *time.Time `alias:"all_types.timestampz_ptr"` - Timestampz time.Time `alias:"all_types.timestampz"` - TimestampPtr *time.Time `alias:"all_types.timestamp_ptr"` - Timestamp time.Time `alias:"all_types.timestamp"` - DatePtr *time.Time `alias:"all_types.date_ptr"` - Date time.Time `alias:"all_types.date"` - TimezPtr *time.Time `alias:"all_types.timez_ptr"` - Timez time.Time `alias:"all_types.timez"` - TimePtr *time.Time `alias:"all_types.time_ptr"` - Time time.Time `alias:"all_types.time"` - IntervalPtr *string `alias:"all_types.interval_ptr"` - Interval string `alias:"all_types.interval"` - BooleanPtr *bool `alias:"all_types.boolean_ptr"` - Boolean bool `alias:"all_types.boolean"` - PointPtr *string `alias:"all_types.point_ptr"` - BitPtr *string `alias:"all_types.bit_ptr"` - Bit string `alias:"all_types.bit"` - BitVaryingPtr *string `alias:"all_types.bit_varying_ptr"` - BitVarying string `alias:"all_types.bit_varying"` - TsvectorPtr *string `alias:"all_types.tsvector_ptr"` - Tsvector string `alias:"all_types.tsvector"` - UUIDPtr *uuid.UUID `alias:"all_types.uuid_ptr"` - UUID uuid.UUID `alias:"all_types.uuid"` - XMLPtr *string `alias:"all_types.xml_ptr"` - XML string `alias:"all_types.xml"` - JSONPtr *string `alias:"all_types.json_ptr"` - JSON string `alias:"all_types.json"` - JsonbPtr *json.RawMessage `alias:"all_types.jsonb_ptr"` - Jsonb json.RawMessage `alias:"all_types.jsonb"` - IntegerArrayPtr *pq.Int32Array `alias:"all_types.integer_array_ptr"` - IntegerArray pq.Int32Array `alias:"all_types.integer_array"` - TextArrayPtr *pq.StringArray `alias:"all_types.text_array_ptr"` - TextArray pq.StringArray `alias:"all_types.text_array"` - JsonbArray pq.StringArray `alias:"all_types.jsonb_array"` - TextMultiDimArrayPtr *string `alias:"all_types.text_multi_dim_array_ptr"` - TextMultiDimArray string `alias:"all_types.text_multi_dim_array"` - MoodPtr *model.Mood `alias:"all_types.mood_ptr"` - Mood model.Mood `alias:"all_types.mood"` + JSON string `alias:"all_types.json"` + JsonbPtr *json.RawMessage `alias:"all_types.jsonb_ptr"` + Jsonb json.RawMessage `alias:"all_types.jsonb"` } func TestJsonRawMessage(t *testing.T) { var dest []AllTypesJsonRawMessageResult - err := SELECT(AllTypes.AllColumns). + err := SELECT(AllTypes.JSON, AllTypes.JsonbPtr, AllTypes.Jsonb). FROM(AllTypes). LIMIT(2). QueryContext(ctx, db, &dest) require.NoError(t, err) + require.Len(t, dest, 2) - for _, row := range dest { - t.Logf("%+v", string(row.Jsonb)) - } + // Row 0: JSON, Jsonb, and JsonbPtr all set + require.JSONEq(t, allTypesRow0.JSON, dest[0].JSON) + require.JSONEq(t, allTypesRow0.Jsonb, string(dest[0].Jsonb)) + require.NotNil(t, dest[0].JsonbPtr) + require.JSONEq(t, *allTypesRow0.JsonbPtr, string(*dest[0].JsonbPtr)) + + // Row 1: JSON and Jsonb set, JsonbPtr is nil + require.JSONEq(t, allTypesRow1.JSON, dest[1].JSON) + require.JSONEq(t, allTypesRow1.Jsonb, string(dest[1].Jsonb)) + require.Nil(t, dest[1].JsonbPtr) } From 89dda7068d528d233afc381e921970a4a04681ba Mon Sep 17 00:00:00 2001 From: Danny Gueta Date: Fri, 13 Feb 2026 09:52:49 +0200 Subject: [PATCH 3/3] Remove commented-out code in JSON test cases for clarity and maintainability. --- tests/postgres/json_test.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/postgres/json_test.go b/tests/postgres/json_test.go index 4b05a8b..f9b8fe3 100644 --- a/tests/postgres/json_test.go +++ b/tests/postgres/json_test.go @@ -27,13 +27,11 @@ func TestJsonRawMessage(t *testing.T) { require.NoError(t, err) require.Len(t, dest, 2) - // Row 0: JSON, Jsonb, and JsonbPtr all set require.JSONEq(t, allTypesRow0.JSON, dest[0].JSON) require.JSONEq(t, allTypesRow0.Jsonb, string(dest[0].Jsonb)) require.NotNil(t, dest[0].JsonbPtr) require.JSONEq(t, *allTypesRow0.JsonbPtr, string(*dest[0].JsonbPtr)) - // Row 1: JSON and Jsonb set, JsonbPtr is nil require.JSONEq(t, allTypesRow1.JSON, dest[1].JSON) require.JSONEq(t, allTypesRow1.Jsonb, string(dest[1].Jsonb)) require.Nil(t, dest[1].JsonbPtr)