Connection.h
Go to the documentation of this file.
1 #ifndef cetlib_sqlite_Connection_h
2 #define cetlib_sqlite_Connection_h
3 // vim: set sw=2 expandtab :
4 
5 // ====================================================================
6 // A Connection is an RAII-motivated class that automatically handles
7 // opening and closing of the database handle.
8 //
9 // It receives a template argument that specifies the database-opening
10 // policy. The database closing policy is sqlite3_close(db).
11 //
12 // Note that whenever a Connection object is created, database locking
13 // is automatically disabled to accommodate operations on NFS systems.
14 // The Connection is created by the ConnectionFactory, which
15 // constructs a Connection in a thread-safe way. However, when using
16 // a connection, the user must ensure that updates to the same
17 // database via Connection objects is serialized.
18 // ====================================================================
19 
22 #include "sqlite3.h"
23 
24 #include <memory>
25 #include <mutex>
26 #include <string>
27 #include <vector>
28 
29 namespace cet::sqlite {
30 
31  class Connection {
32  friend class ConnectionFactory;
33 
34  public:
35  ~Connection() noexcept;
36  // It is permitted to create an invalid Connection object
37  // through default construction. However, any connections to an
38  // SQLite database must be retrieved through the
39  // ConnectionFactory.
40  explicit Connection() = default;
41  Connection(Connection const&) = delete;
42  Connection(Connection&&) = delete;
43  Connection& operator=(Connection const&) = delete;
44  Connection& operator=(Connection&&) = delete;
45 
46  public:
47  sqlite3*
48  get() const
49  {
50  return db_;
51  }
52  operator sqlite3*() { return db_; }
53  template <std::size_t NColumns, typename Row>
54  int flush_no_throw(std::vector<Row> const& buffer,
55  sqlite3_stmt*& insertStmt);
56 
57  private:
58  template <typename DatabaseOpenPolicy>
59  explicit Connection(std::string const& filename,
60  std::shared_ptr<std::recursive_mutex>,
61  DatabaseOpenPolicy);
62 
63  private:
64  sqlite3* db_{nullptr};
65  // Shared with other connections to the same database
66  std::shared_ptr<std::recursive_mutex> mutex_{nullptr};
67  };
68 
69  template <typename DatabaseOpenPolicy>
71  std::shared_ptr<std::recursive_mutex> spmutex,
72  DatabaseOpenPolicy policy)
73  : mutex_{spmutex}
74  {
75  // No lock necessary since the c'tor is called in a protected
76  // environment.
77  db_ = policy.open(filename);
78  }
79 
80  template <std::size_t NColumns, typename Row>
81  int
82  Connection::flush_no_throw(std::vector<Row> const& buffer,
83  sqlite3_stmt*& insertStmt)
84  {
85  // Guard against concurrent updates to the same database.
86  std::lock_guard sentry{*mutex_};
88  for (auto const& r : buffer) {
90  int const rc{sqlite3_step(insertStmt)};
91  if (rc != SQLITE_DONE) {
92  return rc;
93  }
94  sqlite3_reset(insertStmt);
95  }
96  txn.commit();
97  return SQLITE_DONE;
98  }
99 
100 } // namespace cet::sqlite
101 
102 #endif /* cetlib_sqlite_Connection_h */
103 
104 // Local Variables:
105 // mode: c++
106 // End:
std::shared_ptr< std::recursive_mutex > mutex_
Definition: Connection.h:66
std::string string
Definition: nybbler.cc:12
struct sqlite3_stmt sqlite3_stmt
sqlite3 * get() const
Definition: Connection.h:48
string filename
Definition: train.py:213
struct sqlite3 sqlite3
int flush_no_throw(std::vector< Row > const &buffer, sqlite3_stmt *&insertStmt)
Definition: Connection.h:82
static void bind(sqlite3_stmt *s, TUP const &t)
~Connection() noexcept
Definition: Connection.cc:8