Loadable Table Mixins¶
Infrastructure for staged, file-based ingestion into ORM tables.
Supports:
- staged file loading into backend-specific staging tables
- bulk staging sinks per backend: PostgreSQL COPY, DuckDB insert from Arrow, SQLite executemany
- backend-aware merge strategies
- Arrow-based file readers (delimited text and Parquet)
- index handling during merge
FileLoadableTableInterface¶
Bases: ORMTableBase
Mixin for ORM tables that load from files through a staging table.
A file is read in batches by a reader, converted under a conversion policy, written to a staging table by the backend's bulk sink, and merged into the target table. It supports: - dialect-aware staging table creation - delimited text and Parquet files, and other formats through readers - configurable merge strategies - explicit staging table lifecycle management
The class is designed for controlled ingestion pipelines and does not attempt to provide concurrency guarantees.
load_file(session, path, *, reader=None, normalise=True, dedupe=False, chunksize=None, merge_strategy='replace', quote_mode=None, index_strategy='auto', merge_batch_size=None, staging_schema_tag=None, validate_deferred_fks=True, resolved=None, physical_schemas=None, policy=None, rejects_dir=None, report=None)
classmethod
¶
Load a file into the target table.
The file name without its suffix must equal the table name. This method orchestrates the full staged ingestion lifecycle: - staging table creation - file loading - merge into the target table - staging table cleanup
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
session
|
Session
|
An active SQLAlchemy session. |
required |
path
|
Path
|
Path to the input file. |
required |
reader
|
FileReader | None
|
Reader for the file. |
None
|
normalise
|
bool
|
Whether to convert values to the column types under the policy. When false, values are written as read. |
True
|
dedupe
|
bool
|
Whether to deduplicate incoming rows. |
False
|
chunksize
|
int | None
|
Rows per batch for the default reader of formats that batch by rows. |
None
|
merge_strategy
|
str
|
Merge strategy to apply (e.g. |
'replace'
|
quote_mode
|
str | None
|
How double quotes in delimited text are read: |
None
|
index_strategy
|
str
|
Index handling strategy during merge. Use |
'auto'
|
merge_batch_size
|
int | None
|
Rows per merge batch, or |
None
|
staging_schema_tag
|
str | None
|
schema_translate_map tag the staging table lives in. |
None
|
validate_deferred_fks
|
bool
|
After merging, run an anti-join check for any FK this backend's
DB can't enforce itself (see DatabaseBackend.validate_deferred_fks()).
Also run before every intermediate commit a batched merge makes,
so a violation is caught before that batch commits rather than
only after the whole load, when an earlier batch's commit can
no longer be rolled back. Every other key is verified by
|
True
|
resolved
|
ResolvedDatabase | None
|
Topology this table's engine(s) were resolved from. Required on
DuckDB whenever table_cls has any foreign key at all, to
classify each as enforced or omitted via oa-configurator's
|
None
|
physical_schemas
|
Mapping[str, str | None] | None
|
A schema tag's physical name beyond resolved's own configured ones. Forwarded alongside resolved. |
None
|
policy
|
ConversionPolicy | None
|
How values are interpreted and what happens to unreadable ones. The default policy preserves nonempty text and treats only empty values as missing in text columns. |
None
|
rejects_dir
|
Path | None
|
Directory that rejected rows are written to when the policy sets
|
None
|
report
|
LoadReport | None
|
Receives the load's row accounting. A new report is used when omitted. |
None
|
Returns:
| Type | Description |
|---|---|
int
|
Number of rows loaded into staging before merge. |
manage_indices(session, index_strategy='auto', *, backend)
classmethod
¶
Manage non-primary-key indexes around a staged merge.
index_strategy may be "auto", "drop_rebuild", or
"keep". The backend decides what "auto" means. At the
moment SQLite keeps indexes by default, while PostgreSQL drops
and rebuilds them.
Raises:
| Type | Description |
|---|---|
IngestError
|
An index could not be rebuilt after a merge that was committed. |
merge_from_staging(session, merge_strategy='replace', *, backend, staging, merge_batch_size=None, validate_deferred_fks=True)
classmethod
¶
Merge data from the staging table into the target table.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
session
|
Session
|
An active SQLAlchemy session. |
required |
merge_strategy
|
str
|
Merge strategy to apply (for example |
'replace'
|
backend
|
DatabaseBackend
|
Backend of the session's database. |
required |
staging
|
Table
|
Staging table the rows are merged from. |
required |
merge_batch_size
|
int | None
|
Rows per merge batch, or |
None
|
validate_deferred_fks
|
bool
|
Forwarded to the backend's merge methods, which validate
deferred FKs before every intermediate commit a batched merge
makes. See |
True
|
validate_foreign_keys(session, *, staging_schema_tag=None, resolved=None, physical_schemas=None)
classmethod
¶
Raise if any row references a row that does not exist.
Loads relax foreign keys during the merge on PostgreSQL and SQLite, so a row loaded before the row it references is accepted. Call this once every table is loaded to verify referential integrity, whatever the load order. DuckDB enforces most of its keys itself, so only the keys it cannot enforce are checked.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
session
|
Session
|
An active SQLAlchemy session. |
required |
staging_schema_tag
|
str | None
|
schema_translate_map tag used to resolve the backend, as in
|
None
|
resolved
|
ResolvedDatabase | None
|
Topology this table's engine(s) were resolved from. Required on DuckDB for a table with foreign keys. |
None
|
physical_schemas
|
Mapping[str, str | None] | None
|
A schema tag's physical name beyond resolved's own configured ones. |
None
|
Raises:
| Type | Description |
|---|---|
ForeignKeyViolationError
|
A non-null reference has no matching row in the referred table. |