On this page

Inspect SQL-to-Go types

Inspect a representative query’s generated row alongside its table model before adding type overrides. This SQLite example covers integers, floating-point values, dates, binary data and a nullable column.

Select the values the caller will read

Choose the emitter in sgl.yaml first; this example uses database/sql. The migration declares each column. Put a write and matching read in your query file:

-- sgl.query(RecordLanding, one)
INSERT INTO landings (species, boxes, fish, weight_g, length_cm, on_ice, landed_at, tag, notes)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
RETURNING id;

-- sgl.query(GetLanding, one)
SELECT id, species, boxes, fish, weight_g, length_cm, on_ice, landed_at, tag, notes
FROM landings
WHERE id = ?;

Run sgl generate and compare internal/store/models.go with the query’s GetLandingRow. The query result can be more nullable than the table when its SQL introduces missing values.

Inspect values through the real driver

Call the generated method and inspect the Go values, rather than assuming an SQL spelling determines the runtime representation:

	landing, err := queries.GetLanding(ctx, recorded.ID)
	if err != nil {
		return fmt.Errorf("getting landing %d: %w", recorded.ID, err)
	}
	fmt.Fprintf(output, "id         %-10T %d\n", landing.ID, landing.ID)
	fmt.Fprintf(output, "species    %-10T %s\n", landing.Species, landing.Species)
	fmt.Fprintf(output, "boxes      %-10T %d\n", landing.Boxes, landing.Boxes)
	fmt.Fprintf(output, "fish       %-10T %d\n", landing.Fish, landing.Fish)
	fmt.Fprintf(output, "weight_g   %-10T %d\n", landing.WeightG, landing.WeightG)
	fmt.Fprintf(output, "length_cm  %-10T %.1f\n", landing.LengthCm, landing.LengthCm)
	fmt.Fprintf(output, "on_ice     %-10T %t\n", landing.OnIce, landing.OnIce)
	fmt.Fprintf(output, "landed_at  %-10T %s\n", landing.LandedAt, landing.LandedAt.Format(time.RFC3339))
	// %T prints []byte as []uint8, since byte is an alias for uint8.
	fmt.Fprintf(output, "tag        %-10T % x\n", landing.Tag, landing.Tag)
	fmt.Fprintf(output, "notes      %-10T %s\n", landing.Notes, *landing.Notes)

The %T output below shows the actual types for this driver. If a mapping does not fit the application, add an override and repeat the read with representative values.

Check the reported Go types

From the Seagull repository root, run the type-mapping example:

cd examples/sqlite/005_type_mapping
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:

id         int64      1
species    string     mackerel
boxes      int64      12
fish       int64      480
weight_g   int64      163200
length_cm  float64    31.5
on_ice     bool       true
landed_at  time.Time  2026-05-01T05:30:00Z
tag        []uint8    04 a2 19 f3
notes      *string    landed at Newlyn

Check declared names and cast behaviour

SQLite stores integers in up to eight bytes, so all its integer columns default to int64. Driver decoding also depends on exact declared type names: plain DATE, DATETIME and TIMESTAMP can read as time.Time, while a modified name such as TIMESTAMP(3) reads as text. A cast follows SQLite’s affinity rules. See the reference before narrowing a type or changing its representation.

See the type mapping reference for the complete contract. The example browser exposes other engine variants; use their actual SQL rather than changing only the dialect name.

Examples for this page