@photostructure/sqlite 0.3.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +65 -16
- package/README.md +5 -10
- package/binding.gyp +2 -2
- package/dist/index.cjs +314 -11
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +346 -89
- package/dist/index.d.mts +346 -89
- package/dist/index.d.ts +346 -89
- package/dist/index.mjs +311 -10
- package/dist/index.mjs.map +1 -1
- package/package.json +72 -63
- package/prebuilds/darwin-arm64/@photostructure+sqlite.glibc.node +0 -0
- package/prebuilds/darwin-x64/@photostructure+sqlite.glibc.node +0 -0
- package/prebuilds/linux-arm64/@photostructure+sqlite.glibc.node +0 -0
- package/prebuilds/linux-arm64/@photostructure+sqlite.musl.node +0 -0
- package/prebuilds/linux-x64/@photostructure+sqlite.glibc.node +0 -0
- package/prebuilds/linux-x64/@photostructure+sqlite.musl.node +0 -0
- package/prebuilds/test_extension.so +0 -0
- package/prebuilds/win32-arm64/@photostructure+sqlite.glibc.node +0 -0
- package/prebuilds/win32-x64/@photostructure+sqlite.glibc.node +0 -0
- package/src/aggregate_function.cpp +222 -114
- package/src/aggregate_function.h +5 -6
- package/src/binding.cpp +30 -21
- package/src/enhance.ts +552 -0
- package/src/index.ts +84 -9
- package/src/shims/node_errors.h +34 -15
- package/src/shims/sqlite_errors.h +34 -8
- package/src/sql-tag-store.ts +6 -9
- package/src/sqlite_impl.cpp +1044 -394
- package/src/sqlite_impl.h +46 -7
- package/src/transaction.ts +178 -0
- package/src/types/database-sync-instance.ts +6 -40
- package/src/types/pragma-options.ts +23 -0
- package/src/types/statement-sync-instance.ts +38 -12
- package/src/types/transaction.ts +72 -0
- package/src/upstream/node_sqlite.cc +143 -43
- package/src/upstream/node_sqlite.h +15 -11
- package/src/upstream/sqlite3.c +102 -58
- package/src/upstream/sqlite3.h +5 -5
- package/src/user_function.cpp +138 -141
- package/src/user_function.h +3 -0
|
@@ -322,6 +322,8 @@ class CustomAggregate {
|
|
|
322
322
|
|
|
323
323
|
auto recv = Undefined(isolate);
|
|
324
324
|
LocalVector<Value> js_argv(isolate);
|
|
325
|
+
js_argv.reserve(argc + 1);
|
|
326
|
+
|
|
325
327
|
js_argv.emplace_back(Local<Value>::New(isolate, agg->value));
|
|
326
328
|
|
|
327
329
|
for (int i = 0; i < argc; ++i) {
|
|
@@ -625,6 +627,7 @@ void UserDefinedFunction::xFunc(sqlite3_context* ctx,
|
|
|
625
627
|
auto recv = Undefined(isolate);
|
|
626
628
|
auto fn = self->fn_.Get(isolate);
|
|
627
629
|
LocalVector<Value> js_argv(isolate);
|
|
630
|
+
js_argv.reserve(argc);
|
|
628
631
|
|
|
629
632
|
for (int i = 0; i < argc; ++i) {
|
|
630
633
|
sqlite3_value* value = argv[i];
|
|
@@ -1147,14 +1150,114 @@ void DatabaseSync::Prepare(const FunctionCallbackInfo<Value>& args) {
|
|
|
1147
1150
|
return;
|
|
1148
1151
|
}
|
|
1149
1152
|
|
|
1153
|
+
std::optional<bool> return_arrays;
|
|
1154
|
+
std::optional<bool> use_big_ints;
|
|
1155
|
+
std::optional<bool> allow_bare_named_params;
|
|
1156
|
+
std::optional<bool> allow_unknown_named_params;
|
|
1157
|
+
|
|
1158
|
+
if (args.Length() > 1 && !args[1]->IsUndefined()) {
|
|
1159
|
+
if (!args[1]->IsObject()) {
|
|
1160
|
+
THROW_ERR_INVALID_ARG_TYPE(env->isolate(),
|
|
1161
|
+
"The \"options\" argument must be an object.");
|
|
1162
|
+
return;
|
|
1163
|
+
}
|
|
1164
|
+
Local<Object> options = args[1].As<Object>();
|
|
1165
|
+
|
|
1166
|
+
Local<Value> return_arrays_v;
|
|
1167
|
+
if (!options
|
|
1168
|
+
->Get(env->context(),
|
|
1169
|
+
FIXED_ONE_BYTE_STRING(env->isolate(), "returnArrays"))
|
|
1170
|
+
.ToLocal(&return_arrays_v)) {
|
|
1171
|
+
return;
|
|
1172
|
+
}
|
|
1173
|
+
if (!return_arrays_v->IsUndefined()) {
|
|
1174
|
+
if (!return_arrays_v->IsBoolean()) {
|
|
1175
|
+
THROW_ERR_INVALID_ARG_TYPE(
|
|
1176
|
+
env->isolate(),
|
|
1177
|
+
"The \"options.returnArrays\" argument must be a boolean.");
|
|
1178
|
+
return;
|
|
1179
|
+
}
|
|
1180
|
+
return_arrays = return_arrays_v->IsTrue();
|
|
1181
|
+
}
|
|
1182
|
+
|
|
1183
|
+
Local<Value> read_big_ints_v;
|
|
1184
|
+
if (!options
|
|
1185
|
+
->Get(env->context(),
|
|
1186
|
+
FIXED_ONE_BYTE_STRING(env->isolate(), "readBigInts"))
|
|
1187
|
+
.ToLocal(&read_big_ints_v)) {
|
|
1188
|
+
return;
|
|
1189
|
+
}
|
|
1190
|
+
if (!read_big_ints_v->IsUndefined()) {
|
|
1191
|
+
if (!read_big_ints_v->IsBoolean()) {
|
|
1192
|
+
THROW_ERR_INVALID_ARG_TYPE(
|
|
1193
|
+
env->isolate(),
|
|
1194
|
+
"The \"options.readBigInts\" argument must be a boolean.");
|
|
1195
|
+
return;
|
|
1196
|
+
}
|
|
1197
|
+
use_big_ints = read_big_ints_v->IsTrue();
|
|
1198
|
+
}
|
|
1199
|
+
|
|
1200
|
+
Local<Value> allow_bare_named_params_v;
|
|
1201
|
+
if (!options
|
|
1202
|
+
->Get(env->context(),
|
|
1203
|
+
FIXED_ONE_BYTE_STRING(env->isolate(),
|
|
1204
|
+
"allowBareNamedParameters"))
|
|
1205
|
+
.ToLocal(&allow_bare_named_params_v)) {
|
|
1206
|
+
return;
|
|
1207
|
+
}
|
|
1208
|
+
if (!allow_bare_named_params_v->IsUndefined()) {
|
|
1209
|
+
if (!allow_bare_named_params_v->IsBoolean()) {
|
|
1210
|
+
THROW_ERR_INVALID_ARG_TYPE(
|
|
1211
|
+
env->isolate(),
|
|
1212
|
+
"The \"options.allowBareNamedParameters\" argument must be a "
|
|
1213
|
+
"boolean.");
|
|
1214
|
+
return;
|
|
1215
|
+
}
|
|
1216
|
+
allow_bare_named_params = allow_bare_named_params_v->IsTrue();
|
|
1217
|
+
}
|
|
1218
|
+
|
|
1219
|
+
Local<Value> allow_unknown_named_params_v;
|
|
1220
|
+
if (!options
|
|
1221
|
+
->Get(env->context(),
|
|
1222
|
+
FIXED_ONE_BYTE_STRING(env->isolate(),
|
|
1223
|
+
"allowUnknownNamedParameters"))
|
|
1224
|
+
.ToLocal(&allow_unknown_named_params_v)) {
|
|
1225
|
+
return;
|
|
1226
|
+
}
|
|
1227
|
+
if (!allow_unknown_named_params_v->IsUndefined()) {
|
|
1228
|
+
if (!allow_unknown_named_params_v->IsBoolean()) {
|
|
1229
|
+
THROW_ERR_INVALID_ARG_TYPE(
|
|
1230
|
+
env->isolate(),
|
|
1231
|
+
"The \"options.allowUnknownNamedParameters\" argument must be a "
|
|
1232
|
+
"boolean.");
|
|
1233
|
+
return;
|
|
1234
|
+
}
|
|
1235
|
+
allow_unknown_named_params = allow_unknown_named_params_v->IsTrue();
|
|
1236
|
+
}
|
|
1237
|
+
}
|
|
1238
|
+
|
|
1150
1239
|
Utf8Value sql(env->isolate(), args[0].As<String>());
|
|
1151
1240
|
sqlite3_stmt* s = nullptr;
|
|
1152
|
-
int r = sqlite3_prepare_v2(db->connection_, *sql, -1, &s,
|
|
1241
|
+
int r = sqlite3_prepare_v2(db->connection_, *sql, -1, &s, nullptr);
|
|
1153
1242
|
|
|
1154
1243
|
CHECK_ERROR_OR_THROW(env->isolate(), db, r, SQLITE_OK, void());
|
|
1155
1244
|
BaseObjectPtr<StatementSync> stmt =
|
|
1156
1245
|
StatementSync::Create(env, BaseObjectPtr<DatabaseSync>(db), s);
|
|
1157
1246
|
db->statements_.insert(stmt.get());
|
|
1247
|
+
|
|
1248
|
+
if (return_arrays.has_value()) {
|
|
1249
|
+
stmt->return_arrays_ = return_arrays.value();
|
|
1250
|
+
}
|
|
1251
|
+
if (use_big_ints.has_value()) {
|
|
1252
|
+
stmt->use_big_ints_ = use_big_ints.value();
|
|
1253
|
+
}
|
|
1254
|
+
if (allow_bare_named_params.has_value()) {
|
|
1255
|
+
stmt->allow_bare_named_params_ = allow_bare_named_params.value();
|
|
1256
|
+
}
|
|
1257
|
+
if (allow_unknown_named_params.has_value()) {
|
|
1258
|
+
stmt->allow_unknown_named_params_ = allow_unknown_named_params.value();
|
|
1259
|
+
}
|
|
1260
|
+
|
|
1158
1261
|
args.GetReturnValue().Set(stmt->object());
|
|
1159
1262
|
}
|
|
1160
1263
|
|
|
@@ -1963,18 +2066,16 @@ int DatabaseSync::AuthorizerCallback(void* user_data,
|
|
|
1963
2066
|
CHECK(cb->IsFunction());
|
|
1964
2067
|
|
|
1965
2068
|
Local<Function> callback = cb.As<Function>();
|
|
1966
|
-
LocalVector<Value> js_argv(isolate);
|
|
1967
2069
|
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
NullableSQLiteStringToValue(isolate, param4).ToLocalChecked());
|
|
2070
|
+
LocalVector<Value> js_argv(
|
|
2071
|
+
isolate,
|
|
2072
|
+
{
|
|
2073
|
+
Integer::New(isolate, action_code),
|
|
2074
|
+
NullableSQLiteStringToValue(isolate, param1).ToLocalChecked(),
|
|
2075
|
+
NullableSQLiteStringToValue(isolate, param2).ToLocalChecked(),
|
|
2076
|
+
NullableSQLiteStringToValue(isolate, param3).ToLocalChecked(),
|
|
2077
|
+
NullableSQLiteStringToValue(isolate, param4).ToLocalChecked(),
|
|
2078
|
+
});
|
|
1978
2079
|
|
|
1979
2080
|
MaybeLocal<Value> retval = callback->Call(
|
|
1980
2081
|
context, Undefined(isolate), js_argv.size(), js_argv.data());
|
|
@@ -2664,8 +2765,7 @@ SQLTagStore::SQLTagStore(Environment* env,
|
|
|
2664
2765
|
int capacity)
|
|
2665
2766
|
: BaseObject(env, object),
|
|
2666
2767
|
database_(std::move(database)),
|
|
2667
|
-
sql_tags_(capacity)
|
|
2668
|
-
capacity_(capacity) {
|
|
2768
|
+
sql_tags_(capacity) {
|
|
2669
2769
|
MakeWeak();
|
|
2670
2770
|
}
|
|
2671
2771
|
|
|
@@ -2700,11 +2800,13 @@ Local<FunctionTemplate> SQLTagStore::GetConstructorTemplate(Environment* env) {
|
|
|
2700
2800
|
SetProtoMethod(isolate, tmpl, "iterate", Iterate);
|
|
2701
2801
|
SetProtoMethod(isolate, tmpl, "run", Run);
|
|
2702
2802
|
SetProtoMethod(isolate, tmpl, "clear", Clear);
|
|
2703
|
-
|
|
2704
|
-
|
|
2705
|
-
|
|
2803
|
+
SetSideEffectFreeGetter(isolate,
|
|
2804
|
+
tmpl,
|
|
2805
|
+
FIXED_ONE_BYTE_STRING(isolate, "capacity"),
|
|
2806
|
+
CapacityGetter);
|
|
2706
2807
|
SetSideEffectFreeGetter(
|
|
2707
2808
|
isolate, tmpl, FIXED_ONE_BYTE_STRING(isolate, "db"), DatabaseGetter);
|
|
2809
|
+
SetSideEffectFreeGetter(isolate, tmpl, env->size_string(), SizeGetter);
|
|
2708
2810
|
return tmpl;
|
|
2709
2811
|
}
|
|
2710
2812
|
|
|
@@ -2717,35 +2819,47 @@ BaseObjectPtr<SQLTagStore> SQLTagStore::Create(
|
|
|
2717
2819
|
.ToLocal(&obj)) {
|
|
2718
2820
|
return nullptr;
|
|
2719
2821
|
}
|
|
2822
|
+
obj->SetInternalField(kDatabaseObject, database->object());
|
|
2720
2823
|
return MakeBaseObject<SQLTagStore>(env, obj, std::move(database), capacity);
|
|
2721
2824
|
}
|
|
2722
2825
|
|
|
2826
|
+
void SQLTagStore::CapacityGetter(const FunctionCallbackInfo<Value>& args) {
|
|
2827
|
+
SQLTagStore* store;
|
|
2828
|
+
ASSIGN_OR_RETURN_UNWRAP(&store, args.This());
|
|
2829
|
+
args.GetReturnValue().Set(static_cast<double>(store->sql_tags_.Capacity()));
|
|
2830
|
+
}
|
|
2831
|
+
|
|
2723
2832
|
void SQLTagStore::DatabaseGetter(const FunctionCallbackInfo<Value>& args) {
|
|
2833
|
+
args.GetReturnValue().Set(
|
|
2834
|
+
args.This()->GetInternalField(kDatabaseObject).As<Value>());
|
|
2835
|
+
}
|
|
2836
|
+
|
|
2837
|
+
void SQLTagStore::SizeGetter(const FunctionCallbackInfo<Value>& args) {
|
|
2724
2838
|
SQLTagStore* store;
|
|
2725
2839
|
ASSIGN_OR_RETURN_UNWRAP(&store, args.This());
|
|
2726
|
-
args.GetReturnValue().Set(store->
|
|
2840
|
+
args.GetReturnValue().Set(static_cast<double>(store->sql_tags_.Size()));
|
|
2727
2841
|
}
|
|
2728
2842
|
|
|
2729
|
-
void SQLTagStore::Run(const FunctionCallbackInfo<Value>&
|
|
2843
|
+
void SQLTagStore::Run(const FunctionCallbackInfo<Value>& args) {
|
|
2730
2844
|
SQLTagStore* session;
|
|
2731
|
-
ASSIGN_OR_RETURN_UNWRAP(&session,
|
|
2732
|
-
Environment* env = Environment::GetCurrent(
|
|
2845
|
+
ASSIGN_OR_RETURN_UNWRAP(&session, args.This());
|
|
2846
|
+
Environment* env = Environment::GetCurrent(args);
|
|
2733
2847
|
|
|
2734
2848
|
THROW_AND_RETURN_ON_BAD_STATE(
|
|
2735
2849
|
env, !session->database_->IsOpen(), "database is not open");
|
|
2736
2850
|
|
|
2737
|
-
BaseObjectPtr<StatementSync> stmt = PrepareStatement(
|
|
2851
|
+
BaseObjectPtr<StatementSync> stmt = PrepareStatement(args);
|
|
2738
2852
|
|
|
2739
2853
|
if (!stmt) {
|
|
2740
2854
|
return;
|
|
2741
2855
|
}
|
|
2742
2856
|
|
|
2743
|
-
uint32_t n_params =
|
|
2857
|
+
uint32_t n_params = args.Length() - 1;
|
|
2744
2858
|
int r = sqlite3_reset(stmt->statement_);
|
|
2745
2859
|
CHECK_ERROR_OR_THROW(env->isolate(), stmt->db_.get(), r, SQLITE_OK, void());
|
|
2746
2860
|
int param_count = sqlite3_bind_parameter_count(stmt->statement_);
|
|
2747
2861
|
for (int i = 0; i < static_cast<int>(n_params) && i < param_count; ++i) {
|
|
2748
|
-
Local<Value> value =
|
|
2862
|
+
Local<Value> value = args[i + 1];
|
|
2749
2863
|
if (!stmt->BindValue(value, i + 1)) {
|
|
2750
2864
|
return;
|
|
2751
2865
|
}
|
|
@@ -2755,7 +2869,7 @@ void SQLTagStore::Run(const FunctionCallbackInfo<Value>& info) {
|
|
|
2755
2869
|
if (StatementExecutionHelper::Run(
|
|
2756
2870
|
env, stmt->db_.get(), stmt->statement_, stmt->use_big_ints_)
|
|
2757
2871
|
.ToLocal(&result)) {
|
|
2758
|
-
|
|
2872
|
+
args.GetReturnValue().Set(result);
|
|
2759
2873
|
}
|
|
2760
2874
|
}
|
|
2761
2875
|
|
|
@@ -2873,23 +2987,9 @@ void SQLTagStore::All(const FunctionCallbackInfo<Value>& args) {
|
|
|
2873
2987
|
}
|
|
2874
2988
|
}
|
|
2875
2989
|
|
|
2876
|
-
void SQLTagStore::
|
|
2877
|
-
SQLTagStore* store;
|
|
2878
|
-
ASSIGN_OR_RETURN_UNWRAP(&store, info.This());
|
|
2879
|
-
info.GetReturnValue().Set(
|
|
2880
|
-
Integer::New(info.GetIsolate(), store->sql_tags_.Size()));
|
|
2881
|
-
}
|
|
2882
|
-
|
|
2883
|
-
void SQLTagStore::Capacity(const FunctionCallbackInfo<Value>& info) {
|
|
2990
|
+
void SQLTagStore::Clear(const FunctionCallbackInfo<Value>& args) {
|
|
2884
2991
|
SQLTagStore* store;
|
|
2885
|
-
ASSIGN_OR_RETURN_UNWRAP(&store,
|
|
2886
|
-
info.GetReturnValue().Set(
|
|
2887
|
-
Integer::New(info.GetIsolate(), store->sql_tags_.Capacity()));
|
|
2888
|
-
}
|
|
2889
|
-
|
|
2890
|
-
void SQLTagStore::Clear(const FunctionCallbackInfo<Value>& info) {
|
|
2891
|
-
SQLTagStore* store;
|
|
2892
|
-
ASSIGN_OR_RETURN_UNWRAP(&store, info.This());
|
|
2992
|
+
ASSIGN_OR_RETURN_UNWRAP(&store, args.This());
|
|
2893
2993
|
store->sql_tags_.Clear();
|
|
2894
2994
|
}
|
|
2895
2995
|
|
|
@@ -2944,10 +3044,10 @@ BaseObjectPtr<StatementSync> SQLTagStore::PrepareStatement(
|
|
|
2944
3044
|
if (stmt == nullptr) {
|
|
2945
3045
|
sqlite3_stmt* s = nullptr;
|
|
2946
3046
|
int r = sqlite3_prepare_v2(
|
|
2947
|
-
session->database_->connection_, sql.data(), sql.size(), &s,
|
|
3047
|
+
session->database_->connection_, sql.data(), sql.size(), &s, nullptr);
|
|
2948
3048
|
|
|
2949
3049
|
if (r != SQLITE_OK) {
|
|
2950
|
-
THROW_ERR_SQLITE_ERROR(isolate,
|
|
3050
|
+
THROW_ERR_SQLITE_ERROR(isolate, session->database_.get());
|
|
2951
3051
|
sqlite3_finalize(s);
|
|
2952
3052
|
return BaseObjectPtr<StatementSync>();
|
|
2953
3053
|
}
|
|
@@ -79,7 +79,7 @@ class DatabaseOpenConfiguration {
|
|
|
79
79
|
bool return_arrays_ = false;
|
|
80
80
|
bool allow_bare_named_params_ = true;
|
|
81
81
|
bool allow_unknown_named_params_ = false;
|
|
82
|
-
bool defensive_ =
|
|
82
|
+
bool defensive_ = true;
|
|
83
83
|
};
|
|
84
84
|
|
|
85
85
|
class DatabaseSync;
|
|
@@ -246,6 +246,7 @@ class StatementSync : public BaseObject {
|
|
|
246
246
|
bool BindParams(const v8::FunctionCallbackInfo<v8::Value>& args);
|
|
247
247
|
bool BindValue(const v8::Local<v8::Value>& value, const int index);
|
|
248
248
|
|
|
249
|
+
friend class DatabaseSync;
|
|
249
250
|
friend class StatementSyncIterator;
|
|
250
251
|
friend class SQLTagStore;
|
|
251
252
|
friend class StatementExecutionHelper;
|
|
@@ -304,6 +305,11 @@ class Session : public BaseObject {
|
|
|
304
305
|
|
|
305
306
|
class SQLTagStore : public BaseObject {
|
|
306
307
|
public:
|
|
308
|
+
enum InternalFields {
|
|
309
|
+
kDatabaseObject = BaseObject::kInternalFieldCount,
|
|
310
|
+
kInternalFieldCount
|
|
311
|
+
};
|
|
312
|
+
|
|
307
313
|
SQLTagStore(Environment* env,
|
|
308
314
|
v8::Local<v8::Object> object,
|
|
309
315
|
BaseObjectWeakPtr<DatabaseSync> database,
|
|
@@ -313,15 +319,14 @@ class SQLTagStore : public BaseObject {
|
|
|
313
319
|
Environment* env, BaseObjectWeakPtr<DatabaseSync> database, int capacity);
|
|
314
320
|
static v8::Local<v8::FunctionTemplate> GetConstructorTemplate(
|
|
315
321
|
Environment* env);
|
|
316
|
-
static void All(const v8::FunctionCallbackInfo<v8::Value>&
|
|
317
|
-
static void Get(const v8::FunctionCallbackInfo<v8::Value>&
|
|
318
|
-
static void Iterate(const v8::FunctionCallbackInfo<v8::Value>&
|
|
319
|
-
static void Run(const v8::FunctionCallbackInfo<v8::Value>&
|
|
320
|
-
static void
|
|
321
|
-
static void
|
|
322
|
-
static void
|
|
323
|
-
static void
|
|
324
|
-
static void DatabaseGetter(const v8::FunctionCallbackInfo<v8::Value>& info);
|
|
322
|
+
static void All(const v8::FunctionCallbackInfo<v8::Value>& args);
|
|
323
|
+
static void Get(const v8::FunctionCallbackInfo<v8::Value>& args);
|
|
324
|
+
static void Iterate(const v8::FunctionCallbackInfo<v8::Value>& args);
|
|
325
|
+
static void Run(const v8::FunctionCallbackInfo<v8::Value>& args);
|
|
326
|
+
static void Clear(const v8::FunctionCallbackInfo<v8::Value>& args);
|
|
327
|
+
static void CapacityGetter(const v8::FunctionCallbackInfo<v8::Value>& args);
|
|
328
|
+
static void DatabaseGetter(const v8::FunctionCallbackInfo<v8::Value>& args);
|
|
329
|
+
static void SizeGetter(const v8::FunctionCallbackInfo<v8::Value>& args);
|
|
325
330
|
void MemoryInfo(MemoryTracker* tracker) const override;
|
|
326
331
|
SET_MEMORY_INFO_NAME(SQLTagStore)
|
|
327
332
|
SET_SELF_SIZE(SQLTagStore)
|
|
@@ -331,7 +336,6 @@ class SQLTagStore : public BaseObject {
|
|
|
331
336
|
const v8::FunctionCallbackInfo<v8::Value>& args);
|
|
332
337
|
BaseObjectWeakPtr<DatabaseSync> database_;
|
|
333
338
|
LRUCache<std::string, BaseObjectPtr<StatementSync>> sql_tags_;
|
|
334
|
-
int capacity_;
|
|
335
339
|
friend class StatementExecutionHelper;
|
|
336
340
|
};
|
|
337
341
|
|
package/src/upstream/sqlite3.c
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/******************************************************************************
|
|
2
2
|
** This file is an amalgamation of many separate C source files from SQLite
|
|
3
|
-
** version 3.51.
|
|
3
|
+
** version 3.51.2. By combining all the individual C code files into this
|
|
4
4
|
** single large file, the entire code can be compiled as a single translation
|
|
5
5
|
** unit. This allows many compilers to do optimizations that would not be
|
|
6
6
|
** possible if the files were compiled separately. Performance improvements
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
** separate file. This file contains only code for the core SQLite library.
|
|
19
19
|
**
|
|
20
20
|
** The content in this amalgamation comes from Fossil check-in
|
|
21
|
-
**
|
|
21
|
+
** b270f8339eb13b504d0b2ba154ebca966b7d with changes in files:
|
|
22
22
|
**
|
|
23
23
|
**
|
|
24
24
|
*/
|
|
@@ -467,12 +467,12 @@ extern "C" {
|
|
|
467
467
|
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
|
|
468
468
|
** [sqlite_version()] and [sqlite_source_id()].
|
|
469
469
|
*/
|
|
470
|
-
#define SQLITE_VERSION "3.51.
|
|
471
|
-
#define SQLITE_VERSION_NUMBER
|
|
472
|
-
#define SQLITE_SOURCE_ID "
|
|
470
|
+
#define SQLITE_VERSION "3.51.2"
|
|
471
|
+
#define SQLITE_VERSION_NUMBER 3051002
|
|
472
|
+
#define SQLITE_SOURCE_ID "2026-01-09 17:27:48 b270f8339eb13b504d0b2ba154ebca966b7dde08e40c3ed7d559749818cb2075"
|
|
473
473
|
#define SQLITE_SCM_BRANCH "branch-3.51"
|
|
474
|
-
#define SQLITE_SCM_TAGS "release version-3.51.
|
|
475
|
-
#define SQLITE_SCM_DATETIME "
|
|
474
|
+
#define SQLITE_SCM_TAGS "release version-3.51.2"
|
|
475
|
+
#define SQLITE_SCM_DATETIME "2026-01-09T17:27:48.405Z"
|
|
476
476
|
|
|
477
477
|
/*
|
|
478
478
|
** CAPI3REF: Run-Time Library Version Numbers
|
|
@@ -41228,12 +41228,18 @@ static int unixLock(sqlite3_file *id, int eFileLock){
|
|
|
41228
41228
|
pInode->nLock++;
|
|
41229
41229
|
pInode->nShared = 1;
|
|
41230
41230
|
}
|
|
41231
|
-
}else if(
|
|
41232
|
-
|| unixIsSharingShmNode(pFile)
|
|
41233
|
-
){
|
|
41231
|
+
}else if( eFileLock==EXCLUSIVE_LOCK && pInode->nShared>1 ){
|
|
41234
41232
|
/* We are trying for an exclusive lock but another thread in this
|
|
41235
41233
|
** same process is still holding a shared lock. */
|
|
41236
41234
|
rc = SQLITE_BUSY;
|
|
41235
|
+
}else if( unixIsSharingShmNode(pFile) ){
|
|
41236
|
+
/* We are in WAL mode and attempting to delete the SHM and WAL
|
|
41237
|
+
** files due to closing the connection or changing out of WAL mode,
|
|
41238
|
+
** but another process still holds locks on the SHM file, thus
|
|
41239
|
+
** indicating that database locks have been broken, perhaps due
|
|
41240
|
+
** to a rogue close(open(dbFile)) or similar.
|
|
41241
|
+
*/
|
|
41242
|
+
rc = SQLITE_BUSY;
|
|
41237
41243
|
}else{
|
|
41238
41244
|
/* The request was for a RESERVED or EXCLUSIVE lock. It is
|
|
41239
41245
|
** assumed that there is a SHARED or greater lock on the file
|
|
@@ -43872,26 +43878,21 @@ static int unixFcntlExternalReader(unixFile *pFile, int *piOut){
|
|
|
43872
43878
|
** still not a disaster.
|
|
43873
43879
|
*/
|
|
43874
43880
|
static int unixIsSharingShmNode(unixFile *pFile){
|
|
43875
|
-
int rc;
|
|
43876
43881
|
unixShmNode *pShmNode;
|
|
43882
|
+
struct flock lock;
|
|
43877
43883
|
if( pFile->pShm==0 ) return 0;
|
|
43878
43884
|
if( pFile->ctrlFlags & UNIXFILE_EXCL ) return 0;
|
|
43879
43885
|
pShmNode = pFile->pShm->pShmNode;
|
|
43880
|
-
|
|
43881
|
-
|
|
43882
|
-
|
|
43883
|
-
|
|
43884
|
-
|
|
43885
|
-
|
|
43886
|
-
|
|
43887
|
-
|
|
43888
|
-
|
|
43889
|
-
|
|
43890
|
-
rc = 0;
|
|
43891
|
-
}
|
|
43892
|
-
}
|
|
43893
|
-
unixLeaveMutex();
|
|
43894
|
-
return rc;
|
|
43886
|
+
#if SQLITE_ATOMIC_INTRINSICS
|
|
43887
|
+
assert( AtomicLoad(&pShmNode->nRef)==1 );
|
|
43888
|
+
#endif
|
|
43889
|
+
memset(&lock, 0, sizeof(lock));
|
|
43890
|
+
lock.l_whence = SEEK_SET;
|
|
43891
|
+
lock.l_start = UNIX_SHM_DMS;
|
|
43892
|
+
lock.l_len = 1;
|
|
43893
|
+
lock.l_type = F_WRLCK;
|
|
43894
|
+
osFcntl(pShmNode->hShm, F_GETLK, &lock);
|
|
43895
|
+
return (lock.l_type!=F_UNLCK);
|
|
43895
43896
|
}
|
|
43896
43897
|
|
|
43897
43898
|
/*
|
|
@@ -115316,9 +115317,22 @@ SQLITE_PRIVATE int sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){
|
|
|
115316
115317
|
pParse->nMem += nReg;
|
|
115317
115318
|
if( pExpr->op==TK_SELECT ){
|
|
115318
115319
|
dest.eDest = SRT_Mem;
|
|
115319
|
-
|
|
115320
|
+
if( (pSel->selFlags&SF_Distinct) && pSel->pLimit && pSel->pLimit->pRight ){
|
|
115321
|
+
/* If there is both a DISTINCT and an OFFSET clause, then allocate
|
|
115322
|
+
** a separate dest.iSdst array for sqlite3Select() and other
|
|
115323
|
+
** routines to populate. In this case results will be copied over
|
|
115324
|
+
** into the dest.iSDParm array only after OFFSET processing. This
|
|
115325
|
+
** ensures that in the case where OFFSET excludes all rows, the
|
|
115326
|
+
** dest.iSDParm array is not left populated with the contents of the
|
|
115327
|
+
** last row visited - it should be all NULLs if all rows were
|
|
115328
|
+
** excluded by OFFSET. */
|
|
115329
|
+
dest.iSdst = pParse->nMem+1;
|
|
115330
|
+
pParse->nMem += nReg;
|
|
115331
|
+
}else{
|
|
115332
|
+
dest.iSdst = dest.iSDParm;
|
|
115333
|
+
}
|
|
115320
115334
|
dest.nSdst = nReg;
|
|
115321
|
-
sqlite3VdbeAddOp3(v, OP_Null, 0, dest.iSDParm,
|
|
115335
|
+
sqlite3VdbeAddOp3(v, OP_Null, 0, dest.iSDParm, pParse->nMem);
|
|
115322
115336
|
VdbeComment((v, "Init subquery result"));
|
|
115323
115337
|
}else{
|
|
115324
115338
|
dest.eDest = SRT_Exists;
|
|
@@ -148186,9 +148200,14 @@ static void selectInnerLoop(
|
|
|
148186
148200
|
assert( nResultCol<=pDest->nSdst );
|
|
148187
148201
|
pushOntoSorter(
|
|
148188
148202
|
pParse, pSort, p, regResult, regOrig, nResultCol, nPrefixReg);
|
|
148203
|
+
pDest->iSDParm = regResult;
|
|
148189
148204
|
}else{
|
|
148190
148205
|
assert( nResultCol==pDest->nSdst );
|
|
148191
|
-
|
|
148206
|
+
if( regResult!=iParm ){
|
|
148207
|
+
/* This occurs in cases where the SELECT had both a DISTINCT and
|
|
148208
|
+
** an OFFSET clause. */
|
|
148209
|
+
sqlite3VdbeAddOp3(v, OP_Copy, regResult, iParm, nResultCol-1);
|
|
148210
|
+
}
|
|
148192
148211
|
/* The LIMIT clause will jump out of the loop for us */
|
|
148193
148212
|
}
|
|
148194
148213
|
break;
|
|
@@ -154203,12 +154222,24 @@ static SQLITE_NOINLINE void existsToJoin(
|
|
|
154203
154222
|
&& (pSub->selFlags & SF_Aggregate)==0
|
|
154204
154223
|
&& !pSub->pSrc->a[0].fg.isSubquery
|
|
154205
154224
|
&& pSub->pLimit==0
|
|
154225
|
+
&& pSub->pPrior==0
|
|
154206
154226
|
){
|
|
154227
|
+
/* Before combining the sub-select with the parent, renumber the
|
|
154228
|
+
** cursor used by the subselect. This is because the EXISTS expression
|
|
154229
|
+
** might be a copy of another EXISTS expression from somewhere
|
|
154230
|
+
** else in the tree, and in this case it is important that it use
|
|
154231
|
+
** a unique cursor number. */
|
|
154232
|
+
sqlite3 *db = pParse->db;
|
|
154233
|
+
int *aCsrMap = sqlite3DbMallocZero(db, (pParse->nTab+2)*sizeof(int));
|
|
154234
|
+
if( aCsrMap==0 ) return;
|
|
154235
|
+
aCsrMap[0] = (pParse->nTab+1);
|
|
154236
|
+
renumberCursors(pParse, pSub, -1, aCsrMap);
|
|
154237
|
+
sqlite3DbFree(db, aCsrMap);
|
|
154238
|
+
|
|
154207
154239
|
memset(pWhere, 0, sizeof(*pWhere));
|
|
154208
154240
|
pWhere->op = TK_INTEGER;
|
|
154209
154241
|
pWhere->u.iValue = 1;
|
|
154210
154242
|
ExprSetProperty(pWhere, EP_IntValue);
|
|
154211
|
-
|
|
154212
154243
|
assert( p->pWhere!=0 );
|
|
154213
154244
|
pSub->pSrc->a[0].fg.fromExists = 1;
|
|
154214
154245
|
pSub->pSrc->a[0].fg.jointype |= JT_CROSS;
|
|
@@ -174001,6 +174032,9 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){
|
|
|
174001
174032
|
sqlite3 *db = pParse->db;
|
|
174002
174033
|
int iEnd = sqlite3VdbeCurrentAddr(v);
|
|
174003
174034
|
int nRJ = 0;
|
|
174035
|
+
#ifndef SQLITE_DISABLE_SKIPAHEAD_DISTINCT
|
|
174036
|
+
int addrSeek = 0;
|
|
174037
|
+
#endif
|
|
174004
174038
|
|
|
174005
174039
|
/* Generate loop termination code.
|
|
174006
174040
|
*/
|
|
@@ -174013,7 +174047,10 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){
|
|
|
174013
174047
|
** the RIGHT JOIN table */
|
|
174014
174048
|
WhereRightJoin *pRJ = pLevel->pRJ;
|
|
174015
174049
|
sqlite3VdbeResolveLabel(v, pLevel->addrCont);
|
|
174016
|
-
|
|
174050
|
+
/* Replace addrCont with a new label that will never be used, just so
|
|
174051
|
+
** the subsequent call to resolve pLevel->addrCont will have something
|
|
174052
|
+
** to resolve. */
|
|
174053
|
+
pLevel->addrCont = sqlite3VdbeMakeLabel(pParse);
|
|
174017
174054
|
pRJ->endSubrtn = sqlite3VdbeCurrentAddr(v);
|
|
174018
174055
|
sqlite3VdbeAddOp3(v, OP_Return, pRJ->regReturn, pRJ->addrSubrtn, 1);
|
|
174019
174056
|
VdbeCoverage(v);
|
|
@@ -174022,7 +174059,6 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){
|
|
|
174022
174059
|
pLoop = pLevel->pWLoop;
|
|
174023
174060
|
if( pLevel->op!=OP_Noop ){
|
|
174024
174061
|
#ifndef SQLITE_DISABLE_SKIPAHEAD_DISTINCT
|
|
174025
|
-
int addrSeek = 0;
|
|
174026
174062
|
Index *pIdx;
|
|
174027
174063
|
int n;
|
|
174028
174064
|
if( pWInfo->eDistinct==WHERE_DISTINCT_ORDERED
|
|
@@ -174045,25 +174081,26 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){
|
|
|
174045
174081
|
sqlite3VdbeAddOp2(v, OP_Goto, 1, pLevel->p2);
|
|
174046
174082
|
}
|
|
174047
174083
|
#endif /* SQLITE_DISABLE_SKIPAHEAD_DISTINCT */
|
|
174048
|
-
|
|
174049
|
-
|
|
174050
|
-
|
|
174051
|
-
|
|
174052
|
-
|
|
174053
|
-
|
|
174054
|
-
|
|
174055
|
-
|
|
174056
|
-
|
|
174057
|
-
|
|
174058
|
-
|
|
174059
|
-
|
|
174060
|
-
|
|
174061
|
-
|
|
174062
|
-
|
|
174063
|
-
|
|
174064
|
-
|
|
174065
|
-
|
|
174066
|
-
|
|
174084
|
+
}
|
|
174085
|
+
if( pTabList->a[pLevel->iFrom].fg.fromExists && i==pWInfo->nLevel-1 ){
|
|
174086
|
+
/* If the EXISTS-to-JOIN optimization was applied, then the EXISTS
|
|
174087
|
+
** loop(s) will be the inner-most loops of the join. There might be
|
|
174088
|
+
** multiple EXISTS loops, but they will all be nested, and the join
|
|
174089
|
+
** order will not have been changed by the query planner. If the
|
|
174090
|
+
** inner-most EXISTS loop sees a single successful row, it should
|
|
174091
|
+
** break out of *all* EXISTS loops. But only the inner-most of the
|
|
174092
|
+
** nested EXISTS loops should do this breakout. */
|
|
174093
|
+
int nOuter = 0; /* Nr of outer EXISTS that this one is nested within */
|
|
174094
|
+
while( nOuter<i ){
|
|
174095
|
+
if( !pTabList->a[pLevel[-nOuter-1].iFrom].fg.fromExists ) break;
|
|
174096
|
+
nOuter++;
|
|
174097
|
+
}
|
|
174098
|
+
testcase( nOuter>0 );
|
|
174099
|
+
sqlite3VdbeAddOp2(v, OP_Goto, 0, pLevel[-nOuter].addrBrk);
|
|
174100
|
+
VdbeComment((v, "EXISTS break"));
|
|
174101
|
+
}
|
|
174102
|
+
sqlite3VdbeResolveLabel(v, pLevel->addrCont);
|
|
174103
|
+
if( pLevel->op!=OP_Noop ){
|
|
174067
174104
|
sqlite3VdbeAddOp3(v, pLevel->op, pLevel->p1, pLevel->p2, pLevel->p3);
|
|
174068
174105
|
sqlite3VdbeChangeP5(v, pLevel->p5);
|
|
174069
174106
|
VdbeCoverage(v);
|
|
@@ -174076,10 +174113,11 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){
|
|
|
174076
174113
|
VdbeCoverage(v);
|
|
174077
174114
|
}
|
|
174078
174115
|
#ifndef SQLITE_DISABLE_SKIPAHEAD_DISTINCT
|
|
174079
|
-
if( addrSeek )
|
|
174116
|
+
if( addrSeek ){
|
|
174117
|
+
sqlite3VdbeJumpHere(v, addrSeek);
|
|
174118
|
+
addrSeek = 0;
|
|
174119
|
+
}
|
|
174080
174120
|
#endif
|
|
174081
|
-
}else if( pLevel->addrCont ){
|
|
174082
|
-
sqlite3VdbeResolveLabel(v, pLevel->addrCont);
|
|
174083
174121
|
}
|
|
174084
174122
|
if( (pLoop->wsFlags & WHERE_IN_ABLE)!=0 && pLevel->u.in.nIn>0 ){
|
|
174085
174123
|
struct InLoop *pIn;
|
|
@@ -219453,7 +219491,7 @@ static void rtreenode(sqlite3_context *ctx, int nArg, sqlite3_value **apArg){
|
|
|
219453
219491
|
if( node.zData==0 ) return;
|
|
219454
219492
|
nData = sqlite3_value_bytes(apArg[1]);
|
|
219455
219493
|
if( nData<4 ) return;
|
|
219456
|
-
if( nData<NCELL(&node)*tree.nBytesPerCell ) return;
|
|
219494
|
+
if( nData<4+NCELL(&node)*tree.nBytesPerCell ) return;
|
|
219457
219495
|
|
|
219458
219496
|
pOut = sqlite3_str_new(0);
|
|
219459
219497
|
for(ii=0; ii<NCELL(&node); ii++){
|
|
@@ -238534,7 +238572,13 @@ typedef sqlite3_uint64 u64;
|
|
|
238534
238572
|
# define FLEXARRAY 1
|
|
238535
238573
|
#endif
|
|
238536
238574
|
|
|
238537
|
-
#endif
|
|
238575
|
+
#endif /* SQLITE_AMALGAMATION */
|
|
238576
|
+
|
|
238577
|
+
/*
|
|
238578
|
+
** Constants for the largest and smallest possible 32-bit signed integers.
|
|
238579
|
+
*/
|
|
238580
|
+
# define LARGEST_INT32 ((int)(0x7fffffff))
|
|
238581
|
+
# define SMALLEST_INT32 ((int)((-1) - LARGEST_INT32))
|
|
238538
238582
|
|
|
238539
238583
|
/* Truncate very long tokens to this many bytes. Hard limit is
|
|
238540
238584
|
** (65536-1-1-4-9)==65521 bytes. The limiting factor is the 16-bit offset
|
|
@@ -253097,7 +253141,7 @@ static int sqlite3Fts5IndexMerge(Fts5Index *p, int nMerge){
|
|
|
253097
253141
|
fts5StructureRelease(pStruct);
|
|
253098
253142
|
pStruct = pNew;
|
|
253099
253143
|
nMin = 1;
|
|
253100
|
-
nMerge = nMerge*-1;
|
|
253144
|
+
nMerge = (nMerge==SMALLEST_INT32 ? LARGEST_INT32 : (nMerge*-1));
|
|
253101
253145
|
}
|
|
253102
253146
|
if( pStruct && pStruct->nLevel ){
|
|
253103
253147
|
if( fts5IndexMerge(p, &pStruct, nMerge, nMin) ){
|
|
@@ -260304,7 +260348,7 @@ static void fts5SourceIdFunc(
|
|
|
260304
260348
|
){
|
|
260305
260349
|
assert( nArg==0 );
|
|
260306
260350
|
UNUSED_PARAM2(nArg, apUnused);
|
|
260307
|
-
sqlite3_result_text(pCtx, "fts5:
|
|
260351
|
+
sqlite3_result_text(pCtx, "fts5: 2026-01-09 17:27:48 b270f8339eb13b504d0b2ba154ebca966b7dde08e40c3ed7d559749818cb2075", -1, SQLITE_TRANSIENT);
|
|
260308
260352
|
}
|
|
260309
260353
|
|
|
260310
260354
|
/*
|
package/src/upstream/sqlite3.h
CHANGED
|
@@ -146,12 +146,12 @@ extern "C" {
|
|
|
146
146
|
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
|
|
147
147
|
** [sqlite_version()] and [sqlite_source_id()].
|
|
148
148
|
*/
|
|
149
|
-
#define SQLITE_VERSION "3.51.
|
|
150
|
-
#define SQLITE_VERSION_NUMBER
|
|
151
|
-
#define SQLITE_SOURCE_ID "
|
|
149
|
+
#define SQLITE_VERSION "3.51.2"
|
|
150
|
+
#define SQLITE_VERSION_NUMBER 3051002
|
|
151
|
+
#define SQLITE_SOURCE_ID "2026-01-09 17:27:48 b270f8339eb13b504d0b2ba154ebca966b7dde08e40c3ed7d559749818cb2075"
|
|
152
152
|
#define SQLITE_SCM_BRANCH "branch-3.51"
|
|
153
|
-
#define SQLITE_SCM_TAGS "release version-3.51.
|
|
154
|
-
#define SQLITE_SCM_DATETIME "
|
|
153
|
+
#define SQLITE_SCM_TAGS "release version-3.51.2"
|
|
154
|
+
#define SQLITE_SCM_DATETIME "2026-01-09T17:27:48.405Z"
|
|
155
155
|
|
|
156
156
|
/*
|
|
157
157
|
** CAPI3REF: Run-Time Library Version Numbers
|