import argparse
import logging
import os
import sqlite3
# Setup basic configuration for logging
logging . basicConfig (
level = logging . INFO , format = " %(asctime)s - %(levelname)s - %(message)s "
)
def initialize_db ( db_path ) :
# Check if the database file already exists
db_exists = os . path . exists ( db_path )
if db_exists :
logging . info ( f " { db_path } exists " ) # Log a message if the database exists
return
try :
# Using 'with' to ensure that the connection is closed automatically
with sqlite3 . connect ( db_path ) as conn :
configure_database ( conn )
except sqlite3 . Error as e :
logging . error ( f " Database error: { e } " ) # Log any SQLite errors that occur
except Exception as e :
logging . error ( f " Exception in initialize_db: { e } " )
def configure_database ( conn ) :
cursor = conn . cursor ( )
# Setting the journal mode to WAL for better concurrency
cursor . execute ( " PRAGMA journal_mode = WAL; " )
# Ensuring foreign key constraints are enforced for data integrity
cursor . execute ( " PRAGMA foreign_keys = ON; " )
# disable legacy alter table behavior as it will cause problems during
# migrations when tables are renamed as references would otherwise be retained
# in some locations
# https://www.sqlite.org/pragma.html#pragma_legacy_alter_table
cursor . execute ( " PRAGMA legacy_alter_table=OFF " )
# when using the WAL, we do need to sync changes on every write. sqlite
# recommends using 'normal' mode which is much faster
# Setting synchronous to NORMAL for a balance between speed and reliability
cursor . execute ( " PRAGMA synchronous = NORMAL; " )
# Increasing the cache size to reduce the number of disk I/O operations
cursor . execute ( " PRAGMA cache_size = 20000; " )
# Enabling memory-mapped I/O for potentially faster file operations
cursor . execute ( " PRAGMA mmap_size = 536870912; " )
# Setting a busy timeout to prevent immediate failures when the database is locked
# setting the value very high allows for more 'concurrency'
# without running into errors, but may result in slow api calls
cursor . execute ( " PRAGMA busy_timeout = 60000; " )
# Setting locking mode to EXCLUSIVE can enhance performance for single-user scenarios
# cursor.execute("PRAGMA locking_mode = EXCLUSIVE;")
conn . commit ( ) # Commit all PRAGMA configurations
logging . info ( " Set up database with multi-user optimizations. " )
def batch_transact ( db_path , operations ) :
try :
with sqlite3 . connect (
db_path
) as conn : # Ensure that the connection is handled properly
cursor = conn . cursor ( )
# Start a transaction for batch operations
cursor . execute ( " BEGIN TRANSACTION; " )
for operation in operations :
# Execute each SQL operation provided in the operations list
cursor . execute ( operation )
cursor . execute ( " COMMIT; " ) # Commit all operations at once
except sqlite3 . Error as e :
logging . error ( f " Database error during batch transaction: { e } " )
except Exception as e :
logging . error ( f " Exception in batch_transact: { e } " )
def maintenance ( db_path ) :
try :
with sqlite3 . connect ( db_path ) as conn :
cursor = conn . cursor ( )
# Optimize the database to maintain performance
cursor . execute ( " PRAGMA optimize; " )
cursor . execute ( " VACUUM; " ) # Reclaim space and defragment the database file
except sqlite3 . Error as e :
logging . error ( f " Database error during maintenance: { e } " )
except Exception as e :
logging . error ( f " Exception in maintenance: { e } " )
def parse_args ( ) :
parser = argparse . ArgumentParser (
description = " Initialize and manage an SQLite database. "
)
parser . add_argument ( " db_path " , type = str , help = " Path to the SQLite database file. " )
args = parser . parse_args ( )
return args
if __name__ == " __main__ " :
args = parse_args ( ) # Parse the command-line arguments for the database path
initialize_db ( args . db_path ) # Use the parsed path to initialize the database