aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Majewsky <majewsky@gmx.net>2026-09-17 15:50:45 +0200
committerStefan Majewsky <majewsky@gmx.net>2026-09-17 15:50:45 +0200
commitfe37a82d0495a8b59b80677dd42d0d94ffafdfb4 (patch)
tree58339c88054e9662720e76c2e6c8dd0a34f45ab9
parent635c0f118a490112ca2ee797c92f1dd14e6eeed7 (diff)
downloadgo-gg-fe37a82d0495a8b59b80677dd42d0d94ffafdfb4.tar.gz
gsql: add NoneIfNoRows
-rw-r--r--CHANGELOG.md7
-rw-r--r--go.mod2
-rw-r--r--gsql/gsql.go18
-rw-r--r--gsql/gsql_test.go29
4 files changed, 55 insertions, 1 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index f259e37..a37cb78 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,6 +3,13 @@ SPDX-FileCopyrightText: 2026 Stefan Majewsky <majewsky@gmx.net>
SPDX-License-Identifier: Apache-2.0
-->
+# v1.16.0 (TBD)
+
+Changes:
+
+- gsql: Add NoneIfNoRows.
+ This replaces "OrNone" variants of methods in Oblast, e.g. SelectOne() and then also SelectOneOrNone().
+
# v1.15.0 (2026-09-08)
Changes:
diff --git a/go.mod b/go.mod
index 0cd2a2d..9bb7b69 100644
--- a/go.mod
+++ b/go.mod
@@ -1,4 +1,4 @@
module go.xyrillian.de/gg
-// TODO for 1.27: use sql.ConvertAssign for gg/option; deprecate gg/options and offer methods on Option instead; make jsonmatch.Pointer into an alias of jsontext.Pointer
+// TODO for 1.27: use sql.ConvertAssign for gg/option; deprecate gg/options and offer methods on Option instead; make jsonmatch.Pointer into an alias of jsontext.Pointer; replace json.{Unm,M}arshaler with json/v2.{Unm,M}arshaler{From,To}
go 1.26
diff --git a/gsql/gsql.go b/gsql/gsql.go
index 7df830c..e7e2aa3 100644
--- a/gsql/gsql.go
+++ b/gsql/gsql.go
@@ -14,6 +14,9 @@ package gsql
import (
"context"
"database/sql"
+ "errors"
+
+ . "go.xyrillian.de/gg/option"
)
// ConnectionHandle extends [Handle] with methods that make sense for handles referring to entire connections or connection pools, but not e.g. to transactions.
@@ -76,3 +79,18 @@ type Rows interface {
Next() bool
Scan(slots ...any) error
}
+
+// NoneIfNoRows wraps any call returning a record from a DB that may return [sql.ErrNoRows],
+// and converts that error into a [None] in the value position instead.
+//
+// [None]: https://pkg.go.dev/go.xyrillian.de/gg/option#None
+func NoneIfNoRows[T any](value T, err error) (Option[T], error) {
+ switch {
+ case err == nil:
+ return Some(value), nil
+ case errors.Is(err, sql.ErrNoRows):
+ return None[T](), nil
+ default:
+ return None[T](), err
+ }
+}
diff --git a/gsql/gsql_test.go b/gsql/gsql_test.go
new file mode 100644
index 0000000..acf0bbf
--- /dev/null
+++ b/gsql/gsql_test.go
@@ -0,0 +1,29 @@
+// SPDX-FileCopyrightText: 2026 Stefan Majewsky <majewsky@gmx.net>
+// SPDX-License-Identifier: Apache-2.0
+
+package gsql_test
+
+import (
+ "database/sql"
+ "errors"
+ "testing"
+
+ "go.xyrillian.de/gg/assert"
+ "go.xyrillian.de/gg/gsql"
+ . "go.xyrillian.de/gg/option"
+)
+
+func TestNoneIfNoRows(t *testing.T) {
+ x, err := gsql.NoneIfNoRows(42, nil)
+ if assert.ErrEqual(t, err, nil) {
+ assert.Equal(t, x, Some(42))
+ }
+
+ x, err = gsql.NoneIfNoRows(0, sql.ErrNoRows)
+ if assert.ErrEqual(t, err, nil) {
+ assert.Equal(t, x, None[int]())
+ }
+
+ _, err = gsql.NoneIfNoRows(0, errors.New("kaboom"))
+ assert.ErrEqual(t, err, "kaboom")
+}