CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-sqlite3

Asynchronous, non-blocking SQLite3 bindings for Node.js

Pending
Overview
Eval results
Files

backup.mddocs/

Database Backup

Database backup and restoration functionality with step-by-step control and progress monitoring. The Backup class extends EventEmitter and provides comprehensive backup operations for SQLite databases.

Capabilities

Create Backup

Creates a backup instance for database backup operations.

/**
 * Creates a database backup (simple form) - backs up main database to file
 * @param filename - Destination filename for backup
 * @param callback - Optional callback called when backup is initialized
 * @returns Backup instance
 */
backup(filename: string, callback?: (err: Error | null) => void): Backup;

/**
 * Creates a database backup (advanced form) - full control over source/destination
 * @param filename - Source or destination filename
 * @param destName - Destination database name (usually 'main')
 * @param sourceName - Source database name (usually 'main')
 * @param filenameIsDest - Whether filename parameter is destination (true) or source (false)
 * @param callback - Optional callback called when backup is initialized
 * @returns Backup instance
 */
backup(
    filename: string, 
    destName: string, 
    sourceName: string, 
    filenameIsDest: boolean, 
    callback?: (err: Error | null) => void
): Backup;

Usage Examples:

const sqlite3 = require('sqlite3').verbose();
const db = new sqlite3.Database('source.db');

// Simple backup - backup current database to file
const backup = db.backup('backup.db', (err) => {
    if (err) {
        console.error('Backup initialization failed:', err.message);
    } else {
        console.log('Backup initialized successfully');
    }
});

// Advanced backup - restore from file to current database
const restoreBackup = db.backup('backup.db', 'main', 'main', false, (err) => {
    if (err) {
        console.error('Restore initialization failed:', err.message);
    }
});

// Backup to a different database name
const attachedBackup = db.backup('backup.db', 'backup_db', 'main', true);

Step Backup Forward

Advances the backup process by copying a specified number of pages.

/**
 * Steps the backup process forward by copying pages
 * @param pages - Number of pages to copy in this step (-1 for all remaining)
 * @param callback - Optional callback called when step completes
 * @returns Backup instance for chaining
 */
step(pages: number, callback?: (err: Error | null) => void): this;

Usage Examples:

const backup = db.backup('backup.db');

// Copy 5 pages at a time
backup.step(5, (err) => {
    if (err) {
        console.error('Backup step failed:', err.message);
    } else {
        console.log(`Backup progress: ${backup.remaining} pages remaining`);
        
        if (!backup.completed && !backup.failed) {
            // Continue with next step
            backup.step(5);
        }
    }
});

// Copy all remaining pages at once
backup.step(-1, (err) => {
    if (err) {
        console.error('Backup failed:', err.message);
    } else {
        console.log('Backup completed successfully');
    }
});

// Step-by-step with progress monitoring
function performBackupWithProgress() {
    const backup = db.backup('backup.db');
    const totalPages = backup.pageCount;
    
    function stepBackup() {
        backup.step(1, (err) => {
            if (err) {
                console.error('Backup error:', err.message);
                return;
            }
            
            const progress = ((totalPages - backup.remaining) / totalPages) * 100;
            console.log(`Backup progress: ${progress.toFixed(1)}%`);
            
            if (backup.completed) {
                console.log('Backup completed successfully');
                backup.finish();
            } else if (backup.failed) {
                console.log('Backup failed');
                backup.finish();
            } else {
                // Continue with next step
                setTimeout(stepBackup, 10); // Small delay between steps
            }
        });
    }
    
    stepBackup();
}

Finish Backup

Finishes the backup operation and releases resources.

/**
 * Finishes the backup operation and releases resources
 * @param callback - Optional callback called when backup is finished
 * @returns Backup instance for chaining
 */
finish(callback?: (err: Error | null) => void): this;

Usage Examples:

const backup = db.backup('backup.db');

// Perform complete backup
backup.step(-1, (err) => {
    if (err) {
        console.error('Backup failed:', err.message);
    } else {
        console.log('Backup data copied successfully');
    }
    
    // Always finish to clean up resources
    backup.finish((err) => {
        if (err) {
            console.error('Backup finish failed:', err.message);
        } else {
            console.log('Backup operation completed and resources cleaned up');
        }
    });
});

Backup Properties

Read-only properties that provide backup status and progress information.

/**
 * Number of pages remaining to be backed up
 */
readonly remaining: number;

/**
 * Total number of pages in the source database
 */
readonly pageCount: number;

/**
 * Whether the backup has completed successfully
 */
readonly completed: boolean;

/**
 * Whether the backup has failed
 */
readonly failed: boolean;

/**
 * Whether the backup is currently idle (no operation in progress or queued)
 */
readonly idle: boolean;

/**
 * Array of SQLite error codes that should trigger retry attempts
 * Default: [BUSY, LOCKED]
 */
retryErrors: number[];

Usage Examples:

const backup = db.backup('backup.db');

// Monitor backup progress
function checkProgress() {
    console.log(`Pages: ${backup.remaining}/${backup.pageCount} remaining`);
    console.log(`Progress: ${((backup.pageCount - backup.remaining) / backup.pageCount * 100).toFixed(1)}%`);
    console.log(`Completed: ${backup.completed}`);
    console.log(`Failed: ${backup.failed}`);
}

// Configure retry behavior
backup.retryErrors = [sqlite3.BUSY, sqlite3.LOCKED, sqlite3.INTERRUPT];

// Step through backup with monitoring
backup.step(10, (err) => {
    checkProgress();
    
    if (!backup.completed && !backup.failed) {
        // Continue backup
        backup.step(10);
    } else {
        backup.finish();
    }
});

Complete Backup Examples

Simple Complete Backup

const sqlite3 = require('sqlite3').verbose();
const db = new sqlite3.Database('source.db');

function createBackup(sourceDb, backupFile, callback) {
    const backup = sourceDb.backup(backupFile, (err) => {
        if (err) {
            return callback(err);
        }
        
        // Perform complete backup
        backup.step(-1, (err) => {
            if (err) {
                backup.finish();
                return callback(err);
            }
            
            if (backup.completed) {
                backup.finish((err) => {
                    if (err) {
                        return callback(err);
                    }
                    callback(null, 'Backup completed successfully');
                });
            } else {
                backup.finish();
                callback(new Error('Backup did not complete'));
            }
        });
    });
}

// Usage
createBackup(db, 'my-backup.db', (err, message) => {
    if (err) {
        console.error('Backup failed:', err.message);
    } else {
        console.log(message);
    }
    db.close();
});

Progressive Backup with Progress Reporting

function createProgressiveBackup(sourceDb, backupFile, progressCallback, completeCallback) {
    const backup = sourceDb.backup(backupFile, (err) => {
        if (err) {
            return completeCallback(err);
        }
        
        const totalPages = backup.pageCount;
        console.log(`Starting backup of ${totalPages} pages`);
        
        function stepWithProgress() {
            // Copy 100 pages at a time
            backup.step(100, (err) => {
                if (err) {
                    backup.finish();
                    return completeCallback(err);
                }
                
                const remaining = backup.remaining;
                const copied = totalPages - remaining;
                const progress = (copied / totalPages) * 100;
                
                // Report progress
                if (progressCallback) {
                    progressCallback(progress, copied, totalPages);
                }
                
                if (backup.completed) {
                    backup.finish((err) => {
                        if (err) {
                            return completeCallback(err);
                        }
                        completeCallback(null, 'Backup completed successfully');
                    });
                } else if (backup.failed) {
                    backup.finish();
                    completeCallback(new Error('Backup failed'));
                } else {
                    // Continue with next batch
                    setTimeout(stepWithProgress, 50); // Small delay
                }
            });
        }
        
        stepWithProgress();
    });
}

// Usage
createProgressiveBackup(
    db,
    'progressive-backup.db',
    (progress, copied, total) => {
        console.log(`Backup progress: ${progress.toFixed(1)}% (${copied}/${total} pages)`);
    },
    (err, message) => {
        if (err) {
            console.error('Progressive backup failed:', err.message);
        } else {
            console.log(message);
        }
        db.close();
    }
);

Restore from Backup

function restoreFromBackup(targetDb, backupFile, callback) {
    // Note: filenameIsDest = false means we're reading FROM the backupFile
    const restore = targetDb.backup(backupFile, 'main', 'main', false, (err) => {
        if (err) {
            return callback(err);
        }
        
        console.log('Starting restore operation');
        
        // Restore all pages at once
        restore.step(-1, (err) => {
            if (err) {
                restore.finish();
                return callback(err);
            }
            
            if (restore.completed) {
                restore.finish((err) => {
                    if (err) {
                        return callback(err);
                    }
                    callback(null, 'Restore completed successfully');
                });
            } else {
                restore.finish();
                callback(new Error('Restore did not complete'));
            }
        });
    });
}

// Usage
const targetDb = new sqlite3.Database(':memory:'); // Or any target database
restoreFromBackup(targetDb, 'my-backup.db', (err, message) => {
    if (err) {
        console.error('Restore failed:', err.message);
    } else {
        console.log(message);
        
        // Verify restore by querying the restored database
        targetDb.get("SELECT COUNT(*) as count FROM sqlite_master WHERE type='table'", (err, row) => {
            if (err) {
                console.error('Verification failed:', err.message);
            } else {
                console.log(`Restored database contains ${row.count} tables`);
            }
            targetDb.close();
        });
    }
});

Concurrent Backup (Non-Blocking)

function createConcurrentBackup(sourceDb, backupFile, callback) {
    const backup = sourceDb.backup(backupFile);
    
    // Configure for busy databases
    backup.retryErrors = [sqlite3.BUSY, sqlite3.LOCKED];
    
    function performStep() {
        // Copy small chunks to avoid blocking
        backup.step(10, (err) => {
            if (err) {
                // Check if this is a retryable error
                if (backup.retryErrors.includes(err.errno)) {
                    console.log('Database busy, retrying...');
                    setTimeout(performStep, 100); // Retry after delay
                    return;
                }
                
                backup.finish();
                return callback(err);
            }
            
            if (backup.completed) {
                backup.finish((err) => {
                    callback(err, 'Concurrent backup completed');
                });
            } else if (backup.failed) {
                backup.finish();
                callback(new Error('Concurrent backup failed'));
            } else {
                // Continue with next step, allowing other operations
                setImmediate(performStep);
            }
        });
    }
    
    performStep();
}

Install with Tessl CLI

npx tessl i tessl/npm-sqlite3

docs

backup.md

constants.md

database.md

index.md

statement.md

tile.json