Naming conventions

pgcraft generates database objects automatically — tables, views, functions, and triggers — and uses a naming convention system to derive their names deterministically. Conventions are stored in the SQLAlchemy MetaData naming_convention dict, giving you one place to control every generated name in your schema.

This builds directly on SQLAlchemy’s built-in constraint naming conventions feature. If you are not already familiar with it, read that guide first — pgcraft extends the same mechanism rather than inventing a parallel system.

Setting up naming conventions

Pass pgcraft_build_naming_conventions() to your MetaData when you create it:

from sqlalchemy import MetaData
from pgcraft import pgcraft_build_naming_conventions

metadata = MetaData(naming_convention=pgcraft_build_naming_conventions())

This populates the standard SQLAlchemy constraint keys (pk, fk, uq, ix, ck) with length-safe token callables, and also seeds the pgcraft-specific keys that plugins use for views, functions, and triggers. Without it, SQLAlchemy leaves constraint names as None and Alembic autogenerate cannot track them reliably.

The max_length parameter (default 63) controls the maximum character length of generated constraint names. PostgreSQL’s identifier limit is 63 bytes, so the default matches that. Names that would exceed this limit are truncated and an 8-character MD5 digest is appended to avoid collisions:

metadata = MetaData(naming_convention=pgcraft_build_naming_conventions(max_length=63))

Overriding a specific convention

Every naming convention key is just a string in the naming_convention dict. Set it after calling pgcraft_build_naming_conventions() to override only that key while keeping all others:

metadata = MetaData(naming_convention=pgcraft_build_naming_conventions())

# Give the "prices" append-only dimension custom table names.
metadata.naming_convention["append_only_root"] = "%(table_name)s_ids"
metadata.naming_convention["append_only_attributes"] = "%(table_name)s_log"

Overrides are global — they apply to every factory that uses that key. To target a specific dimension only, embed the table name directly in the template:

# Only renames the root table for "prices"; other dimensions are unaffected.
metadata.naming_convention["append_only_root"] = "price_ids"

Templates use Python %-style interpolation. The available substitution variables for each key are listed in the reference below.

Convention reference

Constraint names

These keys are provided by pgcraft_build_naming_conventions() and govern how SQLAlchemy names database constraints and indexes. They follow the same %(token)s interpolation format described in the SQLAlchemy constraint naming conventions guide.

Key

Default template

Example output

pk

%(pk_name)s

pk__products__id

fk

%(fk_name)s

fk__orders__product_id__products

uq

%(uq_name)s

uq__products__sku

ix

%(ix_name)s

ix__products__name

ck

%(ck_name)s

ck__orders__status

The name tokens (pk_name, fk_name, etc.) are callable objects that build the full name from the table and column names. SQLAlchemy’s naming convention system supports both string templates and callables as values — the callables here are an example of that. You should not override them directly; override the corresponding template key (pk, fk, etc.) instead if you need a different format.

Simple dimension

Used by SimpleTriggerPlugin when creating INSTEAD OF triggers on the API view.

Available substitutions: %(table_name)s, %(schema)s, %(op)s (insert, update, or delete).

Key

Default template

Names

simple_function

%(schema)s_%(table_name)s_%(op)s

INSTEAD OF trigger function

simple_trigger

%(schema)s_%(table_name)s_%(op)s

INSTEAD OF trigger

Append-only dimension

Used by AppendOnlyTablePlugin for the two backing tables, and by AppendOnlyTriggerPlugin for INSTEAD OF triggers on the API view.

Available substitutions: %(table_name)s, %(schema)s, %(op)s.

Key

Default template

Names

append_only_root

%(table_name)s_root

Entity (root) table

append_only_attributes

%(table_name)s_attributes

Attributes log table

append_only_function

%(schema)s_%(table_name)s_%(op)s

INSTEAD OF trigger function

append_only_trigger

%(schema)s_%(table_name)s_%(op)s

INSTEAD OF trigger

EAV dimension

Used by EAVTablePlugin for the two backing tables, and by EAVTriggerPlugin for INSTEAD OF triggers on the API view.

Available substitutions: %(table_name)s, %(schema)s, %(op)s.

Key

Default template

Names

eav_entity

%(table_name)s_entity

Entity (root) table

eav_attribute

%(table_name)s_attribute

Attribute log table

eav_function

%(schema)s_%(table_name)s_%(op)s

INSTEAD OF trigger function

eav_trigger

%(schema)s_%(table_name)s_%(op)s

INSTEAD OF trigger

Check plugin

Used by TriggerCheckPlugin when adding validation triggers to EAV dimensions.

Available substitutions: %(table_name)s, %(schema)s, %(op)s.

Key

Default template

Names

check_function

_check_%(schema)s_%(table_name)s_%(op)s

Validation trigger function

check_trigger

_check_%(schema)s_%(table_name)s_%(op)s

Validation trigger

Ledger

Used by the ledger factory plugins. See Ledger tables for full documentation of each plugin.

Available substitutions: %(table_name)s, %(schema)s, %(op)s.

Key

Default template

Names

ledger_function

%(schema)s_%(table_name)s_%(op)s

INSTEAD OF trigger function

ledger_trigger

%(schema)s_%(table_name)s_%(op)s

INSTEAD OF trigger

ledger_balance_view

%(table_name)s_balances

Balance summary view

ledger_latest_view

%(table_name)s_latest

Latest-row view (DISTINCT ON)

balance_check_function

%(schema)s_%(table_name)s_%(op)s

Balance enforcement trigger function

balance_check_trigger

%(schema)s_%(table_name)s_%(op)s

Balance enforcement trigger

double_entry_function

%(schema)s_%(table_name)s_%(op)s

Double-entry validation trigger function

double_entry_trigger

%(schema)s_%(table_name)s_%(op)s

Double-entry validation trigger