rowscan

package
v0.17.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 29, 2026 License: Apache-2.0 Imports: 7 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Scanner

type Scanner[T any] struct {
	// contains filtered or unexported fields
}

Scanner scans a result set into a struct by `db` tag while tolerating a result set whose columns do not match the struct exactly.

sqlx's StructScan is all-or-nothing in one direction: a single result column that no `db` tag claims fails every row with "missing destination name X in *T". Two things routinely produce such a column, and both are outside our control. A warehouse-managed view gains one on a vendor release, which turns an ingest into a total outage rather than a missing field. And an account configured to fold quoted identifiers to upper case returns every alias in a case the query did not ask for, so nothing matches at all.

Pinning an explicit column list in the query instead only moves the problem: the query then fails outright the day a column is withdrawn, or against a narrowed view exposing a subset.

So neither the struct nor the query decides the shape — the result set does. A column with no field is discarded and reported by UnknownColumns; a `db` tag with no column is left at its zero value and reported by MissingColumns. Callers that cannot work without a given column say so with RequireColumns rather than leaving it to the scan to fail somewhere downstream.

Only fields carrying an explicit `db` tag participate; fields the scrapper fills in itself stay untouched. Matching is case-insensitive.

func New

func New[T any](rows *sqlx.Rows) (*Scanner[T], error)

New plans how the columns of an open result set map onto T.

func (*Scanner[T]) LogColumnDrift

func (s *Scanner[T]) LogColumnDrift(ctx context.Context, source string)

LogColumnDrift reports the difference between the result set and the struct, so a vendor adding or withdrawing a column surfaces in logs on the run it first happens rather than the next time someone reads the code. source names the object read, for example "SNOWFLAKE.ACCOUNT_USAGE.TASK_HISTORY"; it is left empty by callers that read an arbitrary statement rather than a named object, where the target type is what identifies the read.

func (*Scanner[T]) MissingColumns

func (s *Scanner[T]) MissingColumns() []string

MissingColumns lists `db` tags the result set does not carry. Those fields stay at their zero value.

func (*Scanner[T]) RequireColumns

func (s *Scanner[T]) RequireColumns(columns ...string) error

RequireColumns fails when a column the caller cannot do without is absent from the result set, so an unusable read is rejected up front instead of producing rows with holes in them.

func (*Scanner[T]) Scan

func (s *Scanner[T]) Scan(rows *sqlx.Rows, dest *T) error

Scan reads the current row into dest.

func (*Scanner[T]) UnknownColumns

func (s *Scanner[T]) UnknownColumns() []string

UnknownColumns lists result columns the struct has no field for. They are discarded rather than fatal, and are the expected shape of a vendor adding a column to a view we read.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL