Documentation
¶
Overview ¶
Package compat defines the engine-neutral contract used by the compatibility implementation. It deliberately requires explicit targets: a claim of exact compatibility has no meaning without source and destination versions.
Index ¶
- func CompileDDL(target Target, schema Schema) ([]string, error)
- func CompileDropTable(target Target, table string) (string, error)
- func CompileDropTableIfExists(target Target, table string) (string, error)
- func RequireEquivalent(report VerificationReport) error
- func RequireExact(findings []Finding) error
- func SnapshotDigest(snapshot Snapshot) (string, error)
- type Assignment
- type CatalogObject
- type Change
- type ChangeKind
- type Column
- type CommonTableExpr
- type CompoundSelect
- type ConflictError
- type Constraint
- type ConstraintKind
- type Contract
- type Domain
- type Engine
- type Expression
- type Feature
- type Finding
- type GeneratedColumn
- type Index
- type IndexColumn
- type Inspection
- type Join
- type MappingStatus
- type Ordering
- type Projection
- type Reference
- type ReferentialAction
- type Routine
- type RoutineAction
- type RoutineOrdering
- type RoutineParameter
- type RoutineResultColumn
- type Row
- type Schema
- type SearchResult
- type SelectQuery
- type Snapshot
- type Store
- func (store *Store) ApplyChanges(ctx context.Context, schema Schema, changes []Change) error
- func (store *Store) ApplyChangesTolerant(ctx context.Context, schema Schema, changes []Change) error
- func (store *Store) ApplySchema(ctx context.Context, schema Schema) error
- func (store *Store) CallRoutine(ctx context.Context, schema Schema, name string, arguments map[string]Value) error
- func (store *Store) Close() error
- func (store *Store) DropTable(ctx context.Context, table string) error
- func (store *Store) DropTableIfExists(ctx context.Context, table string) error
- func (store *Store) ExportSnapshot(ctx context.Context, schema Schema) (Snapshot, error)
- func (store *Store) ImportSnapshot(ctx context.Context, snapshot Snapshot) error
- func (store *Store) InspectSchema(ctx context.Context) (Inspection, error)
- func (store *Store) InstallChangeCapture(ctx context.Context, schema Schema) error
- func (store *Store) QueryRoutine(ctx context.Context, schema Schema, name string, arguments map[string]Value) ([]Row, error)
- func (store *Store) ReadCapturedChanges(ctx context.Context, schema Schema, after uint64, limit int) ([]Change, error)
- func (store *Store) SearchText(ctx context.Context, table, idColumn string, textColumns []string, ...) ([]SearchResult, error)
- type Table
- type TableSource
- type Target
- type Trigger
- type TriggerAction
- type Type
- type TypeFamily
- type Value
- type ValueKind
- type VerificationReport
- type Version
- type View
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func CompileDDL ¶
CompileDDL emits the target-specific physical schema from the canonical AST. Callers must audit transformed features before treating the result as an exact migration plan.
func CompileDropTable ¶ added in v0.2.0
CompileDropTable compiles the statement that drops one existing table.
It does NOT emit IF EXISTS: dropping a table that is not there is a mistake in the caller's model of the database, and the engine's "no such table" error is the only signal that surfaces it. Idempotence is available explicitly through CompileDropTableIfExists / Store.DropTableIfExists — two named entry points instead of an unnamed boolean at the call site, so a reader of the call always sees which semantics were chosen.
The table name is quoted with quoteIdentifier, so a name containing double quotes, a semicolon or any other punctuation stays a single identifier and can never introduce extra SQL.
func CompileDropTableIfExists ¶ added in v0.2.0
CompileDropTableIfExists compiles the idempotent form, `DROP TABLE IF EXISTS`, for callers that genuinely want "make sure this table is gone" (teardown, reruns of a rebuild). IF EXISTS is spelled out in the function name precisely because it hides a real error — a typo in the table name becomes a silent no-op — so choosing it must be visible at the call site.
The IF EXISTS keyword is likewise identical in both engines.
func RequireEquivalent ¶
func RequireEquivalent(report VerificationReport) error
func RequireExact ¶
func SnapshotDigest ¶
SnapshotDigest creates a deterministic data-integrity proof for a canonical snapshot. Row order is normalized; table, column and value names are encoded by encoding/json with stable map ordering.
Types ¶
type Assignment ¶
type Assignment struct {
Column string `json:"column"`
Value Expression `json:"value"`
}
type CatalogObject ¶
type Change ¶
type Change struct {
Source Target `json:"source"`
Sequence uint64 `json:"sequence"`
CommittedAt time.Time `json:"committed_at"`
Kind ChangeKind `json:"kind"`
Table string `json:"table"`
PrimaryKey Row `json:"primary_key"`
Before Row `json:"before,omitempty"`
After Row `json:"after,omitempty"`
TransactionID string `json:"transaction_id"`
}
Change is an engine-neutral mutation. Sequence is monotonically increasing per source, which lets a destination apply the same ordered history.
func OrderedChanges ¶
OrderedChanges rejects ambiguous or out-of-order histories before applying them to the other engine.
type ChangeKind ¶
type ChangeKind string
const ( Insert ChangeKind = "insert" Update ChangeKind = "update" Delete ChangeKind = "delete" )
type Column ¶
type Column struct {
Name string `json:"name"`
Type Type `json:"type"`
Nullable bool `json:"nullable"`
Default *Expression `json:"default,omitempty"`
// DomainRef, when set, names a Schema.Domains entry this column takes its
// CHECK/NOT NULL/DEFAULT from. It is additive and omitempty, so a column
// without it stays byte-identical. The column MUST still carry Type equal to
// the domain's base type: the data chain (export/import canonicalization) keys
// off Column.Type.Family, and both engines physically store the domain value
// as its base type, so the redundant Type keeps that path unchanged and keeps
// PG(native domain) and SQLite(inlined) storing identical values. A
// domain-referencing column must be otherwise neutral — Nullable true, no own
// Default, no Generated — so the domain is the single source of the constraint
// (validated in Schema.Validate). On PostgreSQL the column's SQL type is the
// domain name; on SQLite it is the base type with the domain's CHECK/NOT
// NULL/DEFAULT inlined.
DomainRef string `json:"domain,omitempty"`
// Generated, when set, makes this a STORED generated column whose value is
// computed from Expression rather than supplied on INSERT/UPDATE. It is an
// additive, omitempty field: a column without it stays byte-identical in the
// canonical JSON and in every emitted statement. See GeneratedColumn.
Generated *GeneratedColumn `json:"generated,omitempty"`
}
type CommonTableExpr ¶
type CommonTableExpr struct {
Name string `json:"name"`
Query SelectQuery `json:"query"`
}
CommonTableExpr is one named, non-recursive common table expression: the CTE name and the query it binds. Referenced from a FROM clause by its name like an ordinary table, a CTE has identical materialized-result semantics in SQLite and PostgreSQL. A CTE name shadows a real table of the same name for the duration of the query in both engines (standard SQL), so no special resolution is needed.
type CompoundSelect ¶
type CompoundSelect struct {
Operator string `json:"operator"`
Query SelectQuery `json:"query"`
}
CompoundSelect is one branch of a compound (set-operation) SELECT: the set operator that joins it to everything to its left, plus the branch query. The operator is one of "union", "union_all", "intersect", "except"; all four have identical set semantics in SQLite and PostgreSQL. A chain that mixes "intersect" with any other operator is rejected, because INTERSECT binds more tightly than UNION/EXCEPT in PostgreSQL but has equal (left-associative) precedence in SQLite, so a flat left-associative chain would group differently between the two engines.
type ConflictError ¶
func (*ConflictError) Error ¶
func (err *ConflictError) Error() string
type Constraint ¶
type Constraint struct {
Kind ConstraintKind `json:"kind"`
Columns []string `json:"columns"`
References *Reference `json:"references,omitempty"`
Expression *Expression `json:"expression,omitempty"`
}
type ConstraintKind ¶
type ConstraintKind string
const ( PrimaryKey ConstraintKind = "primary_key" UniqueKey ConstraintKind = "unique" ForeignKey ConstraintKind = "foreign_key" Check ConstraintKind = "check" )
type Contract ¶
type Contract struct {
Source Target `json:"source"`
Destination Target `json:"destination"`
RequiredFeatures []Feature `json:"required_features"`
}
Contract is the complete compatibility claim made for one migration or synchronization relationship. RequiredFeatures must be audited before data movement begins; unknown capabilities are failures, never silent fallbacks.
type Domain ¶
type Domain struct {
Name string `json:"name"`
Type Type `json:"type"`
Check *Expression `json:"check,omitempty"`
NotNull bool `json:"not_null,omitempty"`
Default *Expression `json:"default,omitempty"`
}
Domain is a named SQL domain: a base Type plus an optional CHECK constraint, NOT NULL flag and DEFAULT expression. It is asymmetric across the two engines by nature:
- PostgreSQL emits a native CREATE DOMAIN and columns reference it by name.
- SQLite has no domains, so every column that references the domain is compiled INLINE with the domain's base type and the same CHECK/NOT NULL/DEFAULT — semantically equivalent (same base type, same constraint), the only portable rendering.
The CHECK expression refers to the value under test with the placeholder node Expression{Kind:"domain_value"}: it compiles to the SQL keyword VALUE on PostgreSQL (the domain's own value) and to the referencing column's name when inlined on SQLite. Grammar validity of the CHECK is enforced at compile time by the same compileExpression path as any other expression, so an out-of-grammar CHECK fails with an explicit error.
A domain is a schema-level constraint, not data: the stored value is identical whether the constraint is enforced by a native PG domain or by an inline SQLite CHECK, so data fidelity is preserved. Only the canonical path (schema created by this layer, kept in __compat_schema) round-trips the domain exactly; external inspection cannot rebuild a domain that never physically existed as such (see docs/COMPATIBILITY.md).
type Expression ¶
type Expression struct {
Kind string `json:"kind"`
Value string `json:"value,omitempty"`
Args []Expression `json:"args,omitempty"`
}
Expression is an AST placeholder. Raw SQL is intentionally excluded from this layer because exact compatibility requires the expression to be parsed and compiled separately for each target dialect.
type Feature ¶
type Feature string
const ( Tables Feature = "tables" PrimaryKeys Feature = "primary_keys" ForeignKeys Feature = "foreign_keys" CanonicalForeignKeys Feature = "canonical_foreign_keys" CheckRules Feature = "check_constraints" CanonicalChecks Feature = "canonical_check_constraints" Transactions Feature = "transactions" Indexes Feature = "indexes" CanonicalIndexes Feature = "canonical_indexes" JSONValues Feature = "json" UUIDValues Feature = "uuid" Triggers Feature = "triggers" CanonicalTriggers Feature = "canonical_triggers" Views Feature = "views" CanonicalViews Feature = "canonical_views" StoredRoutines Feature = "stored_routines" CanonicalRoutines Feature = "canonical_routines" FullText Feature = "full_text" CanonicalFullText Feature = "canonical_full_text" CanonicalVectors Feature = "canonical_vectors" )
func InferFeatures ¶
InferFeatures derives the minimum capabilities required by a canonical schema. Migration callers use this to prevent a schema from claiming an exact plan while omitting its difficult capabilities from the contract.
type Finding ¶
type Finding struct {
Feature Feature `json:"feature"`
Status MappingStatus `json:"status"`
Reason string `json:"reason,omitempty"`
}
type GeneratedColumn ¶
type GeneratedColumn struct {
Expression Expression `json:"expression"`
Stored bool `json:"stored"`
}
GeneratedColumn describes a STORED generated column: `col TYPE GENERATED ALWAYS AS (<expression>) STORED`. Only STORED is supported because it is computed and physically stored identically by SQLite (>= 3.31) and PostgreSQL (>= 12) with this exact syntax; the value is recomputed on the destination from the same deterministic expression, which is the equivalence proof. VIRTUAL is deliberately not supported (PostgreSQL cannot express it), so Stored must be true — a false Stored is rejected by Schema.Validate rather than silently emitting divergent DDL. Expression uses the canonical grammar (compat/sqlparse.go, parseCatalogExpression) and is compiled by the same compileExpression path as any other expression, so an out-of-grammar expression fails at compile time with an explicit error. A generated column cannot also carry a Default and cannot be part of a canonical primary key (both engines restrict this).
type Index ¶
type Index struct {
Name string `json:"name"`
Table string `json:"table"`
Unique bool `json:"unique,omitempty"`
Columns []IndexColumn `json:"columns"`
Where *Expression `json:"where,omitempty"`
}
type IndexColumn ¶
type IndexColumn struct {
Column string `json:"column,omitempty"`
Descending bool `json:"descending,omitempty"`
Expression *Expression `json:"expression,omitempty"`
}
IndexColumn is one key of an index. Ordinarily the key is a plain column (Column). When Expression is set the key is that catalog expression (Section 3 grammar) compiled inside parentheses — an expression index, supported by SQLite (>= 3.9) and PostgreSQL with identical `(expr)` key syntax — and Column is left empty. Descending applies to either form. Expression is additive and omitted from JSON when nil, so a plain-column index stays byte-identical in canonical metadata and in every emitted statement.
type Inspection ¶
type Inspection struct {
Schema Schema `json:"schema"`
Exact bool `json:"exact"`
Source string `json:"source"`
Unresolved []CatalogObject `json:"unresolved,omitempty"`
}
type Join ¶
type Join struct {
Kind string `json:"kind"`
Table TableSource `json:"table"`
On Expression `json:"on"`
}
type MappingStatus ¶
type MappingStatus string
const ( Exact MappingStatus = "exact" Transformed MappingStatus = "transformed" Emulated MappingStatus = "emulated" Unsupported MappingStatus = "unsupported" Unknown MappingStatus = "unknown" )
type Ordering ¶
type Ordering struct {
Expression Expression `json:"expression"`
Descending bool `json:"descending,omitempty"`
}
type Projection ¶
type Projection struct {
Expression Expression `json:"expression"`
Alias string `json:"alias,omitempty"`
}
type Reference ¶
type Reference struct {
Table string `json:"table"`
Columns []string `json:"columns"`
OnUpdate ReferentialAction `json:"on_update,omitempty"`
OnDelete ReferentialAction `json:"on_delete,omitempty"`
}
type ReferentialAction ¶
type ReferentialAction string
const ( NoAction ReferentialAction = "no_action" Restrict ReferentialAction = "restrict" Cascade ReferentialAction = "cascade" SetNull ReferentialAction = "set_null" SetDefault ReferentialAction = "set_default" )
type Routine ¶
type Routine struct {
Name string `json:"name"`
Parameters []RoutineParameter `json:"parameters,omitempty"`
Actions []RoutineAction `json:"actions"`
}
type RoutineAction ¶
type RoutineAction struct {
Kind string `json:"kind"`
Table string `json:"table"`
Assignments []Assignment `json:"assignments,omitempty"`
Where *Expression `json:"where,omitempty"`
// The fields below belong to the read action ("select") and are all additive
// and omitempty, so an insert/update/delete action serializes byte-identically
// to how it did before the read action existed.
//
// Relation is the source of a "select": a table OR a view. It is a separate
// field from Table (which names the written table of a write action) because a
// read may target a view, where the joins/aggregates live — the canonical
// division that keeps the read action free of joins.
Relation string `json:"relation,omitempty"`
// Columns are the DECLARED output columns of a "select". A View carries no
// output types (it is {Name, Query}) and they cannot be inferred in general
// (count(*), arbitrary expressions), so the action declares them: this layer
// declares, it does not guess. The declaration is also the check — a value
// that is not of the declared family fails loudly in canonicalValue instead of
// reaching the caller as garbage.
Columns []RoutineResultColumn `json:"columns,omitempty"`
// OrderBy is the DECLARED ordering of a "select". Order columns are never
// caller-supplied: a column name cannot be bound as a placeholder, so taking
// it from the caller would be an injection path. It is mandatory whenever
// Limit or Offset is present, because without a total order "page 2" can mean
// different rows on each engine.
OrderBy []RoutineOrdering `json:"order_by,omitempty"`
// Limit and Offset are values, so they MAY come from the caller: each is a
// routine expression resolving to a non-negative integer ("parameter" or
// "integer"), bound as a placeholder after the WHERE placeholders. Offset
// requires Limit: SQLite has no OFFSET without LIMIT, and emitting a synthetic
// "LIMIT -1" to paper over that would be exactly the silent divergence this
// layer refuses.
Limit *Expression `json:"limit,omitempty"`
Offset *Expression `json:"offset,omitempty"`
}
type RoutineOrdering ¶ added in v0.3.0
type RoutineOrdering struct {
Column string `json:"column"`
Descending bool `json:"descending,omitempty"`
}
RoutineOrdering is one declared ORDER BY key of a "select" routine action. It is a plain column name (quoted at compile time), never an expression and never a caller-supplied value.
type RoutineParameter ¶
type RoutineResultColumn ¶ added in v0.3.0
RoutineResultColumn is one declared output column of a "select" routine action: the column name as projected by the relation, plus the canonical type family used to canonicalize every scanned value (the same contract as Column.Type on a table). It mirrors RoutineParameter, which declares the inputs.
type Schema ¶
type Schema struct {
Tables []Table `json:"tables"`
Indexes []Index `json:"indexes,omitempty"`
// Domains is the list of named SQL domains (a base type plus an optional
// CHECK, NOT NULL and DEFAULT). It is additive and omitempty, so a schema
// without domains stays byte-identical in the canonical JSON and in every
// emitted statement. PostgreSQL has native domains (CREATE DOMAIN emitted
// before the tables); SQLite has none, so a column that references a domain is
// inlined with the domain's base type + CHECK (+ NOT NULL/DEFAULT). See Domain.
Domains []Domain `json:"domains,omitempty"`
Views []View `json:"views,omitempty"`
Triggers []Trigger `json:"triggers,omitempty"`
Routines []Routine `json:"routines,omitempty"`
}
Schema is the engine-neutral representation used before emitting SQLite or PostgreSQL DDL. Every engine-specific construct must be represented as an explicit capability rather than hidden in a raw SQL string.
type SearchResult ¶
type SearchResult struct {
ID string `json:"id"`
}
type SelectQuery ¶
type SelectQuery struct {
// With is the list of non-recursive common table expressions (CTEs) that
// precede this query: WITH name AS (SELECT ...), ... <query>. Each CTE query
// is itself a SelectQuery in the same bounded grammar. WITH RECURSIVE is
// deliberately not modeled and is rejected at parse time, because its
// termination and row-ordering semantics are hard to guarantee byte-identical
// between SQLite and PostgreSQL. Absent CTEs leave the query byte-identical,
// and the field is omitted from JSON so existing view snapshots do not change.
With []CommonTableExpr `json:"with,omitempty"`
Distinct bool `json:"distinct,omitempty"`
Columns []Projection `json:"columns"`
From TableSource `json:"from"`
Joins []Join `json:"joins,omitempty"`
Where *Expression `json:"where,omitempty"`
GroupBy []Expression `json:"group_by,omitempty"`
Having *Expression `json:"having,omitempty"`
// Compounds is the left-associative chain of set operations applied after
// this (the leading) SELECT: q0 op1 q1 op2 q2 ... The trailing OrderBy,
// Limit and Offset below apply to the whole compound, not to the last
// branch, so each CompoundSelect.Query carries none of them. Absent
// compounds leave the single-SELECT behavior byte-identical, and the field
// is omitted from JSON so existing view snapshots do not change.
Compounds []CompoundSelect `json:"compounds,omitempty"`
OrderBy []Ordering `json:"order_by,omitempty"`
Limit *int `json:"limit,omitempty"`
Offset *int `json:"offset,omitempty"`
}
type Store ¶
Store is the database/sql boundary for a concrete engine. All values crossing this boundary are converted into the canonical Value representation.
func (*Store) ApplyChanges ¶
ApplyChanges applies one ordered source stream atomically. Reapplying the same stream is safe: committed source sequences are recorded in the target transaction and skipped on subsequent attempts.
func (*Store) ApplyChangesTolerant ¶
func (store *Store) ApplyChangesTolerant(ctx context.Context, schema Schema, changes []Change) error
ApplyChangesTolerant applies one ordered source stream atomically with an opt-in, catch-up conflict policy. It exists for zero-window migrations whose capture-install → snapshot → catch-up sequence inherently overlaps: a change journaled after capture was installed may already have traveled inside the snapshot, so re-applying it would trip a spurious ConflictError even though the destination already reflects the change's final state.
The only difference from ApplyChanges is conflict resolution. A change is treated as already applied — and recorded in __compat_applied_changes as if it had just been applied — when the destination's CURRENT state already equals the change's FINAL state:
- insert: the row already exists and rowsEqual(after, actual);
- update: the row exists and rowsEqual(after, actual) even though Before no longer matches (the snapshot already carried the after state);
- delete: the row no longer exists.
Any other divergence remains a strict ConflictError: the tolerant mode is a catch-up convenience, not a bypass. ApplyChanges is unchanged.
func (*Store) ApplySchema ¶
func (*Store) CallRoutine ¶
func (store *Store) CallRoutine(ctx context.Context, schema Schema, name string, arguments map[string]Value) error
CallRoutine executes a canonical routine inside one transaction. The routine is stored in the canonical schema and therefore has the same implementation on SQLite and PostgreSQL instead of relying on engine-specific languages.
func (*Store) DropTable ¶ added in v0.2.0
DropTable compiles (CompileDropTable) and executes the drop against this store's database. Engine errors — a missing table, or a foreign key from another table pointing at this one — are wrapped with the operation name and propagated; nothing is retried with CASCADE.
Note on the change-capture triggers installed by InstallChangeCapture: both engines drop the triggers attached to the table together with the table itself. On PostgreSQL the trigger FUNCTIONS (`__compat_capture_<table>_<kind>_fn`) are separate catalog objects and survive the drop, orphaned but harmless; re-running InstallChangeCapture recreates them with CREATE OR REPLACE. The rows already written to `__compat_change_journal` for the dropped table are also kept on both engines — the journal is an append-only history and this package never deletes data implicitly.
func (*Store) DropTableIfExists ¶ added in v0.2.0
DropTableIfExists is DropTable with the idempotent statement; see CompileDropTableIfExists for why the choice is explicit in the name.
func (*Store) ExportSnapshot ¶
func (*Store) ImportSnapshot ¶
ImportSnapshot creates the canonical schema and inserts every canonical row. It is intentionally append-only; replacement and synchronization policies are handled by higher layers so data is never deleted implicitly.
func (*Store) InspectSchema ¶
func (store *Store) InspectSchema(ctx context.Context) (Inspection, error)
InspectSchema reconstructs the exact canonical schema when the database was managed by this compatibility layer. For external databases it falls back to catalog inspection and explicitly reports objects not yet translated.
func (*Store) InstallChangeCapture ¶
InstallChangeCapture installs engine-native triggers which journal every committed row mutation in canonical, ordered form.
func (*Store) QueryRoutine ¶ added in v0.3.0
func (store *Store) QueryRoutine(ctx context.Context, schema Schema, name string, arguments map[string]Value) ([]Row, error)
QueryRoutine executes a canonical READ routine and returns canonical rows. It is the read counterpart of CallRoutine, which stays write-only and unchanged: CallRoutine returns only error and has production consumers, so reading is new, additive surface rather than a signature change.
The routine must contain exactly one action, of kind "select" (enforced by Schema.Validate too). The statement is composed from pieces that already exist: compileRoutineWhere for the filter — which emits the right placeholder per engine and binds every caller value instead of inlining it, and already maps LIKE to ILIKE on PostgreSQL — and the exportTable pattern for reading, which canonicalizes every scanned value by type family. Here the family comes from the action's DECLARED output columns, because a view has no output types.
Every identifier (relation, output columns, order keys) goes through quoteIdentifier; every caller value, including LIMIT and OFFSET, is bound as a placeholder. Nothing supplied by the caller is ever concatenated into the SQL.
func (*Store) ReadCapturedChanges ¶
func (store *Store) ReadCapturedChanges(ctx context.Context, schema Schema, after uint64, limit int) ([]Change, error)
ReadCapturedChanges reads an ordered source stream after the supplied cursor.
func (*Store) SearchText ¶
func (store *Store) SearchText(ctx context.Context, table, idColumn string, textColumns []string, query string) ([]SearchResult, error)
SearchText implements deterministic Unicode token matching in the common Go runtime. It does not delegate tokenization or ranking to either database.
type Table ¶
type Table struct {
Name string `json:"name"`
Columns []Column `json:"columns"`
Constraints []Constraint `json:"constraints,omitempty"`
}
type TableSource ¶
type TableSource struct {
Table string `json:"table,omitempty"`
Alias string `json:"alias,omitempty"`
Subquery *SelectQuery `json:"subquery,omitempty"`
}
TableSource is a FROM/JOIN source: either a named table (Table) or a derived table (Subquery). Exactly one of Table or Subquery is set. A derived table is a full SelectQuery evaluated as a table; both engines give it identical results (it cannot be correlated with the enclosing query in standard SQL). A derived table requires an Alias. Subquery is omitted from JSON when absent, so existing table-source snapshots do not change.
type Trigger ¶
type Trigger struct {
Name string `json:"name"`
Table string `json:"table"`
Timing string `json:"timing"`
Event string `json:"event"`
When *Expression `json:"when,omitempty"`
Actions []TriggerAction `json:"actions"`
}
type TriggerAction ¶
type TriggerAction struct {
Kind string `json:"kind"`
Table string `json:"table"`
Assignments []Assignment `json:"assignments,omitempty"`
Where *Expression `json:"where,omitempty"`
}
type Type ¶
type Type struct {
Family TypeFamily `json:"family"`
// Arguments preserve details such as precision, scale, length or array
// dimensions without coupling the canonical schema to SQL text.
Arguments []int `json:"arguments,omitempty"`
}
type TypeFamily ¶
type TypeFamily string
const ( BooleanType TypeFamily = "boolean" IntegerType TypeFamily = "integer" DecimalType TypeFamily = "decimal" FloatType TypeFamily = "float" TextType TypeFamily = "text" BinaryType TypeFamily = "binary" DateType TypeFamily = "date" TimestampType TypeFamily = "timestamp" JSONType TypeFamily = "json" UUIDType TypeFamily = "uuid" VectorType TypeFamily = "vector" )
type Value ¶
Value keeps data independent from either driver's Go representation. Values are encoded canonically before persistence in a migration artifact or change journal, preserving null and type information across both engines.
type ValueKind ¶
type ValueKind string
const ( NullValue ValueKind = "null" BooleanValue ValueKind = "boolean" IntegerValue ValueKind = "integer" DecimalValue ValueKind = "decimal" FloatValue ValueKind = "float" TextValue ValueKind = "text" BinaryValue ValueKind = "binary" DateValue ValueKind = "date" TimestampValue ValueKind = "timestamp" JSONValue ValueKind = "json" UUIDValue ValueKind = "uuid" VectorValue ValueKind = "vector" )
type VerificationReport ¶
type VerificationReport struct {
SourceDigest string `json:"source_digest"`
DestinationDigest string `json:"destination_digest"`
Equivalent bool `json:"equivalent"`
}
func VerifySnapshots ¶
func VerifySnapshots(source, destination Snapshot) (VerificationReport, error)
type View ¶
type View struct {
Name string `json:"name"`
Query SelectQuery `json:"query"`
}