1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200
|
// file : odb/sqlite/connection.cxx
// copyright : Copyright (c) 2005-2015 Code Synthesis Tools CC
// license : GNU GPL v2; see accompanying LICENSE file
#include <new> // std::bad_alloc
#include <string>
#include <cassert>
#include <odb/details/lock.hxx>
#include <odb/sqlite/database.hxx>
#include <odb/sqlite/connection.hxx>
#include <odb/sqlite/transaction.hxx>
#include <odb/sqlite/statement.hxx>
#include <odb/sqlite/statement-cache.hxx>
#include <odb/sqlite/prepared-query.hxx>
#include <odb/sqlite/error.hxx>
#include <odb/sqlite/exceptions.hxx> // deadlock
#include <odb/sqlite/details/config.hxx> // LIBODB_SQLITE_HAVE_UNLOCK_NOTIFY
using namespace std;
extern "C" void
odb_sqlite_connection_unlock_callback (void**, int);
namespace odb
{
namespace sqlite
{
connection::
connection (database_type& db, int extra_flags)
: odb::connection (db),
db_ (db),
unlock_cond_ (unlock_mutex_),
statements_ (0)
{
int f (db.flags () | extra_flags);
const string& n (db.name ());
// If we are opening a temporary database, then add the create flag.
//
if (n.empty () || n == ":memory:")
f |= SQLITE_OPEN_CREATE;
// A connection can only be used by a single thread at a time. So
// disable locking in SQLite unless explicitly requested.
//
#if defined(SQLITE_OPEN_NOMUTEX)
if ((f & SQLITE_OPEN_FULLMUTEX) == 0)
f |= SQLITE_OPEN_NOMUTEX;
#endif
sqlite3* h (0);
// sqlite3_open_v2() was only addedin SQLite 3.5.0.
//
#if SQLITE_VERSION_NUMBER >= 3005000
const string& vfs (db.vfs ());
int e (
sqlite3_open_v2 (
n.c_str (), &h, f, (vfs.empty () ? 0 : vfs.c_str ())));
#else
// Readonly opening not supported in SQLite earlier than 3.5.0.
//
assert ((f & SQLITE_OPEN_READONLY) == 0);
int e (sqlite3_open (n.c_str (), &h));
#endif
handle_.reset (h);
if (e != SQLITE_OK)
{
if (handle_ == 0)
throw bad_alloc ();
translate_error (e, *this);
}
init ();
}
connection::
connection (database_type& db, sqlite3* handle)
: odb::connection (db),
db_ (db),
handle_ (handle),
unlock_cond_ (unlock_mutex_),
statements_ (0)
{
init ();
}
void connection::
init ()
{
// Enable/disable foreign key constraints.
//
generic_statement st (
*this,
db_.foreign_keys ()
? "PRAGMA foreign_keys=ON"
: "PRAGMA foreign_keys=OFF",
db_.foreign_keys () ? 22 : 23);
st.execute ();
// Create statement cache.
//
statement_cache_.reset (new statement_cache_type (*this));
}
connection::
~connection ()
{
// Destroy prepared query statements before freeing the connections.
//
recycle ();
clear_prepared_map ();
}
transaction_impl* connection::
begin ()
{
return new transaction_impl (
connection_ptr (inc_ref (this)), transaction_impl::deferred);
}
transaction_impl* connection::
begin_immediate ()
{
return new transaction_impl (
connection_ptr (inc_ref (this)), transaction_impl::immediate);
}
transaction_impl* connection::
begin_exclusive ()
{
return new transaction_impl (
connection_ptr (inc_ref (this)), transaction_impl::exclusive);
}
unsigned long long connection::
execute (const char* s, std::size_t n)
{
generic_statement st (*this, s, n);
return st.execute ();
}
inline void
connection_unlock_callback (void** args, int n)
{
for (int i (0); i < n; ++i)
{
connection* c (static_cast<connection*> (args[i]));
details::lock l (c->unlock_mutex_);
c->unlocked_ = true;
c->unlock_cond_.signal ();
}
}
void connection::
wait ()
{
#ifdef LIBODB_SQLITE_HAVE_UNLOCK_NOTIFY
unlocked_ = false;
// unlock_notify() returns SQLITE_OK or SQLITE_LOCKED (deadlock).
//
int e (sqlite3_unlock_notify (handle_,
&odb_sqlite_connection_unlock_callback,
this));
if (e == SQLITE_LOCKED)
throw deadlock ();
details::lock l (unlock_mutex_);
while (!unlocked_)
unlock_cond_.wait ();
#else
translate_error (SQLITE_LOCKED, *this);
#endif
}
void connection::
clear ()
{
// The current first statement will remove itself from the list
// and make the second statement (if any) the new first.
//
while (statements_ != 0)
statements_->reset ();
}
}
}
extern "C" void
odb_sqlite_connection_unlock_callback (void** args, int n)
{
odb::sqlite::connection_unlock_callback (args, n);
}
|