Skip to content

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 time
  • TIMESTAMP '...' - Specific timestamp
  • TRANSACTION <id> - After specific transaction
  • SCN <number> - System Change Number

Examples:

-- Create branch from main at current time
CREATE DATABASE BRANCH dev FROM main AS OF NOW;
-- Create branch from specific timestamp
CREATE BRANCH feature FROM dev AS OF TIMESTAMP '2025-11-15 06:00:00';
-- Create branch with options
CREATE 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 BRANCH via Parser::is_create_branch()
  • Parser extracts components via Parser::parse_create_branch_sql()
  • BranchingParser creates LogicalPlan::CreateBranch node
  • 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 branch
DROP 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::DropBranch node
  • 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 resolution
MERGE BRANCH feature INTO main;
-- Merge with explicit conflict strategy
MERGE BRANCH hotfix INTO main WITH (conflict_resolution='source_wins');
-- Merge and delete source branch
MERGE 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::MergeBranch node
  • 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_name

Examples:

-- Switch to development branch
USE BRANCH dev;
-- Switch back to main
USE 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::UseBranch node directly
  • Executor calls phase3::handle_use_branch()
  • Storage layer validates branch via StorageEngine::use_branch()

5. SHOW BRANCHES

Lists all database branches.

Syntax:

SHOW BRANCHES

Output Schema:

ColumnTypeDescription
branch_nameTEXTBranch name
branch_idINT8Unique branch ID
parent_branchTEXTParent branch name (NULL for main)
created_atTIMESTAMPCreation timestamp
stateTEXTBranch state (Active/Merged/Dropped)

Flow:

  • Parser detects via Parser::is_show_branches()
  • Creates LogicalPlan::ShowBranches node 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:

  1. Detection: Check if SQL starts with CREATE/DROP/MERGE BRANCH
  2. Extraction: Parse SQL manually to extract components
  3. Routing: Pass components to BranchingParser
  4. 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

OperationComplexityTypical Time
CREATE BRANCHO(1) - instant copy-on-write~0.2-0.8 ms
DROP BRANCHO(1) - soft delete with GC~0.04-0.15 ms
MERGE BRANCHO(n) where n = modified keysVaries
USE BRANCHO(1) - validation only< 1 ms
SHOW BRANCHESO(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 branch
  • AS OF - Required for CREATE BRANCH
  • IF EXISTS - Optional for DROP BRANCH
  • WITH 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 EXISTS clause or verify branch name

Limitations and Future Work

Current Limitations

  1. USE BRANCH Session State: Validates branch but doesn’t maintain full session state
  2. Branch-Aware Queries: Regular SQL doesn’t automatically use the active branch
  3. Conflict Resolution UI: Reports conflicts but lacks interactive resolution

Future Enhancements

  1. Branch Comparison: SHOW DIFF BETWEEN branch1 AND branch2
  2. Branch History: SHOW COMMITS ON branch_name
  3. Branch Tags: TAG BRANCH branch_name AS tag_name
  4. Branch Permissions: GRANT/REVOKE BRANCH branch_name TO/FROM user
  5. 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: