API reference

Plugin system

Plugin base class and helpers for pgcraft factory extensions.

class Dynamic(attr)[source]

Reference to an instance attribute that holds the actual ctx key.

Use inside produces() / requires() decorators when the ctx key name is determined at construction time rather than being a fixed string:

@produces(Dynamic("table_key"))
@requires("raw")
class MyPlugin(Plugin):
    def __init__(self, table_key: str = "result") -> None:
        self.table_key = table_key

    def run(self, ctx: FactoryContext) -> None:
        ctx[self.table_key] = build(ctx["raw"])

The factory resolves each Dynamic via getattr(instance, attr) when building the dependency graph.

class MinPGVersion(version)[source]

Minimum PostgreSQL version requirement for a plugin.

Use inside requires() to declare that a plugin needs a specific PostgreSQL major version:

@requires(MinPGVersion(18))
@produces("pk_columns")
class UUIDV7PKPlugin(Plugin):
    ...

The factory stores the requirement as min_pg_version on the class. Call check_pg_version() with the connected server’s major version to validate before applying DDL.

class Plugin[source]

Base class for pgcraft factory plugins.

Each plugin implements run to perform its work. Execution order is determined by topological sort using the produces() and requires() class decorators.

Declaring dependencies:

@produces(Dynamic("out_key"))
@requires("primary")
class MyPlugin(Plugin):
    def __init__(self, out_key: str = "result") -> None:
        self.out_key = out_key

    def run(self, ctx: FactoryContext) -> None:
        ctx[self.out_key] = transform(ctx["primary"])

Plugins communicate through ctx using string keys. Use the singleton() decorator to declare that at most one plugin of a given group may appear in any resolved plugin list.

resolved_produces()[source]

Return the ctx keys this plugin writes, with Dynamic refs resolved.

Reads the _produces list set by the produces() decorator and substitutes each Dynamic with getattr(self, attr).

Return type:

list[str]

Returns:

List of ctx key strings this plugin will write to.

resolved_requires()[source]

Return the ctx keys this plugin reads, with Dynamic refs resolved.

Reads the _requires list set by the requires() decorator and substitutes each Dynamic with getattr(self, attr).

Return type:

list[str]

Returns:

List of ctx key strings this plugin expects to already be set.

run(ctx)[source]

Execute this plugin’s work against ctx.

The factory calls this once per plugin, after topological sorting by produces() / requires().

Parameters:

ctx (FactoryContext) – The factory context.

Return type:

None

check_pg_version(server_version, plugins)[source]

Raise if any plugin requires a newer PostgreSQL version.

Call this with the server’s major version (e.g. conn.dialect.server_version_info[0]) to get an early, clear error instead of a cryptic “function does not exist” from PostgreSQL.

Parameters:
  • server_version (int) – Major version of the connected server.

  • plugins (list[Plugin]) – The resolved plugin list to check.

Raises:

PGCraftValidationError – When a plugin’s min_pg_version exceeds server_version.

Return type:

None

produces(*keys)[source]

Declare the ctx keys this plugin’s run method writes.

Applied as a class decorator, alongside requires() and singleton():

@produces(Dynamic("table_key"))
class MyTablePlugin(Plugin):
    ...
Parameters:

*keys (str | Dynamic) – Ctx key strings or Dynamic references to instance attributes that hold the actual key names.

Return type:

Callable[[TypeVar(T, bound= type[Plugin])], TypeVar(T, bound= type[Plugin])]

Returns:

A class decorator that attaches _produces to the class.

Raises:

TypeError – If a Dynamic attr name is not an __init__ parameter.

requires(*keys)[source]

Declare the ctx keys this plugin’s run method reads.

Applied as a class decorator, alongside produces() and singleton(). Accepts MinPGVersion sentinels to declare a minimum PostgreSQL version requirement:

@requires(MinPGVersion(18), "pk_columns")
class MyPlugin(Plugin):
    ...
Parameters:

*keys (str | Dynamic | MinPGVersion) – Ctx key strings, Dynamic references, or MinPGVersion version requirements.

Return type:

Callable[[TypeVar(T, bound= type[Plugin])], TypeVar(T, bound= type[Plugin])]

Returns:

A class decorator that attaches _requires to the class and sets min_pg_version if any MinPGVersion sentinel is present.

Raises:

TypeError – If a Dynamic attr name is not an __init__ parameter.

singleton(group)[source]

Declare that at most one plugin of group may appear.

The factory raises PGCraftValidationError at construction time if two plugins with the same group name are present in the resolved plugin list.

Example:

@singleton("__pk__")
class MyPKPlugin(Plugin):
    ...
Parameters:

group (str) – Arbitrary group identifier. By convention, built-in groups use dunder names ("__pk__", "__table__").

Return type:

Callable[[TypeVar(T, bound= type[Plugin])], TypeVar(T, bound= type[Plugin])]

Returns:

A class decorator that sets singleton_group on the class and registers the singleton validator.

Core ResourceFactory: plugin runner.

class ResourceFactory(tablename, schemaname, metadata, schema_items, *, config=None, plugins=None, extra_plugins=None)[source]

Core factory: resolves plugins and runs them in dependency order.

Subclasses declare DEFAULT_PLUGINS for user-facing defaults and _INTERNAL_PLUGINS for always-present built-in logic. Callers can override or extend the plugin list via plugins / extra_plugins, and inject global plugins via config.

Plugin execution order is determined by each plugin’s produces and requires declarations. Plugins with no declared dependencies run in the order they appear in the list.

Resolution order: global_plugins + user_plugins + internal_plugins, then topological sort.

If no user or global plugin produces pk_columns and internal plugins are present, a SerialPKPlugin is auto-prepended.

Parameters:
Raises:

PGCraftValidationError – If any schema item fails validation, two plugins share a singleton group, two plugins produce the same ctx key, or a plugin dependency cycle is detected.

ctx: FactoryContext

The factory context after plugin execution.

Downstream view factories (e.g. PostgRESTView) read this to access tables, columns, and other plugin outputs.

table: FromClause

The root selectable created by the factory.

This is the __root__ context value set by the table plugin, exposing the column metadata for use in queries, foreign key references, and ledger event lambdas.

Factory context dataclass.

class FactoryContext(tablename, schemaname, metadata, schema_items, plugins)[source]

Carries inputs and accumulates plugin outputs.

Typed input fields (set by the factory, read-only for plugins):

  • tablename, schemaname, metadata, schema_items, plugins – as passed to the factory constructor.

Plugin store (read/write via item syntax):

Plugins communicate by storing and retrieving arbitrary values using string keys. The key names a plugin reads and writes are explicit constructor arguments on that plugin (with sensible defaults), so multiple independent pipelines can coexist by using distinct keys.

ctx["key"] = value

Store a value. Raises KeyError if key is already set – two plugins writing the same key is almost certainly a mistake. Use ctx.set("key", value, force=True) to override intentionally.

ctx["key"]

Retrieve a value. Raises KeyError with a plugin-ordering hint when the key is absent.

"key" in ctx

Test whether a key has been set without raising.

Injected columns (append-only list):

Plugins that provide columns for table construction (e.g. CreatedAtPlugin, UUIDEntryIDPlugin, DoubleEntryPlugin) append Column objects to ctx.injected_columns. Table plugins spread this list into the table definition alongside PK and dimension columns.

property columns: list[Column]

Return only Column instances from schema_items.

Useful when a plugin needs to iterate over column definitions (e.g. to extract column names or types).

property dim_column_names: list[str]

Return writable (non-PK, non-computed) column names.

Filters out primary-key and computed columns from schema_items, leaving only the user-defined dimension columns that a plugin should read or write. Equivalent to the _dim_column_names helper that was previously duplicated across multiple plugin modules.

property pk_column_name: str

Return the primary key column name.

Shorthand for ctx["pk_columns"].first_key. Requires a PK plugin (e.g. SerialPKPlugin) to have run first.

Raises:

KeyError – If pk_columns has not been set yet.

set(key, value, *, force=False)[source]

Store value under key, with optional override.

Parameters:
  • key (str) – The store key to write.

  • value (Any) – The value to store.

  • force (bool) – If True, overwrite an existing value without raising. Use this when a plugin intentionally replaces a previous plugin’s output.

Raises:

KeyError – If key is already set and force is False.

Return type:

None

property table_items: list[SchemaItem]

Return schema items suitable for table creation.

Filters out PGCraftCheck (which are handled by dedicated check plugins) but keeps all real SQLAlchemy SchemaItem objects: columns, constraints, indexes, computed columns, etc.

Global pgcraft configuration.

class PGCraftConfig(plugins=<factory>, extensions=<factory>, auto_discover=True, utility_schema='pgcraft')[source]

Global plugin and extension registry.

Plugins registered here are prepended to every factory’s resolved plugin list, so they run before factory-specific plugins.

Extensions bundle plugins, metadata hooks, Alembic hooks, and CLI commands into a single unit.

Example:

from pgcraft.extensions.postgrest import (
    PostgRESTExtension,
)

config = PGCraftConfig()
config.use(PostgRESTExtension())
config.register(TimestampPlugin(), TenantPlugin())

PGCraftSimple(
    "users", "public", metadata, ..., config=config
)
Parameters:
  • plugins (list[Plugin]) – Global plugins prepended to every factory.

  • extensions (list[PGCraftExtension]) – Manually registered extension instances.

  • auto_discover (bool) – Whether to discover extensions via entry points. Defaults to True.

  • utility_schema (str) – PostgreSQL schema for pgcraft-managed utility functions (e.g. ledger_apply_state). Defaults to "pgcraft". Override only if your project already uses a schema named "pgcraft".

property all_plugins: list[Plugin]

Return extension plugins + direct plugins.

Extension plugins are prepended before direct plugins.

Returns:

Combined plugin list.

register(*plugins)[source]

Register one or more plugins globally.

Parameters:

*plugins (Plugin) – Plugin instances to add.

Return type:

PGCraftConfig

Returns:

self for chaining.

use(*extensions)[source]

Register one or more extensions.

Parameters:

*extensions (PGCraftExtension) – Extension instances to add.

Return type:

PGCraftConfig

Returns:

self for chaining.

Check constraint support for pgcraft dimensions.

Provides PGCraftCheck, a declarative check constraint that uses {column_name} markers in its expression. Plugins resolve these markers to the appropriate column references depending on the dimension type (table-level for simple/append-only, NEW.col for EAV trigger-based enforcement).

class PGCraftCheck(expression, name)[source]

A declarative check constraint with {col} markers.

Parameters:
  • expression (str) – Constraint expression using {column_name} markers, e.g. "{price} > 0".

  • name (str) – Required constraint name — no auto-naming.

column_names()[source]

Extract {name} markers from the expression.

Return type:

list[str]

Returns:

List of column names referenced in the expression, in order of first appearance with duplicates removed.

resolve(mapping)[source]

Replace each {col} with mapping(col).

Parameters:

mapping (Callable[[str], str]) – A callable that maps column names to their resolved form (e.g. identity for table-level, lambda c: f"NEW.{c}" for triggers).

Return type:

str

Returns:

The resolved SQL expression.

collect_checks(schema_items)[source]

Filter PGCraftCheck instances from a schema items list.

Parameters:

schema_items (list) – Mixed list of Column, PGCraftCheck, and other schema items.

Return type:

list[PGCraftCheck]

Returns:

Only the PGCraftCheck items, in their original order.

Index support for pgcraft dimensions.

Provides PGCraftIndex, a declarative index definition that mirrors sqlalchemy.Index and uses {column_name} markers for column references.

class PGCraftIndex(name, *expressions, unique=False, **kw)[source]

A declarative index definition with {col} markers.

Mirrors the sqlalchemy.Index constructor signature:

PGCraftIndex("idx_name", "{col1}", "{col2}",
             unique=True, postgresql_using="btree")

Simple column references ("{name}") and functional expressions ("lower({name})") are both supported. Extra keyword arguments are passed through to the underlying sqlalchemy.Index.

Parameters:
  • name (str) – Required index name.

  • *expressions (str) – Index expressions using {column_name} markers.

  • unique (bool) – Whether to create a unique index.

  • **kw (Any) – Passed through to sqlalchemy.Index (e.g. postgresql_using, postgresql_where).

column_names()[source]

Extract {name} markers from all expressions.

Return type:

list[str]

Returns:

Column names in order of first appearance, deduplicated across all expressions.

resolve(mapping)[source]

Replace {col} markers in each expression.

Parameters:

mapping (Callable[[str], str]) – A callable that maps column names to their resolved form.

Return type:

list[str]

Returns:

List of resolved expression strings.

collect_indices(schema_items)[source]

Filter PGCraftIndex instances from schema items.

Parameters:

schema_items (list) – Mixed list of schema items.

Return type:

list[PGCraftIndex]

Returns:

Only the PGCraftIndex items, in original order.

Foreign key support for pgcraft dimensions.

Provides PGCraftFK, a declarative foreign key constraint definition that pairs {column_name} markers with their target references in a single dict.

Two reference modes are supported:

  • references — a dict mapping {local_col} markers to "dimension.column" strings, resolved at factory time via the dimension registry in metadata.info["pgcraft_dimensions"].

  • raw_references — a dict mapping {local_col} markers to "schema.table.column" strings, passed through to SQLAlchemy directly.

Exactly one of the two must be provided.

class DimensionRef(schema, table)[source]

Registry entry for a dimension’s FK-targetable table.

Stored in metadata.info["pgcraft_dimensions"] keyed by dimension name (tablename).

Parameters:
  • schema (str) – PostgreSQL schema name.

  • table (str) – Physical table name for FK targets.

class PGCraftFK(references=<factory>, raw_references=<factory>, name='', ondelete=None, onupdate=None)[source]

A declarative foreign key constraint.

Each entry in the dict maps a local {column} marker to its target reference. Exactly one of references or raw_references must be provided:

  • references — targets use "dimension.column" format, resolved via the dimension registry:

    PGCraftFK(
        references={"{customer_id}": "customers.id"},
        name="fk_orders_customer",
    )
    
  • raw_references — targets use "schema.table.column" format, passed through directly:

    PGCraftFK(
        raw_references={"{org_id}": "public.orgs.id"},
        name="fk_orders_org",
    )
    
Parameters:
  • references (dict[str, str]) – Mapping of {col} markers to dimension references (resolved via registry).

  • raw_references (dict[str, str]) – Mapping of {col} markers to literal schema.table.column references.

  • name (str) – Required constraint name — no auto-naming.

  • ondelete (str | None) – ON DELETE action (e.g. "CASCADE").

  • onupdate (str | None) – ON UPDATE action (e.g. "CASCADE").

Raises:

PGCraftValidationError – If both or neither of references and raw_references are provided.

column_names()[source]

Extract {name} markers from local column keys.

Return type:

list[str]

Returns:

Column names in order of first appearance, deduplicated.

resolve(mapping)[source]

Replace {col} markers in local column keys.

Parameters:

mapping (Callable[[str], str]) – A callable that maps column names to their resolved form.

Return type:

list[str]

Returns:

List of resolved column name strings.

resolve_references(metadata)[source]

Resolve target references to full FK strings.

If raw_references was used, returns values as-is. If references was used, resolves each via the dimension registry.

Parameters:

metadata (Any) – SQLAlchemy MetaData for registry lookup.

Return type:

list[str]

Returns:

List of fully qualified FK reference strings.

collect_fks(schema_items)[source]

Filter PGCraftFK instances from schema items.

Parameters:

schema_items (list) – Mixed list of schema items.

Return type:

list[PGCraftFK]

Returns:

Only the PGCraftFK items, in original order.

register_dimension(metadata, name, ref)[source]

Register a dimension for FK resolution.

Parameters:
  • metadata (MetaData) – SQLAlchemy MetaData instance.

  • name (str) – Dimension name (tablename).

  • ref (DimensionRef) – The dimension’s FK target info.

Return type:

None

resolve_fk_reference(metadata, reference)[source]

Resolve a "dimension.column" reference.

Looks up the dimension name in the registry and expands it to "schema.table.column".

Parameters:
  • metadata (MetaData) – SQLAlchemy MetaData for registry lookup.

  • reference (str) – Two-part "dimension.column" string.

Return type:

str

Returns:

Fully qualified "schema.table.column" string.

Raises:

PGCraftValidationError – If the reference does not contain exactly one dot, or names an unknown dimension.

Shared column-reference validation and marker helpers.

All pgcraft constraint types (PGCraftCheck, PGCraftIndex, PGCraftFK) use {column_name} markers. This module provides the regex, extraction, resolution, and validation helpers they share.

COLUMN_MARKER_RE = re.compile('\\{(\\w+)\\}')

Regex matching {column_name} markers in expressions.

extract_column_names(expression)[source]

Extract {name} markers from an expression.

Parameters:

expression (str) – String containing {column_name} markers.

Return type:

list[str]

Returns:

Column names in order of first appearance, deduplicated.

resolve_markers(expression, mapping)[source]

Replace each {col} marker with mapping(col).

Parameters:
  • expression (str) – String containing {column_name} markers.

  • mapping (Callable[[str], str]) – Callable that maps column names to their resolved form (e.g. identity for table-level, or lambda c: f"NEW.{c}" for triggers).

Return type:

str

Returns:

The expression with all markers replaced.

validate_column_references(label, columns, known_columns)[source]

Raise if any column is not in known_columns.

Shared by check, index, and foreign-key plugins to ensure that user-provided column names actually exist on the target table or view.

Parameters:
  • label (str) – Human-readable name for error messages (e.g. "PGCraftCheck 'pos_price'").

  • columns (list[str]) – Column names to validate.

  • known_columns (set[str]) – Set of known column names.

Raises:

PGCraftValidationError – If a column is not in known_columns.

Return type:

None

Statistics view support for pgcraft dimensions.

Provides PGCraftStatisticsView, a declarative statistics view definition that can be joined into the API view as read-only fields.

class JoinedView(view_name, join_key, column_names)[source]

A view to LEFT JOIN into the API view.

Produced by plugins (e.g. StatisticsViewPlugin) and consumed by PostgRESTPlugin when building the API view SQL.

Parameters:
  • view_name (str) – Fully qualified view name (e.g. "dim.customer_orders_statistics").

  • join_key (str) – Column name used for the JOIN condition.

  • column_names (list[str]) – Output column names to include in SELECT (excludes the join key).

class PGCraftStatisticsView(name, query, materialized=False, join_key=None, schema=None)[source]

A declarative statistics view definition.

The query is a SQLAlchemy Select whose selected columns define both the view body and the column names exposed through the API. The join key column (used to join back to the primary table) should be included in the query but is excluded from the API select list automatically.

The view is named {tablename}_{name}_statistics — pass just the source name (e.g. "orders"), not the full suffix.

Parameters:
  • name (str) – Source name for the statistics view. The view will be named {tablename}_{name}_statistics (e.g. "orders""customer_orders_statistics").

  • query (Select) – A SQLAlchemy select() expression.

  • materialized (bool) – Whether to create a materialized view.

  • join_key (str | None) – Column name used to join back to the primary table. Defaults to the PK column name at runtime.

  • schema (str | None) – PostgreSQL schema for the view. Defaults to the dimension’s schema at runtime.

Example:

from sqlalchemy import func, select

orders = Table("orders", metadata, ...)

PGCraftStatisticsView(
    name="orders",
    query=select(
        orders.c.customer_id,
        func.count().label("order_count"),
    ).group_by(orders.c.customer_id),
    join_key="customer_id",
)
property column_names: list[str]

Return all column names from the query.

Returns:

List of column names derived from the query’s selected columns.

property view_suffix: str

Return the view name suffix.

Returns:

"{name}_statistics" — appended to the tablename by the statistics plugin.

collect_statistics(schema_items)[source]

Filter PGCraftStatisticsView from a schema items list.

Parameters:

schema_items (list) – Mixed list of Column, PGCraftStatisticsView, and other schema items.

Return type:

list[PGCraftStatisticsView]

Returns:

Only the PGCraftStatisticsView items, in original order.

Cave exception types.

exception PGCraftValidationError[source]

Raised when a pgcraft validation check fails.

Schema item validators for dimension factories.

is_schema_item_not_primary_key(item)[source]

Return True if the item is not a primary key column.

Parameters:

item (SchemaItem | PGCraftCheck | PGCraftFK | PGCraftIndex) – The schema item to inspect.

Return type:

bool

Returns:

True if item is not a primary key column.

validate_schema_items(items, *, validators=None)[source]

Validate a list of SchemaItems against the given validators.

Parameters:
  • items (list) – Schema items to validate.

  • validators (list[_SchemaItemValidator] | None) – Validators to run; defaults to [is_schema_item_not_primary_key].

Raises:

PGCraftValidationError – If any item fails a validator.

Return type:

None

Decorator for applying pgcraft plugins to plain classes.

Table creation is fully deferred to pgcraft’s plugin pipeline — the decorated class does NOT inherit from a SQLAlchemy declarative base and no __table__ is created until plugins run.

After decoration the class is imperatively mapped so that select(User) and other ORM operations work normally.

register(*, base=None, metadata=None, schema=None, config=None, plugins=None, extra_plugins=None, api=None)[source]

Apply pgcraft plugins to a plain class and optionally ORM-map.

The class declares columns as plain Column attributes. pgcraft’s plugin pipeline handles table creation, PK generation, and any other registered work. After plugins run the class is imperatively mapped (when base is provided) so that select(cls) works.

Usage:

@register(
    base=Base,
    api={"grants": ["select", "insert", "update"]},
)
class User:
    __tablename__ = "users"
    __table_args__ = {"schema": "public"}

    name = Column(String)
    email = Column(String, nullable=True)

After decoration:

  • User.__table__ is the pgcraft-created table.

  • select(User) works (when base is given).

  • An API view with the specified grants is registered.

Parameters:
  • base (type[DeclarativeBase] | None) – A SQLAlchemy DeclarativeBase subclass. When provided, the class is imperatively mapped via base.registry and base.metadata is used as the target metadata.

  • metadata (MetaData | None) – Explicit MetaData instance. Required when base is not given. Ignored when base is provided.

  • schema (str | None) – PostgreSQL schema name. Overrides __table_args__["schema"] when given.

  • config (object | None) – Optional PGCraftConfig providing global plugins.

  • plugins (list[Plugin] | None) – Behaviour-modifying plugins (e.g. UUIDV4PKPlugin).

  • extra_plugins (list[Plugin] | None) – Appended to the resolved plugin list.

  • api (dict[str, Any] | None) – When provided, creates a PostgRESTView after table creation. Accepts keyword arguments forwarded to PostgRESTView (e.g. {"grants": ["select"]}).

Return type:

Callable[[type[TypeVar(T)]], type[TypeVar(T)]]

Returns:

A class decorator.

Raises:

PGCraftValidationError – If required attributes are missing or plugin validation fails.

Dimension resource factories

Simple dimension resource factory.

class PGCraftSimple(tablename, schemaname, metadata, schema_items, *, config=None, plugins=None, extra_plugins=None)[source]

Create a simple dimension: one table with optional checks.

Internal plugins (always present):

  1. SimpleTablePlugin – backing table.

  2. TableCheckPlugin – materializes PGCraftCheck items.

  3. TableIndexPlugin – materializes PGCraftIndex items.

  4. TableFKPlugin – materializes PGCraftFK items.

A SerialPKPlugin is auto-added when no user plugin produces pk_columns.

Use PostgRESTView to expose this table through a PostgREST API view with CRUD triggers.

Parameters:
TRIGGER_PLUGIN_CLS

alias of SimpleTriggerPlugin

Append-only dimension resource factory.

class PGCraftAppendOnly(tablename, schemaname, metadata, schema_items, *, config=None, plugins=None, extra_plugins=None)[source]

Create an append-only (SCD Type 2) dimension.

Internal plugins (always present):

  1. CreatedAtPlugincreated_at column name.

  2. AppendOnlyTablePlugin – root + attributes tables.

  3. AppendOnlyViewPlugin – join view proxy.

  4. TableCheckPlugin – materializes PGCraftCheck items.

  5. TableIndexPlugin – materializes PGCraftIndex items.

  6. TableFKPlugin – materializes PGCraftFK items.

A SerialPKPlugin is auto-added when no user plugin produces pk_columns.

Use PostgRESTView to expose this table through a PostgREST API view with CRUD triggers.

TRIGGER_PLUGIN_CLS

alias of AppendOnlyTriggerPlugin

EAV dimension resource factory.

class PGCraftEAV(tablename, schemaname, metadata, schema_items, *, config=None, plugins=None, extra_plugins=None)[source]

Create an EAV (Entity-Attribute-Value) dimension.

Internal plugins (always present):

  1. CreatedAtPlugincreated_at column name.

  2. EAVTablePlugin – entity + attribute tables.

  3. EAVViewPlugin – pivot view proxy.

  4. TriggerCheckPlugin – trigger-based checks on the pivot view.

A SerialPKPlugin is auto-added when no user plugin produces pk_columns.

Use PostgRESTView to expose this table through a PostgREST API view with CRUD triggers.

TRIGGER_PLUGIN_CLS

alias of EAVTriggerPlugin

Ledger resource factory

Ledger resource factory.

class PGCraftLedger(tablename, schemaname, metadata, schema_items, *, events=None, config=None, plugins=None, extra_plugins=None)[source]

Create a ledger: append-only table with a value column.

Internal plugins (always present):

  1. UUIDEntryIDPlugin – UUID entry ID for correlating related entries.

  2. CreatedAtPlugincreated_at column name.

  3. LedgerTablePlugin – backing table with value column.

A SerialPKPlugin is auto-added when no user plugin produces pk_columns.

Use PostgRESTView to expose this table through a PostgREST API view with INSERT triggers. Use BalanceView, LatestView, and LedgerActions for derived views and event functions.

Parameters:

events (list | None) – Deprecated. Use LedgerActions instead.

TRIGGER_PLUGIN_CLS

alias of LedgerTriggerPlugin

View factories

PostgREST extension for pgcraft.

class PostgRESTExtension(name='postgrest', schema='api')[source]

Wire PostgREST roles and grants into the pgcraft lifecycle.

When registered on a PGCraftConfig, this extension calls register_roles() during metadata configuration so that PostgREST roles and per-resource grants are emitted by Alembic autogenerate.

Without this extension, no roles or grants are registered.

Example:

from pgcraft.config import PGCraftConfig
from pgcraft.extensions.postgrest import (
    PostgRESTExtension,
    PostgRESTView,
)

config = PGCraftConfig()
config.use(PostgRESTExtension())
Parameters:
  • name (str) – Extension name. Defaults to "postgrest".

  • schema (str) – Default API schema name. Reserved for future use by API view plugins.

configure_metadata(metadata)[source]

Register PostgREST roles and grants on metadata.

Return type:

None

class PostgRESTPlugin(schema='api', grants=None, table_key='primary', view_key='api', columns=None, exclude_columns=None, joins_key='joins')[source]

Create a PostgREST-facing view and register its grants.

Reads ctx[table_key] to build a view query, registers the resulting view, stores it as ctx[view_key], and registers the API resource for role/grant generation.

Parameters:
  • schema (str) – Schema for the API view (default "api").

  • grants (list[Literal['select', 'insert', 'update', 'delete']] | None) – PostgREST privileges (default ["select"]).

  • table_key (str) – Key in ctx to read the source table or view proxy from (default "primary").

  • view_key (str) – Key in ctx to store the created view under (default "api").

  • columns (list[str] | None) – Column names to include in the view. Mutually exclusive with exclude_columns.

  • exclude_columns (list[str] | None) – Column names to exclude from the view. Mutually exclusive with columns.

  • joins_key (str) – Key in ctx holding a dict of JoinedView entries. LEFT JOINs each view into the API view when the key exists and is non-empty.

run(ctx)[source]

Create the API view and register the resource.

Return type:

None

class PostgRESTView(source, schema='api', grants=None, query=None, *, columns=None, exclude_columns=None)[source]

Create a PostgREST-facing view with auto-selected triggers.

Reads from a table factory’s context to create an API view and INSTEAD OF triggers. The trigger strategy is auto-selected based on the factory type (source.TRIGGER_PLUGIN_CLS).

Grants drive triggers: only operations listed in grants get INSTEAD OF triggers. "select"-only views have no triggers and are read-only.

Parameters:
  • source (ResourceFactory) – A ResourceFactory instance whose table/context to expose.

  • schema (str) – Schema for the API view (default "api").

  • grants (list[Literal['select', 'insert', 'update', 'delete']] | None) – PostgREST privileges (default ["select"]). Determines which INSTEAD OF triggers are created.

  • query (Callable[[Select, Table], Select] | None) – Optional callable (query, source_table) -> Select for SQLAlchemy-style view customization (joins, column filtering, etc.).

  • columns (list[str] | None) – Column names to include. Mutually exclusive with exclude_columns.

  • exclude_columns (list[str] | None) – Column names to exclude. Mutually exclusive with columns.

Generic view factories.

class PGCraftMaterializedView(name, schema, metadata, query)[source]

Create a materialized view with an auto-generated refresh.

After construction, self.table is a joinable SQLAlchemy Table whose columns mirror the query.

Parameters:
  • name (str) – View name.

  • schema (str) – PostgreSQL schema for the view.

  • metadata (MetaData) – SQLAlchemy MetaData to register on.

  • query (Select) – A SQLAlchemy Select defining the view body.

class PGCraftView(name, schema, metadata, query)[source]

Create a plain PostgreSQL view from a SQLAlchemy select.

After construction, self.table is a joinable SQLAlchemy Table whose columns mirror the query.

Parameters:
  • name (str) – View name.

  • schema (str) – PostgreSQL schema for the view.

  • metadata (MetaData) – SQLAlchemy MetaData to register on.

  • query (Select) – A SQLAlchemy Select defining the view body.

BalanceView: ledger balance aggregation view.

class BalanceView(source, dimensions)[source]

Create a view showing current balances per dimension group.

Generates SELECT dim_cols, SUM(value) AS balance FROM ledger GROUP BY dim_cols.

Parameters:
Raises:

PGCraftValidationError – If dimensions is empty.

LatestView: latest ledger entry per dimension group.

class LatestView(source, dimensions)[source]

Create a view showing the most recent row per dimension.

Uses DISTINCT ON ordered by created_at DESC.

Parameters:
Raises:

PGCraftValidationError – If dimensions is empty.

LedgerActions: generate PostgreSQL functions for ledger events.

class LedgerActions(source, events)[source]

Generate PostgreSQL functions for ledger events.

Each LedgerEvent becomes a PostgreSQL function that inserts rows into the ledger through the API view.

Parameters:

Ledger events

LedgerEvent configuration and helpers.

A LedgerEvent declares a named operation on a ledger. The user provides lambdas that produce SQLAlchemy selects; the plugin compiles them into a single PostgreSQL function per event.

Two modes are supported:

  • Simple mode (input only): the input select is inserted directly into the ledger via the API view.

  • Diff mode (input + desired + existing): the desired state is diffed against the existing state and only the correcting deltas are inserted.

class LedgerEvent(name, input, desired=None, existing=None, diff_keys=<factory>)[source]

Declare a named ledger operation.

Each event compiles into a single PostgreSQL function that inserts rows into the ledger API view and returns the inserted rows via RETURNING *.

Simple mode — provide only input. The input select’s columns are inserted directly.

Diff mode — provide input, desired, existing, and diff_keys. The desired and existing selects are unioned and only non-zero deltas are inserted.

Parameters:
class ParamCollector[source]

Collect SQL function parameters during lambda evaluation.

Usage inside an input lambda:

lambda p: select(
    p("warehouse", String).label("warehouse"),
    p("sku", String).label("sku"),
)

Each call to p(name, sa_type) records the parameter and returns a literal_column() reference (p_name) suitable for embedding in a select.

Parameters:

None.

property function_params: list[FunctionParam]

Build the FunctionParam list for function registration.

Returns:

List of FunctionParam.input(...) entries.

ledger_balances(*keys)[source]

Return an existing callable for common balance lookup.

Produces a select that negates the current balances for each diff-key group present in the desired CTE:

SELECT key1, key2, SUM(value) * -1 AS value
FROM ledger_table
WHERE (key1, key2) IN (SELECT key1, key2 FROM desired)
GROUP BY key1, key2
Parameters:

*keys (str) – Dimension column names to group by.

Return type:

Callable[[Table, FromClause], Select]

Returns:

A callable suitable for LedgerEvent(existing=...).

Plugin that generates PostgreSQL functions for ledger events.

class LedgerActionsPlugin(events, view_key='api')[source]

Generate PostgreSQL functions for ledger events.

Processes each LedgerEvent and registers a PostgreSQL function on ctx.metadata.

Must run after LedgerTablePlugin (needs "__root__") and PostgRESTPlugin (needs the API view key).

Parameters:
Raises:

PGCraftValidationError – At run time if any event fails validation against the ledger schema.

run(ctx)[source]

Validate events and generate SQL functions.

Parameters:

ctx (FactoryContext) – The factory context.

Return type:

None

Built-in plugins

Primary key plugins.

class SerialPKPlugin(column_name='id')[source]

Provide an auto-increment integer primary key column.

Parameters:

column_name (str) – Name of the PK column (default "id").

run(ctx)[source]

Store a PrimaryKeyColumns in the ctx store.

Return type:

None

class UUIDV4PKPlugin(column_name='id')[source]

Provide a UUIDv4 primary key column.

Uses PostgreSQL’s gen_random_uuid() as the server default so rows get a unique identifier without client-side generation.

Parameters:

column_name (str) – Name of the PK column (default "id").

run(ctx)[source]

Store a PrimaryKeyColumns in the ctx store.

Return type:

None

class UUIDV7PKPlugin(column_name='id')[source]

Provide a UUIDv7 primary key column.

Uses PostgreSQL 18’s uuidv7() as the server default to generate time-ordered UUIDs. These sort chronologically, making them friendlier to B-tree indexes than random UUIDv4 values.

Requires PostgreSQL 18 or later (declared via @requires(MinPGVersion(18))). Use check_pg_version() to validate the server version before applying DDL.

Parameters:

column_name (str) – Name of the PK column (default "id").

run(ctx)[source]

Store a PrimaryKeyColumns in the ctx store.

Return type:

None

Plugin that provides a created_at timestamp column name.

class CreatedAtPlugin(column_name='created_at')[source]

Provide the created_at column name for table plugins.

Stores the column name as a string in ctx["created_at_column"]. Each table plugin that needs a created_at column is responsible for constructing it from this name (see AppendOnlyTablePlugin, EAVTablePlugin, LedgerTablePlugin).

Parameters:

column_name (str) – Name of the timestamp column (default "created_at").

run(ctx)[source]

Store the column name in ctx.

Return type:

None

Entry ID plugin for correlating related ledger entries.

class UUIDEntryIDPlugin(column_name='entry_id')[source]

Provide a UUIDv4 entry ID column for ledger tables.

Stores a Column in ctx["entry_id_column"] that downstream table plugins (e.g. LedgerTablePlugin) splice into the table definition. The column uses PostgreSQL’s gen_random_uuid() as a server default so callers can omit it for single-entry inserts while still providing an explicit value to correlate multi-row entries.

Parameters:

column_name (str) – Name of the entry ID column (default "entry_id").

run(ctx)[source]

Store the entry ID column and inject it.

Return type:

None

Plugins for simple (single-table) dimensions.

class SimpleTablePlugin(table_key='primary')[source]

Create a single backing table for a simple dimension.

Combines ctx["pk_columns"] and ctx.schema_items into one table.

Parameters:

table_key (str) – Key under which the created table is stored in ctx (default "primary").

run(ctx)[source]

Create the dimension table and store it in ctx.

Return type:

None

class SimpleTriggerPlugin(table_key='primary', view_key='api', columns=None, permitted_operations=None)[source]

Register INSERT/UPDATE/DELETE INSTEAD OF triggers on a view.

Parameters:
  • table_key (str) – Key in ctx for the backing table (default "primary").

  • view_key (str) – Key in ctx for the trigger target view (default "api").

run(ctx)[source]

Register INSTEAD OF triggers on the target view.

Return type:

None

Plugins for append-only (SCD Type 2) dimensions.

class AppendOnlyTablePlugin(root_key='root_table', attributes_key='attributes')[source]

Create the root and attributes tables for an append-only dim.

Parameters:
  • root_key (str) – Key in ctx for the entity root table (default "root_table").

  • attributes_key (str) – Key in ctx for the append-only attributes log (default "attributes").

run(ctx)[source]

Create root and attributes tables.

Return type:

None

class AppendOnlyTriggerPlugin(root_key='root_table', attributes_key='attributes', view_key='api', columns=None)[source]

Register INSTEAD OF triggers for an append-only dimension.

Registers identical trigger logic on the private join view and, if present, the view stored at view_key.

Parameters:
  • root_key (str) – Key in ctx for the entity root table (default "root_table").

  • attributes_key (str) – Key in ctx for the attributes log (default "attributes").

  • view_key (str) – Key in ctx for the additional trigger target, e.g. the API view (default "api"). If the key is absent from ctx no second trigger is registered.

run(ctx)[source]

Register INSTEAD OF triggers on join and API views.

Return type:

None

class AppendOnlyViewPlugin(root_key='root_table', attributes_key='attributes', primary_key='primary')[source]

Create the join view for an append-only dimension.

Parameters:
  • root_key (str) – Key in ctx for the entity root table (default "root_table").

  • attributes_key (str) – Key in ctx for the attributes log (default "attributes").

  • primary_key (str) – Key in ctx to store the view proxy under, for downstream plugins such as PostgRESTPlugin (default "primary").

run(ctx)[source]

Register the join view and store the proxy in ctx.

Return type:

None

Check constraint plugins for pgcraft dimensions.

TableCheckPlugin converts PGCraftCheck items into real SQLAlchemy CheckConstraint objects on a table (for simple and append-only dimensions).

TriggerCheckPlugin generates INSTEAD OF trigger functions that enforce checks before the main dimension triggers (for EAV dimensions where columns are virtual).

class TableCheckPlugin(table_key='primary')[source]

Materialize PGCraftCheck as table constraints.

Reads PGCraftCheck items from ctx.schema_items, resolves {col} markers to plain column names (identity), and appends real CheckConstraint objects to the target table.

Parameters:

table_key (str) – Key in ctx for the target table (default "primary").

class TriggerCheckPlugin(table_key='primary')[source]

Enforce checks via INSTEAD OF triggers (EAV dimensions).

Generates a single trigger function per view per operation (INSERT/UPDATE) that validates all PGCraftCheck items. Triggers use a _check_ prefix to fire before the main dimension triggers (Postgres fires multiple INSTEAD OF triggers in alphabetical order by name).

Parameters:

table_key (str) – Key in ctx for the trigger target view (default "primary").

Index plugin for pgcraft dimensions.

TableIndexPlugin converts PGCraftIndex items into real SQLAlchemy Index objects on a table.

class TableIndexPlugin(table_key='primary')[source]

Materialize PGCraftIndex as table indexes.

Reads PGCraftIndex items from ctx.schema_items, validates column names, and creates Index objects on the target table. Extra keyword arguments on each PGCraftIndex are passed through to the underlying sqlalchemy.Index.

Parameters:

table_key (str) – Key in ctx for the target table (default "primary").

run(ctx)[source]

Collect, validate, and create indexes.

Return type:

None

Foreign key plugin for pgcraft dimensions.

TableFKPlugin converts PGCraftFK items into real SQLAlchemy ForeignKeyConstraint objects on a table. Two-part references ("dimension.column") are resolved via the dimension registry in metadata.info.

class TableFKPlugin(table_key='primary')[source]

Materialize PGCraftFK as FK constraints.

Reads PGCraftFK items from ctx.schema_items, validates local column names, resolves references via the dimension registry, and creates ForeignKeyConstraint objects on the target table.

Parameters:

table_key (str) – Key in ctx for the target table (default "primary").

run(ctx)[source]

Collect, validate, and create foreign key constraints.

Return type:

None

Plugins for EAV (Entity-Attribute-Value) dimensions.

class EAVTablePlugin(entity_key='entity', attribute_key='attribute', mappings_key='eav_mappings')[source]

Create entity and attribute tables for an EAV dimension.

Parameters:
  • entity_key (str) – Key in ctx for the entity root table (default "entity").

  • attribute_key (str) – Key in ctx for the attribute log (default "attribute").

  • mappings_key (str) – Key in ctx for the EAV mappings list, shared with the view and trigger plugins (default "eav_mappings").

run(ctx)[source]

Create entity and attribute tables.

Return type:

None

class EAVTriggerPlugin(entity_key='entity', attribute_key='attribute', mappings_key='eav_mappings', view_key='api')[source]

Register INSTEAD OF triggers for an EAV dimension.

Registers on the private pivot view and, if present, the view at view_key.

Parameters:
  • entity_key (str) – Key in ctx for the entity root table (default "entity").

  • attribute_key (str) – Key in ctx for the attribute log (default "attribute").

  • mappings_key (str) – Key in ctx for the EAV mappings list (default "eav_mappings").

  • view_key (str) – Key in ctx for the additional trigger target (default "api"). Skipped if absent.

run(ctx)[source]

Register INSTEAD OF triggers on pivot and API views.

Return type:

None

class EAVViewPlugin(entity_key='entity', attribute_key='attribute', mappings_key='eav_mappings', primary_key='primary')[source]

Create the pivot view for an EAV dimension.

Parameters:
  • entity_key (str) – Key in ctx for the entity root table (default "entity").

  • attribute_key (str) – Key in ctx for the attribute log (default "attribute").

  • mappings_key (str) – Key in ctx for the EAV mappings list (default "eav_mappings").

  • primary_key (str) – Key in ctx to store the view proxy under (default "primary").

run(ctx)[source]

Register the pivot view and store the proxy in ctx.

Return type:

None

Plugins for ledger (append-only value) tables.

class DoubleEntryPlugin(column_name='direction')[source]

Add debit/credit semantics to a ledger table.

Adds a direction column ('debit' or 'credit') to the schema items so that LedgerTablePlugin includes it in the table. Also registers an AFTER INSERT constraint trigger that validates all rows sharing an entry_id have equal total debits and credits.

This plugin must appear before LedgerTablePlugin in the plugin list so its column is included in the table definition.

Parameters:

column_name (str) – Name of the direction column (default "direction").

run(ctx)[source]

Inject the direction column and store its name.

Return type:

None

class DoubleEntryTriggerPlugin(table_key='primary')[source]

Register an AFTER INSERT trigger enforcing balanced entries.

Validates that for every entry_id in the inserted batch, the sum of debit values equals the sum of credit values. Raises a PostgreSQL exception if any entry is unbalanced.

Uses a statement-level trigger with a REFERENCING NEW TABLE transition table so that multi-row inserts are checked as a whole, not row-by-row.

Must run after LedgerTablePlugin (needs the table) and after DoubleEntryPlugin (needs column name).

Parameters:

table_key (str) – Key in ctx for the backing table (default "primary").

run(ctx)[source]

Register the constraint trigger on the ledger table.

Return type:

None

class LedgerBalanceCheckPlugin(dimensions, min_balance=0, table_key='primary')[source]

Enforce a minimum balance per dimension group.

Registers an AFTER INSERT FOR EACH STATEMENT trigger that checks SUM(value) >= min_balance for every dimension group affected by the inserted rows. If any group violates the constraint the entire statement is rejected.

Uses the same REFERENCING NEW TABLE transition-table pattern as DoubleEntryTriggerPlugin.

Parameters:
  • dimensions (list[str]) – Column names that define a balance group. Must be a non-empty list.

  • min_balance (int) – The minimum allowed SUM(value) per group (default 0).

  • table_key (str) – Key in ctx for the backing table (default "primary").

Raises:

PGCraftValidationError – If dimensions is empty.

run(ctx)[source]

Register the balance-check trigger.

Return type:

None

class LedgerBalanceViewPlugin(dimensions, table_key='primary', balance_view_key='balance_view')[source]

Create a view that shows current balances per dimension group.

Generates SELECT dim_cols, SUM(value) AS balance FROM ledger GROUP BY dim_cols and registers it as a view.

Parameters:
  • dimensions (list[str]) – Column names to group by. Must be a non-empty list of column names present on the ledger table.

  • table_key (str) – Key in ctx for the backing table (default "primary").

  • balance_view_key (str) – Key in ctx to store the balance view name under (default "balance_view").

Raises:

PGCraftValidationError – If dimensions is empty.

class LedgerLatestViewPlugin(dimensions, table_key='primary', latest_view_key='latest_view')[source]

Create a view showing the most recent row per dimension group.

Uses PostgreSQL DISTINCT ON to select the latest row (by created_at) for each unique combination of dimension values. Useful for status-tracking ledgers where you care about current state, not historical sums.

Parameters:
  • dimensions (list[str]) – Column names to partition by. Must be a non-empty list of column names present on the ledger table.

  • table_key (str) – Key in ctx for the backing table (default "primary").

  • latest_view_key (str) – Key in ctx to store the view name under (default "latest_view").

Raises:

PGCraftValidationError – If dimensions is empty.

class LedgerTablePlugin(value_type='integer', table_key='primary')[source]

Create a ledger table with a value column.

Combines ctx["pk_columns"], ctx.injected_columns (provided by upstream plugins like UUIDEntryIDPlugin, CreatedAtPlugin, and DoubleEntryPlugin), a value column, and ctx.table_items (dimension columns) into a single append-only table.

Parameters:
  • value_type (str) – Type for the value column. Must be "integer" or "numeric" (default "integer").

  • table_key (str) – Key under which the created table is stored in ctx (default "primary").

Raises:

PGCraftValidationError – If value_type is not a recognised type.

run(ctx)[source]

Create the ledger table and store it in ctx.

Return type:

None

class LedgerTriggerPlugin(table_key='primary', view_key='api')[source]

Register an INSERT INSTEAD OF trigger on a ledger view.

Only INSERT is supported – ledger entries are immutable. UPDATE and DELETE on the API view will raise a PostgreSQL error naturally (no INSTEAD OF trigger defined).

Parameters:
  • table_key (str) – Key in ctx for the backing table (default "primary").

  • view_key (str) – Key in ctx for the trigger target view (default "api").

run(ctx)[source]

Register INSTEAD OF triggers on the API view.

Registers INSERT (routes to backing table), UPDATE (raises error), and DELETE (raises error) triggers to enforce append-only semantics.

Return type:

None

Statistics view plugin: creates views from PGCraftStatisticsView.

class StatisticsViewPlugin(joins_key='joins', table_key='primary')[source]

Create statistics views from PGCraftStatisticsView items.

For each PGCraftStatisticsView in ctx.schema_items, creates a view (or materialized view) and stores a JoinedView entry in ctx[joins_key] for the API plugin to LEFT JOIN.

Parameters:
  • joins_key (str) – Key to store the joined view info dict under (default "joins").

  • table_key (str) – Key in ctx for the source table (default "primary").

run(ctx)[source]

Create statistics views and store join info.

Return type:

None

Plugin that prevents direct DML on raw backing tables.

Direct INSERT/UPDATE/DELETE on raw backing tables bypasses the INSTEAD OF triggers on the API views, which can corrupt dimension state (e.g. breaking SCD Type 2 history in append-only dimensions, leaving orphaned EAV rows).

RawTableProtectionPlugin installs BEFORE triggers on every raw table it is given. The triggers raise an exception if called outside a trigger context (pg_trigger_depth() = 0), forcing all mutations to go through the API view. When a mutation arrives via the API view, the INSTEAD OF trigger fires first (pg_trigger_depth() = 1), so the protection triggers see depth > 0 and allow the operation.

class RawTableProtectionPlugin(*table_keys)[source]

Prevent direct DML on raw backing tables.

Installs BEFORE INSERT/UPDATE/DELETE triggers on every raw table specified by table_keys. The triggers raise an exception when called at trigger depth 0 (i.e. directly, not from within another trigger), so mutations must go through the API view.

All mutations through the API view arrive via an INSTEAD OF trigger at depth >= 1, which the protection triggers allow through.

Parameters:

*table_keys (str) – One or more ctx keys whose values are the raw Table objects to protect.

Example:

RawTableProtectionPlugin("root_table", "attributes")
resolved_requires()[source]

Return the ctx keys this plugin reads.

Overrides the base implementation so that the topological sort correctly places this plugin after all table-creating plugins.

Return type:

list[str]

run(ctx)[source]

Register protection triggers on each raw backing table.

Return type:

None

Alembic integration

pgcraft_alembic_hook(config=None)[source]

Register pgcraft’s alembic extensions.

Call before importing models.

Usage in env.py:

from pgcraft.alembic.register import (
    pgcraft_alembic_hook,
    pgcraft_configure_metadata,
    pgcraft_process_revision_directives,
)

pgcraft_alembic_hook()

# ... import models / build metadata ...

pgcraft_configure_metadata(target_metadata)

Then pass pgcraft_process_revision_directives to context.configure(process_revision_directives=...).

Parameters:

config (PGCraftConfig | None) – Optional config providing extensions whose configure_alembic() hooks will be called.

Return type:

None

pgcraft_configure_metadata(metadata, config=None)[source]

Register schemas and extension hooks on metadata.

Roles and grants are no longer registered automatically. Register PostgRESTExtension on your config to enable PostgREST roles.

Parameters:
  • metadata (MetaData) – The SQLAlchemy MetaData to configure.

  • config (PGCraftConfig | None) – Optional config providing extensions. If None, falls back to metadata.info["pgcraft_config"].

Return type:

None

class EntityIdentifier(schema='public', name=None, phase=None)[source]

Identifies a database entity within a migration’s dependency graph.

name is None for schema-level entities (i.e. the entity is the schema). For tables, views, and functions, name holds the unqualified object name and schema holds its containing schema.

phase distinguishes drop and create ops for the same entity when an Update*Op has been expanded. "drop" ops are ordered before "create" ops for the same entity.

build_fk_graph_from_metadata(metadata)[source]

Build a table FK dependency map from SQLAlchemy metadata.

Uses the metadata’s knowledge of foreign key relationships rather than parsing column objects from migration ops.

Return type:

dict[tuple[str, str], set[tuple[str, str]]]

expand_update_ops(migration_ops)[source]

Split Update*Op into Drop*Op + Create*Op.

CREATE OR REPLACE VIEW fails when another view that depends on this one has an incompatible column list. Splitting into separate drop/create operations lets the topological sort interleave them correctly: drop dependents first, then drop and recreate dependencies, then recreate dependents.

Return type:

list[MigrateOperation | MigrateOp]

sort_migration_ops(migration_ops, *, fk_graph=None)[source]

Return migration_ops topologically sorted by entity dependencies.

Dependency edges are derived from the ops themselves:

  • A table depends on its schema.

  • A table depends on tables it references via foreign keys.

  • A replaceable entity (view, function, …) depends on its schema and on every schema-qualified table or view referenced in its SQL definition.

Only dependencies between ops in the current migration produce edges; references to already-existing objects are ignored.

Edge direction is determined per-op by phase: drop-phase ops reverse their edges (dependents dropped first), create-phase ops use normal direction (dependencies created first).

Parameters:
Return type:

list[MigrateOperation | MigrateOp]

Returns:

A new list containing the same ops in dependency order.

Automatic schema discovery for alembic autogenerate.

Scans a MetaData instance for schemas referenced by tables and views, then registers them with sqlalchemy-declarative-extensions so its built-in schema comparator emits the appropriate CREATE SCHEMA / DROP SCHEMA ops.

collect_schemas(metadata)[source]

Return non-system schema names referenced by tables and views.

Return type:

set[str]

register_schemas(metadata)[source]

Populate metadata.info["schemas"] from tables and views.

Merges with any schemas already registered on the metadata. Safe to call multiple times — existing entries are preserved.

Return type:

None

Custom alembic renderers that format SQL with pglast.

register_renderers()[source]

Override the library’s renderers with pglast-formatted versions.

Return type:

None

PostgREST / API

API resource registration for PostgREST grant generation.

class APIResource(name, schema='api', grants=<factory>)[source]

A database object exposed via PostgREST.

property qualified_name: str

Return the schema-qualified name.

get_api_resources(metadata)[source]

Return all registered API resources.

Return type:

list[APIResource]

register_api_resource(metadata, resource)[source]

Register an API resource on metadata.

Return type:

None

PostgREST role and grant declarations.

register_roles(metadata)[source]

Register PostgREST roles and grants on metadata.

Reads APIResource objects from the metadata and generates per-resource grants.

Return type:

None