Documentation
¶
Index ¶
- Variables
- func DecodeCursor(token string) (string, error)
- func EmptyIfNil[T any](s []T) []T
- func EncodeCursor(id string) string
- func GenerateAlterSQL(diff SchemaDiff, dialect Dialect, allowDestructive bool) ([]string, error)
- func GenerateCreateTableSQL(schema TableSchema) string
- func JSON(v any) driver.Valuer
- func ListDialects() []string
- func NewQueryError(query string, err error) error
- func NewSchemaError(table, message string, err error) error
- func NewTransactionError(operation string, err error) error
- func RegisterDialect(dialect Dialect)
- func ScanJSON(dst any) sql.Scanner
- func ValidateIdentifier(name string) error
- func ValidateOrderBy(clause string, allowedColumns []string) error
- func ValidateSchema(ctx context.Context, client *Client, schema TableSchema) error
- type Client
- func (c *Client) BeginTx(ctx context.Context, opts *sql.TxOptions) (*Tx, error)
- func (c *Client) Bun() bun.IDB
- func (c *Client) BunDB() *bun.DB
- func (c *Client) Close() error
- func (c *Client) DB() *sql.DB
- func (c *Client) Dialect() Dialect
- func (c *Client) Exec(ctx context.Context, query string, args ...interface{}) (sql.Result, error)
- func (c *Client) Query(ctx context.Context, query string, args ...interface{}) (*sql.Rows, error)
- func (c *Client) QueryRow(ctx context.Context, query string, args ...interface{}) *sql.Row
- func (c *Client) RunTransaction(ctx context.Context, fn func(ctx Context) error) error
- func (c *Client) RunTransactionWithOptions(ctx context.Context, opts *sql.TxOptions, fn func(ctx Context) error) error
- type ColumnDiff
- type Context
- type Dialect
- type FieldSchema
- type FieldType
- type IndexSchema
- type Int64Array
- type IntrospectedColumn
- type IntrospectedIndex
- type Migration
- type MigrationManager
- func (m *MigrationManager) AutoMigrate(ctx context.Context, schemas []TableSchema) error
- func (m *MigrationManager) GenerateMigration(ctx context.Context, schemas []TableSchema) (*Migration, error)
- func (m *MigrationManager) Migrate(ctx context.Context) error
- func (m *MigrationManager) MigrateTo(ctx context.Context, targetVersion string) error
- func (m *MigrationManager) PlanMigration(ctx context.Context, schemas []TableSchema) (string, error)
- func (m *MigrationManager) Register(migration *Migration) error
- func (m *MigrationManager) RegisterMany(migrations ...*Migration) error
- func (m *MigrationManager) RegisterPairedMigration(paired *PairedMigration) error
- func (m *MigrationManager) Rollback(ctx context.Context, steps int) error
- func (m *MigrationManager) SetTableName(name string)
- func (m *MigrationManager) Status(ctx context.Context) ([]MigrationStatus, error)
- type MigrationStatus
- type NullTime
- type Operator
- type Order
- type PairedMigration
- type PostgresDialect
- func (d *PostgresDialect) DriverName() string
- func (d *PostgresDialect) IntrospectColumnsQuery(tableName string) string
- func (d *PostgresDialect) IntrospectIndexesQuery(tableName string) string
- func (d *PostgresDialect) ListTablesQuery() string
- func (d *PostgresDialect) MapFieldType(fieldType FieldType) string
- func (d *PostgresDialect) Name() string
- func (d *PostgresDialect) OnConflictClause(conflictColumn string, updateColumns []string) string
- func (d *PostgresDialect) ParseColumnType(dbType string) (FieldType, error)
- func (d *PostgresDialect) Placeholder(index int) string
- func (d *PostgresDialect) QuoteIdentifier(identifier string) string
- func (d *PostgresDialect) ScanColumn(rows *sql.Rows) (IntrospectedColumn, error)
- func (d *PostgresDialect) ScanIndex(rows *sql.Rows) (indexName, columnName string, isUnique bool, err error)
- func (d *PostgresDialect) SupportsReturning() bool
- func (d *PostgresDialect) TableExistsQuery(tableName string) string
- type QueryError
- type QueryOption
- func WhereEq(column string, value any) QueryOption
- func WhereGt(column string, value any) QueryOption
- func WhereGte(column string, value any) QueryOption
- func WhereILike(column string, value any) QueryOption
- func WhereILikeAny(columns []string, value any) QueryOption
- func WhereIn(column string, values any) QueryOption
- func WhereIsNotNull(column string) QueryOption
- func WhereIsNull(column string) QueryOption
- func WhereLike(column string, value any) QueryOption
- func WhereLt(column string, value any) QueryOption
- func WhereLte(column string, value any) QueryOption
- func WhereNotEq(column string, value any) QueryOption
- func WhereNotIn(column string, values any) QueryOption
- func WithLimit(limit int) QueryOption
- func WithOffset(offset int) QueryOption
- func WithOrderBy(clause string, order Order) QueryOption
- func WithWhere(column string, op Operator, value any) QueryOption
- type SchemaDiff
- type SchemaError
- type StringArray
- type TableSchema
- type TransactionError
- type Tx
- func (t *Tx) Bun() bun.IDB
- func (t *Tx) Commit() error
- func (t *Tx) Dialect() Dialect
- func (t *Tx) Exec(ctx context.Context, query string, args ...interface{}) (sql.Result, error)
- func (t *Tx) Query(ctx context.Context, query string, args ...interface{}) (*sql.Rows, error)
- func (t *Tx) QueryRow(ctx context.Context, query string, args ...interface{}) *sql.Row
- func (t *Tx) Rollback() error
- type UnknownFieldError
Constants ¶
This section is empty.
Variables ¶
var ( // ErrDestructiveOperation is returned when attempting a destructive operation without permission ErrDestructiveOperation = errors.New("orm: destructive operation not allowed") // ErrUnsupportedOperation is returned when a dialect doesn't support an operation ErrUnsupportedOperation = errors.New("orm: operation not supported by dialect") // ErrIncompatibleTypes is returned when column types cannot be safely converted ErrIncompatibleTypes = errors.New("orm: incompatible column types") )
Diff errors
var ( // ErrNoRows is returned when a query returns no rows ErrNoRows = sql.ErrNoRows // ErrTxDone is returned when a transaction is already committed or rolled back ErrTxDone = sql.ErrTxDone // ErrConnDone is returned when the connection is already closed ErrConnDone = sql.ErrConnDone // ErrNoPrimaryKey is returned when attempting operations on a message without a primary key ErrNoPrimaryKey = errors.New("orm: message has no primary key defined") // ErrInvalidDialect is returned when an invalid or unregistered dialect is specified ErrInvalidDialect = errors.New("orm: invalid or unregistered dialect") // ErrNilContext is returned when a nil context is provided ErrNilContext = errors.New("orm: nil context provided") // ErrSchemaValidationFailed is returned when schema validation fails ErrSchemaValidationFailed = errors.New("orm: schema validation failed") )
Common ORM errors
Functions ¶
func DecodeCursor ¶
DecodeCursor decodes a page cursor token back into the primary key value. Returns an error if the token is empty or not valid base64url.
func EmptyIfNil ¶
func EmptyIfNil[T any](s []T) []T
EmptyIfNil returns an empty (non-nil) slice when s is nil, else s. Used at generated write sites so a nil repeated field binds as an empty array literal, not NULL, against `NOT NULL DEFAULT '{}'` columns.
func EncodeCursor ¶
EncodeCursor encodes a primary key value into an opaque page cursor token. The cursor is base64url-encoded (no padding) for safe use in query strings.
func GenerateAlterSQL ¶
func GenerateAlterSQL(diff SchemaDiff, dialect Dialect, allowDestructive bool) ([]string, error)
GenerateAlterSQL generates ALTER TABLE statements to apply the schema diff GenerateAlterSQL generates ALTER TABLE statements for the given schema diff.
Following the protobuf philosophy, this function ONLY generates ADD and DROP statements. Column modifications (type changes, constraint changes, etc.) are NOT supported.
To modify a column, use a multi-step migration with PairedMigration:
- ADD new column with desired schema
- Migrate data from old column to new column (using DataMigration)
- DROP old column (in a separate migration after verification)
This approach:
- Works on all databases (SQLite, PostgreSQL, MySQL, etc.)
- Forces explicit thinking about data transformations
- Prevents accidental data loss
- Follows protobuf's additive-only philosophy
func GenerateCreateTableSQL ¶
func GenerateCreateTableSQL(schema TableSchema) string
GenerateCreateTableSQL generates a CREATE TABLE statement
func JSON ¶
JSON wraps a Go value for storage as a JSON column value. The generated ORM code uses it for repeated scalar entity fields (e.g. `repeated string tags`): the value is marshalled to JSON text on write, which both postgres (a jsonb column accepts an untyped text parameter) and sqlite (a TEXT-affinity column) store natively — one generated code path, two dialects.
A nil/empty slice round-trips as SQL NULL so the column stays cleanly nullable and scans back to the zero value.
func ListDialects ¶
func ListDialects() []string
ListDialects returns a list of all registered dialect names.
func NewQueryError ¶
NewQueryError creates a new QueryError
func NewSchemaError ¶
NewSchemaError creates a new SchemaError
func NewTransactionError ¶
NewTransactionError creates a new TransactionError
func RegisterDialect ¶
func RegisterDialect(dialect Dialect)
RegisterDialect registers a dialect for use with the ORM. This should be called from init() functions in dialect packages.
func ScanJSON ¶
ScanJSON returns a sql.Scanner that unmarshals a JSON column into dst (a pointer, e.g. *[]string). NULL / empty values leave dst at its zero value. It accepts []byte (postgres jsonb) and string (sqlite TEXT) sources.
func ValidateIdentifier ¶
ValidateIdentifier checks that a string is a safe SQL identifier (letters, digits, underscores only). Returns an error if the identifier contains characters that could be used for SQL injection.
func ValidateOrderBy ¶
ValidateOrderBy validates a comma-separated ORDER BY clause against a column allowlist.
Two layers:
- Shape: only identifier characters (letters, digits, underscores) in column names, with an optional ASC/DESC direction token.
- Allowlist: when allowedColumns is non-empty, every column must be one of the declared columns. Shape validation alone is NOT enough: an undeclared-but-identifier-shaped column (order_by=password_hash) reaches the database where it can be a silent ordering no-op.
Generated entity code exports its declared column list (db.<Entity>Columns) precisely so handlers can pass it here.
func ValidateSchema ¶
func ValidateSchema(ctx context.Context, client *Client, schema TableSchema) error
ValidateSchema validates that the database schema matches the expected schema. It uses IntrospectTable and CompareSchemas to check for differences.
Types ¶
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client is the forge ORM handle. Post-Phase-2 it is a thin wrapper over a *bun.DB (uptrace/bun, postgres-pinned): generated CRUD ops reach the engine via Bun(); the kept schema-truth machinery (introspect/differ/ migration) still consults Dialect() and the raw Exec/Query/QueryRow seam. forge is postgres-only — the dialect argument is retained on the constructors for call-site compatibility and must be "postgres".
func NewClientWithDB ¶
NewClientWithDB wraps an existing *sql.DB into an ORM client. This is the seam the generated bootstrap/setup and pkg/testkit use: open a postgres *sql.DB, hand it here. dialectName must be "postgres".
func (*Client) BunDB ¶
BunDB returns the concrete *bun.DB (for advanced callers that need connection-pool control or BeginTx with bun's transaction type).
func (*Client) DB ¶
DB returns the underlying *sql.DB for advanced usage and for the kept schema-truth machinery's database/sql seam.
func (*Client) Dialect ¶
Dialect returns the SQL dialect (postgres). Consumed by the kept schema-truth machinery (introspect/differ/migration), not by the runtime CRUD engine.
func (*Client) Exec ¶
Exec runs a raw SQL statement (escape hatch). It goes straight to the underlying *sql.DB, NOT through bun's query formatter: callers write native postgres SQL with $1/$2 placeholders, and bun's `?`-rewriting must not touch it. (Generated code uses db.Bun()'s typed builders, which handle their own placeholders.)
func (*Client) Query ¶
Query runs a raw SQL query (escape hatch). See Exec for the raw-passthrough rationale.
func (*Client) RunTransaction ¶
RunTransaction executes fn within a transaction, committing on success and rolling back on error or panic. The transaction Context is passed to fn so generated ORM ops transparently use it.
type ColumnDiff ¶
type ColumnDiff struct {
ColumnName string
OldType string
NewType FieldType
OldNotNull bool
NewNotNull bool
OldDefault sql.NullString
NewDefault string
}
ColumnDiff represents a difference in a column definition
type Context ¶
type Context interface {
// Bun returns the underlying bun.IDB. Generated CRUD functions build
// their queries on it (db.Bun().NewSelect()/NewInsert()/...). It is
// also the raw-SQL escape hatch: bun.IDB exposes NewRaw plus the
// IConn methods below.
Bun() bun.IDB
// Exec executes a query without returning any rows. Thin wrapper over
// bun's ExecContext — the raw-SQL path for user handlers.
Exec(ctx context.Context, query string, args ...interface{}) (sql.Result, error)
// Query executes a query that returns rows (raw-SQL path).
Query(ctx context.Context, query string, args ...interface{}) (*sql.Rows, error)
// QueryRow executes a query expected to return at most one row
// (raw-SQL path).
QueryRow(ctx context.Context, query string, args ...interface{}) *sql.Row
// Dialect returns the SQL dialect (postgres — forge is postgres-pinned).
// The raw-SQL escape hatch needs it: a hand-written handler that builds
// its own SQL string calls db.Dialect().Placeholder(i) for $N parameter
// markers and db.Dialect().QuoteIdentifier(name) for safe identifiers,
// instead of hardcoding postgres syntax. Available on both *Client and
// *Tx so raw SQL composes the same way inside and outside a transaction.
Dialect() Dialect
}
Context is the unified database handle the generated ORM layer and forge/pkg/crud operate against. It can represent either a direct connection (*Client) or a transaction (*Tx), so the same generated CRUD functions work inside and outside transactions.
Bun engine (epic Phase 2): the query/CRUD engine is uptrace/bun. The canonical accessor is Bun(), which returns a bun.IDB — generated ops build their SELECT/INSERT/UPDATE/DELETE on Bun's typed query builders off this handle. The raw escape hatch (Exec/Query/QueryRow) wraps Bun's IConn, preserved here so user-owned handlers can run hand-written SQL and so the kept schema-truth machinery (introspect/differ/ migration) keeps a database/sql seam.
type Dialect ¶
type Dialect interface {
// Name returns the name of the dialect (e.g., "postgres", "sqlite")
Name() string
// DriverName returns the name of the database driver to use with sql.Open
DriverName() string
// Placeholder returns the placeholder string for a given parameter index (0-based)
// PostgreSQL uses $1, $2, etc.
// SQLite and MySQL use ?
Placeholder(index int) string
// QuoteIdentifier quotes an identifier (table name, column name) for the dialect
QuoteIdentifier(identifier string) string
// MapFieldType maps an ORM FieldType to the dialect-specific SQL type
MapFieldType(fieldType FieldType) string
// SupportsReturning returns true if the dialect supports RETURNING clause
SupportsReturning() bool
// OnConflictClause returns the dialect-specific ON CONFLICT or equivalent clause
// for upserts. Takes the conflict column and update columns.
OnConflictClause(conflictColumn string, updateColumns []string) string
// TableExistsQuery returns a SQL query to check if a table exists
TableExistsQuery(tableName string) string
// ListTablesQuery returns a SQL query to list all tables in the current schema
ListTablesQuery() string
// IntrospectColumnsQuery returns a SQL query to introspect columns of a table
IntrospectColumnsQuery(tableName string) string
// IntrospectIndexesQuery returns a SQL query to introspect indexes of a table
IntrospectIndexesQuery(tableName string) string
// ParseColumnType converts a database-specific type string to FieldType
ParseColumnType(dbType string) (FieldType, error)
// ScanColumn scans a row from IntrospectColumnsQuery into an IntrospectedColumn
ScanColumn(rows *sql.Rows) (IntrospectedColumn, error)
// ScanIndex scans a row from IntrospectIndexesQuery into index information
ScanIndex(rows *sql.Rows) (indexName, columnName string, isUnique bool, err error)
}
Dialect defines the interface for database-specific implementations. Each supported database (PostgreSQL, SQLite, MySQL, etc.) should implement this interface.
func GetDialect ¶
GetDialect returns the dialect with the given name. Returns nil if the dialect is not registered.
type FieldSchema ¶
type FieldSchema struct {
Name string
Type FieldType
PrimaryKey bool
Unique bool
NotNull bool
DefaultValue string
}
FieldSchema represents a database field schema
type FieldType ¶
type FieldType string
FieldType represents a database field type
const ( TypeText FieldType = "TEXT" TypeVarchar FieldType = "VARCHAR" TypeInteger FieldType = "INTEGER" TypeBigInt FieldType = "BIGINT" TypeBoolean FieldType = "BOOLEAN" TypeTimestampTZ FieldType = "TIMESTAMPTZ" TypeJSONB FieldType = "JSONB" TypeBytea FieldType = "BYTEA" TypeSerial FieldType = "SERIAL" TypeBigSerial FieldType = "BIGSERIAL" // TypeReal stores a single-precision floating point value (IEEE 754 // 32-bit). Maps to PostgreSQL REAL and to SQLite REAL (which is 8-byte // internally — SQLite has no float32 column type). Used for proto // `float` / `google.protobuf.FloatValue` fields. TypeReal FieldType = "REAL" // TypeDoublePrecision stores a double-precision floating point value // (IEEE 754 64-bit). Maps to PostgreSQL DOUBLE PRECISION and to // SQLite REAL. Used for proto `double` / `google.protobuf.DoubleValue` // fields. Before TypeDoublePrecision landed, protoc-gen-forge emitted // orm.TypeText for double columns; the runtime Scan still worked // because Scan uses *float64, but anything that consults // TableSchema() (DDL introspection / contract sync) saw TEXT for // numeric columns. See orm-typetext-for-double in FORGE_BACKLOG. TypeDoublePrecision FieldType = "DOUBLE PRECISION" )
type IndexSchema ¶
IndexSchema represents a database index
type Int64Array ¶
type Int64Array []int64
Int64Array scans an integer-array column from either encoding.
type IntrospectedColumn ¶
type IntrospectedColumn struct {
Name string
Type FieldType
Nullable bool
DefaultValue *string
IsPrimaryKey bool
IsUnique bool
}
IntrospectedColumn represents a database column discovered through introspection
type IntrospectedIndex ¶
IntrospectedIndex represents a database index discovered through introspection
type Migration ¶
type Migration struct {
// Version is a unique identifier for this migration (e.g., "20240101_001", "v1.0.0")
Version string
// Description is a human-readable description of the migration
Description string
// Up is the function to apply the migration
Up func(ctx context.Context, db Context) error
// Down is the function to rollback the migration (optional)
Down func(ctx context.Context, db Context) error
}
Migration represents a database migration
func NewSQLMigration ¶
Helper function to create a simple schema migration from a SQL string
func NewSchemaCreateMigration ¶
func NewSchemaCreateMigration(version string, schemas ...TableSchema) *Migration
Helper to create a migration that generates schema from protobuf
type MigrationManager ¶
type MigrationManager struct {
// contains filtered or unexported fields
}
MigrationManager manages database migrations
func NewMigrationManager ¶
func NewMigrationManager(client *Client) *MigrationManager
NewMigrationManager creates a new migration manager
func (*MigrationManager) AutoMigrate ¶
func (m *MigrationManager) AutoMigrate(ctx context.Context, schemas []TableSchema) error
AutoMigrate is a convenience function that automatically generates and applies migrations for the provided schemas WARNING: This is a DANGEROUS operation that should ONLY be used in development environments. - It automatically modifies your database schema without explicit review - There is no automatic rollback mechanism - It may cause data loss if destructive operations are allowed - Production databases should use explicit migrations instead
Returns error early if schema diff, SQL generation, or database operations fail.
func (*MigrationManager) GenerateMigration ¶
func (m *MigrationManager) GenerateMigration(ctx context.Context, schemas []TableSchema) (*Migration, error)
GenerateMigration diffs the provided schemas against the database and generates ALTER statements Returns a Migration with the generated SQL. Returns error early if schema diff or SQL generation fails.
func (*MigrationManager) Migrate ¶
func (m *MigrationManager) Migrate(ctx context.Context) error
Migrate runs all pending migrations
func (*MigrationManager) MigrateTo ¶
func (m *MigrationManager) MigrateTo(ctx context.Context, targetVersion string) error
MigrateTo migrates to a specific version
func (*MigrationManager) PlanMigration ¶
func (m *MigrationManager) PlanMigration(ctx context.Context, schemas []TableSchema) (string, error)
PlanMigration is a dry-run function that returns the SQL that would be executed without executing it Returns the SQL statements as a string. Returns error early if schema diff or SQL generation fails.
func (*MigrationManager) Register ¶
func (m *MigrationManager) Register(migration *Migration) error
Register registers a migration
func (*MigrationManager) RegisterMany ¶
func (m *MigrationManager) RegisterMany(migrations ...*Migration) error
RegisterMany registers multiple migrations
func (*MigrationManager) RegisterPairedMigration ¶
func (m *MigrationManager) RegisterPairedMigration(paired *PairedMigration) error
RegisterPairedMigration registers a paired migration that combines schema changes with optional data migrations Schema changes are executed first, then data migrations, all in the same transaction. Returns error early if version conflicts are detected or if migrations are invalid.
func (*MigrationManager) Rollback ¶
func (m *MigrationManager) Rollback(ctx context.Context, steps int) error
Rollback rolls back the last N migrations
func (*MigrationManager) SetTableName ¶
func (m *MigrationManager) SetTableName(name string)
SetTableName sets the name of the migrations tracking table
func (*MigrationManager) Status ¶
func (m *MigrationManager) Status(ctx context.Context) ([]MigrationStatus, error)
Status returns the status of all migrations
type MigrationStatus ¶
MigrationStatus represents the status of a migration
type NullTime ¶
NullTime is a nullable timestamp scanner that tolerates every representation forge's supported engines hand back for a timestamp column:
- time.Time (Postgres via pgx/stdlib; SQLite when the declared type is one the driver recognizes),
- string / []byte (SQLite for declared types like TIMESTAMPTZ, which mattn/go-sqlite3 does NOT auto-convert — it only recognizes "timestamp", "datetime" and "date" verbatim),
- nil (NULL column).
database/sql's own sql.NullTime rejects the string forms, which made generated entity scans fail at runtime against the SQLite test harness. Generated *_orm.go scan code uses this type instead.
type Operator ¶
type Operator string
Operator represents a SQL comparison operator used by WithWhere and the Where* convenience helpers. Postgres semantics (ILIKE is native).
const ( Eq Operator = "=" NotEq Operator = "!=" GreaterThan Operator = ">" GreaterThanOrEq Operator = ">=" LessThan Operator = "<" LessThanOrEq Operator = "<=" Like Operator = "LIKE" ILike Operator = "ILIKE" In Operator = "IN" NotIn Operator = "NOT IN" IsNull Operator = "IS NULL" IsNotNull Operator = "IS NOT NULL" )
type PairedMigration ¶
type PairedMigration struct {
// Version is a unique identifier for this migration (e.g., "20240101_001", "v1.0.0")
Version string
// Description is a human-readable description of the migration
Description string
// SchemaChanges are the proto-based table schemas to migrate to
SchemaChanges []TableSchema
// DataMigration is an optional raw SQL migration to run after schema changes
// This is executed in the same transaction as the schema changes
DataMigration *Migration
}
PairedMigration represents a migration that combines schema changes with optional data migrations
type PostgresDialect ¶
type PostgresDialect struct{}
PostgresDialect implements the Dialect interface for PostgreSQL
func (*PostgresDialect) DriverName ¶
func (d *PostgresDialect) DriverName() string
func (*PostgresDialect) IntrospectColumnsQuery ¶
func (d *PostgresDialect) IntrospectColumnsQuery(tableName string) string
IntrospectColumnsQuery returns a query to introspect columns of a table
func (*PostgresDialect) IntrospectIndexesQuery ¶
func (d *PostgresDialect) IntrospectIndexesQuery(tableName string) string
IntrospectIndexesQuery returns a query to introspect indexes of a table
func (*PostgresDialect) ListTablesQuery ¶
func (d *PostgresDialect) ListTablesQuery() string
ListTablesQuery returns a query to list all tables in the public schema
func (*PostgresDialect) MapFieldType ¶
func (d *PostgresDialect) MapFieldType(fieldType FieldType) string
func (*PostgresDialect) Name ¶
func (d *PostgresDialect) Name() string
func (*PostgresDialect) OnConflictClause ¶
func (d *PostgresDialect) OnConflictClause(conflictColumn string, updateColumns []string) string
func (*PostgresDialect) ParseColumnType ¶
func (d *PostgresDialect) ParseColumnType(dbType string) (FieldType, error)
ParseColumnType converts a PostgreSQL type to FieldType
func (*PostgresDialect) Placeholder ¶
func (d *PostgresDialect) Placeholder(index int) string
func (*PostgresDialect) QuoteIdentifier ¶
func (d *PostgresDialect) QuoteIdentifier(identifier string) string
func (*PostgresDialect) ScanColumn ¶
func (d *PostgresDialect) ScanColumn(rows *sql.Rows) (IntrospectedColumn, error)
ScanColumn scans a row from IntrospectColumnsQuery into an IntrospectedColumn
func (*PostgresDialect) ScanIndex ¶
func (d *PostgresDialect) ScanIndex(rows *sql.Rows) (indexName, columnName string, isUnique bool, err error)
ScanIndex scans a row from IntrospectIndexesQuery into index information
func (*PostgresDialect) SupportsReturning ¶
func (d *PostgresDialect) SupportsReturning() bool
func (*PostgresDialect) TableExistsQuery ¶
func (d *PostgresDialect) TableExistsQuery(tableName string) string
TableExistsQuery returns a query to check if a table exists in PostgreSQL
type QueryError ¶
QueryError represents an error that occurred during a query execution
func (*QueryError) Error ¶
func (e *QueryError) Error() string
func (*QueryError) Unwrap ¶
func (e *QueryError) Unwrap() error
type QueryOption ¶
type QueryOption func(*bun.SelectQuery)
QueryOption is a composable mutation of a Bun SELECT query. The generated List/Count/Get ops and forge/pkg/crud build their filters, ordering, and pagination as a slice of these and apply them to a *bun.SelectQuery.
Phase-2 note: pre-Bun this was func(*QueryBuilder) over forge's hand-rolled builder. The signature now targets *bun.SelectQuery — the engine is Bun, and there is no hand-rolled builder left.
func WhereEq ¶
func WhereEq(column string, value any) QueryOption
func WhereGt ¶
func WhereGt(column string, value any) QueryOption
func WhereGte ¶
func WhereGte(column string, value any) QueryOption
func WhereILike ¶
func WhereILike(column string, value any) QueryOption
func WhereILikeAny ¶
func WhereILikeAny(columns []string, value any) QueryOption
WhereILikeAny matches value case-insensitively against ANY of the given columns: (c1 ILIKE ? OR c2 ILIKE ? ...), AND-ed with the other WHERE clauses. This is the canonical mapping for a `search` filter field: it spans the entity's declared string columns instead of inventing a phantom `search` column.
The OR group is grouped with WhereGroup so it composes correctly with surrounding AND clauses (tenant scope, soft-delete, pagination cursor).
func WhereIn ¶
func WhereIn(column string, values any) QueryOption
func WhereIsNotNull ¶
func WhereIsNotNull(column string) QueryOption
func WhereIsNull ¶
func WhereIsNull(column string) QueryOption
func WhereLike ¶
func WhereLike(column string, value any) QueryOption
func WhereLt ¶
func WhereLt(column string, value any) QueryOption
func WhereLte ¶
func WhereLte(column string, value any) QueryOption
func WhereNotEq ¶
func WhereNotEq(column string, value any) QueryOption
func WhereNotIn ¶
func WhereNotIn(column string, values any) QueryOption
func WithOrderBy ¶
func WithOrderBy(clause string, order Order) QueryOption
WithOrderBy adds an ORDER BY clause. The clause may carry one or more comma-separated columns (validate user input with ValidateOrderBy first). order applies to the whole clause.
type SchemaDiff ¶
type SchemaDiff struct {
TableName string
MissingColumns []FieldSchema // Columns in proto but not in DB
ExtraColumns []string // Columns in DB but not in proto
ModifiedColumns []ColumnDiff // Columns with type/constraint changes
MissingIndexes []IndexSchema // Indexes in proto but not in DB
ExtraIndexes []string // Indexes in DB but not in proto
}
SchemaDiff represents all differences between expected and actual schema for a table
func CompareSchemas ¶
func CompareSchemas(expected, actual TableSchema) (SchemaDiff, error)
CompareSchemas compares expected schema against actual schema and returns differences
func DiffDatabase ¶
func DiffDatabase(ctx context.Context, db Context, dialect Dialect, expectedSchemas []TableSchema) ([]SchemaDiff, error)
DiffDatabase compares expected schemas against the actual database schema
func (*SchemaDiff) HasChanges ¶
func (d *SchemaDiff) HasChanges() bool
HasChanges returns true if there are any differences between schemas
func (*SchemaDiff) IsDestructive ¶
func (d *SchemaDiff) IsDestructive() bool
IsDestructive returns true if the diff contains destructive changes
type SchemaError ¶
SchemaError represents a schema-related error
func (*SchemaError) Error ¶
func (e *SchemaError) Error() string
func (*SchemaError) Unwrap ¶
func (e *SchemaError) Unwrap() error
type StringArray ¶
type StringArray []string
StringArray scans a string-array column from either encoding.
type TableSchema ¶
type TableSchema struct {
Name string
Fields []FieldSchema
Indexes []IndexSchema
}
TableSchema represents a database table schema
func IntrospectAllTables ¶
IntrospectAllTables retrieves schemas for all user tables in the database. It returns a slice of TableSchema objects, one for each table. Returns NewSchemaError if the query fails or any table introspection fails.
func IntrospectTable ¶
func IntrospectTable(ctx context.Context, db Context, dialect Dialect, tableName string) (TableSchema, error)
IntrospectTable retrieves the actual schema of a table from the database. It returns detailed information about columns and indexes. Returns NewSchemaError if the table doesn't exist or any operation fails.
type TransactionError ¶
TransactionError represents an error that occurred during a transaction
func (*TransactionError) Error ¶
func (e *TransactionError) Error() string
func (*TransactionError) Unwrap ¶
func (e *TransactionError) Unwrap() error
type Tx ¶
type Tx struct {
// contains filtered or unexported fields
}
Tx wraps a bun transaction as an orm.Context, so the same generated CRUD functions run transparently inside a transaction.
func (*Tx) Dialect ¶
Dialect returns the SQL dialect (postgres), so raw-SQL handlers running inside a transaction get the same Placeholder()/QuoteIdentifier() seam as on *Client. Carried from the parent Client at BeginTx time.
func (*Tx) Exec ¶
Exec runs a raw SQL statement within the transaction. Like Client.Exec it bypasses bun's query formatter (native $1/$2 placeholders) by going to the embedded *sql.Tx.
type UnknownFieldError ¶
type UnknownFieldError struct {
Field string
}
UnknownFieldError is returned by the generated Update<Entity>Masked helpers when an update_mask path names a column that is not in the entity's updatable set — unknown columns, the primary key, the tenant key, and immutable bookkeeping columns (created_at, deleted_at) all qualify. pkg/crud maps it to CodeInvalidArgument with a clean, SQL-free message naming the path.
func (*UnknownFieldError) Error ¶
func (e *UnknownFieldError) Error() string