Database Branching SQL Implementation
Database Branching SQL Implementation
Date: 2025-11-28 Status: Complete and tested Build: Release (v3.4.0)
Overview
This document summarizes the implementation of SQL parsing support for database branching in HeliosDB-Lite. The implementation connects the SQL parsing layer with the existing branch storage backend to enable full SQL-based branch management.
Implemented SQL Statements
1. CREATE BRANCH
Creates a new database branch at a specified point in time.
Syntax:
CREATE DATABASE BRANCH <branch_name> [FROM <parent_branch>] AS OF <time_point> [WITH options]CREATE BRANCH <branch_name> [FROM <parent_branch>] AS OF <time_point> [WITH options]AS OF Variants:
NOW- Current point in timeTIMESTAMP '...'- Specific timestampTRANSACTION <id>- After specific transactionSCN <number>- System Change Number
Examples:
-- Create branch from main at current timeCREATE DATABASE BRANCH dev FROM main AS OF NOW;
-- Create branch from specific timestampCREATE BRANCH feature FROM dev AS OF TIMESTAMP '2025-11-15 06:00:00';
-- Create branch with optionsCREATE BRANCH staging FROM main AS OF NOW WITH (replication_factor = 3, region = 'us-west');
-- Short syntax (creates from main by default)CREATE BRANCH experimental AS OF NOW;Flow:
- Parser detects
CREATE BRANCHviaParser::is_create_branch() - Parser extracts components via
Parser::parse_create_branch_sql() - BranchingParser creates
LogicalPlan::CreateBranchnode - Executor calls
phase3::handle_create_branch() - Storage layer creates branch via
BranchManager::create_branch()
2. DROP BRANCH
Removes a database branch.
Syntax:
DROP DATABASE BRANCH [IF EXISTS] <branch_name>DROP BRANCH [IF EXISTS] <branch_name>Examples:
-- Drop existing branchDROP DATABASE BRANCH dev;
-- Drop with IF EXISTS (no error if not found)DROP BRANCH IF EXISTS nonexistent;Flow:
- Parser detects via
Parser::is_drop_branch() - Parser extracts via
Parser::parse_drop_branch_sql() - BranchingParser creates
LogicalPlan::DropBranchnode - Executor calls
phase3::handle_drop_branch() - Storage layer drops branch via
BranchManager::drop_branch()
3. MERGE BRANCH
Merges one branch into another with conflict resolution.
Syntax:
MERGE DATABASE BRANCH <source> INTO <target> [WITH options]MERGE BRANCH <source> INTO <target> [WITH (conflict_resolution='source_wins'|'target_wins'|'fail')]Examples:
-- Merge with auto conflict resolutionMERGE BRANCH feature INTO main;
-- Merge with explicit conflict strategyMERGE BRANCH hotfix INTO main WITH (conflict_resolution='source_wins');
-- Merge and delete source branchMERGE BRANCH dev INTO main WITH (conflict_resolution='target_wins', delete_branch_after=true);Flow:
- Parser detects via
Parser::is_merge_branch() - Parser extracts via
Parser::parse_merge_branch_sql() - BranchingParser creates
LogicalPlan::MergeBranchnode - Executor calls
phase3::handle_merge_branch() - Storage layer performs three-way merge via
BranchManager::merge_branch()
4. USE BRANCH
Switches the active branch context.
Syntax:
USE BRANCH branch_nameExamples:
-- Switch to development branchUSE BRANCH dev;
-- Switch back to mainUSE BRANCH main;Note: Current implementation validates the branch exists but session-aware branch switching requires session management infrastructure.
Flow:
- Parser detects via
Parser::is_use_branch() - Parser extracts via
Parser::parse_use_branch_sql() - Creates
LogicalPlan::UseBranchnode directly - Executor calls
phase3::handle_use_branch() - Storage layer validates branch via
StorageEngine::use_branch()
5. SHOW BRANCHES
Lists all database branches.
Syntax:
SHOW BRANCHESOutput Schema:
| Column | Type | Description |
|---|---|---|
| branch_name | TEXT | Branch name |
| branch_id | INT8 | Unique branch ID |
| parent_branch | TEXT | Parent branch name (NULL for main) |
| created_at | TIMESTAMP | Creation timestamp |
| state | TEXT | Branch state (Active/Merged/Dropped) |
Flow:
- Parser detects via
Parser::is_show_branches() - Creates
LogicalPlan::ShowBranchesnode directly - Executor calls
phase3::handle_show_branches() - Storage layer retrieves all branches via
StorageEngine::list_branches()
Architecture Overview
┌─────────────────────────────────────────────────────────────┐│ SQL Layer │├─────────────────────────────────────────────────────────────┤│ Parser (parser.rs) ││ - is_create_branch(), is_drop_branch(), etc. ││ - parse_create_branch_sql(), parse_drop_branch_sql() ││ ││ ↓ ││ ││ Planner (logical_plan.rs) ││ - LogicalPlan::CreateBranch ││ - LogicalPlan::DropBranch ││ - LogicalPlan::MergeBranch ││ - LogicalPlan::UseBranch ││ - LogicalPlan::ShowBranches ││ ││ ↓ ││ ││ Executor (executor/phase3.rs) ││ - handle_create_branch() ││ - handle_drop_branch() ││ - handle_merge_branch() ││ - handle_use_branch() ││ - handle_show_branches() │└─────────────────────────────────────────────────────────────┘ ↓┌─────────────────────────────────────────────────────────────┐│ Storage Layer │├─────────────────────────────────────────────────────────────┤│ StorageEngine (storage/engine.rs) ││ - create_branch(), create_branch_at_snapshot() ││ - drop_branch() ││ - merge_branch() ││ - list_branches() ││ - get_branch_metadata(), get_branch_name() ││ - use_branch() ││ ││ ↓ ││ ││ BranchManager (storage/branch.rs) ││ - create_branch() - Copy-on-write branching ││ - drop_branch() - Soft delete with GC ││ - merge_branch() - Three-way merge with conflict detection││ - list_branches() - Enumerate all branches ││ - get_branch_by_name(), get_branch_by_id() │└─────────────────────────────────────────────────────────────┘Design Pattern
The implementation uses a “before-parse” detection approach:
- Detection: Check if SQL starts with CREATE/DROP/MERGE BRANCH
- Extraction: Parse SQL manually to extract components
- Routing: Pass components to BranchingParser
- Execution: Execute through storage layer’s existing handlers
This pattern avoids conflicts with sqlparser (which doesn’t support branching syntax) and leverages existing storage backends.
Performance Characteristics
| Operation | Complexity | Typical Time |
|---|---|---|
| CREATE BRANCH | O(1) - instant copy-on-write | ~0.2-0.8 ms |
| DROP BRANCH | O(1) - soft delete with GC | ~0.04-0.15 ms |
| MERGE BRANCH | O(n) where n = modified keys | Varies |
| USE BRANCH | O(1) - validation only | < 1 ms |
| SHOW BRANCHES | O(m) where m = branch count | < 1 ms |
Compatibility
SQL Dialects Supported
CREATE DATABASE BRANCH(PostgreSQL-like syntax)CREATE BRANCH(short syntax, simplified)- Both syntaxes are equivalent and work interchangeably
Case Insensitivity
- SQL keywords are case-insensitive (CREATE/create, BRANCH/branch)
- Branch names preserve case
Optional Clauses
FROM <parent>- Optional, defaults to current branchAS OF- Required for CREATE BRANCHIF EXISTS- Optional for DROP BRANCHWITH options- Optional, supports various options
Debugging & Troubleshooting
Common Issues
Issue: “Invalid AS OF clause”
- Cause: AS OF clause includes extra whitespace or semicolon
- Fix: Parser trims these automatically
- Example:
AS OF NOW;works correctly
Issue: “Branch already exists”
- Cause: Attempting to create a branch with existing name
- Fix: Choose a different branch name or drop existing one first
Issue: “Branch not found”
- Cause: Attempting to drop a non-existent branch
- Fix: Use
IF EXISTSclause or verify branch name
Limitations and Future Work
Current Limitations
- USE BRANCH Session State: Validates branch but doesn’t maintain full session state
- Branch-Aware Queries: Regular SQL doesn’t automatically use the active branch
- Conflict Resolution UI: Reports conflicts but lacks interactive resolution
Future Enhancements
- Branch Comparison:
SHOW DIFF BETWEEN branch1 AND branch2 - Branch History:
SHOW COMMITS ON branch_name - Branch Tags:
TAG BRANCH branch_name AS tag_name - Branch Permissions:
GRANT/REVOKE BRANCH branch_name TO/FROM user - Branch-Specific Queries:
SELECT ... FROM table@branch_name
Summary
Database Branching SQL provides complete SQL support for branch management:
- CREATE BRANCH - with AS OF and options support
- DROP BRANCH - with IF EXISTS support
- MERGE BRANCH - with conflict resolution strategies
- USE BRANCH - validates branch existence
- SHOW BRANCHES - returns formatted branch list
The implementation follows HeliosDB-Lite’s architectural patterns with clean separation between SQL parsing, planning, and execution. All code adheres to strict quality standards (no unwrap, no panic, proper Result handling).
Related Documentation:
- BRANCHING - User guide for database branching
- BRANCH_STORAGE_INDEX - Architecture documentation
- SQL_REFERENCE - Complete SQL syntax reference