-
Notifications
You must be signed in to change notification settings - Fork 2
Foreign Key Visualizer
Interactive graph-based foreign key relationship management with visual editing capabilities.
Note: For read-only schema visualization and documentation, see ER Diagram. This page covers the interactive editor for adding, modifying, and deleting foreign key constraints.
The Foreign Key Visualizer/Editor provides a comprehensive visual interface for managing foreign key constraints in your D1 databases. Using an interactive graph powered by ReactFlow, you can see all table relationships at a glance, add new constraints, modify existing ones, and delete relationships - all through an intuitive visual interface.
Key Features:
- Interactive Graph Visualization - Pan, zoom, and explore table relationships
- Dual Layout System - Switch between hierarchical and force-directed layouts
- Add Foreign Keys - Create new constraints with guided validation
- Modify Constraints - Edit ON DELETE and ON UPDATE behaviors
- Delete Constraints - Remove foreign key relationships safely
- Type Validation - Automatic column type compatibility checking
- Orphan Detection - Prevents adding FKs that would violate referential integrity
- Color-Coded Edges - Visual distinction between CASCADE, RESTRICT, SET NULL, and NO ACTION
- Table Filtering - Focus on specific tables and their relationships
- Column Display - Shows table columns with types and primary key indicators
The Foreign Key Visualizer is accessible within the Relationships tab:
- Navigate to a database
- Click the "Relationships" tab (alongside "Tables" and "Query Builder")
- Ensure "Foreign Key Editor" is selected in the view toggle (default)
- The graph loads automatically showing all foreign key relationships
Tab Icon: Network/Graph icon
Location: Database-level navigation tabs
View Toggle: "Foreign Key Editor" (editable) vs "ER Diagram" (read-only)
Hierarchical Layout (Default):
Top-to-bottom hierarchical arrangement using dagre algorithm
- Parent tables at top
- Child tables below
- Clear dependency flow
- Optimal for understanding cascade direction
Force-Directed Layout:
Physics-based layout with circular arrangement
- Tables positioned by relationship strength
- Natural clustering of related tables
- Better for densely connected schemas
- Interactive repositioning
Switching Layouts:
- Use the layout selector in the toolbar
- Graph automatically re-arranges
- Node positions calculated dynamically
Each table is displayed as a node with:
βββββββββββββββββββββββββββ
β table_name β (Table name in bold)
β 152 rows β (Row count)
βββββββββββββββββββββββββββ€
β id INTEGER (PK)β (Columns with types)
β user_id INTEGER β
β title TEXT β
β content TEXT β
βββββββββββββββββββββββββββ
Node Information:
- Table Name - Bold text at top
- Row Count - Total rows in table
- Columns - Name, type, and PK indicator
- Border Color - Primary color scheme
Node Interactions:
- Click - Select node (optional callback to navigate to table)
- Drag - Reposition in graph (force-directed mode)
- Hover - Highlight connections
Edges represent foreign key constraints with visual indicators:
Edge Colors (by ON DELETE action):
- π‘ Yellow - CASCADE (data will be deleted)
- π΄ Red - RESTRICT/NO ACTION (blocks deletion)
- π΅ Blue - SET NULL/SET DEFAULT (data modified)
- βͺ Gray - Default/no action
Edge Labels:
- Shows ON DELETE action (if not NO ACTION)
- Positioned along edge path
- Color matches edge
Edge Styles:
- Solid Line - Standard constraint
- Dashed Line - ON UPDATE is not NO ACTION (future enhancement)
- Arrow - Points from source to target table
Example:
posts ββCASCADEββ> users
(posts.user_id references users.id)
Pan & Zoom:
- Mouse Wheel - Zoom in/out
- Click & Drag - Pan across graph
Tip: Click on a relationship line (edge) to edit or delete a constraint.
Background:
- Dotted grid pattern
- Helps with alignment
- Visible at all zoom levels
From Toolbar:
- Click "Add Foreign Key" button in top-left panel
- Editor dialog opens
Editor Layout:
βββββββββββββββββββββββββββββββββββββββ
β Add Foreign Key β
βββββββββββββββββββββββββββββββββββββββ€
β Constraint Name (optional) β
β [fk_source_column] β
β β
β Source Table [Select βΌ] β
β Source Column [Select βΌ] β
β β
β References Table [Select βΌ] β
β References Column [Select βΌ] β
β β
β ON DELETE [Select βΌ] β
β ON UPDATE [Select βΌ] β
β β
β [Cancel] [Add Foreign Key]β
βββββββββββββββββββββββββββββββββββββββ
1. Select Source Table
- Dropdown lists all tables in database
- Select the table that will contain the foreign key
2. Select Source Column
- Dropdown lists all columns in selected source table
- Shows column type for reference
- Example:
user_id (INTEGER)
3. Select Target Table (References)
- Dropdown lists all tables in database
- This is the table being referenced
- Example:
users
4. Select Target Column (References)
- Dropdown lists all columns in selected target table
- Shows column type and PK indicator
- Example:
id (INTEGER) (PK)
5. Choose ON DELETE Action
-
NO ACTION(default) - Blocks deletion if references exist -
CASCADE- Automatically delete dependent rows -
RESTRICT- Explicitly blocks deletion -
SET NULL- Set foreign key column to NULL -
SET DEFAULT- Set foreign key column to default value
6. Choose ON UPDATE Action
- Same options as ON DELETE
- Typically left as
NO ACTION
7. Optional Constraint Name
- Auto-generated:
fk_sourcetable_sourcecolumn - Customize if desired
- Used for modification and deletion
8. Add Foreign Key
- Click "Add Foreign Key" button
- Backend validates and creates constraint
- Graph refreshes automatically
The backend performs comprehensive validation before creating the foreign key:
Column Type Compatibility:
β INTEGER β INTEGER
β TEXT β TEXT
β REAL β REAL
β INTEGER β TEXT (incompatible)
β TEXT β INTEGER (incompatible)
Target Column Requirements:
β Target column is PRIMARY KEY
β Target column has UNIQUE constraint
β Target column is not unique (rejected)
Orphan Row Detection:
β All source values exist in target table
β Orphaned rows detected (rejected with count)
Validation Errors:
- Display in red error box
- Clear error message
- Specific guidance on resolution
Example Error:
β Cannot add foreign key:
Column type mismatch (INTEGER vs TEXT)
Example Warning:
β Cannot add foreign key:
Would create 15 orphaned rows.
Target column values not found in reference table.
1. Click an Edge
- Click any edge (relationship line) in the graph
- Details panel appears in bottom-right corner
Details Panel:
βββββββββββββββββββββββββββββββ
β Foreign Key Details β
βββββββββββββββββββββββββββββββ€
β posts.user_id β users.id β
β β
β ON DELETE: CASCADE β
β ON UPDATE: NO ACTION β
β β
β [Edit] [Delete] β
βββββββββββββββββββββββββββββββ
2. Click Edit Button
- Opens Foreign Key Editor in modify mode
- Source/target tables and columns are read-only
- ON DELETE and ON UPDATE are editable
Read-Only Fields:
- Constraint Name (shown for reference)
- Source Table (grayed out)
- Source Column (grayed out)
- References Table (grayed out)
- References Column (grayed out)
Editable Fields:
- ON DELETE action (dropdown)
- ON UPDATE action (dropdown)
Process:
- Modify ON DELETE or ON UPDATE
- Click "Save Changes"
- Backend recreates table with new constraint
- Graph refreshes automatically
Example Modification:
Change: CASCADE β RESTRICT
Result: Deletions now blocked if references exist
Behind the Scenes:
Foreign key modification in SQLite requires table recreation:
- Get Current Schema - Fetch CREATE TABLE statement
- Parse Foreign Keys - Identify constraint to modify
- Generate New Schema - Update ON DELETE/ON UPDATE
- Create Temp Table - New structure with modified constraint
- Copy Data - Transfer all rows to temp table
- Drop Original - Remove old table
- Rename Temp - Rename temp to original name
- Recreate Indexes - Restore all indexes
Note: This is transparent to the user but may take a few seconds for large tables.
1. Select Edge
- Click the edge representing the constraint
- Details panel appears
2. Click Delete Button
- Confirmation dialog opens
Confirmation Dialog:
βββββββββββββββββββββββββββββββββββββββ
β Delete Foreign Key? β
βββββββββββββββββββββββββββββββββββββββ€
β Are you sure you want to delete β
β the foreign key constraint between β
β posts.user_id and users.id? β
β β
β This action cannot be undone. β
β β
β [Cancel] [Delete FK] β
βββββββββββββββββββββββββββββββββββββββ
3. Confirm Deletion
- Click "Delete Foreign Key"
- Backend removes constraint via table recreation
- Graph refreshes automatically
Result:
- Edge disappears from graph
- Constraint removed from table schema
- Referential integrity no longer enforced
Valid Reasons:
- Relationship no longer needed
- Changing schema design
- Constraint causing issues
- Preparing for data migration
Caution:
- Data integrity no longer enforced
- Orphaned rows may occur
- Consider implications before deleting
Schema:
CREATE TABLE users (
id INTEGER PRIMARY KEY,
name TEXT NOT NULL
);
CREATE TABLE posts (
id INTEGER PRIMARY KEY,
user_id INTEGER NOT NULL,
title TEXT NOT NULL
);
CREATE TABLE comments (
id INTEGER PRIMARY KEY,
post_id INTEGER NOT NULL,
user_id INTEGER NOT NULL,
content TEXT
);Adding Foreign Keys via Visualizer:
Step 1: posts β users
- Source:
poststable,user_idcolumn - Target:
userstable,idcolumn - ON DELETE:
CASCADE(delete posts when user deleted) - ON UPDATE:
NO ACTION
Step 2: comments β posts
- Source:
commentstable,post_idcolumn - Target:
poststable,idcolumn - ON DELETE:
CASCADE(delete comments when post deleted) - ON UPDATE:
NO ACTION
Step 3: comments β users
- Source:
commentstable,user_idcolumn - Target:
userstable,idcolumn - ON DELETE:
CASCADE(delete comments when user deleted) - ON UPDATE:
NO ACTION
Resulting Graph:
users
/ \
CASCADE CASCADE
/ \
posts comments
|
CASCADE
|
comments
Schema:
CREATE TABLE customers (
id INTEGER PRIMARY KEY
);
CREATE TABLE orders (
id INTEGER PRIMARY KEY,
customer_id INTEGER NOT NULL
);
CREATE TABLE order_items (
id INTEGER PRIMARY KEY,
order_id INTEGER NOT NULL,
product_id INTEGER NOT NULL
);
CREATE TABLE products (
id INTEGER PRIMARY KEY
);Adding Foreign Keys:
-
orders β customers (RESTRICT)
- Prevents customer deletion if orders exist
- Protects financial data
-
order_items β orders (CASCADE)
- Delete items when order deleted
- Maintains consistency
-
order_items β products (RESTRICT)
- Prevents product deletion if in orders
- Data integrity
Resulting Graph:
customers βRESTRICTβ orders βCASCADEβ order_items βRESTRICTβ products
Scenario: Change user deletion from CASCADE to RESTRICT
Original:
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADEProcess:
- Click edge between
postsandusers - Click Edit in details panel
- Change ON DELETE from
CASCADEtoRESTRICT - Click Save Changes
New Behavior:
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE RESTRICTResult:
- User deletion now blocked if posts exist
- Must delete posts first before deleting user
- More safety, less automation
Concept:
- Enter table name to filter graph
- Only show selected table and direct dependencies
- Useful for complex schemas
Current: All columns shown in nodes Future: Toggle to show only FK columns
Shown in Details Panel:
- Constraint name
- Source/target tables and columns
- ON DELETE and ON UPDATE actions
- Row counts (from source table)
Future Enhancement:
- Export graph as PNG/SVG
- Export relationships as JSON
- Generate documentation
GET /api/tables/:dbId/foreign-keysResponse:
{
"result": {
"nodes": [
{
"id": "users",
"label": "users",
"columns": [
{"name": "id", "type": "INTEGER", "isPK": true},
{"name": "name", "type": "TEXT", "isPK": false}
],
"rowCount": 152
},
{
"id": "posts",
"label": "posts",
"columns": [
{"name": "id", "type": "INTEGER", "isPK": true},
{"name": "user_id", "type": "INTEGER", "isPK": false},
{"name": "title", "type": "TEXT", "isPK": false}
],
"rowCount": 487
}
],
"edges": [
{
"id": "fk_posts_user_id_users_id",
"source": "posts",
"target": "users",
"sourceColumn": "user_id",
"targetColumn": "id",
"onDelete": "CASCADE",
"onUpdate": "NO ACTION"
}
]
},
"success": true
}POST /api/tables/:dbId/foreign-keys/add
Content-Type: application/jsonBody:
{
"sourceTable": "posts",
"sourceColumn": "user_id",
"targetTable": "users",
"targetColumn": "id",
"onDelete": "CASCADE",
"onUpdate": "NO ACTION",
"constraintName": "fk_posts_user_id"
}Response:
{
"result": {
"message": "Foreign key constraint added successfully"
},
"success": true
}PATCH /api/tables/:dbId/foreign-keys/:constraintName
Content-Type: application/jsonBody:
{
"onDelete": "RESTRICT",
"onUpdate": "NO ACTION"
}Response:
{
"result": {
"message": "Foreign key constraint modified successfully"
},
"success": true
}DELETE /api/tables/:dbId/foreign-keys/:constraintNameResponse:
{
"result": {
"message": "Foreign key constraint deleted successfully"
},
"success": true
}See API Reference for complete API documentation.
Choose appropriate ON DELETE:
- CASCADE - For dependent data (comments, order items)
- RESTRICT - For important records (invoices, audit logs)
- SET NULL - For optional relationships (nullable foreign keys)
- NO ACTION - When uncertain (can change later)
Before Making Changes:
- Open the visualizer
- Understand existing relationships
- Plan new constraints
- Consider cascade impact
During Development:
- Add constraints as you build
- Visualize relationships immediately
- Test cascade behavior
- Adjust as needed
Constraint Names:
- Use descriptive names
- Include table and column
- Example:
fk_posts_user_idnotfk1
Comments in Schema:
-- User posts: CASCADE because posts have no meaning without user
CREATE TABLE posts (
id INTEGER PRIMARY KEY,
user_id INTEGER NOT NULL,
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
);Workflow:
- Add constraint in visualizer
- Test deletion in development
- Use Cascade Impact Simulator for preview
- Verify expected behavior
- Deploy to production
Use Both Tools:
- Visualizer - Schema design and constraint management
- Foreign Key Dependencies - Pre-deletion impact analysis
- Cascade Impact Simulator - Detailed cascade preview
Possible Causes:
- No tables in database
- No foreign key constraints defined
- Network error
Solution:
- Check that tables exist
- Verify foreign keys with
PRAGMA foreign_key_list(table_name) - Click Refresh button in toolbar
Common Errors:
Type Mismatch:
β Column type mismatch (INTEGER vs TEXT)
Solution: Ensure source and target columns have compatible types
Orphaned Rows:
β Would create 15 orphaned rows
Solution: Clean up data first or remove/update orphaned values
Target Column Not Unique:
β Target column must be PRIMARY KEY or have UNIQUE constraint
Solution: Add UNIQUE constraint or use a different column
Cause: Large table requires recreation
What's Happening:
- SQLite is recreating table with new constraint
- Copying all data to temporary table
- May take 10-30 seconds for large tables (>100k rows)
Solution:
- Wait for operation to complete
- Avoid modifying very large tables during peak hours
Cause: Node overlap or zoom level
Solution:
- Zoom in/out to see all edges
- Switch to hierarchical layout
- Click on node to highlight connections
Cannot Change:
- Source table/column (must delete and recreate)
- Target table/column (must delete and recreate)
Can Change:
- ON DELETE action (via modification)
- ON UPDATE action (via modification)
Large Tables:
- Table recreation may be slow (>100k rows)
- Consider maintenance windows
- Test with smaller datasets first
Many Relationships:
- Graph may become cluttered (>50 tables)
- Use table filtering (future enhancement)
- Consider breaking into multiple databases
Current: UI supports single-column foreign keys only Workaround: Create composite keys via Query Console
- Foreign Key Dependencies - Pre-deletion dependency analysis
- Cascade Impact Simulator - Detailed cascade preview with graph
- Table Operations - Table management and deletion
- Query Console - Create complex foreign keys with SQL
- Schema Designer - Visual table creation tool
- Foreign Key Dependencies - Understand relationship analysis
- Cascade Impact Simulator - Preview deletion cascades
- Table Operations - Learn table management
- API Reference - Programmatic access to FK operations
Need Help? See Troubleshooting or open an issue.
- Database Management
- R2 Backup Restore
- Scheduled Backups
- Table Operations
- Query Console
- Schema Designer
- Column Management
- Bulk Operations
- Job History
- Time Travel
- Read Replication
- Undo Rollback
- Foreign Key Visualizer
- ER Diagram
- Foreign Key Dependencies
- Foreign Key Navigation
- Circular Dependency Detector
- Cascade Impact Simulator
- AI Search
- FTS5 Full Text Search
- Cross Database Search
- Index Analyzer
- Database Comparison
- Database Optimization