Botan 2.13.0 Crypto and TLS for C++11

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

sqlite3.cpp
Go to the documentation of this file.
1 /*
2 * SQLite wrapper
3 * (C) 2012 Jack Lloyd
4 *
5 * Botan is released under the Simplified BSD License (see license.txt)
6 */
7
8 #include <botan/sqlite3.h>
9 #include <botan/exceptn.h>
10 #include <botan/mem_ops.h>
11 #include <sqlite3.h>
12
13 namespace Botan {
14
15 Sqlite3_Database::Sqlite3_Database(const std::string& db_filename)
16 {
17 int rc = ::sqlite3_open(db_filename.c_str(), &m_db);
18
19 if(rc)
20 {
21 const std::string err_msg = ::sqlite3_errmsg(m_db);
22 ::sqlite3_close(m_db);
23 m_db = nullptr;
24 throw SQL_DB_Error("sqlite3_open failed - " + err_msg);
25 }
26 }
27
28 Sqlite3_Database::~Sqlite3_Database()
29 {
30 if(m_db)
31 ::sqlite3_close(m_db);
32 m_db = nullptr;
33 }
34
35 std::shared_ptr<SQL_Database::Statement> Sqlite3_Database::new_statement(const std::string& base_sql) const
36 {
37 return std::make_shared<Sqlite3_Statement>(m_db, base_sql);
38 }
39
40 size_t Sqlite3_Database::row_count(const std::string& table_name)
41 {
42 auto stmt = new_statement("select count(*) from " + table_name);
43
44 if(stmt->step())
45 return stmt->get_size_t(0);
46 else
47 throw SQL_DB_Error("Querying size of table " + table_name + " failed");
48 }
49
50 void Sqlite3_Database::create_table(const std::string& table_schema)
51 {
52 char* errmsg = nullptr;
53 int rc = ::sqlite3_exec(m_db, table_schema.c_str(), nullptr, nullptr, &errmsg);
54
55 if(rc != SQLITE_OK)
56 {
57 const std::string err_msg = errmsg;
58 ::sqlite3_free(errmsg);
59 ::sqlite3_close(m_db);
60 m_db = nullptr;
61 throw SQL_DB_Error("sqlite3_exec for table failed - " + err_msg);
62 }
63 }
64
65 Sqlite3_Database::Sqlite3_Statement::Sqlite3_Statement(sqlite3* db, const std::string& base_sql)
66 {
67 int rc = ::sqlite3_prepare_v2(db, base_sql.c_str(), -1, &m_stmt, nullptr);
68
69 if(rc != SQLITE_OK)
70 throw SQL_DB_Error("sqlite3_prepare failed on " + base_sql, rc);
71 }
72
73 void Sqlite3_Database::Sqlite3_Statement::bind(int column, const std::string& val)
74 {
75 int rc = ::sqlite3_bind_text(m_stmt, column, val.c_str(), -1, SQLITE_TRANSIENT);
76 if(rc != SQLITE_OK)
77 throw SQL_DB_Error("sqlite3_bind_text failed", rc);
78 }
79
80 void Sqlite3_Database::Sqlite3_Statement::bind(int column, size_t val)
81 {
82 if(val != static_cast<size_t>(static_cast<int>(val))) // is this cast legit?
83 throw SQL_DB_Error("sqlite3 cannot store " + std::to_string(val) + " without truncation");
84 int rc = ::sqlite3_bind_int(m_stmt, column, val);
85 if(rc != SQLITE_OK)
86 throw SQL_DB_Error("sqlite3_bind_int failed", rc);
87 }
88
89 void Sqlite3_Database::Sqlite3_Statement::bind(int column, std::chrono::system_clock::time_point time)
90 {
91 const int timeval = std::chrono::duration_cast<std::chrono::seconds>(time.time_since_epoch()).count();
92 bind(column, timeval);
93 }
94
95 void Sqlite3_Database::Sqlite3_Statement::bind(int column, const std::vector<uint8_t>& val)
96 {
97 int rc = ::sqlite3_bind_blob(m_stmt, column, val.data(), val.size(), SQLITE_TRANSIENT);
98 if(rc != SQLITE_OK)
99 throw SQL_DB_Error("sqlite3_bind_text failed", rc);
100 }
101
102 void Sqlite3_Database::Sqlite3_Statement::bind(int column, const uint8_t* p, size_t len)
103 {
104 int rc = ::sqlite3_bind_blob(m_stmt, column, p, len, SQLITE_TRANSIENT);
105 if(rc != SQLITE_OK)
106 throw SQL_DB_Error("sqlite3_bind_text failed", rc);
107 }
108
109 std::pair<const uint8_t*, size_t> Sqlite3_Database::Sqlite3_Statement::get_blob(int column)
110 {
111 BOTAN_ASSERT(::sqlite3_column_type(m_stmt, column) == SQLITE_BLOB,
112 "Return value is a blob");
113
114 const void* session_blob = ::sqlite3_column_blob(m_stmt, column);
115 const int session_blob_size = ::sqlite3_column_bytes(m_stmt, column);
116
117 BOTAN_ASSERT(session_blob_size >= 0, "Blob size is non-negative");
118
119 return std::make_pair(static_cast<const uint8_t*>(session_blob),
120 static_cast<size_t>(session_blob_size));
121 }
122
123 std::string Sqlite3_Database::Sqlite3_Statement::get_str(int column)
124 {
125 BOTAN_ASSERT(::sqlite3_column_type(m_stmt, column) == SQLITE_TEXT,
126 "Return value is text");
127
128 const unsigned char* str = ::sqlite3_column_text(m_stmt, column);
129
130 return std::string(cast_uint8_ptr_to_char(str));
131 }
132
133 size_t Sqlite3_Database::Sqlite3_Statement::get_size_t(int column)
134 {
135 BOTAN_ASSERT(::sqlite3_column_type(m_stmt, column) == SQLITE_INTEGER,
136 "Return count is an integer");
137
138 const int sessions_int = ::sqlite3_column_int(m_stmt, column);
139
140 BOTAN_ASSERT(sessions_int >= 0, "Expected size_t is non-negative");
141
142 return static_cast<size_t>(sessions_int);
143 }
144
145 size_t Sqlite3_Database::Sqlite3_Statement::spin()
146 {
147 size_t steps = 0;
148 while(step())
149 {
150 ++steps;
151 }
152
153 return steps;
154 }
155
156 bool Sqlite3_Database::Sqlite3_Statement::step()
157 {
158 return (::sqlite3_step(m_stmt) == SQLITE_ROW);
159 }
160
161 Sqlite3_Database::Sqlite3_Statement::~Sqlite3_Statement()
162 {
163 ::sqlite3_finalize(m_stmt);
164 }
165
166 }
Botan::ASN1::to_string
std::string to_string(const BER_Object &obj)
Definition: asn1_obj.cpp:213
Botan::SQL_Database::SQL_DB_Error
Definition: database.h:23
BOTAN_ASSERT
#define BOTAN_ASSERT(expr, assertion_made)
Definition: assert.h:55
sqlite3.h
Botan
Definition: alg_id.cpp:13
Botan::Sqlite3_Database::create_table
void create_table(const std::string &table_schema) override
Definition: sqlite3.cpp:50
Botan::Sqlite3_Database::~Sqlite3_Database
~Sqlite3_Database()
Definition: sqlite3.cpp:28
Botan::Sqlite3_Database::Sqlite3_Database
Sqlite3_Database(const std::string &file)
Definition: sqlite3.cpp:15
Botan::Sqlite3_Database::new_statement
std::shared_ptr< Statement > new_statement(const std::string &sql) const override
Definition: sqlite3.cpp:35
Botan::cast_uint8_ptr_to_char
const char * cast_uint8_ptr_to_char(const uint8_t *b)
Definition: mem_ops.h:194
Botan::Sqlite3_Database::row_count
size_t row_count(const std::string &table_name) override
Definition: sqlite3.cpp:40