Skip to content

Commit 0ea634b

Browse files
committed
Enabled configuring database limits without active connection
1 parent 85df81c commit 0ea634b

File tree

4 files changed

+82
-66
lines changed

4 files changed

+82
-66
lines changed

dev/functional/cxx_scope_guard.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
namespace sqlite_orm::internal {
44
/*
5-
Poor-man's scope (exit) guard.
5+
Poor-man's scope (exit) guard until C++29 finally comes with proper standard facilities [Draft D3610].
66
*/
77
template<class F>
88
struct scope_guard {

dev/limit_accessor.h

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
#include <sqlite3.h>
44
#ifndef SQLITE_ORM_IMPORT_STD_MODULE
55
#include <map> // std::map
6-
#include <functional> // std::function
7-
#include <memory> // std::shared_ptr
6+
#include <functional> // std::function, std::reference_wrapper
7+
#include <utility> // std::move
88
#endif
99

1010
#include "connection_holder.h"
@@ -14,9 +14,7 @@ namespace sqlite_orm {
1414
namespace internal {
1515

1616
struct limit_accessor {
17-
using get_connection_t = std::function<connection_ref()>;
18-
19-
limit_accessor(get_connection_t get_connection_) : get_connection(std::move(get_connection_)) {}
17+
limit_accessor(std::unique_ptr<connection_holder>& connection) : connection{connection} {}
2018

2119
int length() {
2220
return this->get(SQLITE_LIMIT_LENGTH);
@@ -117,7 +115,7 @@ namespace sqlite_orm {
117115
#endif
118116

119117
protected:
120-
get_connection_t get_connection;
118+
std::reference_wrapper<std::unique_ptr<connection_holder>> connection;
121119

122120
friend struct storage_base;
123121

@@ -127,14 +125,15 @@ namespace sqlite_orm {
127125
std::map<int, int> limits;
128126

129127
int get(int id) {
130-
auto connection = this->get_connection();
128+
connection_ref connection = *this->connection.get();
131129
return sqlite3_limit(connection.get(), id, -1);
132130
}
133131

134132
void set(int id, int newValue) {
135133
this->limits[id] = newValue;
136-
auto connection = this->get_connection();
137-
sqlite3_limit(connection.get(), id, newValue);
134+
if (connection_ptr maybeConnection = *this->connection.get()) {
135+
sqlite3_limit(maybeConnection.get(), id, newValue);
136+
}
138137
}
139138
};
140139
}

dev/storage_base.h

Lines changed: 32 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,29 @@ namespace sqlite_orm {
3939
namespace internal {
4040

4141
struct storage_base {
42+
public:
4243
using collating_function = std::function<int(int, const void*, int, const void*)>;
4344

45+
protected:
46+
const bool inMemory;
47+
bool isOpenedForever = false;
48+
std::unique_ptr<connection_holder> connection;
49+
std::map<std::string, collating_function> collatingFunctions;
50+
const int cachedForeignKeysCount;
51+
std::function<int(int)> _busy_handler;
52+
std::list<udf_proxy> scalarFunctions;
53+
std::list<udf_proxy> aggregateFunctions;
54+
const sqlite_executor executor;
55+
56+
public:
57+
/**
58+
* Attention: You must ensure that to set this function only from a single-threaded context.
59+
*/
4460
std::function<void(sqlite3*)> on_open;
4561
pragma_t pragma;
62+
/**
63+
* Attention: You must ensure that to set database limite only from a single-threaded context.
64+
*/
4665
limit_accessor limit;
4766

4867
transaction_guard_t transaction_guard() {
@@ -746,30 +765,30 @@ namespace sqlite_orm {
746765
will_run_query_spec willRunQuerySpec,
747766
did_run_query_spec didRunQuerySpec,
748767
int foreignKeysCount) :
749-
on_open{std::move(onOpenSpec.onOpen)}, pragma(std::bind(&storage_base::get_connection, this), executor),
750-
limit(std::bind(&storage_base::get_connection, this)),
751-
inMemory(filename.empty() || filename == ":memory:"),
768+
inMemory{filename.empty() || filename == ":memory:"},
752769
isOpenedForever{connectionCtrl.open_forever || this->inMemory},
753770
connection{std::make_unique<connection_holder>(
754771
this->isOpenedForever,
755772
db_arguments{std::move(filename), connectionCtrl},
756773
std::bind(&storage_base::on_open_internal, this, std::placeholders::_1))},
757774
cachedForeignKeysCount(foreignKeysCount),
758-
executor{std::move(willRunQuerySpec.willRunQuery), std::move(didRunQuerySpec.didRunQuery)} {
775+
executor{std::move(willRunQuerySpec.willRunQuery), std::move(didRunQuerySpec.didRunQuery)},
776+
on_open{std::move(onOpenSpec.onOpen)}, pragma(std::bind(&storage_base::get_connection, this), executor),
777+
limit{std::ref(storage_base::connection)} {
759778
if (this->isOpenedForever) {
760779
this->connection->open();
761780
}
762781
}
763782

764783
storage_base(const storage_base& other) :
765-
on_open(other.on_open), pragma(std::bind(&storage_base::get_connection, this), executor),
766-
limit(std::bind(&storage_base::get_connection, this)), inMemory(other.inMemory),
767-
isOpenedForever{other.isOpenedForever},
784+
inMemory{other.inMemory}, isOpenedForever{other.isOpenedForever},
768785
connection{std::make_unique<connection_holder>(
769786
*other.connection,
770787
std::bind(&storage_base::on_open_internal, this, std::placeholders::_1))},
771788
cachedForeignKeysCount(other.cachedForeignKeysCount),
772-
executor{other.executor.will_run_query, other.executor.did_run_query} {
789+
executor{other.executor.will_run_query, other.executor.did_run_query}, on_open(other.on_open),
790+
pragma(std::bind(&storage_base::get_connection, this), executor),
791+
limit{std::ref(storage_base::connection)} {
773792
if (this->isOpenedForever) {
774793
this->connection->open();
775794
}
@@ -1074,11 +1093,11 @@ namespace sqlite_orm {
10741093

10751094
static int busy_handler_callback(void* selfPointer, int triesCount) {
10761095
auto& storage = *static_cast<storage_base*>(selfPointer);
1077-
if (storage._busy_handler) {
1078-
return storage._busy_handler(triesCount);
1079-
} else {
1080-
return 0;
1081-
}
1096+
#ifdef SQLITE_ORM_CONTRACTS_SUPPORTED
1097+
// `sqlite3_busy_handler()` was called properly before so `busy_handler_callback()` will not be called.
1098+
contract_assert(storage._busy_handler);
1099+
#endif
1100+
return storage._busy_handler(triesCount);
10821101
}
10831102

10841103
bool calculate_remove_add_columns(std::vector<const table_xinfo*>& columnsToAdd,
@@ -1123,16 +1142,6 @@ namespace sqlite_orm {
11231142
}
11241143
return notEqual;
11251144
}
1126-
1127-
const bool inMemory;
1128-
bool isOpenedForever = false;
1129-
std::unique_ptr<connection_holder> connection;
1130-
std::map<std::string, collating_function> collatingFunctions;
1131-
const int cachedForeignKeysCount;
1132-
std::function<int(int)> _busy_handler;
1133-
std::list<udf_proxy> scalarFunctions;
1134-
std::list<udf_proxy> aggregateFunctions;
1135-
const sqlite_executor executor;
11361145
};
11371146
}
11381147
}

include/sqlite_orm/sqlite_orm.h

Lines changed: 41 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -14506,7 +14506,7 @@ namespace sqlite_orm {
1450614506

1450714507
namespace sqlite_orm::internal {
1450814508
/*
14509-
Poor-man's scope (exit) guard.
14509+
Poor-man's scope (exit) guard until C++29 finally comes with proper standard facilities [Draft D3610].
1451014510
*/
1451114511
template<class F>
1451214512
struct scope_guard {
@@ -18083,8 +18083,8 @@ namespace sqlite_orm {
1808318083
#include <sqlite3.h>
1808418084
#ifndef SQLITE_ORM_IMPORT_STD_MODULE
1808518085
#include <map> // std::map
18086-
#include <functional> // std::function
18087-
#include <memory> // std::shared_ptr
18086+
#include <functional> // std::function, std::reference_wrapper
18087+
#include <utility> // std::move
1808818088
#endif
1808918089

1809018090
// #include "connection_holder.h"
@@ -18094,9 +18094,7 @@ namespace sqlite_orm {
1809418094
namespace internal {
1809518095

1809618096
struct limit_accessor {
18097-
using get_connection_t = std::function<connection_ref()>;
18098-
18099-
limit_accessor(get_connection_t get_connection_) : get_connection(std::move(get_connection_)) {}
18097+
limit_accessor(std::unique_ptr<connection_holder>& connection) : connection{connection} {}
1810018098

1810118099
int length() {
1810218100
return this->get(SQLITE_LIMIT_LENGTH);
@@ -18197,7 +18195,7 @@ namespace sqlite_orm {
1819718195
#endif
1819818196

1819918197
protected:
18200-
get_connection_t get_connection;
18198+
std::reference_wrapper<std::unique_ptr<connection_holder>> connection;
1820118199

1820218200
friend struct storage_base;
1820318201

@@ -18207,14 +18205,15 @@ namespace sqlite_orm {
1820718205
std::map<int, int> limits;
1820818206

1820918207
int get(int id) {
18210-
auto connection = this->get_connection();
18208+
connection_ref connection = *this->connection.get();
1821118209
return sqlite3_limit(connection.get(), id, -1);
1821218210
}
1821318211

1821418212
void set(int id, int newValue) {
1821518213
this->limits[id] = newValue;
18216-
auto connection = this->get_connection();
18217-
sqlite3_limit(connection.get(), id, newValue);
18214+
if (connection_ptr maybeConnection = *this->connection.get()) {
18215+
sqlite3_limit(maybeConnection.get(), id, newValue);
18216+
}
1821818217
}
1821918218
};
1822018219
}
@@ -18827,10 +18826,29 @@ namespace sqlite_orm {
1882718826
namespace internal {
1882818827

1882918828
struct storage_base {
18829+
public:
1883018830
using collating_function = std::function<int(int, const void*, int, const void*)>;
1883118831

18832+
protected:
18833+
const bool inMemory;
18834+
bool isOpenedForever = false;
18835+
std::unique_ptr<connection_holder> connection;
18836+
std::map<std::string, collating_function> collatingFunctions;
18837+
const int cachedForeignKeysCount;
18838+
std::function<int(int)> _busy_handler;
18839+
std::list<udf_proxy> scalarFunctions;
18840+
std::list<udf_proxy> aggregateFunctions;
18841+
const sqlite_executor executor;
18842+
18843+
public:
18844+
/**
18845+
* Attention: You must ensure that to set this function only from a single-threaded context.
18846+
*/
1883218847
std::function<void(sqlite3*)> on_open;
1883318848
pragma_t pragma;
18849+
/**
18850+
* Attention: You must ensure that to set database limite only from a single-threaded context.
18851+
*/
1883418852
limit_accessor limit;
1883518853

1883618854
transaction_guard_t transaction_guard() {
@@ -19534,30 +19552,30 @@ namespace sqlite_orm {
1953419552
will_run_query_spec willRunQuerySpec,
1953519553
did_run_query_spec didRunQuerySpec,
1953619554
int foreignKeysCount) :
19537-
on_open{std::move(onOpenSpec.onOpen)}, pragma(std::bind(&storage_base::get_connection, this), executor),
19538-
limit(std::bind(&storage_base::get_connection, this)),
19539-
inMemory(filename.empty() || filename == ":memory:"),
19555+
inMemory{filename.empty() || filename == ":memory:"},
1954019556
isOpenedForever{connectionCtrl.open_forever || this->inMemory},
1954119557
connection{std::make_unique<connection_holder>(
1954219558
this->isOpenedForever,
1954319559
db_arguments{std::move(filename), connectionCtrl},
1954419560
std::bind(&storage_base::on_open_internal, this, std::placeholders::_1))},
1954519561
cachedForeignKeysCount(foreignKeysCount),
19546-
executor{std::move(willRunQuerySpec.willRunQuery), std::move(didRunQuerySpec.didRunQuery)} {
19562+
executor{std::move(willRunQuerySpec.willRunQuery), std::move(didRunQuerySpec.didRunQuery)},
19563+
on_open{std::move(onOpenSpec.onOpen)}, pragma(std::bind(&storage_base::get_connection, this), executor),
19564+
limit{std::ref(storage_base::connection)} {
1954719565
if (this->isOpenedForever) {
1954819566
this->connection->open();
1954919567
}
1955019568
}
1955119569

1955219570
storage_base(const storage_base& other) :
19553-
on_open(other.on_open), pragma(std::bind(&storage_base::get_connection, this), executor),
19554-
limit(std::bind(&storage_base::get_connection, this)), inMemory(other.inMemory),
19555-
isOpenedForever{other.isOpenedForever},
19571+
inMemory{other.inMemory}, isOpenedForever{other.isOpenedForever},
1955619572
connection{std::make_unique<connection_holder>(
1955719573
*other.connection,
1955819574
std::bind(&storage_base::on_open_internal, this, std::placeholders::_1))},
1955919575
cachedForeignKeysCount(other.cachedForeignKeysCount),
19560-
executor{other.executor.will_run_query, other.executor.did_run_query} {
19576+
executor{other.executor.will_run_query, other.executor.did_run_query}, on_open(other.on_open),
19577+
pragma(std::bind(&storage_base::get_connection, this), executor),
19578+
limit{std::ref(storage_base::connection)} {
1956119579
if (this->isOpenedForever) {
1956219580
this->connection->open();
1956319581
}
@@ -19862,11 +19880,11 @@ namespace sqlite_orm {
1986219880

1986319881
static int busy_handler_callback(void* selfPointer, int triesCount) {
1986419882
auto& storage = *static_cast<storage_base*>(selfPointer);
19865-
if (storage._busy_handler) {
19866-
return storage._busy_handler(triesCount);
19867-
} else {
19868-
return 0;
19869-
}
19883+
#ifdef SQLITE_ORM_CONTRACTS_SUPPORTED
19884+
// `sqlite3_busy_handler()` was called properly before so `busy_handler_callback()` will not be called.
19885+
contract_assert(storage._busy_handler);
19886+
#endif
19887+
return storage._busy_handler(triesCount);
1987019888
}
1987119889

1987219890
bool calculate_remove_add_columns(std::vector<const table_xinfo*>& columnsToAdd,
@@ -19911,16 +19929,6 @@ namespace sqlite_orm {
1991119929
}
1991219930
return notEqual;
1991319931
}
19914-
19915-
const bool inMemory;
19916-
bool isOpenedForever = false;
19917-
std::unique_ptr<connection_holder> connection;
19918-
std::map<std::string, collating_function> collatingFunctions;
19919-
const int cachedForeignKeysCount;
19920-
std::function<int(int)> _busy_handler;
19921-
std::list<udf_proxy> scalarFunctions;
19922-
std::list<udf_proxy> aggregateFunctions;
19923-
const sqlite_executor executor;
1992419932
};
1992519933
}
1992619934
}

0 commit comments

Comments
 (0)