LCOV - code coverage report
Current view: top level - src/sl3 - database.cpp (source / functions) Coverage Total Hit
Test: coverage.info.cleaned Lines: 100.0 % 106 106
Test Date: 2024-12-09 18:45:33 Functions: 96.6 % 29 28
Branches: 70.7 % 82 58

             Branch data     Line data    Source code
       1                 :             : /******************************************************************************
       2                 :             :  ------------- Copyright (c) 2009-2023 H a r a l d  A c h i t z ---------------
       3                 :             :  ---------- < h a r a l d dot a c h i t z at g m a i l dot c o m > ------------
       4                 :             :  ---- This Source Code Form is subject to the terms of the Mozilla Public -----
       5                 :             :  ---- License, v. 2.0. If a copy of the MPL was not distributed with this -----
       6                 :             :  ---------- file, You can obtain one at http://mozilla.org/MPL/2.0/. ----------
       7                 :             :  ******************************************************************************/
       8                 :             : 
       9                 :             : #include <sl3/database.hpp>
      10                 :             : 
      11                 :             : #include <sqlite3.h>
      12                 :             : 
      13                 :             : #include "connection.hpp"
      14                 :             : 
      15                 :             : namespace
      16                 :             : {
      17                 :             :   sqlite3*
      18                 :         102 :   opendb (const std::string& name, int openFlags)
      19                 :             :   {
      20         [ +  - ]:         102 :     if (openFlags == 0)
      21                 :             :       {
      22                 :         102 :         openFlags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
      23                 :             :       }
      24                 :             : 
      25                 :         102 :     sqlite3* db    = nullptr;
      26         [ +  - ]:         102 :     auto     sl3rc = sqlite3_open_v2 (name.c_str (), &db, openFlags, nullptr);
      27                 :             : 
      28         [ +  + ]:         102 :     if (sl3rc != SQLITE_OK)
      29                 :             :       {
      30                 :             :         using scope_guard
      31                 :             :             = std::unique_ptr<sqlite3, decltype (&sqlite3_close)>;
      32                 :           1 :         scope_guard guard{db, &sqlite3_close};
      33   [ +  -  +  - ]:           1 :         throw sl3::SQLite3Error{sl3rc, sqlite3_errmsg (db)};
      34                 :           1 :       }
      35                 :         101 :     return db;
      36                 :             :   }
      37                 :             : 
      38                 :             : }
      39                 :             : 
      40                 :             : namespace sl3
      41                 :             : {
      42                 :             : 
      43                 :             :   std::string
      44                 :           4 :   getErrStr (int errcode)
      45                 :             :   {
      46   [ +  -  +  - ]:           8 :     return std::string (sqlite3_errstr (errcode));
      47                 :             :   }
      48                 :             : 
      49                 :         102 :   Database::Database (const std::string& name, int flags)
      50   [ +  +  +  -  :         102 :   : _connection{new internal::Connection{opendb (name, flags)}}
                   +  - ]
      51                 :             :   {
      52         [ +  - ]:         101 :     sqlite3_extended_result_codes (_connection->db (), true);
      53                 :         101 :   }
      54                 :             : 
      55                 :          11 :   Database::Database (Database&& other) noexcept
      56                 :          11 :   : _connection (std::move (other._connection))
      57                 :             :   {
      58                 :             :     // always have a connection, but an invalid one
      59                 :          11 :     other._connection.reset (new internal::Connection{nullptr});
      60                 :          11 :   }
      61                 :             : 
      62                 :         112 :   Database::~Database () noexcept
      63                 :             :   {
      64         [ +  - ]:         112 :     if (_connection != nullptr)
      65                 :             :       {
      66                 :         112 :         _connection->close ();
      67                 :             :       }
      68                 :         112 :   }
      69                 :             : 
      70                 :             :   Command
      71                 :          55 :   Database::prepare (const std::string& sql)
      72                 :             :   {
      73         [ +  + ]:          55 :     return {_connection, sql};
      74                 :             :   }
      75                 :             : 
      76                 :             :   Command
      77                 :           9 :   Database::prepare (const std::string& sql, const DbValues& parameters)
      78                 :             :   {
      79   [ +  -  +  + ]:          14 :     return {_connection, sql, parameters};
      80                 :             :   }
      81                 :             : 
      82                 :             :   void
      83                 :           1 :   Database::execute (const std::string& sql)
      84                 :             :   {
      85                 :           1 :     execute (sql.c_str ());
      86                 :           1 :   }
      87                 :             : 
      88                 :             :   void
      89                 :         102 :   Database::execute (const char* sql)
      90                 :             :   {
      91         [ +  + ]:         102 :     _connection->ensureValid ();
      92                 :         100 :     char* dbMsg = nullptr;
      93                 :             : 
      94         [ +  - ]:         100 :     int rc = sqlite3_exec (_connection->db (), sql, nullptr, nullptr, &dbMsg);
      95                 :             : 
      96         [ +  + ]:         100 :     if (rc != SQLITE_OK)
      97                 :             :       {
      98                 :             :         using scope_guard = std::unique_ptr<char, decltype (&sqlite3_free)>;
      99                 :           6 :         scope_guard guard (dbMsg, &sqlite3_free);
     100         [ +  - ]:           6 :         throw SQLite3Error{rc, dbMsg};
     101                 :           6 :       }
     102                 :          94 :   }
     103                 :             : 
     104                 :             :   void
     105                 :           7 :   Database::execute (const std::string& sql, RowCallback& cb)
     106                 :             :   {
     107   [ +  +  +  - ]:           7 :     prepare (sql).execute (cb);
     108                 :           5 :   }
     109                 :             : 
     110                 :             :   void
     111                 :          29 :   Database::execute (const std::string& sql, Callback cb)
     112                 :             :   {
     113   [ +  +  +  - ]:          29 :     prepare (sql).execute (std::move (cb));
     114                 :          27 :   }
     115                 :             : 
     116                 :             :   Dataset
     117                 :          20 :   Database::select (const std::string& sql)
     118                 :             :   {
     119   [ +  +  +  - ]:          22 :     return Command (_connection, sql).select ();
     120                 :             :   }
     121                 :             : 
     122                 :             :   Dataset
     123                 :          22 :   Database::select (const std::string& sql, const Types& types)
     124                 :             :   {
     125   [ +  +  +  + ]:          33 :     return Command (_connection, sql).select (types);
     126                 :             :   }
     127                 :             : 
     128                 :             :   DbValue
     129                 :           7 :   Database::selectValue (const std::string& sql)
     130                 :             :   {
     131                 :           7 :     DbValue retVal (Type::Variant);
     132                 :             : 
     133                 :          19 :     Callback cb = [&retVal] (Columns cols) -> bool {
     134   [ +  -  +  - ]:           5 :       retVal = cols.getValue (0);
     135                 :           5 :       return false; // exit after first row
     136                 :           7 :     };
     137                 :             : 
     138         [ +  + ]:           9 :     Command cmd (_connection, sql);
     139   [ +  -  +  - ]:           5 :     cmd.execute (cb);
     140                 :             : 
     141                 :          10 :     return retVal;
     142                 :           9 :   }
     143                 :             : 
     144                 :             :   DbValue
     145                 :           5 :   Database::selectValue (const std::string& sql, Type type)
     146                 :             :   {
     147                 :           5 :     DbValue retVal{type};
     148                 :             : 
     149                 :          13 :     Callback cb = [&retVal, type] (Columns cols) -> bool {
     150   [ +  +  +  - ]:           3 :       retVal = cols.getValue (0, type);
     151                 :           2 :       return false; // exit after first row
     152                 :           5 :     };
     153                 :             : 
     154         [ +  + ]:           7 :     Command cmd (_connection, sql);
     155   [ +  -  +  + ]:           5 :     cmd.execute (cb);
     156                 :             : 
     157                 :           4 :     return retVal;
     158                 :           9 :   }
     159                 :             : 
     160                 :             :   int
     161                 :           5 :   Database::getMostRecentErrCode ()
     162                 :             :   {
     163                 :           5 :     _connection->ensureValid ();
     164                 :           4 :     return sqlite3_extended_errcode (_connection->db ());
     165                 :             :   }
     166                 :             : 
     167                 :             :   std::string
     168                 :           5 :   Database::getMostRecentErrMsg ()
     169                 :             :   {
     170                 :           5 :     _connection->ensureValid ();
     171   [ +  -  +  - ]:           8 :     return std::string (sqlite3_errmsg (_connection->db ()));
     172                 :             :   }
     173                 :             : 
     174                 :             :   std::size_t
     175                 :           9 :   Database::getTotalChanges ()
     176                 :             :   {
     177                 :           9 :     _connection->ensureValid ();
     178                 :             :     return static_cast<std::size_t> (
     179                 :           8 :         sqlite3_total_changes (_connection->db ()));
     180                 :             :   }
     181                 :             : 
     182                 :             :   std::size_t
     183                 :           5 :   Database::getRecentlyChanged ()
     184                 :             :   {
     185                 :           5 :     _connection->ensureValid ();
     186                 :           4 :     return static_cast<std::size_t> (sqlite3_changes (_connection->db ()));
     187                 :             :   }
     188                 :             : 
     189                 :             :   int64_t
     190                 :           4 :   Database::getLastInsertRowid ()
     191                 :             :   {
     192                 :           4 :     _connection->ensureValid ();
     193                 :           3 :     return sqlite3_last_insert_rowid (_connection->db ());
     194                 :             :   }
     195                 :             : 
     196                 :             :   sqlite3*
     197                 :           2 :   Database::db ()
     198                 :             :   {
     199                 :           2 :     return _connection->db ();
     200                 :             :   }
     201                 :             : 
     202                 :             :   auto
     203                 :           4 :   Database::beginTransaction () -> Transaction
     204                 :             :   {
     205                 :           4 :     return Transaction{*this};
     206                 :             :   }
     207                 :             : 
     208                 :           4 :   Database::Transaction::Transaction (Database& db)
     209                 :           4 :   : _db (&db)
     210                 :             :   {
     211                 :           4 :     _db->execute ("BEGIN TRANSACTION");
     212                 :           4 :   }
     213                 :             : 
     214                 :           2 :   Database::Transaction::Transaction (Transaction&& other) noexcept
     215                 :           2 :   : _db (other._db)
     216                 :             :   {
     217                 :           2 :     other._db = nullptr; // ensure other does not commit in d'tor
     218                 :           2 :   }
     219                 :             : 
     220                 :           6 :   Database::Transaction::~Transaction ()
     221                 :             :   {
     222         [ +  + ]:           6 :     if (_db)
     223                 :           2 :       _db->execute ("ROLLBACK TRANSACTION");
     224                 :           6 :   }
     225                 :             : 
     226                 :             :   void
     227                 :           3 :   Database::Transaction::commit ()
     228                 :             :   {
     229         [ +  + ]:           3 :     if (_db)
     230                 :             :       {
     231                 :           2 :         _db->execute ("COMMIT TRANSACTION");
     232                 :           2 :         _db = nullptr;
     233                 :             :       }
     234                 :           3 :   }
     235                 :             : 
     236                 :             : } // ns
        

Generated by: LCOV version 2.0-1