aboutsummaryrefslogtreecommitdiff
path: root/query.go
diff options
context:
space:
mode:
authorStefan Majewsky <majewsky@gmx.net>2026-04-12 17:18:43 +0200
committerStefan Majewsky <majewsky@gmx.net>2026-04-12 17:19:34 +0200
commit5e30087db4a06c24c103737d4cb7dcdf06da5b24 (patch)
treedc606d3575b6287b80b4558da3d00df083358d9c /query.go
parent8d60f626d819f8bdb038ce619d00946442cc2594 (diff)
downloadgo-oblast-5e30087db4a06c24c103737d4cb7dcdf06da5b24.tar.gz
add Store.SelectOne
Diffstat (limited to 'query.go')
-rw-r--r--query.go92
1 files changed, 0 insertions, 92 deletions
diff --git a/query.go b/query.go
deleted file mode 100644
index fd80f56..0000000
--- a/query.go
+++ /dev/null
@@ -1,92 +0,0 @@
-// SPDX-FileCopyrightText: 2026 Stefan Majewsky <majewsky@gmx.net>
-// SPDX-License-Identifier: Apache-2.0
-
-package oblast
-
-import (
- "database/sql"
- "fmt"
- "reflect"
-
- "go.xyrillian.de/oblast/internal"
-)
-
-func (s Store[R]) Select(db Handle, query string, args ...any) (result []R, returnedError error) {
- // NOTE: This function body should be as short as possible to reduce the binary size after monomorphization.
- // Any expression that does not depend on type R should be factored out into a reusable function.
-
- rows, indexes, err := startQuery(db, s.plan, query, args...)
- if err != nil {
- return nil, err
- }
- defer func() {
- returnedError = mergeRowsCloseError(returnedError, rows.Close())
- }()
-
- slots := make([]any, len(indexes))
- for rows.Next() {
- var target R
- err = collectRow(rows, reflect.ValueOf(&target).Elem(), slots, indexes)
- if err != nil {
- return nil, err
- }
- result = append(result, target)
- }
-
- return result, nil
-}
-
-func startQuery(db Handle, plan internal.Plan, query string, args ...any) (rows *sql.Rows, indexes [][]int, err error) {
- rows, err = db.Query(query, args...)
- if err != nil {
- return nil, nil, fmt.Errorf("during Query(): %w", err)
- }
- defer func() {
- if err != nil {
- closeErr := rows.Close()
- if closeErr != nil {
- err = fmt.Errorf("%w (additional error during rows.Close(): %s)", err, closeErr.Error())
- }
- }
- }()
-
- columnNames, err := rows.Columns()
- if err != nil {
- return nil, nil, fmt.Errorf("during rows.Columns(): %w", err)
- }
- indexes = make([][]int, len(columnNames))
- for idx, columnName := range columnNames {
- var ok bool
- indexes[idx], ok = plan.IndexByColumnName[columnName]
- if !ok {
- return nil, nil, fmt.Errorf(
- "result has column %q in position %d, but no field in record type has `db:%[1]q`",
- columnName, idx,
- )
- }
- }
-
- return rows, indexes, nil
-}
-
-func collectRow(rows *sql.Rows, v reflect.Value, slots []any, indexes [][]int) error {
- for idx, index := range indexes {
- slots[idx] = v.FieldByIndex(index).Addr().Interface()
- }
- err := rows.Scan(slots...)
- if err != nil {
- return fmt.Errorf("during rows.Scan(): %w", err)
- }
- return nil
-}
-
-func mergeRowsCloseError(err, closeErr error) error {
- switch {
- case closeErr == nil:
- return err
- case err == nil:
- return fmt.Errorf("during rows.Close(): %w", closeErr)
- default:
- return fmt.Errorf("%w (additional error during rows.Close(): %s)", err, closeErr.Error())
- }
-}