Skip to content

feat: add preliminary json support for qrm_pgx. #495

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: pgx
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
102 changes: 101 additions & 1 deletion qrm/qrm_pgx.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,61 @@

// QueryablePGX interface for pgx Query method
type QueryablePGX interface {
Query(ctx context.Context, sql string, args ...any) (pgx.Rows, error)
Query(ctx context.Context, query string, args ...any) (pgx.Rows, error)
}

// QueryPGXJsonObj executes a SQL query that returns a JSON object, unmarshals the result into the provided destination,
// and returns the number of rows processed.
//
// The query must return exactly one row with a single column; otherwise, an error is returned.
//
// Parameters:
//
// ctx - The context for managing query execution (timeouts, cancellations).
// db - The database connection or transaction that implements the QueryablePGX interface.
// query - The SQL query string to be executed.
// args - A slice of arguments to be used with the query.
// destPtr - A pointer to the variable where the unmarshaled JSON result will be stored.
// The destination should be a pointer to a struct or map[string]any.
//
// Returns:
//
// rowsProcessed - The number of rows processed by the query execution.
// err - An error if query execution or unmarshaling fails.
func QueryPGXJsonObj(ctx context.Context, db QueryablePGX, query string, args []interface{}, destPtr interface{}) (rowsProcessed int64, err error) {
must.BeInitializedPtr(destPtr, "jet: destination is nil")
must.BeTypeKind(destPtr, reflect.Ptr, jsonDestObjErr)
destType := reflect.TypeOf(destPtr).Elem()
must.BeTrue(destType.Kind() == reflect.Struct || destType.Kind() == reflect.Map, jsonDestObjErr)

return queryPGXJson(ctx, db, query, args, destPtr)

Check warning on line 40 in qrm/qrm_pgx.go

View check run for this annotation

Codecov / codecov/patch

qrm/qrm_pgx.go#L34-L40

Added lines #L34 - L40 were not covered by tests
}

// QueryPGXJsonArr executes a SQL query that returns a JSON array, unmarshals the result into the provided destination,
// and returns the number of rows processed.
//
// The query must return exactly one row with a single column; otherwise, an error is returned.
//
// Parameters:
//
// ctx - The context for managing query execution (timeouts, cancellations).
// db - The database connection or transaction that implements the QueryablePGX interface.
// query - The SQL query string to be executed.
// args - A slice of arguments to be used with the query.
// destPtr - A pointer to the variable where the unmarshaled JSON array will be stored.
// The destination should be a pointer to a slice of structs or []map[string]any.
//
// Returns:
//
// rowsProcessed - The number of rows processed by the query execution.
// err - An error if query execution or unmarshaling fails.
func QueryPGXJsonArr(ctx context.Context, db QueryablePGX, query string, args []interface{}, destPtr interface{}) (rowsProcessed int64, err error) {
must.BeInitializedPtr(destPtr, "jet: destination is nil")
must.BeTypeKind(destPtr, reflect.Ptr, jsonDestArrErr)
destType := reflect.TypeOf(destPtr).Elem()
must.BeTrue(destType.Kind() == reflect.Slice, jsonDestArrErr)

return queryPGXJson(ctx, db, query, args, destPtr)

Check warning on line 67 in qrm/qrm_pgx.go

View check run for this annotation

Codecov / codecov/patch

qrm/qrm_pgx.go#L61-L67

Added lines #L61 - L67 were not covered by tests
}

// QueryPGX executes Query Result Mapping (QRM) of `query` with list of parametrized arguments `arg` over database connection `db`
Expand Down Expand Up @@ -106,3 +160,49 @@

return scanContext.rowNum, rows.Err()
}

func queryPGXJson(ctx context.Context, db QueryablePGX, query string, args []interface{}, destPtr interface{}) (rowsProcessed int64, err error) {
must.BeInitializedPtr(db, "jet: db is nil")

var rows pgx.Rows
rows, err = db.Query(ctx, query, args...)

if err != nil {
return 0, err
}

Check warning on line 172 in qrm/qrm_pgx.go

View check run for this annotation

Codecov / codecov/patch

qrm/qrm_pgx.go#L164-L172

Added lines #L164 - L172 were not covered by tests

defer rows.Close()

if !rows.Next() {
err = rows.Err()
if err != nil {
return 0, err
}
return 0, ErrNoRows

Check warning on line 181 in qrm/qrm_pgx.go

View check run for this annotation

Codecov / codecov/patch

qrm/qrm_pgx.go#L174-L181

Added lines #L174 - L181 were not covered by tests
}

var jsonData []byte
err = rows.Scan(&jsonData)

if err != nil {
return 1, err
}

Check warning on line 189 in qrm/qrm_pgx.go

View check run for this annotation

Codecov / codecov/patch

qrm/qrm_pgx.go#L184-L189

Added lines #L184 - L189 were not covered by tests

if jsonData == nil {
return 1, nil
}

Check warning on line 193 in qrm/qrm_pgx.go

View check run for this annotation

Codecov / codecov/patch

qrm/qrm_pgx.go#L191-L193

Added lines #L191 - L193 were not covered by tests

err = GlobalConfig.JsonUnmarshalFunc(jsonData, &destPtr)

if err != nil {
return 1, fmt.Errorf("jet: invalid json, %w", err)
}

Check warning on line 199 in qrm/qrm_pgx.go

View check run for this annotation

Codecov / codecov/patch

qrm/qrm_pgx.go#L195-L199

Added lines #L195 - L199 were not covered by tests

if rows.Next() {
return 1, fmt.Errorf("jet: query returned more then one row")
}

Check warning on line 203 in qrm/qrm_pgx.go

View check run for this annotation

Codecov / codecov/patch

qrm/qrm_pgx.go#L201-L203

Added lines #L201 - L203 were not covered by tests

rows.Close()

return 1, nil

Check warning on line 207 in qrm/qrm_pgx.go

View check run for this annotation

Codecov / codecov/patch

qrm/qrm_pgx.go#L205-L207

Added lines #L205 - L207 were not covered by tests
}