Skip to content

Commit 564afba

Browse files
authored
Merge pull request #1393 from Minimal-Audio/feature/1392-support-sqlite-vfs
Added support for choosing the SQLite VFS and open mode flags
2 parents 8e8ef20 + 7aada90 commit 564afba

10 files changed

+377
-75
lines changed

dev/connection_holder.h

+17-10
Original file line numberDiff line numberDiff line change
@@ -8,33 +8,38 @@
88
#endif
99

1010
#include "error_code.h"
11+
#include "vfs_name.h"
12+
#include "db_open_mode.h"
13+
#include "storage_options.h"
1114

1215
namespace sqlite_orm {
1316
namespace internal {
1417

1518
struct connection_holder {
16-
connection_holder(std::string filename, std::function<void(sqlite3*)> didOpenDb) :
17-
_didOpenDb{std::move(didOpenDb)}, filename(std::move(filename)) {}
19+
connection_holder(std::string filename,
20+
std::function<void(sqlite3*)> didOpenDb,
21+
const connection_control& options = {}) :
22+
_didOpenDb{std::move(didOpenDb)}, filename(std::move(filename)), vfs_name(options.vfs_name),
23+
open_mode(options.open_mode) {}
1824

1925
connection_holder(const connection_holder&) = delete;
2026

2127
connection_holder(const connection_holder& other, std::function<void(sqlite3*)> didOpenDb) :
22-
_didOpenDb{std::move(didOpenDb)}, filename{other.filename} {}
28+
_didOpenDb{std::move(didOpenDb)}, filename{other.filename}, vfs_name(other.vfs_name),
29+
open_mode{other.open_mode} {}
2330

2431
void retain() {
2532
// first one opens the connection.
2633
// we presume that the connection is opened once in a single-threaded context [also open forever].
2734
// therefore we can just use an atomic increment but don't need sequencing due to `prevCount > 0`.
2835
if (_retainCount.fetch_add(1, std::memory_order_relaxed) == 0) {
29-
int rc = sqlite3_open_v2(this->filename.c_str(),
30-
&this->db,
31-
SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE
36+
int open_flags = internal::db_open_mode_to_int_flags(this->open_mode);
3237
#if SQLITE_VERSION_NUMBER >= 3008008
33-
| SQLITE_OPEN_EXRESCODE,
34-
#else
35-
| 0,
38+
open_flags |= SQLITE_OPEN_EXRESCODE;
3639
#endif
37-
nullptr);
40+
41+
int rc = sqlite3_open_v2(this->filename.c_str(), &this->db, open_flags, this->vfs_name.c_str());
42+
3843
if (rc != SQLITE_OK) SQLITE_ORM_CPP_UNLIKELY /*possible, but unexpected*/ {
3944
throw_translated_sqlite_error(rc);
4045
}
@@ -81,6 +86,8 @@ namespace sqlite_orm {
8186

8287
public:
8388
const std::string filename;
89+
const std::string vfs_name;
90+
const db_open_mode open_mode;
8491
};
8592

8693
struct connection_ref {

dev/db_open_mode.h

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
#pragma once
2+
3+
SQLITE_ORM_EXPORT namespace sqlite_orm {
4+
5+
enum class db_open_mode {
6+
default_ = 0,
7+
create_readwrite = 0,
8+
readonly = 1,
9+
};
10+
}
11+
12+
SQLITE_ORM_EXPORT namespace sqlite_orm {
13+
namespace internal {
14+
constexpr int db_open_mode_to_int_flags(db_open_mode open) {
15+
16+
switch (open) {
17+
case db_open_mode::readonly:
18+
return SQLITE_OPEN_READONLY;
19+
case db_open_mode::create_readwrite:
20+
return SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE;
21+
};
22+
23+
return -1;
24+
}
25+
}
26+
}

dev/functional/config.h

+9
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,15 @@
7272

7373
#define SQLITE_ORM_WITH_CTE
7474

75+
#if defined(_WIN32)
76+
#define SQLITE_ORM_WIN
77+
#elif defined(__APPLE__)
78+
#define SQLITE_ORM_APPLE
79+
#define SQLITE_ORM_UNIX
80+
#elif defined(__unix__) || defined(__unix) || defined(__linux__) || defined(__FreeBSD__)
81+
#define SQLITE_ORM_UNIX
82+
#endif
83+
7584
// define the inline namespace "literals" so that it is available even if it was not introduced by a feature
7685
namespace sqlite_orm {
7786
inline namespace literals {}

dev/serialize_result_type.h

+2
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,11 @@ namespace sqlite_orm {
1212
#ifdef SQLITE_ORM_STRING_VIEW_SUPPORTED
1313
using serialize_result_type = std::string_view;
1414
using serialize_arg_type = std::string_view;
15+
using string_constant_type = std::string_view;
1516
#else
1617
using serialize_result_type = std::string;
1718
using serialize_arg_type = const std::string&;
19+
using string_constant_type = const char*;
1820
#endif
1921
}
2022
}

dev/storage_base.h

+26-3
Original file line numberDiff line numberDiff line change
@@ -611,7 +611,7 @@ namespace sqlite_orm {
611611
}
612612

613613
backup_t make_backup_to(const std::string& filename) {
614-
auto holder = std::make_unique<connection_holder>(filename, nullptr);
614+
auto holder = std::make_unique<connection_holder>(filename, nullptr, connection_control{});
615615
connection_ref conRef{*holder};
616616
return {conRef, "main", this->get_connection(), "main", std::move(holder)};
617617
}
@@ -621,7 +621,7 @@ namespace sqlite_orm {
621621
}
622622

623623
backup_t make_backup_from(const std::string& filename) {
624-
auto holder = std::make_unique<connection_holder>(filename, nullptr);
624+
auto holder = std::make_unique<connection_holder>(filename, nullptr, connection_control{});
625625
connection_ref conRef{*holder};
626626
return {this->get_connection(), "main", conRef, "main", std::move(holder)};
627627
}
@@ -642,6 +642,28 @@ namespace sqlite_orm {
642642
return this->connection->retain_count() > 0;
643643
}
644644

645+
/**
646+
* Return the name of the VFS object used by the database connection.
647+
*/
648+
const std::string& vfs_name() const {
649+
return this->connection->vfs_name;
650+
}
651+
652+
/**
653+
* Return the current open_mode for this storage object.
654+
*/
655+
db_open_mode open_mode() const {
656+
return this->connection->open_mode;
657+
}
658+
659+
/**
660+
* Return true if this database object is opened in a readonly state.
661+
*/
662+
bool db_readonly() {
663+
auto con = this->get_connection();
664+
return static_cast<bool>(sqlite3_db_readonly(con.get(), "main"));
665+
}
666+
645667
/*
646668
* returning false when there is a transaction in place
647669
* otherwise true; function is not const because it has to call get_connection()
@@ -674,7 +696,8 @@ namespace sqlite_orm {
674696
inMemory(filename.empty() || filename == ":memory:"), isOpenedForever{connectionCtrl.open_forever},
675697
connection(std::make_unique<connection_holder>(
676698
std::move(filename),
677-
std::bind(&storage_base::on_open_internal, this, std::placeholders::_1))),
699+
std::bind(&storage_base::on_open_internal, this, std::placeholders::_1),
700+
connectionCtrl)),
678701
cachedForeignKeysCount(foreignKeysCount) {
679702
if (this->inMemory) {
680703
this->connection->retain();

dev/storage_options.h

+2
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ SQLITE_ORM_EXPORT namespace sqlite_orm {
3030
/// Whether to open the database once and for all.
3131
/// Required if using a 'storage' instance from multiple threads.
3232
bool open_forever = false;
33+
std::string vfs_name{default_vfs_name};
34+
db_open_mode open_mode = db_open_mode::default_;
3335

3436
using storage_opt_tag = int;
3537
};

dev/vfs_name.h

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#pragma once
2+
3+
#include "serialize_result_type.h"
4+
5+
SQLITE_ORM_EXPORT namespace sqlite_orm {
6+
7+
#ifdef SQLITE_ORM_UNIX
8+
SQLITE_ORM_INLINE_VAR constexpr internal::string_constant_type unix_vfs_name = "unix";
9+
SQLITE_ORM_INLINE_VAR constexpr internal::string_constant_type unix_posix_vfs_name = unix_vfs_name;
10+
SQLITE_ORM_INLINE_VAR constexpr internal::string_constant_type unix_dotfile_vfs_name = "unix-dotfile";
11+
#ifdef SQLITE_ORM_APPLE
12+
SQLITE_ORM_INLINE_VAR constexpr internal::string_constant_type unix_afp_vfs_name = "unix-afp";
13+
#endif
14+
SQLITE_ORM_INLINE_VAR constexpr internal::string_constant_type default_vfs_name = unix_vfs_name;
15+
#endif
16+
17+
#ifdef SQLITE_ORM_WIN
18+
SQLITE_ORM_INLINE_VAR constexpr internal::string_constant_type win32_vfs_name = "win32";
19+
SQLITE_ORM_INLINE_VAR constexpr internal::string_constant_type win32_longpath_vfs_name = "win32-longpath";
20+
21+
SQLITE_ORM_INLINE_VAR constexpr internal::string_constant_type default_vfs_name = win32_vfs_name;
22+
#endif
23+
}

0 commit comments

Comments
 (0)