Composite Domains¶
Generate data across multiple domains with shared entities and cross-domain FK relationships. For example, generate Retail + HR + Financial data where employees are also customers and stores have locations linked to branches.
Quick Start¶
from sqllocks_spindle import Spindle, RetailDomain, HrDomain, FinancialDomain
from sqllocks_spindle.domains.composite import CompositeDomain
composite = CompositeDomain(
domains=[RetailDomain(), HrDomain(), FinancialDomain()],
shared_entities={
"person": {
"primary": "hr.employee",
"links": {
"retail": "customer.employee_id",
"financial": "account.holder_id",
},
},
},
)
result = Spindle().generate(domain=composite, scale="small", seed=42)
# Tables are prefixed with domain name to avoid collisions
print(result.table_names)
# ['hr_employee', 'hr_department', ..., 'retail_customer', 'retail_order', ..., 'financial_account', ...]
How It Works¶
- Schema merging — all domain schemas are combined into a single
SpindleSchema - Table prefixing — each table gets a
<domain>_prefix to avoid name collisions - Shared entity resolution — the
SharedEntityRegistrymaps cross-domain concepts (PERSON, LOCATION, ORGANIZATION, CALENDAR) to specific tables - Cross-domain FK rewiring — FK relationships are created between shared entities across domains
- Dependency-ordered generation — tables are generated in topological order respecting cross-domain FKs
SharedEntityRegistry¶
The built-in registry has default mappings for all 13 domains:
from sqllocks_spindle.domains.shared_registry import SharedEntityRegistry, SharedConcept
registry = SharedEntityRegistry()
# What domains have a PERSON concept?
domains = registry.get_domains_for_concept(SharedConcept.PERSON)
# ['retail', 'healthcare', 'financial', 'hr', 'insurance', ...]
# What table maps to PERSON in retail?
mapping = registry.get_mapping_for_domain(SharedConcept.PERSON, "retail")
# DomainEntityMapping(domain='retail', table='customer', pk_column='customer_id', ...)
Shared Concepts¶
| Concept | Description | Example Tables |
|---|---|---|
PERSON |
People/individuals | customer, patient, employee, policyholder |
LOCATION |
Physical locations | address, facility, store, warehouse |
ORGANIZATION |
Companies/departments | department, branch, supplier |
CALENDAR |
Time dimensions | (used for shared date ranges) |
Custom Shared Entities¶
Override the default registry with custom mappings:
composite = CompositeDomain(
domains=[RetailDomain(), HrDomain()],
shared_entities={
"person": {
"primary": "hr.employee", # HR employees are the canonical people
"links": {
"retail": "customer.employee_id", # retail customers link to employees
},
},
},
)
The primary entity is generated first. Linked entities get FK references to the primary's PK.
See Also¶
- Tutorial: 09: Composite Domains — step-by-step walkthrough
- Example script:
17_composite_domain.py - Notebook:
T16_composite_domains.ipynb - Notebook:
F09_cross_domain_enterprise.ipynb