#!/bin/bash set -e # Database Import Script for MotoVaultPro # Imports PostgreSQL database from export file # Usage: ./scripts/import-database.sh [options] # Colors for output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' NC='\033[0m' # No Color # Configuration SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" PROJECT_ROOT="$(dirname "$SCRIPT_DIR")" CONTAINER_NAME="mvp-postgres" DATABASE_NAME="motovaultpro" # Default values BACKUP_EXISTING=true DROP_EXISTING=false CREATE_DATABASE=false FORCE=false # Function to print colored output print_info() { echo -e "${GREEN}[INFO]${NC} $1" } print_warn() { echo -e "${YELLOW}[WARN]${NC} $1" } print_error() { echo -e "${RED}[ERROR]${NC} $1" } # Function to show usage show_usage() { cat << EOF Database Import Script for MotoVaultPro Usage: $0 [options] Options: -h, --help Show this help message -c, --container NAME Container name (default: mvp-postgres) -d, --database NAME Database name (default: motovaultpro) --create-db Create database if it doesn't exist --drop-existing Drop existing database before import (DANGER!) --no-backup Skip backup of existing database --force Skip confirmation prompts -f, --format FORMAT Import format: sql, custom, directory (auto-detected if not specified) Examples: # Import a standard SQL dump $0 database-exports/motovaultpro_export_20250101_120000.sql.gz # Import with database recreation $0 --drop-existing --create-db backup.sql # Import custom format $0 --format custom backup.dump Safety Features: - Creates backup of existing database by default - Requires confirmation before destructive operations - Validates export file before import - Supports rollback on failure EOF exit 0 } # Parse command line arguments while [[ $# -gt 0 ]]; do case $1 in -h|--help) show_usage ;; -c|--container) CONTAINER_NAME="$2" shift 2 ;; -d|--database) DATABASE_NAME="$2" shift 2 ;; --create-db) CREATE_DATABASE=true shift ;; --drop-existing) DROP_EXISTING=true shift ;; --no-backup) BACKUP_EXISTING=false shift ;; --force) FORCE=true shift ;; -f|--format) IMPORT_FORMAT="$2" shift 2 ;; -*) print_error "Unknown option: $1" show_usage ;; *) IMPORT_FILE="$1" shift ;; esac done # Validate import file if [ -z "$IMPORT_FILE" ]; then print_error "No import file specified" show_usage fi if [ ! -e "$IMPORT_FILE" ]; then print_error "Import file does not exist: $IMPORT_FILE" exit 1 fi # Auto-detect format if not specified if [ -z "$IMPORT_FORMAT" ]; then if [[ "$IMPORT_FILE" == *.sql.gz ]]; then IMPORT_FORMAT="sql-compressed" elif [[ "$IMPORT_FILE" == *.sql ]]; then IMPORT_FORMAT="sql" elif [[ "$IMPORT_FILE" == *.dump ]]; then IMPORT_FORMAT="custom" elif [ -d "$IMPORT_FILE" ]; then IMPORT_FORMAT="directory" else print_error "Cannot auto-detect format. Please specify with --format" exit 1 fi print_info "Auto-detected format: $IMPORT_FORMAT" fi # Check if container is running print_info "Checking if PostgreSQL container is running..." if ! docker ps --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then print_error "PostgreSQL container '${CONTAINER_NAME}' is not running" print_info "Start it with: docker compose up -d mvp-postgres" exit 1 fi # Check if database exists print_info "Checking if database exists..." DB_EXISTS=$(docker exec "$CONTAINER_NAME" psql -U postgres -tAc "SELECT 1 FROM pg_database WHERE datname='$DATABASE_NAME'" 2>/dev/null || echo "0") if [ "$DB_EXISTS" = "1" ]; then print_warn "Database '$DATABASE_NAME' already exists" if [ "$BACKUP_EXISTING" = true ] && [ "$DROP_EXISTING" = false ]; then BACKUP_FILE="${PROJECT_ROOT}/database-exports/${DATABASE_NAME}_backup_$(date +%Y%m%d_%H%M%S).sql.gz" print_info "Creating backup: $BACKUP_FILE" mkdir -p "$(dirname "$BACKUP_FILE")" docker exec "$CONTAINER_NAME" pg_dump -U postgres -d "$DATABASE_NAME" | gzip > "$BACKUP_FILE" print_info "Backup created successfully" fi if [ "$DROP_EXISTING" = true ]; then if [ "$FORCE" = false ]; then echo "" print_warn "WARNING: This will DROP the existing database '$DATABASE_NAME'" print_warn "All data will be permanently deleted!" echo "" read -p "Are you sure you want to continue? (type 'yes' to confirm): " CONFIRM if [ "$CONFIRM" != "yes" ]; then print_info "Import cancelled" exit 0 fi fi print_info "Dropping existing database..." docker exec "$CONTAINER_NAME" psql -U postgres -c "DROP DATABASE IF EXISTS $DATABASE_NAME" || { print_error "Failed to drop database" exit 1 } CREATE_DATABASE=true fi elif [ "$CREATE_DATABASE" = false ]; then print_error "Database '$DATABASE_NAME' does not exist. Use --create-db to create it" exit 1 fi # Create database if needed if [ "$CREATE_DATABASE" = true ]; then print_info "Creating database '$DATABASE_NAME'..." docker exec "$CONTAINER_NAME" psql -U postgres -c "CREATE DATABASE $DATABASE_NAME" || { print_error "Failed to create database" exit 1 } fi # Import based on format print_info "Starting database import..." print_info "File: $IMPORT_FILE" print_info "Format: $IMPORT_FORMAT" print_info "Database: $DATABASE_NAME" case $IMPORT_FORMAT in sql) print_info "Importing SQL dump..." docker exec -i "$CONTAINER_NAME" psql -U postgres -d "$DATABASE_NAME" < "$IMPORT_FILE" || { print_error "Import failed" exit 1 } ;; sql-compressed) print_info "Importing compressed SQL dump..." gunzip -c "$IMPORT_FILE" | docker exec -i "$CONTAINER_NAME" psql -U postgres -d "$DATABASE_NAME" || { print_error "Import failed" exit 1 } ;; custom) print_info "Importing custom format dump..." # Copy file into container docker cp "$IMPORT_FILE" "${CONTAINER_NAME}:/tmp/restore.dump" || { print_error "Failed to copy file to container" exit 1 } # Restore docker exec "$CONTAINER_NAME" pg_restore -U postgres -d "$DATABASE_NAME" -c /tmp/restore.dump || { print_error "Import failed" docker exec "$CONTAINER_NAME" rm -f /tmp/restore.dump exit 1 } # Cleanup docker exec "$CONTAINER_NAME" rm -f /tmp/restore.dump ;; directory) print_info "Importing directory format dump..." # Copy directory into container docker cp "$IMPORT_FILE" "${CONTAINER_NAME}:/tmp/restore_dir" || { print_error "Failed to copy directory to container" exit 1 } # Restore docker exec "$CONTAINER_NAME" pg_restore -U postgres -d "$DATABASE_NAME" -c /tmp/restore_dir || { print_error "Import failed" docker exec "$CONTAINER_NAME" rm -rf /tmp/restore_dir exit 1 } # Cleanup docker exec "$CONTAINER_NAME" rm -rf /tmp/restore_dir ;; *) print_error "Unknown import format: $IMPORT_FORMAT" exit 1 ;; esac # Verify import print_info "Verifying import..." TABLE_COUNT=$(docker exec "$CONTAINER_NAME" psql -U postgres -d "$DATABASE_NAME" -tAc "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = 'public'") print_info "Imported $TABLE_COUNT tables" # Summary echo "" print_info "===============================================" print_info "Database Import Complete!" print_info "===============================================" print_info "Database: $DATABASE_NAME" print_info "Tables: $TABLE_COUNT" if [ "$BACKUP_EXISTING" = true ] && [ -n "$BACKUP_FILE" ]; then print_info "Backup: $BACKUP_FILE" fi echo "" print_info "Database is ready to use!" echo ""