LCOV - code coverage report
Current view: top level - src - db_init.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 83.7 % 49 41
Test Date: 2026-03-01 04:31:48 Functions: 100.0 % 1 1
Branches: 78.6 % 28 22

             Branch data     Line data    Source code
       1                 :             : #include "precizer.h"
       2                 :             : #define STRINGIFY(x) #x
       3                 :             : #define TOSTRING(x) STRINGIFY(x)
       4                 :             : 
       5                 :             : /**
       6                 :             :  *
       7                 :             :  * Initialize SQLite database
       8                 :             :  *
       9                 :             :  */
      10                 :         313 : Return db_init(void)
      11                 :             : {
      12                 :             :         /* Status returned by this function through provide()
      13                 :             :            Default value assumes successful completion */
      14                 :         313 :         Return status = SUCCESS;
      15                 :             : 
      16                 :             :         /* Interrupt the function smoothly */
      17                 :             :         /* Interrupt when Ctrl+C */
      18         [ -  + ]:         313 :         if(global_interrupt_flag == true)
      19                 :             :         {
      20                 :           0 :                 provide(status);
      21                 :             :         }
      22                 :             : 
      23                 :             :         // SQL request result
      24                 :             :         int rc;
      25                 :             : 
      26                 :             :         /* Open database */
      27                 :             : 
      28                 :         313 :         const char *db_file_path = confstr(db_primary_file_path);
      29                 :             : 
      30         [ +  + ]:         313 :         if(config->sqlite_open_flag == SQL_DRY_RUN_MODE)
      31                 :             :         {
      32                 :           6 :                 db_file_path = ":memory:";
      33                 :           6 :                 config->db_primary_path_is_memory = true;
      34                 :           6 :                 config->sqlite_open_flag = SQLITE_OPEN_READWRITE;
      35                 :           6 :                 slog(TRACE,"Dry Run mode was activated. In-memory database will be used to simulate activity.\n");
      36                 :             :         }
      37                 :             : 
      38         [ +  + ]:         313 :         if(SQLITE_OK == (rc = sqlite3_open_v2(db_file_path,&config->db,config->sqlite_open_flag,NULL)))
      39                 :             :         {
      40                 :         311 :                 slog(TRACE,"Successfully opened database %s\n",confstr(db_file_name));
      41         [ +  - ]:           2 :         } else if(config->compare != true){
      42                 :           2 :                 log_sqlite_error(config->db,
      43                 :             :                         rc,
      44                 :             :                         NULL,
      45                 :             :                         "Can't open database %s",
      46                 :           2 :                         confstr(db_primary_file_path));
      47                 :           2 :                 status = FAILURE;
      48                 :             :         }
      49                 :             : 
      50                 :             :         /**
      51                 :             :          * Allow or disallow database table initialization.
      52                 :             :          * If Dry Run mode is active, this option can be useful
      53                 :             :          * to prevent modification of the existing database.
      54                 :             :          *
      55                 :             :          * Table initialization will be necessary when the database
      56                 :             :          * is used in in-memory mode and is effectively recreated
      57                 :             :          * during the first connection.
      58                 :             :          *
      59                 :             :          * Additionally, database table initialization can be used
      60                 :             :          * to update the database schema during software upgrades.
      61                 :             :          *
      62                 :             :          * This describes several database management scenarios:
      63                 :             :          *
      64                 :             :          * 1. Table Initialization Control
      65                 :             :          *   - Option to enable/disable table schema creation
      66                 :             :          *   - Particularly useful with Dry Run mode to prevent schema changes
      67                 :             :          *   - Acts as a safety mechanism for existing databases
      68                 :             :          * 2. In-Memory Database Scenarios
      69                 :             :          *   - When using in-memory mode, tables need initialization
      70                 :             :          *   - Tables are recreated on first connection
      71                 :             :          *   - No persistent storage between sessions
      72                 :             :          * 3. Schema Migration Use Case
      73                 :             :          *   - Can be used during software updates
      74                 :             :          *   - Allows automatic schema updates
      75                 :             :          *   - Supports database structure evolution with software versions
      76                 :             :          */
      77         [ +  + ]:         313 :         if(config->db_initialize_tables == true)
      78                 :             :         {
      79         [ +  + ]:         127 :                 if(SUCCESS == status)
      80                 :             :                 {
      81                 :             : #if 0 // Frozen multiPATH feature
      82                 :             :                         const char *sql =
      83                 :             :                                 "PRAGMA foreign_keys=OFF;"
      84                 :             :                                 "PRAGMA journal_mode=DELETE;"        // Use DELETE journal to avoid WAL artifacts
      85                 :             :                                 "PRAGMA page_size=4096;"            // Set page size to 4KB (default, but explicit for clarity)
      86                 :             :                                 "PRAGMA cache_size=-8192;"          // Use 8MB of memory for caching (negative value = KB)
      87                 :             :                                 "PRAGMA synchronous=NORMAL;"        // Balance speed and safety (NORMAL = fsync only for checkpoints)
      88                 :             :                                 "PRAGMA strict = ON;"
      89                 :             :                                 "BEGIN TRANSACTION;"
      90                 :             :                                 "CREATE TABLE IF NOT EXISTS metadata (db_version INTEGER NOT NULL UNIQUE);"
      91                 :             :                                 "CREATE TABLE IF NOT EXISTS files("  \
      92                 :             :                                 "ID INTEGER PRIMARY KEY NOT NULL,"
      93                 :             :                                 "offset INTEGER DEFAULT NULL,"
      94                 :             :                                 "path_prefix_index INTEGER NOT NULL,"
      95                 :             :                                 "relative_path TEXT NOT NULL,"
      96                 :             :                                 "sha512 BLOB DEFAULT NULL,"
      97                 :             :                                 "stat BLOB DEFAULT NULL,"
      98                 :             :                                 "mdContext BLOB DEFAULT NULL,"
      99                 :             :                                 "CONSTRAINT full_path UNIQUE (path_prefix_index, relative_path) ON CONFLICT FAIL);"
     100                 :             :                                 "CREATE INDEX IF NOT EXISTS full_path_ASC ON files (path_prefix_index, relative_path ASC);"
     101                 :             :                                 "CREATE TABLE IF NOT EXISTS paths ("
     102                 :             :                                 "ID INTEGER PRIMARY KEY UNIQUE NOT NULL,"
     103                 :             :                                 "prefix TEXT NOT NULL UNIQUE);"
     104                 :             :                                 "REPLACE INTO metadata (db_version) VALUES (" TOSTRING(CURRENT_DB_VERSION) ");"
     105                 :             :                                 "COMMIT;";
     106                 :             : #endif
     107                 :             : 
     108                 :             :                         /* Full runtime path is stored in the table 'paths' */
     109                 :         125 :                         const char *sql =
     110                 :             :                                 "PRAGMA foreign_keys=OFF;"
     111                 :             :                                 "PRAGMA journal_mode=DELETE;"        // Use DELETE journal to avoid WAL artifacts
     112                 :             :                                 "PRAGMA page_size=4096;"            // Set page size to 4KB (default, but explicit for clarity)
     113                 :             :                                 "PRAGMA cache_size=-8192;"          // Use 8MB of memory for caching (negative value = KB)
     114                 :             :                                 "PRAGMA synchronous=NORMAL;"        // Balance speed and safety (NORMAL = fsync only for checkpoints)
     115                 :             :                                 "PRAGMA strict = ON;"
     116                 :             :                                 "BEGIN TRANSACTION;"
     117                 :             :                                 "CREATE TABLE IF NOT EXISTS metadata (db_version INTEGER NOT NULL UNIQUE);"
     118                 :             :                                 "CREATE TABLE IF NOT EXISTS files("  \
     119                 :             :                                 "ID INTEGER PRIMARY KEY NOT NULL,"
     120                 :             :                                 "offset INTEGER DEFAULT NULL,"
     121                 :             :                                 "relative_path TEXT UNIQUE NOT NULL,"
     122                 :             :                                 "sha512 BLOB DEFAULT NULL,"
     123                 :             :                                 "stat BLOB DEFAULT NULL,"
     124                 :             :                                 "mdContext BLOB DEFAULT NULL);"
     125                 :             :                                 "CREATE UNIQUE INDEX IF NOT EXISTS 'TEXT_ASC' ON 'files' ('relative_path' ASC);"
     126                 :             :                                 "CREATE TABLE IF NOT EXISTS paths ("
     127                 :             :                                 "ID INTEGER PRIMARY KEY UNIQUE NOT NULL,"
     128                 :             :                                 "prefix TEXT NOT NULL UNIQUE);"
     129                 :             :                                 "REPLACE INTO metadata (db_version) VALUES (" TOSTRING(CURRENT_DB_VERSION) ");"
     130                 :             :                                 "COMMIT;";
     131                 :             : 
     132                 :             :                         /* Execute SQL statement */
     133                 :         125 :                         rc = sqlite3_exec(config->db,sql,NULL,NULL,NULL);
     134                 :             : 
     135         [ +  - ]:         125 :                         if(rc == SQLITE_OK)
     136                 :             :                         {
     137                 :         125 :                                 slog(TRACE,"The primary database and tables have been successfully initialized\n");
     138                 :             :                         } else {
     139                 :           0 :                                 log_sqlite_error(config->db,rc,NULL,"Can't execute table initialization");
     140                 :           0 :                                 status = FAILURE;
     141                 :             :                         }
     142                 :             :                 }
     143                 :             :         } else {
     144                 :         186 :                 slog(TRACE,"The primary database and tables do not require initialization\n");
     145                 :             :         }
     146                 :             : 
     147         [ +  + ]:         313 :         if(SUCCESS == status)
     148                 :             :         {
     149                 :             :                 // Tune the DB performance
     150                 :         311 :                 const char *pragma_sql = NULL;
     151                 :             : 
     152         [ +  + ]:         311 :                 if(config->sqlite_open_flag == SQLITE_OPEN_READONLY)
     153                 :             :                 {
     154                 :             :                         // Read-only mode
     155                 :          86 :                         pragma_sql =
     156                 :             :                                 "PRAGMA synchronous=OFF;"            // Disable fsync to speed up read-only access
     157                 :             :                                 "PRAGMA cache_size=-8192;"           // Increased cache to 8MB
     158                 :             :                                 "PRAGMA temp_store=MEMORY;"          // Keep temporary data in RAM
     159                 :             :                                 "PRAGMA mmap_size=30000000000;"      // Using memory-mapped I/O
     160                 :             :                                 "PRAGMA locking_mode=EXCLUSIVE;"     // Hold exclusive locks for the session
     161                 :             :                                 "PRAGMA strict=ON;";                  // Enforce STRICT table schema validation
     162                 :             :                 } else {
     163                 :             :                         // Read-write mode
     164                 :         225 :                         pragma_sql =
     165                 :             :                                 "PRAGMA journal_mode=DELETE; "       // Use DELETE journal
     166                 :             :                                 "PRAGMA cache_size=-8192; "          // Use 8MB of memory for caching (negative value = KB)
     167                 :             :                                 "PRAGMA synchronous=NORMAL; "        // Balance speed and safety (NORMAL = fsync only for checkpoints)
     168                 :             :                                 "PRAGMA temp_store=MEMORY; "         // Store temporary tables in memory (not on disk)
     169                 :             :                                 "PRAGMA strict=ON;"                  // Enforce STRICT table schema validation
     170                 :             :                                 "PRAGMA locking_mode=EXCLUSIVE;"     // Hold exclusive locks for the session
     171                 :             :                                 "PRAGMA fsync=OFF;";                 // Disables fsync() for faster writes but risks data loss on crash
     172                 :             :                 }
     173                 :             : 
     174                 :             :                 // Set SQLite pragmas
     175                 :         311 :                 rc = sqlite3_exec(config->db,pragma_sql,NULL,NULL,NULL);
     176                 :             : 
     177         [ +  - ]:         311 :                 if(rc == SQLITE_OK)
     178                 :             :                 {
     179                 :         311 :                         slog(TRACE,"The primary database named %s is ready for operations\n",confstr(db_file_name));
     180                 :             :                 } else {
     181                 :           0 :                         log_sqlite_error(config->db,rc,NULL,"Can't execute pragma setup");
     182                 :           0 :                         status = FAILURE;
     183                 :             :                 }
     184                 :             :         }
     185                 :             : 
     186         [ +  + ]:         313 :         if(SUCCESS == status)
     187                 :             :         {
     188                 :         311 :                 const char *remember_history_sql =
     189                 :             :                         "CREATE TEMP TABLE IF NOT EXISTS remember_history ("
     190                 :             :                         "id INTEGER PRIMARY KEY AUTOINCREMENT,"
     191                 :             :                         "message TEXT NOT NULL"
     192                 :             :                         ");";
     193                 :             : 
     194                 :         311 :                 rc = sqlite3_exec(config->db,remember_history_sql,NULL,NULL,NULL);
     195                 :             : 
     196         [ -  + ]:         311 :                 if(rc != SQLITE_OK)
     197                 :             :                 {
     198                 :           0 :                         log_sqlite_error(config->db,rc,NULL,"Can't create TEMP remember_history table");
     199                 :             :                 }
     200                 :             : 
     201         [ +  + ]:         311 :                 if(config->compare != true)
     202                 :             :                 {
     203                 :         235 :                         const char *db_runtime_paths =
     204                 :             :                                 "CREATE TEMP TABLE IF NOT EXISTS the_path_id_does_not_exists"
     205                 :             :                                 "(path_id INTEGER UNIQUE NOT NULL);";
     206                 :             : 
     207                 :         235 :                         rc = sqlite3_exec(config->db,db_runtime_paths,NULL,NULL,NULL);
     208                 :             : 
     209         [ +  - ]:         235 :                         if(rc == SQLITE_OK)
     210                 :             :                         {
     211                 :         235 :                                 slog(TRACE,"The TEMP table the_path_id_does_not_exists is ready for runtime checks\n");
     212                 :             :                         } else {
     213                 :           0 :                                 log_sqlite_error(config->db,rc,NULL,"Can't create runtime TEMP table");
     214                 :           0 :                                 status = FAILURE;
     215                 :             :                         }
     216                 :             :                 }
     217                 :             :         }
     218                 :             : 
     219                 :         313 :         slog(TRACE,"Database initialization process completed\n");
     220                 :             : 
     221                 :         313 :         provide(status);
     222                 :             : }
        

Generated by: LCOV version 2.0-1