Botan 3.13.0
Crypto and TLS for C&
Botan::Sqlite3_Database Class Referencefinal

#include <sqlite3.h>

Inheritance diagram for Botan::Sqlite3_Database:
Botan::SQL_Database

Public Types

enum class  Column_Type : uint8_t { Blob , String , Integer }

Public Member Functions

void create_table (const Table_Schema &schema) override
virtual size_t exec (std::string_view sql)
bool is_threadsafe () const override
virtual bool is_valid_table_name (std::string_view table) const
std::shared_ptr< Statementnew_statement (std::string_view sql) const override
Sqlite3_Databaseoperator= (const Sqlite3_Database &other)=delete
Sqlite3_Databaseoperator= (Sqlite3_Database &&other)=delete
size_t row_count (std::string_view table_name) override
size_t rows_changed_by_last_statement () override
virtual std::shared_ptr< Statementselect (std::string_view columns, std::string_view table, std::string_view where={}, std::optional< size_t > limit=std::nullopt) const
 Sqlite3_Database (const Sqlite3_Database &other)=delete
 Sqlite3_Database (Sqlite3_Database &&other)=delete
BOTAN_FUTURE_EXPLICIT Sqlite3_Database (std::string_view file, std::optional< int > sqlite_open_flags=std::nullopt)
std::shared_ptr< Statementupsert (std::string_view table, std::initializer_list< std::string_view > columns) const override
 ~Sqlite3_Database () override

Detailed Description

An SQL_Database implementation backed by SQLite3

Definition at line 24 of file sqlite3.h.

Member Enumeration Documentation

◆ Column_Type

enum class Botan::SQL_Database::Column_Type : uint8_t
stronginherited

The supported column types

Enumerator
Blob 
String 
Integer 

Definition at line 196 of file database.h.

196 : uint8_t {
197 Blob,
198 String,
199 Integer,
200 };

Constructor & Destructor Documentation

◆ Sqlite3_Database() [1/3]

Botan::Sqlite3_Database::Sqlite3_Database ( std::string_view file,
std::optional< int > sqlite_open_flags = std::nullopt )

Create a new SQLite database handle from a file.

Parameters
filepath to the database file be opened and/or created
sqlite_open_flagsflags that will be passed to sqlite3_open_v2() (default: SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_FULLMUTEX)

Definition at line 18 of file sqlite3.cpp.

18 {
19 // SQLITE_OPEN_FULLMUTEX ensures that the database object can be used
20 // concurrently from multiple threads.
21 const int open_flags =
22 sqlite_open_flags.value_or(SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_FULLMUTEX);
23 sqlite3* db = nullptr;
24 const int rc = ::sqlite3_open_v2(std::string(db_filename).c_str(), &db, open_flags, nullptr);
25
26 if(rc != 0) [[unlikely]] {
27 const std::string err_msg = (db != nullptr) ? ::sqlite3_errmsg(db) : "unknown error";
28 ::sqlite3_close_v2(db);
29 throw SQL_DB_Error("sqlite3_open failed - " + err_msg);
30 }
31
32 m_db = std::shared_ptr<sqlite3>(db, [](sqlite3* p) noexcept { ::sqlite3_close_v2(p); });
33}

Referenced by operator=(), operator=(), Sqlite3_Database(), and Sqlite3_Database().

◆ ~Sqlite3_Database()

Botan::Sqlite3_Database::~Sqlite3_Database ( )
overridedefault

◆ Sqlite3_Database() [2/3]

Botan::Sqlite3_Database::Sqlite3_Database ( const Sqlite3_Database & other)
delete

References Sqlite3_Database().

◆ Sqlite3_Database() [3/3]

Botan::Sqlite3_Database::Sqlite3_Database ( Sqlite3_Database && other)
delete

References Sqlite3_Database().

Member Function Documentation

◆ create_table()

void Botan::Sqlite3_Database::create_table ( const Table_Schema & schema)
overridevirtual

Create a table

Parameters
schemathe name and columns of the table to create

Implements Botan::SQL_Database.

Definition at line 78 of file sqlite3.cpp.

78 {
79 BOTAN_ARG_CHECK(!schema.name().empty(), "create_table requires a table name");
80 BOTAN_ARG_CHECK(!schema.columns().empty(), "create_table requires at least one column");
81
82 std::string sql = "CREATE TABLE ";
83 if(schema.is_if_not_exists()) {
84 sql += "IF NOT EXISTS ";
85 }
86 sql += schema.name();
87 sql += " (";
88 bool first = true;
89 for(const auto& col : schema.columns()) {
90 if(!first) {
91 sql += ", ";
92 }
93 sql += col.name();
94 sql += ' ';
95 switch(col.type()) {
97 sql += "BLOB";
98 break;
100 sql += "TEXT";
101 break;
103 sql += "INTEGER";
104 break;
105 }
106 if(col.is_primary_key()) {
107 sql += " PRIMARY KEY";
108 }
109 if(col.is_unique()) {
110 sql += " UNIQUE";
111 }
112 if(col.is_not_null()) {
113 sql += " NOT NULL";
114 }
115 first = false;
116 }
117 sql += ")";
118
119 char* errmsg = nullptr;
120 const int rc = ::sqlite3_exec(m_db.get(), sql.c_str(), nullptr, nullptr, &errmsg);
121
122 if(rc != SQLITE_OK) {
123 const std::string err_msg = (errmsg != nullptr) ? errmsg : "unknown error";
124 ::sqlite3_free(errmsg);
125 throw SQL_DB_Error("sqlite3_exec for create_table failed - " + err_msg, rc);
126 }
127}
#define BOTAN_ARG_CHECK(expr, msg)
Definition assert.h:33

References Botan::SQL_Database::Blob, BOTAN_ARG_CHECK, Botan::SQL_Database::Table_Schema::columns(), Botan::SQL_Database::Integer, Botan::SQL_Database::Table_Schema::is_if_not_exists(), Botan::SQL_Database::Table_Schema::name(), and Botan::SQL_Database::String.

Referenced by operator=().

◆ exec()

virtual size_t Botan::SQL_Database::exec ( std::string_view sql)
inlinevirtualinherited

Prepare and run a statement to completion

Parameters
sqlthe SQL text to execute
Returns
the number of result rows which were stepped over

Definition at line 342 of file database.h.

342{ return new_statement(sql)->spin(); }
virtual std::shared_ptr< Statement > new_statement(std::string_view base_sql) const =0

References new_statement().

◆ is_threadsafe()

bool Botan::Sqlite3_Database::is_threadsafe ( ) const
overridevirtual

Query whether this database may be used from multiple threads

Returns
true if SQLite3 was compiled with threading support

Reimplemented from Botan::SQL_Database.

Definition at line 135 of file sqlite3.cpp.

135 {
136 // sqlite3_db_mutex() returns the connection's mutex if the connection is in
137 // serialized mode, and nullptr otherwise. This reflects both the compile-time
138 // SQLITE_THREADSAFE setting and the per-connection SQLITE_OPEN_(FULL|NO)MUTEX
139 // open flags actually used.
140 //
141 // https://www.sqlite.org/c3ref/db_mutex.html
142 return ::sqlite3_db_mutex(m_db.get()) != nullptr;
143}

Referenced by operator=().

◆ is_valid_table_name()

bool Botan::SQL_Database::is_valid_table_name ( std::string_view table) const
virtualinherited

Return true if the given name seems to be valid as the name for a table

Default implementation accepts non-empty [a-zA-Z0-9_]

Parameters
tablethe name to check
Returns
true if the name is acceptable as a table name

Definition at line 14 of file database.cpp.

14 {
15 if(table.empty()) {
16 return false;
17 }
18
19 constexpr auto valid_table_name_char = CharacterValidityTable::alpha_numeric_plus("_");
20 for(const char c : table) {
21 if(!valid_table_name_char(c)) {
22 return false;
23 }
24 }
25 return true;
26}
static constexpr CharacterValidityTable alpha_numeric_plus(std::string_view extras)
Definition charset.h:114

References Botan::CharacterValidityTable::alpha_numeric_plus().

◆ new_statement()

std::shared_ptr< SQL_Database::Statement > Botan::Sqlite3_Database::new_statement ( std::string_view sql) const
overridevirtual

Create a new statement for execution

Parameters
sqlthe SQL text of the statement
Returns
the prepared statement

Implements Botan::SQL_Database.

Definition at line 37 of file sqlite3.cpp.

37 {
38 return std::make_shared<Sqlite3_Statement>(m_db, base_sql);
39}

Referenced by operator=(), row_count(), and upsert().

◆ operator=() [1/2]

Sqlite3_Database & Botan::Sqlite3_Database::operator= ( const Sqlite3_Database & other)
delete

References Sqlite3_Database().

Referenced by operator=().

◆ operator=() [2/2]

◆ row_count()

size_t Botan::Sqlite3_Database::row_count ( std::string_view table_name)
overridevirtual

Count the rows of a table

Parameters
table_namethe table to count
Returns
the number of rows in the table

Implements Botan::SQL_Database.

Definition at line 68 of file sqlite3.cpp.

68 {
69 auto stmt = new_statement(fmt("select count(*) from {}", table_name));
70
71 if(stmt->step()) {
72 return stmt->get_size_t(0);
73 } else {
74 throw SQL_DB_Error(fmt("Querying size of table '{}' failed", table_name));
75 }
76}
std::shared_ptr< Statement > new_statement(std::string_view sql) const override
Definition sqlite3.cpp:37
std::string fmt(std::string_view format, const T &... args)
Definition fmt.h:53

References Botan::fmt(), and new_statement().

Referenced by operator=().

◆ rows_changed_by_last_statement()

size_t Botan::Sqlite3_Database::rows_changed_by_last_statement ( )
overridevirtual

Count the rows modified by the most recently executed statement

Returns
the number of rows inserted, updated or deleted

Implements Botan::SQL_Database.

Definition at line 129 of file sqlite3.cpp.

129 {
130 const auto result = ::sqlite3_changes64(m_db.get());
131 BOTAN_ASSERT_NOMSG(result >= 0);
132 return static_cast<size_t>(result);
133}
#define BOTAN_ASSERT_NOMSG(expr)
Definition assert.h:75

References BOTAN_ASSERT_NOMSG.

Referenced by operator=().

◆ select()

std::shared_ptr< SQL_Database::Statement > Botan::SQL_Database::select ( std::string_view columns,
std::string_view table,
std::string_view where = {},
std::optional< size_t > limit = std::nullopt ) const
virtualinherited

Prepare a "SELECT <columns> FROM <table> [WHERE <where>] [LIMIT <limit>]" statement. where is the body of the WHERE clause (e.g. "id = ?1 AND name = ?2"); pass an empty string for no WHERE clause. Use ?1, ?2, ... for bound parameters. Virtual so backends can override if helpful.

Parameters
columnsthe columns to select
tablethe table to select from
wherethe body of the WHERE clause, or empty for no WHERE clause
limitthe maximum number of rows, or nullopt for no limit
Returns
the prepared statement

Definition at line 28 of file database.cpp.

31 {
32 std::string sql = "SELECT ";
33 sql += columns;
34 sql += " FROM ";
35 sql += table;
36 if(!where.empty()) {
37 sql += " WHERE ";
38 sql += where;
39 }
40 if(limit.has_value()) {
41 sql += " LIMIT ";
42 sql += std::to_string(*limit);
43 }
44 return new_statement(sql);
45}

References new_statement().

Referenced by new_statement().

◆ upsert()

std::shared_ptr< SQL_Database::Statement > Botan::Sqlite3_Database::upsert ( std::string_view table,
std::initializer_list< std::string_view > columns ) const
overridevirtual

Prepare an insert-or-replace statement

Parameters
tablethe table to upsert into
columnsthe columns to write, in placeholder order
Returns
the prepared statement

Implements Botan::SQL_Database.

Definition at line 41 of file sqlite3.cpp.

42 {
43 BOTAN_ARG_CHECK(columns.size() > 0, "upsert requires at least one column");
44
45 std::string sql = "INSERT OR REPLACE INTO ";
46 sql += table;
47 sql += " (";
48 bool first = true;
49 for(const auto& col : columns) {
50 if(!first) {
51 sql += ", ";
52 }
53 sql += col;
54 first = false;
55 }
56 sql += ") VALUES (";
57 for(size_t i = 1; i <= columns.size(); ++i) {
58 if(i > 1) {
59 sql += ", ";
60 }
61 sql += fmt("?{}", i);
62 }
63 sql += ")";
64
65 return new_statement(sql);
66}

References BOTAN_ARG_CHECK, Botan::fmt(), and new_statement().

Referenced by operator=().


The documentation for this class was generated from the following files: