feat: add StrictFieldMapping config

This commit is contained in:
k4n4ry 2025-12-29 23:27:27 +09:00
parent adef2f9b1a
commit f33c2ee357
4 changed files with 219 additions and 9 deletions

View file

@ -6,8 +6,9 @@ import (
"encoding/json"
"errors"
"fmt"
"github.com/go-jet/jet/v2/internal/utils/must"
"reflect"
"github.com/go-jet/jet/v2/internal/utils/must"
)
// Config holds the configuration settings for QRM scanning behavior.
@ -18,6 +19,13 @@ type Config struct {
// Does not apply to statements build with SELECT_JSON_OBJ or SELECT_JSON_ARR
StrictScan bool
// StrictFieldMapping, when true, causes the scanning function to panic if it encounters any
// destination struct fields that do not have matching columns in the SQL query result.
// This check applies only to fields that are mapped from a single column (simple/scanner/json_column).
// Complex fields (struct/slice) are excluded because they are populated recursively and can be optional.
// Does not apply to statements build with SELECT_JSON_OBJ or SELECT_JSON_ARR
StrictFieldMapping bool
// JsonUnmarshalFunc is called by the Query method to unmarshal JSON query results created by
// SELECT_JSON_OBJ and SELECT_JSON_ARR statements.
// It can be replaced with any implementation that matches the standard "encoding/json" `Unmarshal` function signature.
@ -28,8 +36,9 @@ type Config struct {
// GlobalConfig is the package-wide configuration for SQL scanning.
// This variable is not thread safe, and it should be modified only once, for instance, during application initialization.
var GlobalConfig = Config{
StrictScan: false,
JsonUnmarshalFunc: json.Unmarshal,
StrictScan: false,
StrictFieldMapping: false,
JsonUnmarshalFunc: json.Unmarshal,
}
// ErrNoRows is returned by Query when query result set is empty
@ -230,6 +239,9 @@ func ScanOneRowToDest(scanContext *ScanContext, rows *sql.Rows, destPtr interfac
}
scanContext.EnsureEveryColumnRead() // can panic
if GlobalConfig.StrictFieldMapping {
scanContext.EnsureEveryFieldMapped() // can panic
}
return nil
}
@ -276,6 +288,9 @@ func queryToSlice(ctx context.Context, db Queryable, query string, args []interf
if scanContext.rowNum == 1 && GlobalConfig.StrictScan {
scanContext.EnsureEveryColumnRead()
}
if scanContext.rowNum == 1 && GlobalConfig.StrictFieldMapping {
scanContext.EnsureEveryFieldMapped()
}
}
err = rows.Close()