LCOV - code coverage report
Current view: top level - lib - database.c (source / functions) Hit Total Coverage
Test: smtpd.info Lines: 29 70 41.4 %
Date: 2015-11-25 19:06:20 Functions: 3 4 75.0 %

          Line data    Source code
       1             : /* This file is part of the cmail project (http://cmail.rocks/)
       2             :  * (c) 2015 Fabian "cbdev" Stumpf
       3             :  * License: Simplified BSD (2-Clause)
       4             :  * For further information, consult LICENSE.txt
       5             :  */
       6             : 
       7           0 : void database_instr(sqlite3_context* context, int argc, sqlite3_value** argv){
       8             :         //mostly copied from sqlite-src/func.c
       9             : 
      10             :         int nHaystack;
      11             :         int nNeedle;
      12           0 :         int N = 1;
      13             : 
      14             :         const unsigned char* hay;
      15             :         const unsigned char* needle;
      16           0 :         bool text=false;
      17             : 
      18           0 :         if(sqlite3_value_type(argv[0]) == SQLITE_NULL
      19           0 :                 || sqlite3_value_type(argv[1]) == SQLITE_NULL){
      20             :                 //bail out
      21           0 :                 return;
      22             :         }
      23             : 
      24           0 :         nHaystack = sqlite3_value_bytes(argv[0]);
      25           0 :         nNeedle = sqlite3_value_bytes(argv[1]);
      26             : 
      27           0 :         if(sqlite3_value_type(argv[0]) == SQLITE_BLOB
      28           0 :                 && sqlite3_value_type(argv[1]) == SQLITE_BLOB){
      29             : 
      30           0 :                 hay = sqlite3_value_blob(argv[0]);
      31           0 :                 needle = sqlite3_value_blob(argv[1]);
      32             :         }
      33             :         else{
      34           0 :                 hay = sqlite3_value_text(argv[0]);
      35           0 :                 needle = sqlite3_value_text(argv[1]);
      36           0 :                 text = true;
      37             :         }
      38             : 
      39           0 :         while(nNeedle <= nHaystack && memcmp(hay, needle, nNeedle) != 0){
      40           0 :                 N++;
      41             :                 do{
      42           0 :                         nHaystack--;
      43           0 :                         hay++;
      44             :                 }
      45             :                 //this includes checks for UTF-8 characters
      46           0 :                 while(text && (hay[0] & 0xc0) == 0x80);
      47             :         }
      48             : 
      49           0 :         if(nNeedle > nHaystack){
      50           0 :                 N = 0;
      51             :         }
      52           0 :         sqlite3_result_int(context, N);
      53             : }
      54             : 
      55          12 : sqlite3_stmt* database_prepare(LOGGER log, sqlite3* conn, char* query){
      56             :         int status;
      57          12 :         sqlite3_stmt* target = NULL;
      58             : 
      59          12 :         status = sqlite3_prepare_v2(conn, query, strlen(query), &target, NULL);
      60             : 
      61          12 :         switch(status){
      62             :                 case SQLITE_OK:
      63          12 :                         logprintf(log, LOG_DEBUG, "Statement (%s) compiled ok\n", query);
      64          12 :                         return target;
      65             :                 default:
      66           0 :                         logprintf(log, LOG_ERROR, "Failed to prepare statement (%s): %s\n", query, sqlite3_errmsg(conn));
      67             :         }
      68             : 
      69           0 :         return NULL;
      70             : }
      71             : 
      72           4 : sqlite3* database_open(LOGGER log, const char* filename, int flags){
      73           4 :         sqlite3* db = NULL;
      74             : 
      75           4 :         switch(sqlite3_open_v2(filename, &db, flags, NULL)){
      76             :                 case SQLITE_OK:
      77           3 :                         logprintf(log, LOG_INFO, "Opened database %s\n", filename);
      78           3 :                         break;
      79             :                 default:
      80           1 :                         logprintf(log, LOG_ERROR, "Failed to open database %s: %s\n", filename, sqlite3_errmsg(db));
      81           1 :                         sqlite3_close(db);
      82           1 :                         return NULL;
      83             :         }
      84             : 
      85           3 :         switch(sqlite3_exec(db, "PRAGMA foreign_keys = ON;", NULL, NULL, NULL)){
      86             :                 case SQLITE_OK:
      87             :                 case SQLITE_DONE:
      88           3 :                         break;
      89             :                 default:
      90           0 :                         logprintf(log, LOG_ERROR, "Failed to enable foreign key support: %s\n", sqlite3_errmsg(db));
      91           0 :                         sqlite3_close(db);
      92           0 :                         return NULL;
      93             :         }
      94             : 
      95           3 :         if(sqlite3_create_function(db, "instr", 2, SQLITE_UTF8 | SQLITE_DETERMINISTIC, NULL, database_instr, NULL, NULL) != SQLITE_OK){
      96           0 :                 logprintf(log, LOG_ERROR, "Failed to register instr() with sqlite: %s\n", sqlite3_errmsg(db));
      97           0 :                 sqlite3_close(db);
      98           0 :                 return NULL;
      99             :         }
     100             : 
     101           3 :         if(sqlite3_busy_timeout(db, 500000) != SQLITE_OK){
     102           0 :                 logprintf(log, LOG_ERROR, "Failed to set sqlite busy timeout\n");
     103           0 :                 sqlite3_close(db);
     104           0 :                 return NULL;
     105             :         }
     106             : 
     107           3 :         return db;
     108             : }
     109             : 
     110           1 : int database_schema_version(LOGGER log, sqlite3* conn){
     111             :         int status;
     112           1 :         char* QUERY_SCHEMA_VERSION = "SELECT value FROM meta WHERE key='schema_version'";
     113           1 :         sqlite3_stmt* query_version = database_prepare(log, conn, QUERY_SCHEMA_VERSION);
     114             : 
     115           1 :         if(!query_version){
     116           0 :                 logprintf(log, LOG_ERROR, "Failed to query the database schema version, your database file might not be a valid master database\n");
     117           0 :                 return -1;
     118             :         }
     119             : 
     120           1 :         switch(sqlite3_step(query_version)){
     121             :                 case SQLITE_ROW:
     122           1 :                         status = strtoul((char*)sqlite3_column_text(query_version, 0), NULL, 10);
     123           1 :                         logprintf(log, LOG_INFO, "Database schema version is %d\n", status);
     124           1 :                         break;
     125             :                 case SQLITE_DONE:
     126           0 :                         logprintf(log, LOG_ERROR, "The database did not contain a schema_version key\n");
     127           0 :                         status = -1;
     128           0 :                         break;
     129             :                 default:
     130           0 :                         logprintf(log, LOG_ERROR, "Failed to get schema version: %s\n", sqlite3_errmsg(conn));
     131           0 :                         status = -1;
     132             :         }
     133             : 
     134           1 :         sqlite3_finalize(query_version);
     135           1 :         return status;
     136             : }

Generated by: LCOV version 1.11