Skip to main content

Function Signature

pub async fn dump_database(
    database_url: String,
    database_token: Option<String>,
    migration_table: String,
    migration_folder: String,
    schema_file: String,
    wait_timeout: Option<usize>,
) -> anyhow::Result<()>

Description

Dumps the current database schema to a SQL file. This creates a snapshot of your database structure (tables, indexes, constraints, etc.) that can be used for version control, documentation, or backup purposes. The schema dump is automatically created after running migrations if dump_schema is enabled.

Parameters

database_url
String
required
The database connection URL:
  • PostgreSQL: postgres://user:password@host:port/database?sslmode=disable
  • MySQL: mysql://root:password@localhost:3306/app
  • MariaDB: mariadb://root:password@localhost:3307/app
  • SQLite: sqlite://./database.sqlite
  • LibSQL/Turso: https://your-database.turso.io
database_token
Option<String>
required
Authentication token for LibSQL/Turso databases. Use None for other database types.
migration_table
String
required
Name of the migrations tracking table. This table will be included in the schema dump.
migration_folder
String
required
Path to the directory where the schema file will be saved. Example: "./migrations".
schema_file
String
required
Name of the file where the schema will be dumped. Example: "schema.sql" or "database_schema.sql".
wait_timeout
Option<usize>
required
Timeout in seconds to wait for the database to be ready. Use Some(30) for 30 seconds, or None for default timeout.

Return Value

Returns Result<()> which:
  • Returns Ok(()) if the schema was dumped successfully
  • Returns Err if there was a connection error, permission issue, or dump command failure

Usage Example

use geni;

#[tokio::main]
async fn main() {
    // Dump database schema to file
    let result = geni::dump_database(
        "sqlite://./test.db".to_string(),
        None,
        "schema_migrations".to_string(),
        "./migrations".to_string(),
        "schema.sql".to_string(),
        Some(30),
    )
    .await;

    match result {
        Ok(_) => println!("Schema dumped successfully to ./migrations/schema.sql"),
        Err(e) => eprintln!("Failed to dump schema: {}", e),
    }
}

PostgreSQL Example

// Dump PostgreSQL schema
geni::dump_database(
    "postgres://postgres:[email protected]:5432/myapp?sslmode=disable".to_string(),
    None,
    "schema_migrations".to_string(),
    "./db".to_string(),
    "schema.sql".to_string(),
    Some(30),
)
.await
.unwrap();

MySQL Example

// Dump MySQL schema
geni::dump_database(
    "mysql://root:password@localhost:3306/myapp".to_string(),
    None,
    "schema_migrations".to_string(),
    "./migrations".to_string(),
    "schema.sql".to_string(),
    Some(30),
)
.await
.unwrap();

LibSQL/Turso Example

// Dump LibSQL schema
geni::dump_database(
    "https://my-database.turso.io".to_string(),
    Some("your-auth-token".to_string()),
    "schema_migrations".to_string(),
    "./migrations".to_string(),
    "schema.sql".to_string(),
    Some(30),
)
.await
.unwrap();

Database-Specific Behavior

PostgreSQL

  • Uses SQL queries to extract schema information
  • No external tools required
  • Includes tables, views, indexes, constraints, and sequences
  • Excludes data, only structure is dumped

MySQL

  • Requires mysqldump binary to be installed on the system
  • Dumps table structures, indexes, and constraints
  • The mysqldump command is executed as a subprocess
  • Already available in Docker MySQL images

MariaDB

  • Requires mariadb-dump binary to be installed
  • Similar functionality to MySQL dumping
  • Already available in Docker MariaDB images
  • Includes table definitions, indexes, and foreign keys

SQLite

  • Uses SQL queries to extract schema (no external tools needed)
  • Includes all table definitions and indexes
  • Lightweight and fast
  • Schema is extracted using SQLite’s built-in .schema functionality

LibSQL

  • Uses SQL queries to extract schema (no external tools needed)
  • Similar to SQLite schema dumping
  • Works with both local and remote LibSQL databases
  • Includes all DDL statements

Output File Format

The generated schema file contains SQL statements that recreate the database structure:
-- Database schema dump
-- Generated by Geni

CREATE TABLE users (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    username TEXT NOT NULL UNIQUE,
    email TEXT NOT NULL UNIQUE,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

CREATE TABLE posts (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    user_id INTEGER NOT NULL,
    title TEXT NOT NULL,
    content TEXT,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (user_id) REFERENCES users(id)
);

CREATE INDEX idx_posts_user_id ON posts(user_id);

CREATE TABLE schema_migrations (
    version TEXT PRIMARY KEY NOT NULL
);

Use Cases

Version Control

use geni;

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    let db_url = "sqlite://./production.db".to_string();
    
    // Dump schema for version control
    geni::dump_database(
        db_url,
        None,
        "schema_migrations".to_string(),
        "./db".to_string(),
        "schema.sql".to_string(),
        Some(30),
    )
    .await?;
    
    println!("Schema dumped! Commit schema.sql to version control.");
    Ok(())
}

Pre-Deployment Backup

use geni;
use chrono::Utc;

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    let db_url = std::env::var("DATABASE_URL")?;
    let timestamp = Utc::now().format("%Y%m%d_%H%M%S");
    let backup_file = format!("schema_backup_{}.sql", timestamp);
    
    // Create timestamped backup before migrations
    geni::dump_database(
        db_url.clone(),
        None,
        "schema_migrations".to_string(),
        "./backups".to_string(),
        backup_file,
        Some(30),
    )
    .await?;
    
    println!("Backup created. Proceeding with migrations...");
    
    // Now safe to run migrations
    geni::migrate_database(
        db_url,
        None,
        "schema_migrations".to_string(),
        "./migrations".to_string(),
        "schema.sql".to_string(),
        Some(30),
        true,
    )
    .await?;
    
    Ok(())
}

Documentation Generation

use geni;

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    // Dump schema for documentation
    geni::dump_database(
        "postgres://postgres:password@localhost:5432/myapp?sslmode=disable".to_string(),
        None,
        "schema_migrations".to_string(),
        "./docs/database".to_string(),
        "current_schema.sql".to_string(),
        Some(30),
    )
    .await?;
    
    println!("Schema documentation updated in docs/database/");
    Ok(())
}

Automated Migration Workflow

use geni;

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    let db_url = "sqlite://./app.db".to_string();
    let migration_folder = "./migrations".to_string();
    let migration_table = "schema_migrations".to_string();
    let schema_file = "schema.sql".to_string();
    
    println!("Step 1: Checking migration status...");
    geni::status_migrations(
        db_url.clone(),
        None,
        migration_table.clone(),
        migration_folder.clone(),
        schema_file.clone(),
        Some(30),
        true,
    )
    .await?;
    
    println!("\nStep 2: Applying migrations...");
    geni::migrate_database(
        db_url.clone(),
        None,
        migration_table.clone(),
        migration_folder.clone(),
        schema_file.clone(),
        Some(30),
        false, // Don't auto-dump, we'll do it manually
    )
    .await?;
    
    println!("\nStep 3: Dumping schema...");
    geni::dump_database(
        db_url,
        None,
        migration_table,
        migration_folder,
        schema_file,
        Some(30),
    )
    .await?;
    
    println!("\nMigration workflow complete!");
    Ok(())
}

Error Handling

The function may return errors in these cases:
  • Database connection failure
  • Missing required dump utilities (mysqldump, mariadb-dump)
  • Insufficient permissions to read database schema
  • Insufficient permissions to write to the output file
  • Invalid migration folder path
  • Disk space issues when writing the dump file

Requirements by Database

External Tool Requirements
  • PostgreSQL: No external tools needed
  • MySQL: Requires mysqldump (usually pre-installed with MySQL)
  • MariaDB: Requires mariadb-dump (usually pre-installed with MariaDB)
  • SQLite: No external tools needed
  • LibSQL: No external tools needed

Docker Considerations

When using Geni in Docker:
  • Use the standard Docker image (not the -slim variant) for MySQL/MariaDB support
  • The slim image doesn’t include mysqldump or mariadb-dump
  • PostgreSQL, SQLite, and LibSQL work in both standard and slim images

Best Practices

  1. Commit to version control: Always commit schema.sql to track database structure changes
  2. Review schema changes: Check schema.sql diffs in pull requests to review database changes
  3. Automate dumping: Enable automatic schema dumping after migrations with dump_schema: true
  4. Create backups: Dump schema before major migrations or deployments
  5. Use consistent naming: Use the same schema_file name across all environments
  6. Document schema: Keep schema.sql as living documentation of your database structure

See Also

Build docs developers (and LLMs) love