sqlz

package
v0.21.0 Latest Latest
Warning

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

Go to latest
Published: Dec 30, 2022 License: MIT Imports: 9 Imported by: 0

Documentation

Overview

Package sqlz contains core types such as Kind and Record.

Index

Constants

View Source
const (
	TableTypeTable = "table"
	TableTypeView  = "view"
)

Canonical driver-independent names for "table" and "view".

Variables

View Source
var (
	RTypeInt         = reflect.TypeOf(0)
	RTypeInt8        = reflect.TypeOf(int8(0))
	RTypeInt16       = reflect.TypeOf(int16(0))
	RTypeInt32       = reflect.TypeOf(int32(0))
	RTypeInt64       = reflect.TypeOf(int64(0))
	RTypeInt64P      = reflect.TypeOf((*int64)(nil))
	RTypeNullInt64   = reflect.TypeOf(sql.NullInt64{})
	RTypeFloat32     = reflect.TypeOf(float32(0))
	RTypeFloat64     = reflect.TypeOf(float64(0))
	RTypeFloat64P    = reflect.TypeOf((*float64)(nil))
	RTypeNullFloat64 = reflect.TypeOf(sql.NullFloat64{})
	RTypeBool        = reflect.TypeOf(true)
	RTypeBoolP       = reflect.TypeOf((*bool)(nil))
	RTypeNullBool    = reflect.TypeOf(sql.NullBool{})
	RTypeString      = reflect.TypeOf("")
	RTypeStringP     = reflect.TypeOf((*string)(nil))
	RTypeNullString  = reflect.TypeOf(sql.NullString{})
	RTypeTime        = reflect.TypeOf(time.Time{})
	RTypeTimeP       = reflect.TypeOf((*time.Time)(nil))
	RTypeNullTime    = reflect.TypeOf(sql.NullTime{})
	RTypeBytes       = reflect.TypeOf([]byte{})
	RTypeBytesP      = reflect.TypeOf((*[]byte)(nil))
	RTypeNil         = reflect.TypeOf(nil)
	RTypeAny         = reflect.TypeOf((any)(nil))
)

Cached results from reflect.TypeOf for commonly used types.

Functions

func ExecAffected added in v0.15.0

func ExecAffected(ctx context.Context, db Execer, query string, args ...any) (affected int64, err error)

ExecAffected invokes db.ExecContext, returning the count of rows affected and any error.

func SetKindIfUnknown added in v0.17.0

func SetKindIfUnknown(meta RecordMeta, i int, k kind.Kind)

SetKindIfUnknown sets meta[i].kind to k, iff the kind is currently kind.Unknown or kind.Null. This function can be used to set the kind after-the-fact, which is useful for some databases that don't always return sufficient type info upfront.

func ValidRecord

func ValidRecord(recMeta RecordMeta, rec Record) (i int, err error)

ValidRecord checks that each element of the record vals is of an acceptable type. On the first unacceptable element, the index of that element and an error are returned. On success (-1, nil) is returned.

These acceptable types, per the stdlib sql pkg, are:

nil, *int64, *float64, *bool, *string, *[]byte, *time.Time

Types

type ColumnTypeData

type ColumnTypeData struct {
	Name string `json:"name"`

	HasNullable       bool `json:"has_nullable"`
	HasLength         bool `json:"has_length"`
	HasPrecisionScale bool `json:"has_precision_scale"`

	Nullable         bool         `json:"nullable"`
	Length           int64        `json:"length"`
	DatabaseTypeName string       `json:"database_type_name"`
	Precision        int64        `json:"precision"`
	Scale            int64        `json:"scale"`
	ScanType         reflect.Type `json:"scan_type"`

	Kind kind.Kind `json:"kind"`
}

ColumnTypeData contains the same data as sql.ColumnType as well SQ's derived data kind. This type exists with exported fields instead of methods (as on sql.ColumnType) due to the need to work with the fields for testing, and also because for some drivers it's useful to twiddle with the scan type.

This is all a bit ugly.

func NewColumnTypeData

func NewColumnTypeData(col *sql.ColumnType, knd kind.Kind) *ColumnTypeData

NewColumnTypeData returns a new instance with field values taken from col, supplemented with the kind param.

type DB

type DB interface {
	Execer
	Queryer
	Preparer
}

DB is a union of Execer, Queryer and Preparer. DB's method set is implemented by sql.DB, sql.Conn and sql.Tx. This can probably be better named, as it conflicts with sql.DB.

type Execer

type Execer interface {
	// ExecContext is documented by sql.DB.ExecContext.
	ExecContext(ctx context.Context, query string, args ...any) (sql.Result, error)
}

Execer abstracts the ExecContext method from sql.DB and friends.

type FieldMeta

type FieldMeta struct {
	// contains filtered or unexported fields
}

FieldMeta is a bit of a strange entity, and in an ideal world, it wouldn't exist. It's here because:

- The DB driver impls that sq utilizes (postgres, sqlite, etc) often have individual quirks (not reporting nullability etc) that necessitate modifying sql.ColumnType so that there's consistent behavior across the drivers.

- We wanted to retain (and supplement) the method set of sql.ColumnType (basically, use the same "interface", even though sql.ColumnType is a struct, not interface) so that devs don't need to learn a whole new thing.

- For that reason, stdlib sql.ColumnType needs to be supplemented with kind.Kind, and there needs to be a mechanism for modifying sql.ColumnType's fields.

- But sql.ColumnType is sealed (its fields cannot be changed from outside its package).

- Hence this construct where we have FieldMeta (which abstractly is an adapter around sql.ColumnType) and also a data holder struct (ColumnDataType), which permits the mutation of the column type fields.

Likely there's a better design available than this one, but it suffices.

func NewFieldMeta

func NewFieldMeta(data *ColumnTypeData) *FieldMeta

NewFieldMeta returns a new instance backed by the data arg.

func (*FieldMeta) DatabaseTypeName

func (fm *FieldMeta) DatabaseTypeName() string

DatabaseTypeName is documented by sql.ColumnType.DatabaseTypeName.

func (*FieldMeta) DecimalSize

func (fm *FieldMeta) DecimalSize() (precision, scale int64, ok bool)

DecimalSize is documented by sql.ColumnType.DecimalSize.

func (*FieldMeta) Kind

func (fm *FieldMeta) Kind() kind.Kind

Kind returns the data kind for the column.

func (*FieldMeta) Length

func (fm *FieldMeta) Length() (length int64, ok bool)

Length is documented by sql.ColumnType.Length.

func (*FieldMeta) Name

func (fm *FieldMeta) Name() string

Name is documented by sql.ColumnType.Name.

func (*FieldMeta) Nullable

func (fm *FieldMeta) Nullable() (nullable, ok bool)

Nullable is documented by sql.ColumnType.Nullable.

func (*FieldMeta) ScanType

func (fm *FieldMeta) ScanType() reflect.Type

ScanType is documented by sql.ColumnType.ScanType.

func (*FieldMeta) String

func (fm *FieldMeta) String() string

type NullBool

type NullBool struct {
	sql.NullBool
}

NullBool is similar to sql.NullBool, but accepts more boolean representations, e.g. "YES", "Y", "NO", "N", etc. These boolean values are returned by SQL Server and Postgres at times.

func (*NullBool) Scan

func (n *NullBool) Scan(value any) error

Scan implements the Scanner interface.

type Preparer

type Preparer interface {
	// PrepareContext is documented by sql.DB.PrepareContext.
	PrepareContext(ctx context.Context, query string) (*sql.Stmt, error)
}

Preparer abstracts the PrepareContext method from sql.DB and friends.

type Queryer

type Queryer interface {
	// QueryContext is documented by sql.DB.QueryContext.
	QueryContext(ctx context.Context, query string, args ...any) (*sql.Rows, error)

	// QueryRowContext is documented by sql.DB.QueryRowContext.
	QueryRowContext(ctx context.Context, query string, args ...any) *sql.Row
}

Queryer abstracts the QueryContext and QueryRowContext methods from sql.DB and friends.

type Record

type Record []any

Record is a []any row of field values returned from a query.

In the codebase, we distinguish between a "Record" and a "ScanRow", although both are []any and are closely related.

An instance of ScanRow is passed to the sql rows.Scan method, and its elements may include implementations of the sql.Scanner interface such as sql.NullString, sql.NullInt64 or even driver-specific types.

A Record is typically built from a ScanRow, unwrapping and munging elements such that the Record only contains standard types:

nil, *int64, *float64, *bool, *string, *[]byte, *time.Time

It is an error for a Record to contain elements of any other type.

type RecordMeta

type RecordMeta []*FieldMeta

RecordMeta is a slice of *FieldMeta, encapsulating the metadata for a record.

func (RecordMeta) Kinds

func (rm RecordMeta) Kinds() []kind.Kind

Kinds returns the data kinds for the record.

func (RecordMeta) Names

func (rm RecordMeta) Names() []string

Names returns the column names.

func (RecordMeta) NewScanRow

func (rm RecordMeta) NewScanRow() []any

NewScanRow returns a new []any that can be scanned into by sql.Rows.Scan.

func (RecordMeta) ScanTypes

func (rm RecordMeta) ScanTypes() []reflect.Type

ScanTypes returns the scan types for the record.

Jump to

Keyboard shortcuts

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