Documentation
¶
Overview ¶
Package dbschema provides a portable schema-description vocabulary and read-side (introspection) capability for DALgo.
The package contains Tier-1 engine-neutral types — FieldDef, CollectionDef, IndexDef, Type, Precision, DefaultExpr and concretes — designed for three-tier composition: engine-specific extensions in each driver repo (Tier 2) embed Tier 1; application-specific wrappers in consumer repos (Tier 3) embed Tier 2.
The package also defines the SchemaReader capability interface for schema introspection (the read-side mirror of [ddl.SchemaModifier]) and the shared NotSupportedError typed error used by both the read and write sides.
dbschema does NOT contain operations. CREATE / DROP / ALTER live in the sibling [ddl] sub-package, which imports dbschema for the types it operates on.
Index ¶
- func ListCollections(ctx context.Context, db dal.DB, parent *dal.Key) ([]dal.CollectionRef, error)
- type CollectionDef
- type ConstraintDef
- type DefaultCurrentTimestamp
- type DefaultExpr
- type DefaultLiteral
- type FieldDef
- type IndexDef
- type NotSupportedError
- type Precision
- type Referrer
- type SchemaReader
- type Type
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
Types ¶
type CollectionDef ¶
type CollectionDef struct {
// Name is the collection / table name.
Name string
// Fields lists the fields (columns) in declared order.
Fields []FieldDef
// PrimaryKey lists the names of fields composing the primary key.
// Empty = no PK declared (driver-specific behavior applies).
PrimaryKey []dal.FieldName
// Indexes lists the secondary indexes declared inline with this
// collection definition.
Indexes []IndexDef
}
CollectionDef is the portable description of one collection (a.k.a. table) — its name, ordered fields, primary key, and inline declared secondary indexes.
PrimaryKey is a slice of dal.FieldName. A single-field PK is a one-element slice; a composite PK has multiple entries; an empty slice means "no primary key declared" and driver-specific behavior applies (SQLite may auto-assign ROWID, PostgreSQL may reject, etc.).
Indexes declared inline with CollectionDef are created together with the collection in a CreateCollection call. Indexes added or removed AFTER the collection exists are passed as ddl.AddIndex / ddl.DropIndex AlterOps to ddl.AlterCollection.
The package does NOT validate that PrimaryKey or Indexes reference fields actually present in Fields. That's a driver concern — drivers MUST return a driver-specific error (or *NotSupportedError if the operation itself isn't supported) when validating against the engine.
func DescribeCollection ¶
func DescribeCollection(ctx context.Context, db dal.DB, ref *dal.CollectionRef) (*CollectionDef, error)
DescribeCollection type-asserts db to SchemaReader and delegates.
type ConstraintDef ¶
type ConstraintDef struct {
// Name is the constraint name.
Name string
// Type is the engine-neutral kind:
// "check", "unique", "primary-key", "foreign-key".
Type string
}
ConstraintDef is the portable description of one constraint on a collection. Tier-1 keeps this minimal — Name and Type only. The richer shape required for specific constraint kinds (check expression, unique field list, foreign-key target + cascade actions, etc.) is intentionally deferred. Engine-specific reader extensions (Tier 2) MAY define richer constraint types in their own packages without waiting for Tier 1 to grow.
func ListConstraints ¶
func ListConstraints(ctx context.Context, db dal.DB, ref *dal.CollectionRef) ([]ConstraintDef, error)
ListConstraints type-asserts db to SchemaReader and delegates.
type DefaultCurrentTimestamp ¶
type DefaultCurrentTimestamp struct{}
DefaultCurrentTimestamp signals "use the engine's current-timestamp default at insertion time." Drivers translate to engine-specific SQL (CURRENT_TIMESTAMP on SQLite, now() or CURRENT_TIMESTAMP on PostgreSQL) or the equivalent.
Cross-engine precision: SQLite returns timestamps at second resolution by default; PostgreSQL at microsecond. The Feature does not pin precision — drivers translate as their engine allows.
type DefaultExpr ¶
type DefaultExpr interface {
// contains filtered or unexported methods
}
DefaultExpr is the sealed interface for column default value expressions. The interface is sealed via an unexported marker method (defaultExpr) so the set of valid DefaultExpr cases is closed at the package boundary — drivers know which cases exist and translate accordingly. New cases require adding to this package.
MVP concretes:
- DefaultLiteral carries a plain Go value
- DefaultCurrentTimestamp signals "use the engine's current timestamp default at insertion time"
type DefaultLiteral ¶
type DefaultLiteral struct {
Value any
}
DefaultLiteral is a column default that uses a literal Go value. Drivers MUST handle at minimum: int, int64, float64, string, bool, []byte, and nil. Drivers MAY return a driver-specific error if the underlying Go type cannot be serialized to the target engine.
type FieldDef ¶
type FieldDef struct {
// Name is the field's identifier.
Name dal.FieldName
// Type is the portable column type.
Type Type
// Length is an optional length hint for String / Bytes types.
// nil means "driver default."
Length *int
// Precision is an optional precision hint for Decimal types.
// nil means "driver default."
Precision *Precision
// Nullable is true if the field permits NULL values. Default
// (zero value) is false = NOT NULL.
Nullable bool
// Default is an optional default expression. nil means "no
// default."
Default DefaultExpr
// AutoIncrement is true if the field should auto-generate values.
// Typically restricted by drivers to integer primary-key fields.
AutoIncrement bool
}
FieldDef is the portable description of one field (a.k.a. column) of a CollectionDef.
FieldDef is the schema-DEFINITION shape. It is distinct from the unrelated runtime types in the dal package: dal.Column (a SELECT-clause expression+alias), dal.FieldRef (a query field reference), dal.FieldVal (a runtime name+value pair). Those exist for query and runtime concerns; FieldDef exists to describe a column's structure in a portable way.
AutoIncrement is advisory: drivers MAY restrict it to integer types in the primary key and return *NotSupportedError if a caller passes AutoIncrement on a non-integer field or a field not in the primary key. dbschema itself does NOT enforce the restriction.
type IndexDef ¶
type IndexDef struct {
// Name is the index name.
Name string
// Collection is the simple name of the collection this index belongs to.
Collection string
// Fields is the ordered list of fields the index covers.
Fields []dal.FieldName
// Unique is true if the index enforces uniqueness.
Unique bool
}
IndexDef is the portable description of one index on a CollectionDef. The Fields slice is ordered — order matters for composite indexes (field ordinality affects which queries the index can serve).
Collection is the simple name of the collection the index belongs to. Richer collection addressing (catalog/schema/parent-key) lives in dal.CollectionRef and is the argument type passed to reader and writer methods; this stored value is a plain name. Tier-2 engine extensions MAY add a richer reference field if needed.
func ListIndexes ¶
ListIndexes type-asserts db to SchemaReader and delegates.
type NotSupportedError ¶
type NotSupportedError struct {
// Op names the operation that was not supported (e.g.
// "CreateCollection", "DescribeCollection", "DropIndex").
Op string
// Backend optionally identifies the driver (e.g.
// "dalgo2sql/sqlite"). When the helper function constructs the
// error after a failed type assertion, it sets Backend from
// db.Adapter().Name() if Adapter() returns a non-nil dal.Adapter;
// otherwise Backend is left empty.
Backend string
// Reason is an optional human-readable explanation.
Reason string
}
NotSupportedError is the typed error returned by dbschema and ddl helper functions when a driver does not support a given operation (either because the driver does not implement the relevant capability interface at all, or because the specific operation is unsupported).
NotSupportedError.Unwrap returns the existing dal.ErrNotSupported sentinel so callers can do a coarse errors.Is(err, dal.ErrNotSupported) check or extract detail via errors.As(err, &ue) with ue of type *dbschema.NotSupportedError.
The same error type is used by both the read side (this package's helpers) and the write side ([ddl] package helpers) so consumers have a single typed error to handle across the whole DDL surface.
func (*NotSupportedError) Error ¶
func (e *NotSupportedError) Error() string
Error returns a readable single-line message.
func (*NotSupportedError) Unwrap ¶
func (e *NotSupportedError) Unwrap() error
Unwrap returns the dal.ErrNotSupported sentinel so callers can use errors.Is(err, dal.ErrNotSupported) for a coarse check.
type Precision ¶
Precision describes decimal precision. Total is the total number of significant digits; Scale is the number of digits to the right of the decimal point. Both are non-negative; the package does NOT enforce Scale <= Total.
type Referrer ¶
type Referrer struct {
// Collection identifies the referencing collection.
Collection dal.CollectionRef
// Fields lists the fields in Collection that reference back to
// the queried collection.
Fields []dal.FieldName
}
Referrer describes one collection that references the queried collection via a foreign key.
func ListReferrers ¶
ListReferrers type-asserts db to SchemaReader and delegates.
type SchemaReader ¶
type SchemaReader interface {
// ListCollections returns the collections (tables) accessible to
// db. The optional parent key narrows scope when the backend
// supports hierarchical addressing (e.g. SQL catalog/schema).
// Pass nil for "everything visible."
ListCollections(ctx context.Context, parent *dal.Key) ([]dal.CollectionRef, error)
// DescribeCollection returns the structural definition of one
// collection, including its fields, primary key, and inline
// indexes.
DescribeCollection(ctx context.Context, ref *dal.CollectionRef) (*CollectionDef, error)
// ListIndexes returns the indexes on a collection. The returned
// slice MAY include indexes already reported inline via
// DescribeCollection's Indexes field.
ListIndexes(ctx context.Context, ref *dal.CollectionRef) ([]IndexDef, error)
// ListConstraints is OPTIONAL. Drivers that do not support
// constraint introspection MUST return *NotSupportedError.
ListConstraints(ctx context.Context, ref *dal.CollectionRef) ([]ConstraintDef, error)
// ListReferrers is OPTIONAL. Drivers MAY return
// *NotSupportedError. Returns the collections that reference ref
// via foreign keys.
ListReferrers(ctx context.Context, ref *dal.CollectionRef) ([]Referrer, error)
}
SchemaReader is the capability interface for schema introspection. Drivers that support introspection (SQL backends via information_schema / SQLite pragmas, Firestore via the admin API, etc.) opt in by implementing SchemaReader on their dal.DB value or a related type reachable via type assertion. Drivers that don't implement SchemaReader simply don't satisfy it; the top-level helper functions return *NotSupportedError on the failed assertion.
ListCollections, DescribeCollection, and ListIndexes are REQUIRED for drivers that implement SchemaReader at all. ListConstraints and ListReferrers are OPTIONAL: drivers whose backend lacks the concept (e.g. Firestore has no SQL-style constraints) MUST return *NotSupportedError from those methods. The interface satisfaction is structural — all five methods must be present for a driver to satisfy SchemaReader; runtime behavior decides which methods actually do work.
type Type ¶
type Type int8
Type is the portable column-type enumeration. Drivers translate these to engine-specific column types when emitting DDL.
The zero value is Null so an unset FieldDef.Type is meaningful rather than silently Bool.
const ( // Null indicates an unset or null-typed field. Also the zero value of Type. Null Type = iota // Bool is a boolean column. Bool // Int is an integer column. Drivers pick an appropriate width // (e.g. INT, BIGINT) based on optional Length hints. Int // Float is a floating-point column. Float // String is a textual column. Drivers honor optional Length // hints (e.g. VARCHAR(N) on PostgreSQL). String // Bytes is a binary blob column. Bytes // Time is a date-time column. Time // Decimal is a fixed-point numeric column. Drivers honor optional // Precision hints (e.g. NUMERIC(total, scale) on PostgreSQL). Decimal )