On this page
Handle an optional single row
Use one, optional: true when a missing row is an expected outcome. The method returns a row, a presence boolean and an error; check them in that order of responsibility: error first, then presence.
Declare the expected absence
Add optional: true to a static one query. The same option handles an insert skipped on conflict:
-- sgl.query(RingGull, one, optional: true)
INSERT INTO gulls (ring, species) VALUES (?, ?)
ON CONFLICT (ring) DO NOTHING
RETURNING id, ring;
-- sgl.query(FindGull, one, optional: true)
SELECT id, ring, species FROM gulls WHERE ring = ?;
The migration makes each ring unique. A miss or skipped insert returns (zero, false, nil) rather than the driver’s no-rows sentinel.
Check the error before the presence flag
Run sgl generate, construct store.New(database), and keep the row access after both checks:
for _, ring := range []string{"GB1002", "GB9999"} {
gull, ok, err := queries.FindGull(ctx, ring)
if err != nil {
return fmt.Errorf("finding %s: %w", ring, err)
}
if !ok {
fmt.Fprintf(output, "no gull wears ring %s\n", ring)
continue
}
fmt.Fprintf(output, "ring %s is on gull %d, a %s\n", ring, gull.ID, gull.Species)
}
An unexpected database failure still returns an error. Do not treat every error as an ordinary missing row.
Check a found row and a miss
From the Seagull repository root, run the optional-row example:
cd examples/sqlite/018_optional_one
go test .
The example test provides its local inputs. See its caller for the exact Go API and its test for assertions and failure handling.
The complete example produces:
ringed a herring gull as GB1001, gull 1
ringed a kittiwake as GB1002, gull 2
ring GB1001 is already taken, so the black-headed gull was not ringed
ring GB1002 is on gull 2, a kittiwake
no gull wears ring GB9999
Use presence for the whole row
This option applies only to a static one query. It does not change nullable fields within a present row and is unavailable on runtime builders.
See the query commands reference for the complete contract. The example browser exposes other engine variants; use their actual SQL rather than changing only the dialect name.