Data Generation
Relationships and Integrity
Foreign keys, one-to-one, unique and composite keys, and parent-first insert order.
Relationships and Integrity
Generated data is built to insert into your real database without constraint errors. This page explains how foreign keys, unique constraints and insert order are handled.
Where Relationships Come From
Relationships are collected, in order of trust, from:
- Foreign keys declared in your schema, both inline (
REFERENCES orders(id)) and inALTER TABLE … ADD CONSTRAINT … FOREIGN KEYstatements, as written bypg_dumpand MySQL dumps. - Relationships you add in the Relationships panel or through the Data Assistant, for application-level foreign keys the database never declares.
- AI detection, only when the schema declares no foreign keys at all.
Foreign keys are always checked against your original SQL. Any that the SQL doesn't declare are discarded, and so is any column that references itself (for example orders.id → orders.id).
Foreign Keys
Every foreign key column takes its values from the parent table's generated rows, never from made-up ids.
- Parent tables are always generated before the tables that reference them.
- If a parent table isn't selected for generation:
- a nullable foreign key is left
NULL; - a required foreign key stops generation with a clear error, for example "order_items.order_id references orders, which is not selected for generation".
- a nullable foreign key is left
- Two tables that require each other (circular foreign keys) also stop with an error. Make one side nullable or remove one relationship.
- A table can still reference itself through a different column, for example
categories.parent_id → categories.id. Those values only point at rows generated earlier.
One-to-One
A foreign key on a primary key column, or on a column with its own UNIQUE constraint, is one-to-one: each parent row is used at most once.
If you ask for more child rows than there are parents (for example 80 organizer_profiles for 50 users):
- a required column caps the child table at the parent count, and the progress message explains why;
- a nullable column gets
NULLfor the extra rows.
Unique Columns
- Single-column unique text values (emails, slugs, usernames, codes) are de-duplicated.
- Unique integers that aren't keys count up from 1, so they never collide and always fit the type.
Multi-Column Unique Keys
Constraints over several columns, such as UNIQUE (follower_id, vendor_profile_id) or a composite primary key, are enforced across the whole table:
- A row that repeats an existing combination is drawn again with fresh values.
- If no unused combination can be found, the row is skipped, so the table may end up slightly smaller than requested but inserts cleanly.
- When every column in the key is a required foreign key, the table is capped at the number of possible combinations, for example 200 users × 50 vendors = 10,000 follows.
- A combination that contains
NULLnever counts as a duplicate, matching SQL behaviour.
Asking for close to the maximum number of combinations may skip some rows. Stay comfortably below it for complete tables.
Insert Order
Every export (SQL, JSON, CSV, XML, from the web app, the MCP export tool or the CLI) lists tables parents first, whatever order you selected them in.
- MySQL and SQLite SQL exports also switch foreign key checks off for the import.
- PostgreSQL has no per-session switch for this:
SET CONSTRAINTS ALL DEFERREDonly affects constraints declaredDEFERRABLE, andsession_replication_roleneeds a superuser. The parent-first order is what makes Postgres imports work.
Re-Resolving Relationships
After changing your schema, open Relationships and click Regenerate. This:
- re-reads foreign keys from your original SQL file;
- keeps relationships added through the Data Assistant;
- does not touch your column mappings or profiles.