koffi 2.2.0 → 2.2.2-beta.1
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 +6 -0
- package/package.json +2 -2
- package/src/koffi/build/2.2.2-beta.1/koffi_darwin_arm64.tar.gz +0 -0
- package/src/koffi/build/2.2.2-beta.1/koffi_darwin_x64.tar.gz +0 -0
- package/src/koffi/build/2.2.2-beta.1/koffi_freebsd_arm64.tar.gz +0 -0
- package/src/koffi/build/2.2.2-beta.1/koffi_freebsd_ia32.tar.gz +0 -0
- package/src/koffi/build/2.2.2-beta.1/koffi_freebsd_x64.tar.gz +0 -0
- package/src/koffi/build/2.2.2-beta.1/koffi_linux_arm32hf.tar.gz +0 -0
- package/src/koffi/build/2.2.2-beta.1/koffi_linux_arm64.tar.gz +0 -0
- package/src/koffi/build/2.2.2-beta.1/koffi_linux_ia32.tar.gz +0 -0
- package/src/koffi/build/2.2.2-beta.1/koffi_linux_riscv64hf64.tar.gz +0 -0
- package/src/koffi/build/2.2.2-beta.1/koffi_linux_x64.tar.gz +0 -0
- package/src/koffi/build/2.2.2-beta.1/koffi_openbsd_ia32.tar.gz +0 -0
- package/src/koffi/build/2.2.2-beta.1/koffi_openbsd_x64.tar.gz +0 -0
- package/src/koffi/build/2.2.2-beta.1/koffi_win32_arm64.tar.gz +0 -0
- package/src/koffi/build/2.2.2-beta.1/koffi_win32_ia32.tar.gz +0 -0
- package/src/koffi/build/2.2.2-beta.1/koffi_win32_x64.tar.gz +0 -0
- package/src/koffi/qemu/qemu.js +12 -10
- package/src/koffi/src/abi_arm32.cc +7 -11
- package/src/koffi/src/abi_arm64.cc +7 -11
- package/src/koffi/src/abi_riscv64.cc +7 -11
- package/src/koffi/src/abi_x64_sysv.cc +7 -11
- package/src/koffi/src/abi_x64_win.cc +7 -11
- package/src/koffi/src/abi_x86.cc +7 -11
- package/src/koffi/src/call.cc +53 -2
- package/src/koffi/src/call.hh +6 -1
- package/src/koffi/src/ffi.cc +66 -12
- package/src/koffi/src/ffi.hh +2 -0
- package/src/koffi/src/index.js +6 -2
- package/src/koffi/test/CMakeLists.txt +1 -1
- package/src/koffi/test/async.js +3 -0
- package/src/koffi/test/callbacks.js +30 -0
- package/src/koffi/test/misc.c +11 -0
- package/vendor/{sqlite3mc → sqlite3}/sqlite3.c +139 -43
- package/vendor/{sqlite3mc → sqlite3}/sqlite3.h +10 -3
- package/vendor/{sqlite3mc → sqlite3}/sqlite3ext.h +0 -0
- package/vendor/{sqlite3mc → sqlite3}/sqlite3mc.c +156 -53
- package/vendor/{sqlite3mc → sqlite3}/sqlite3mc.def +0 -0
- package/vendor/{sqlite3mc → sqlite3}/sqlite3mc.h +12 -5
- package/vendor/sqlite3/wasm/README.txt +23 -0
- package/vendor/sqlite3/wasm/common/SqliteTestUtil.js +236 -0
- package/vendor/sqlite3/wasm/common/emscripten.css +24 -0
- package/vendor/sqlite3/wasm/common/testing.css +63 -0
- package/vendor/sqlite3/wasm/demo-123-worker.html +44 -0
- package/vendor/sqlite3/wasm/demo-123.html +24 -0
- package/vendor/sqlite3/wasm/demo-123.js +289 -0
- package/vendor/sqlite3/wasm/demo-jsstorage.html +49 -0
- package/vendor/sqlite3/wasm/demo-jsstorage.js +114 -0
- package/vendor/sqlite3/wasm/demo-worker1-promiser.html +34 -0
- package/vendor/sqlite3/wasm/demo-worker1-promiser.js +270 -0
- package/vendor/sqlite3/wasm/demo-worker1.html +34 -0
- package/vendor/sqlite3/wasm/demo-worker1.js +345 -0
- package/vendor/sqlite3/wasm/index.html +90 -0
- package/vendor/sqlite3/wasm/jswasm/sqlite3-opfs-async-proxy.js +830 -0
- package/vendor/sqlite3/wasm/jswasm/sqlite3-worker1-promiser.js +259 -0
- package/vendor/sqlite3/wasm/jswasm/sqlite3-worker1.js +49 -0
- package/vendor/sqlite3/wasm/jswasm/sqlite3.js +10119 -0
- package/vendor/sqlite3/wasm/jswasm/sqlite3.wasm +0 -0
- package/vendor/sqlite3/wasm/tester1-worker.html +63 -0
- package/vendor/sqlite3/wasm/tester1.html +28 -0
- package/vendor/sqlite3/wasm/tester1.js +1864 -0
- package/src/koffi/build/2.2.0/koffi_darwin_arm64.tar.gz +0 -0
- package/src/koffi/build/2.2.0/koffi_darwin_x64.tar.gz +0 -0
- package/src/koffi/build/2.2.0/koffi_freebsd_arm64.tar.gz +0 -0
- package/src/koffi/build/2.2.0/koffi_freebsd_ia32.tar.gz +0 -0
- package/src/koffi/build/2.2.0/koffi_freebsd_x64.tar.gz +0 -0
- package/src/koffi/build/2.2.0/koffi_linux_arm32hf.tar.gz +0 -0
- package/src/koffi/build/2.2.0/koffi_linux_arm64.tar.gz +0 -0
- package/src/koffi/build/2.2.0/koffi_linux_ia32.tar.gz +0 -0
- package/src/koffi/build/2.2.0/koffi_linux_riscv64hf64.tar.gz +0 -0
- package/src/koffi/build/2.2.0/koffi_linux_x64.tar.gz +0 -0
- package/src/koffi/build/2.2.0/koffi_openbsd_ia32.tar.gz +0 -0
- package/src/koffi/build/2.2.0/koffi_openbsd_x64.tar.gz +0 -0
- package/src/koffi/build/2.2.0/koffi_win32_arm64.tar.gz +0 -0
- package/src/koffi/build/2.2.0/koffi_win32_ia32.tar.gz +0 -0
- package/src/koffi/build/2.2.0/koffi_win32_x64.tar.gz +0 -0
package/src/koffi/src/ffi.cc
CHANGED
|
@@ -44,6 +44,8 @@ namespace RG {
|
|
|
44
44
|
const int TypeInfoMarker = 0xDEADBEEF;
|
|
45
45
|
const int CastMarker = 0xDEADBEEF;
|
|
46
46
|
|
|
47
|
+
static RG_THREAD_LOCAL CallData *exec_call;
|
|
48
|
+
|
|
47
49
|
static bool ChangeSize(const char *name, Napi::Value value, Size min_size, Size max_size, Size *out_size)
|
|
48
50
|
{
|
|
49
51
|
Napi::Env env = value.Env();
|
|
@@ -972,16 +974,16 @@ static Napi::Value GetTypeDefinition(const Napi::CallbackInfo &info)
|
|
|
972
974
|
Napi::Object members = Napi::Object::New(env);
|
|
973
975
|
|
|
974
976
|
for (const RecordMember &member: type->members) {
|
|
975
|
-
Napi::Object
|
|
977
|
+
Napi::Object obj = Napi::Object::New(env);
|
|
976
978
|
|
|
977
979
|
Napi::External<TypeInfo> external = Napi::External<TypeInfo>::New(env, (TypeInfo *)member.type);
|
|
978
980
|
SetValueTag(instance, external, &TypeInfoMarker);
|
|
979
981
|
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
982
|
+
obj.Set("name", member.name);
|
|
983
|
+
obj.Set("type", external);
|
|
984
|
+
obj.Set("offset", member.offset);
|
|
983
985
|
|
|
984
|
-
members.Set(member.name,
|
|
986
|
+
members.Set(member.name, obj);
|
|
985
987
|
}
|
|
986
988
|
|
|
987
989
|
defn.Set("members", members);
|
|
@@ -1057,7 +1059,10 @@ static Napi::Value TranslateNormalCall(const Napi::CallbackInfo &info)
|
|
|
1057
1059
|
}
|
|
1058
1060
|
|
|
1059
1061
|
InstanceMemory *mem = instance->memories[0];
|
|
1060
|
-
CallData call(env, instance, func, mem);
|
|
1062
|
+
CallData call(env, instance, func, mem, false);
|
|
1063
|
+
|
|
1064
|
+
RG_DEFER_C(prev_call = exec_call) { exec_call = prev_call; };
|
|
1065
|
+
exec_call = &call;
|
|
1061
1066
|
|
|
1062
1067
|
if (!RG_UNLIKELY(call.Prepare(info)))
|
|
1063
1068
|
return env.Null();
|
|
@@ -1065,7 +1070,14 @@ static Napi::Value TranslateNormalCall(const Napi::CallbackInfo &info)
|
|
|
1065
1070
|
if (instance->debug) {
|
|
1066
1071
|
call.DumpForward();
|
|
1067
1072
|
}
|
|
1068
|
-
|
|
1073
|
+
|
|
1074
|
+
// Execute call
|
|
1075
|
+
{
|
|
1076
|
+
RG_DEFER_C(prev_call = exec_call) { exec_call = prev_call; };
|
|
1077
|
+
exec_call = &call;
|
|
1078
|
+
|
|
1079
|
+
call.Execute();
|
|
1080
|
+
}
|
|
1069
1081
|
|
|
1070
1082
|
return call.Complete();
|
|
1071
1083
|
}
|
|
@@ -1124,7 +1136,7 @@ static Napi::Value TranslateVariadicCall(const Napi::CallbackInfo &info)
|
|
|
1124
1136
|
return env.Null();
|
|
1125
1137
|
|
|
1126
1138
|
InstanceMemory *mem = instance->memories[0];
|
|
1127
|
-
CallData call(env, instance, &func, mem);
|
|
1139
|
+
CallData call(env, instance, &func, mem, false);
|
|
1128
1140
|
|
|
1129
1141
|
if (!RG_UNLIKELY(call.Prepare(info)))
|
|
1130
1142
|
return env.Null();
|
|
@@ -1132,7 +1144,14 @@ static Napi::Value TranslateVariadicCall(const Napi::CallbackInfo &info)
|
|
|
1132
1144
|
if (instance->debug) {
|
|
1133
1145
|
call.DumpForward();
|
|
1134
1146
|
}
|
|
1135
|
-
|
|
1147
|
+
|
|
1148
|
+
// Execute call
|
|
1149
|
+
{
|
|
1150
|
+
RG_DEFER_C(prev_call = exec_call) { exec_call = prev_call; };
|
|
1151
|
+
exec_call = &call;
|
|
1152
|
+
|
|
1153
|
+
call.Execute();
|
|
1154
|
+
}
|
|
1136
1155
|
|
|
1137
1156
|
return call.Complete();
|
|
1138
1157
|
}
|
|
@@ -1148,7 +1167,7 @@ public:
|
|
|
1148
1167
|
AsyncCall(Napi::Env env, InstanceData *instance, const FunctionInfo *func,
|
|
1149
1168
|
InstanceMemory *mem, Napi::Function &callback)
|
|
1150
1169
|
: Napi::AsyncWorker(callback), env(env), func(func->Ref()),
|
|
1151
|
-
call(env, instance, func, mem) {}
|
|
1170
|
+
call(env, instance, func, mem, true) {}
|
|
1152
1171
|
~AsyncCall() { func->Unref(); }
|
|
1153
1172
|
|
|
1154
1173
|
bool Prepare(const Napi::CallbackInfo &info) {
|
|
@@ -1170,6 +1189,9 @@ public:
|
|
|
1170
1189
|
void AsyncCall::Execute()
|
|
1171
1190
|
{
|
|
1172
1191
|
if (prepared) {
|
|
1192
|
+
RG_DEFER_C(prev_call = exec_call) { exec_call = prev_call; };
|
|
1193
|
+
exec_call = &call;
|
|
1194
|
+
|
|
1173
1195
|
call.Execute();
|
|
1174
1196
|
}
|
|
1175
1197
|
}
|
|
@@ -1673,6 +1695,10 @@ InstanceData::~InstanceData()
|
|
|
1673
1695
|
for (InstanceMemory *mem: memories) {
|
|
1674
1696
|
delete mem;
|
|
1675
1697
|
}
|
|
1698
|
+
|
|
1699
|
+
if (broker) {
|
|
1700
|
+
napi_release_threadsafe_function(broker, napi_tsfn_abort);
|
|
1701
|
+
}
|
|
1676
1702
|
}
|
|
1677
1703
|
|
|
1678
1704
|
static Napi::Value CastValue(const Napi::CallbackInfo &info)
|
|
@@ -1828,6 +1854,30 @@ static Napi::Value DecodeValue(const Napi::CallbackInfo &info)
|
|
|
1828
1854
|
return env.Null();
|
|
1829
1855
|
}
|
|
1830
1856
|
|
|
1857
|
+
extern "C" void RelayCallback(Size idx, uint8_t *own_sp, uint8_t *caller_sp, BackRegisters *out_reg)
|
|
1858
|
+
{
|
|
1859
|
+
exec_call->RelaySafe(idx, own_sp, caller_sp, out_reg);
|
|
1860
|
+
}
|
|
1861
|
+
|
|
1862
|
+
static InstanceData *CreateInstance(Napi::Env env)
|
|
1863
|
+
{
|
|
1864
|
+
InstanceData *instance = new InstanceData();
|
|
1865
|
+
RG_DEFER_N(err_guard) { delete instance; };
|
|
1866
|
+
|
|
1867
|
+
Napi::String resource_name = Napi::String::New(env, "Koffi Async Callback Broker");
|
|
1868
|
+
|
|
1869
|
+
if (napi_create_threadsafe_function(env, nullptr, nullptr, resource_name,
|
|
1870
|
+
0, 1, nullptr, nullptr, nullptr,
|
|
1871
|
+
CallData::RelayAsync, &instance->broker) != napi_ok) {
|
|
1872
|
+
LogError("Failed to create async callback broker");
|
|
1873
|
+
return nullptr;
|
|
1874
|
+
}
|
|
1875
|
+
napi_unref_threadsafe_function(env, instance->broker);
|
|
1876
|
+
|
|
1877
|
+
err_guard.Disable();
|
|
1878
|
+
return instance;
|
|
1879
|
+
}
|
|
1880
|
+
|
|
1831
1881
|
template <typename Func>
|
|
1832
1882
|
static void SetExports(Napi::Env env, Func func)
|
|
1833
1883
|
{
|
|
@@ -1906,7 +1956,9 @@ static void InitInternal(v8::Local<v8::Object> target, v8::Local<v8::Value>,
|
|
|
1906
1956
|
delete env_napi;
|
|
1907
1957
|
}, env_napi);
|
|
1908
1958
|
|
|
1909
|
-
InstanceData *instance =
|
|
1959
|
+
InstanceData *instance = CreateInstance(env_cxx);
|
|
1960
|
+
RG_CRITICAL(instance, "Failed to initialize Koffi");
|
|
1961
|
+
|
|
1910
1962
|
env_cxx.SetInstanceData(instance);
|
|
1911
1963
|
|
|
1912
1964
|
instance->debug = GetDebugFlag("DUMP_CALLS");
|
|
@@ -1922,7 +1974,9 @@ static Napi::Object InitModule(Napi::Env env, Napi::Object exports)
|
|
|
1922
1974
|
{
|
|
1923
1975
|
using namespace RG;
|
|
1924
1976
|
|
|
1925
|
-
InstanceData *instance =
|
|
1977
|
+
InstanceData *instance = CreateInstance(env);
|
|
1978
|
+
RG_CRITICAL(instance, "Failed to initialize Koffi");
|
|
1979
|
+
|
|
1926
1980
|
env.SetInstanceData(instance);
|
|
1927
1981
|
|
|
1928
1982
|
instance->debug = GetDebugFlag("DUMP_CALLS");
|
package/src/koffi/src/ffi.hh
CHANGED
package/src/koffi/src/index.js
CHANGED
|
@@ -18,6 +18,10 @@
|
|
|
18
18
|
const util = require('util');
|
|
19
19
|
|
|
20
20
|
let filename = __dirname + '/../build/koffi.node';
|
|
21
|
-
module.exports = require(filename);
|
|
22
21
|
|
|
23
|
-
module.exports
|
|
22
|
+
module.exports = {
|
|
23
|
+
...require(filename),
|
|
24
|
+
|
|
25
|
+
// Deprecated functions
|
|
26
|
+
handle: util.deprecate(module.exports.opaque, 'The koffi.handle() function was deprecated in Koffi 2.1, use koffi.opaque() instead', 'KOFFI001');
|
|
27
|
+
};
|
package/src/koffi/test/async.js
CHANGED
|
@@ -28,6 +28,8 @@ const PackedBFG = koffi.pack('PackedBFG', {
|
|
|
28
28
|
})
|
|
29
29
|
});
|
|
30
30
|
|
|
31
|
+
const CharCallback = koffi.callback('int CharCallback(int idx, char c)');
|
|
32
|
+
|
|
31
33
|
main();
|
|
32
34
|
|
|
33
35
|
async function main() {
|
|
@@ -46,6 +48,7 @@ async function test() {
|
|
|
46
48
|
|
|
47
49
|
const ConcatenateToInt1 = lib.func('ConcatenateToInt1', 'int64_t', Array(12).fill('int8_t'));
|
|
48
50
|
const MakePackedBFG = lib.func('PackedBFG __fastcall MakePackedBFG(int x, double y, _Out_ PackedBFG *p, const char *str)');
|
|
51
|
+
const CallMeChar = lib.func('int CallMeChar(CharCallback *func)');
|
|
49
52
|
|
|
50
53
|
let promises = [];
|
|
51
54
|
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
|
|
16
16
|
const koffi = require('./build/koffi.node');
|
|
17
17
|
const assert = require('assert');
|
|
18
|
+
const util = require('util');
|
|
18
19
|
|
|
19
20
|
const BFG = koffi.struct('BFG', {
|
|
20
21
|
a: 'int8_t',
|
|
@@ -41,6 +42,7 @@ const ApplyCallback = koffi.callback('int __stdcall ApplyCallback(int a, int b,
|
|
|
41
42
|
const IntCallback = koffi.callback('int IntCallback(int x)');
|
|
42
43
|
const VectorCallback = koffi.callback('int VectorCallback(int len, Vec2 *vec)');
|
|
43
44
|
const SortCallback = koffi.callback('int SortCallback(const void *ptr1, const void *ptr2)');
|
|
45
|
+
const CharCallback = koffi.callback('int CharCallback(int idx, char c)');
|
|
44
46
|
|
|
45
47
|
const StructCallbacks = koffi.struct('StructCallbacks', {
|
|
46
48
|
first: koffi.pointer(IntCallback),
|
|
@@ -75,6 +77,8 @@ async function test() {
|
|
|
75
77
|
const CallCallback = lib.func('int CallCallback(int x)');
|
|
76
78
|
const MakeVectors = lib.func('int MakeVectors(int len, VectorCallback *func)');
|
|
77
79
|
const CallQSort = lib.func('void CallQSort(_Inout_ void *base, size_t nmemb, size_t size, SortCallback *cb)');
|
|
80
|
+
const CallMeChar = lib.func('int CallMeChar(CharCallback *func)');
|
|
81
|
+
const GetMinusOne1 = lib.func('int8_t GetMinusOne1(void)');
|
|
78
82
|
|
|
79
83
|
// Simple test similar to README example
|
|
80
84
|
{
|
|
@@ -230,4 +234,30 @@ async function test() {
|
|
|
230
234
|
|
|
231
235
|
assert.deepEqual(array, ['123', 'bar', 'foo', 'foobar']);
|
|
232
236
|
}
|
|
237
|
+
|
|
238
|
+
// Make sure thread local CallData is restored after nested call inside callback
|
|
239
|
+
// Regression test for issue #15
|
|
240
|
+
{
|
|
241
|
+
let chars = [97, 98];
|
|
242
|
+
|
|
243
|
+
let cb = koffi.register((idx, c) => {
|
|
244
|
+
assert.equal(GetMinusOne1(), -1);
|
|
245
|
+
assert.equal(c, chars[idx]);
|
|
246
|
+
|
|
247
|
+
return c;
|
|
248
|
+
}, 'CharCallback *');
|
|
249
|
+
|
|
250
|
+
let ret = CallMeChar(cb);
|
|
251
|
+
assert.equal(ret, 97 + 98);
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
// Test callback inside async function
|
|
255
|
+
{
|
|
256
|
+
let chars = [97, 98];
|
|
257
|
+
|
|
258
|
+
let cb = koffi.register((idx, c) => (idx + 1) * c, 'CharCallback *');
|
|
259
|
+
let ret = await util.promisify(CallMeChar.async)(cb);
|
|
260
|
+
|
|
261
|
+
assert.equal(ret, 97 + 2 * 98);
|
|
262
|
+
}
|
|
233
263
|
}
|
package/src/koffi/test/misc.c
CHANGED
|
@@ -169,6 +169,7 @@ typedef struct Vec2 {
|
|
|
169
169
|
|
|
170
170
|
typedef int VectorCallback(int len, Vec2 *vec);
|
|
171
171
|
typedef int SortCallback(const void *ptr1, const void *ptr2);
|
|
172
|
+
typedef int CharCallback(int idx, char c);
|
|
172
173
|
|
|
173
174
|
EXPORT int8_t GetMinusOne1(void)
|
|
174
175
|
{
|
|
@@ -776,3 +777,13 @@ EXPORT void CallQSort(void *base, size_t nmemb, size_t size, SortCallback *cb)
|
|
|
776
777
|
{
|
|
777
778
|
qsort(base, nmemb, size, cb);
|
|
778
779
|
}
|
|
780
|
+
|
|
781
|
+
EXPORT int CallMeChar(CharCallback *func)
|
|
782
|
+
{
|
|
783
|
+
int ret = 0;
|
|
784
|
+
|
|
785
|
+
ret += func(0, 'a');
|
|
786
|
+
ret += func(1, 'b');
|
|
787
|
+
|
|
788
|
+
return ret;
|
|
789
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/******************************************************************************
|
|
2
2
|
** This file is an amalgamation of many separate C source files from SQLite
|
|
3
|
-
** version 3.40.
|
|
3
|
+
** version 3.40.1. 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
|
|
@@ -452,9 +452,9 @@ extern "C" {
|
|
|
452
452
|
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
|
|
453
453
|
** [sqlite_version()] and [sqlite_source_id()].
|
|
454
454
|
*/
|
|
455
|
-
#define SQLITE_VERSION "3.40.
|
|
456
|
-
#define SQLITE_VERSION_NUMBER
|
|
457
|
-
#define SQLITE_SOURCE_ID "2022-
|
|
455
|
+
#define SQLITE_VERSION "3.40.1"
|
|
456
|
+
#define SQLITE_VERSION_NUMBER 3040001
|
|
457
|
+
#define SQLITE_SOURCE_ID "2022-12-28 14:03:47 df5c253c0b3dd24916e4ec7cf77d3db5294cc9fd45ae7b9c5e82ad8197f38a24"
|
|
458
458
|
|
|
459
459
|
/*
|
|
460
460
|
** CAPI3REF: Run-Time Library Version Numbers
|
|
@@ -1498,6 +1498,12 @@ struct sqlite3_io_methods {
|
|
|
1498
1498
|
**
|
|
1499
1499
|
** <li>[[SQLITE_FCNTL_CKSM_FILE]]
|
|
1500
1500
|
** Used by the cksmvfs VFS module only.
|
|
1501
|
+
**
|
|
1502
|
+
** <li>[[SQLITE_FCNTL_RESET_CACHE]]
|
|
1503
|
+
** If there is currently no transaction open on the database, and the
|
|
1504
|
+
** database is not a temp db, then this file-control purges the contents
|
|
1505
|
+
** of the in-memory page cache. If there is an open transaction, or if
|
|
1506
|
+
** the db is a temp-db, it is a no-op, not an error.
|
|
1501
1507
|
** </ul>
|
|
1502
1508
|
*/
|
|
1503
1509
|
#define SQLITE_FCNTL_LOCKSTATE 1
|
|
@@ -1540,6 +1546,7 @@ struct sqlite3_io_methods {
|
|
|
1540
1546
|
#define SQLITE_FCNTL_CKPT_START 39
|
|
1541
1547
|
#define SQLITE_FCNTL_EXTERNAL_READER 40
|
|
1542
1548
|
#define SQLITE_FCNTL_CKSM_FILE 41
|
|
1549
|
+
#define SQLITE_FCNTL_RESET_CACHE 42
|
|
1543
1550
|
|
|
1544
1551
|
/* deprecated names */
|
|
1545
1552
|
#define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE
|
|
@@ -15714,6 +15721,8 @@ SQLITE_PRIVATE int sqlite3BtreeCheckpoint(Btree*, int, int *, int *);
|
|
|
15714
15721
|
|
|
15715
15722
|
SQLITE_PRIVATE int sqlite3BtreeTransferRow(BtCursor*, BtCursor*, i64);
|
|
15716
15723
|
|
|
15724
|
+
SQLITE_PRIVATE void sqlite3BtreeClearCache(Btree*);
|
|
15725
|
+
|
|
15717
15726
|
/*
|
|
15718
15727
|
** If we are not using shared cache, then there is no need to
|
|
15719
15728
|
** use mutexes to access the BtShared structures. So make the
|
|
@@ -27290,9 +27299,13 @@ static int memsys5Roundup(int n){
|
|
|
27290
27299
|
if( n<=mem5.szAtom ) return mem5.szAtom;
|
|
27291
27300
|
return mem5.szAtom*2;
|
|
27292
27301
|
}
|
|
27293
|
-
if( n>
|
|
27302
|
+
if( n>0x10000000 ){
|
|
27303
|
+
if( n>0x40000000 ) return 0;
|
|
27304
|
+
if( n>0x20000000 ) return 0x40000000;
|
|
27305
|
+
return 0x20000000;
|
|
27306
|
+
}
|
|
27294
27307
|
for(iFullSz=mem5.szAtom*8; iFullSz<n; iFullSz *= 4);
|
|
27295
|
-
if( (iFullSz/2)>=n ) return iFullSz/2;
|
|
27308
|
+
if( (iFullSz/2)>=(i64)n ) return iFullSz/2;
|
|
27296
27309
|
return iFullSz;
|
|
27297
27310
|
}
|
|
27298
27311
|
|
|
@@ -37350,6 +37363,9 @@ static int robust_open(const char *z, int f, mode_t m){
|
|
|
37350
37363
|
break;
|
|
37351
37364
|
}
|
|
37352
37365
|
if( fd>=SQLITE_MINIMUM_FILE_DESCRIPTOR ) break;
|
|
37366
|
+
if( (f & (O_EXCL|O_CREAT))==(O_EXCL|O_CREAT) ){
|
|
37367
|
+
(void)osUnlink(z);
|
|
37368
|
+
}
|
|
37353
37369
|
osClose(fd);
|
|
37354
37370
|
sqlite3_log(SQLITE_WARNING,
|
|
37355
37371
|
"attempt to open \"%s\" as file descriptor %d", z, fd);
|
|
@@ -51083,6 +51099,7 @@ static int memdbTruncate(sqlite3_file*, sqlite3_int64 size);
|
|
|
51083
51099
|
static int memdbSync(sqlite3_file*, int flags);
|
|
51084
51100
|
static int memdbFileSize(sqlite3_file*, sqlite3_int64 *pSize);
|
|
51085
51101
|
static int memdbLock(sqlite3_file*, int);
|
|
51102
|
+
static int memdbUnlock(sqlite3_file*, int);
|
|
51086
51103
|
/* static int memdbCheckReservedLock(sqlite3_file*, int *pResOut);// not used */
|
|
51087
51104
|
static int memdbFileControl(sqlite3_file*, int op, void *pArg);
|
|
51088
51105
|
/* static int memdbSectorSize(sqlite3_file*); // not used */
|
|
@@ -51141,7 +51158,7 @@ static const sqlite3_io_methods memdb_io_methods = {
|
|
|
51141
51158
|
memdbSync, /* xSync */
|
|
51142
51159
|
memdbFileSize, /* xFileSize */
|
|
51143
51160
|
memdbLock, /* xLock */
|
|
51144
|
-
|
|
51161
|
+
memdbUnlock, /* xUnlock */
|
|
51145
51162
|
0, /* memdbCheckReservedLock, */ /* xCheckReservedLock */
|
|
51146
51163
|
memdbFileControl, /* xFileControl */
|
|
51147
51164
|
0, /* memdbSectorSize,*/ /* xSectorSize */
|
|
@@ -51342,39 +51359,81 @@ static int memdbLock(sqlite3_file *pFile, int eLock){
|
|
|
51342
51359
|
MemFile *pThis = (MemFile*)pFile;
|
|
51343
51360
|
MemStore *p = pThis->pStore;
|
|
51344
51361
|
int rc = SQLITE_OK;
|
|
51345
|
-
if( eLock
|
|
51362
|
+
if( eLock<=pThis->eLock ) return SQLITE_OK;
|
|
51346
51363
|
memdbEnter(p);
|
|
51347
|
-
|
|
51348
|
-
|
|
51349
|
-
|
|
51350
|
-
|
|
51351
|
-
|
|
51352
|
-
|
|
51353
|
-
|
|
51354
|
-
|
|
51364
|
+
|
|
51365
|
+
assert( p->nWrLock==0 || p->nWrLock==1 );
|
|
51366
|
+
assert( pThis->eLock<=SQLITE_LOCK_SHARED || p->nWrLock==1 );
|
|
51367
|
+
assert( pThis->eLock==SQLITE_LOCK_NONE || p->nRdLock>=1 );
|
|
51368
|
+
|
|
51369
|
+
if( eLock>SQLITE_LOCK_SHARED && (p->mFlags & SQLITE_DESERIALIZE_READONLY) ){
|
|
51370
|
+
rc = SQLITE_READONLY;
|
|
51371
|
+
}else{
|
|
51372
|
+
switch( eLock ){
|
|
51373
|
+
case SQLITE_LOCK_SHARED: {
|
|
51374
|
+
assert( pThis->eLock==SQLITE_LOCK_NONE );
|
|
51375
|
+
if( p->nWrLock>0 ){
|
|
51376
|
+
rc = SQLITE_BUSY;
|
|
51377
|
+
}else{
|
|
51378
|
+
p->nRdLock++;
|
|
51379
|
+
}
|
|
51380
|
+
break;
|
|
51381
|
+
};
|
|
51382
|
+
|
|
51383
|
+
case SQLITE_LOCK_RESERVED:
|
|
51384
|
+
case SQLITE_LOCK_PENDING: {
|
|
51385
|
+
assert( pThis->eLock>=SQLITE_LOCK_SHARED );
|
|
51386
|
+
if( ALWAYS(pThis->eLock==SQLITE_LOCK_SHARED) ){
|
|
51387
|
+
if( p->nWrLock>0 ){
|
|
51388
|
+
rc = SQLITE_BUSY;
|
|
51389
|
+
}else{
|
|
51390
|
+
p->nWrLock = 1;
|
|
51391
|
+
}
|
|
51392
|
+
}
|
|
51393
|
+
break;
|
|
51394
|
+
}
|
|
51395
|
+
|
|
51396
|
+
default: {
|
|
51397
|
+
assert( eLock==SQLITE_LOCK_EXCLUSIVE );
|
|
51398
|
+
assert( pThis->eLock>=SQLITE_LOCK_SHARED );
|
|
51399
|
+
if( p->nRdLock>1 ){
|
|
51400
|
+
rc = SQLITE_BUSY;
|
|
51401
|
+
}else if( pThis->eLock==SQLITE_LOCK_SHARED ){
|
|
51402
|
+
p->nWrLock = 1;
|
|
51403
|
+
}
|
|
51404
|
+
break;
|
|
51355
51405
|
}
|
|
51356
51406
|
}
|
|
51357
|
-
}
|
|
51358
|
-
|
|
51359
|
-
|
|
51360
|
-
|
|
51361
|
-
|
|
51362
|
-
|
|
51363
|
-
|
|
51364
|
-
|
|
51407
|
+
}
|
|
51408
|
+
if( rc==SQLITE_OK ) pThis->eLock = eLock;
|
|
51409
|
+
memdbLeave(p);
|
|
51410
|
+
return rc;
|
|
51411
|
+
}
|
|
51412
|
+
|
|
51413
|
+
/*
|
|
51414
|
+
** Unlock an memdb-file.
|
|
51415
|
+
*/
|
|
51416
|
+
static int memdbUnlock(sqlite3_file *pFile, int eLock){
|
|
51417
|
+
MemFile *pThis = (MemFile*)pFile;
|
|
51418
|
+
MemStore *p = pThis->pStore;
|
|
51419
|
+
if( eLock>=pThis->eLock ) return SQLITE_OK;
|
|
51420
|
+
memdbEnter(p);
|
|
51421
|
+
|
|
51422
|
+
assert( eLock==SQLITE_LOCK_SHARED || eLock==SQLITE_LOCK_NONE );
|
|
51423
|
+
if( eLock==SQLITE_LOCK_SHARED ){
|
|
51424
|
+
if( ALWAYS(pThis->eLock>SQLITE_LOCK_SHARED) ){
|
|
51425
|
+
p->nWrLock--;
|
|
51365
51426
|
}
|
|
51366
51427
|
}else{
|
|
51367
|
-
assert( eLock==SQLITE_LOCK_NONE );
|
|
51368
51428
|
if( pThis->eLock>SQLITE_LOCK_SHARED ){
|
|
51369
|
-
|
|
51370
|
-
p->nWrLock = 0;
|
|
51429
|
+
p->nWrLock--;
|
|
51371
51430
|
}
|
|
51372
|
-
assert( p->nRdLock>0 );
|
|
51373
51431
|
p->nRdLock--;
|
|
51374
51432
|
}
|
|
51375
|
-
|
|
51433
|
+
|
|
51434
|
+
pThis->eLock = eLock;
|
|
51376
51435
|
memdbLeave(p);
|
|
51377
|
-
return
|
|
51436
|
+
return SQLITE_OK;
|
|
51378
51437
|
}
|
|
51379
51438
|
|
|
51380
51439
|
#if 0
|
|
@@ -51484,7 +51543,7 @@ static int memdbOpen(
|
|
|
51484
51543
|
|
|
51485
51544
|
memset(pFile, 0, sizeof(*pFile));
|
|
51486
51545
|
szName = sqlite3Strlen30(zName);
|
|
51487
|
-
if( szName>1 && zName[0]=='/' ){
|
|
51546
|
+
if( szName>1 && (zName[0]=='/' || zName[0]=='\\') ){
|
|
51488
51547
|
int i;
|
|
51489
51548
|
#ifndef SQLITE_MUTEX_OMIT
|
|
51490
51549
|
sqlite3_mutex *pVfsMutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1);
|
|
@@ -51831,6 +51890,13 @@ end_deserialize:
|
|
|
51831
51890
|
return rc;
|
|
51832
51891
|
}
|
|
51833
51892
|
|
|
51893
|
+
/*
|
|
51894
|
+
** Return true if the VFS is the memvfs.
|
|
51895
|
+
*/
|
|
51896
|
+
SQLITE_PRIVATE int sqlite3IsMemdb(const sqlite3_vfs *pVfs){
|
|
51897
|
+
return pVfs==&memdb_vfs;
|
|
51898
|
+
}
|
|
51899
|
+
|
|
51834
51900
|
/*
|
|
51835
51901
|
** This routine is called when the extension is loaded.
|
|
51836
51902
|
** Register the new VFS.
|
|
@@ -79159,6 +79225,17 @@ SQLITE_PRIVATE int sqlite3BtreeIsReadonly(Btree *p){
|
|
|
79159
79225
|
*/
|
|
79160
79226
|
SQLITE_PRIVATE int sqlite3HeaderSizeBtree(void){ return ROUND8(sizeof(MemPage)); }
|
|
79161
79227
|
|
|
79228
|
+
/*
|
|
79229
|
+
** If no transaction is active and the database is not a temp-db, clear
|
|
79230
|
+
** the in-memory pager cache.
|
|
79231
|
+
*/
|
|
79232
|
+
SQLITE_PRIVATE void sqlite3BtreeClearCache(Btree *p){
|
|
79233
|
+
BtShared *pBt = p->pBt;
|
|
79234
|
+
if( pBt->inTransaction==TRANS_NONE ){
|
|
79235
|
+
sqlite3PagerClearCache(pBt->pPager);
|
|
79236
|
+
}
|
|
79237
|
+
}
|
|
79238
|
+
|
|
79162
79239
|
#if !defined(SQLITE_OMIT_SHARED_CACHE)
|
|
79163
79240
|
/*
|
|
79164
79241
|
** Return true if the Btree passed as the only argument is sharable.
|
|
@@ -83398,7 +83475,7 @@ SQLITE_PRIVATE void sqlite3VdbeAppendP4(Vdbe *p, void *pP4, int n){
|
|
|
83398
83475
|
if( p->db->mallocFailed ){
|
|
83399
83476
|
freeP4(p->db, n, pP4);
|
|
83400
83477
|
}else{
|
|
83401
|
-
assert( pP4!=0 );
|
|
83478
|
+
assert( pP4!=0 || n==P4_DYNAMIC );
|
|
83402
83479
|
assert( p->nOp>0 );
|
|
83403
83480
|
pOp = &p->aOp[p->nOp-1];
|
|
83404
83481
|
assert( pOp->p4type==P4_NOTUSED );
|
|
@@ -132310,7 +132387,7 @@ static const sqlite3_api_routines sqlite3Apis = {
|
|
|
132310
132387
|
#endif
|
|
132311
132388
|
sqlite3_db_name,
|
|
132312
132389
|
/* Version 3.40.0 and later */
|
|
132313
|
-
|
|
132390
|
+
sqlite3_value_encoding
|
|
132314
132391
|
};
|
|
132315
132392
|
|
|
132316
132393
|
/* True if x is the directory separator character
|
|
@@ -145451,7 +145528,7 @@ SQLITE_PRIVATE Trigger *sqlite3TriggerList(Parse *pParse, Table *pTab){
|
|
|
145451
145528
|
if( pTrig->pTabSchema==pTab->pSchema
|
|
145452
145529
|
&& pTrig->table
|
|
145453
145530
|
&& 0==sqlite3StrICmp(pTrig->table, pTab->zName)
|
|
145454
|
-
&& pTrig->pTabSchema!=pTmpSchema
|
|
145531
|
+
&& (pTrig->pTabSchema!=pTmpSchema || pTrig->bReturning)
|
|
145455
145532
|
){
|
|
145456
145533
|
pTrig->pNext = pList;
|
|
145457
145534
|
pList = pTrig;
|
|
@@ -155635,7 +155712,7 @@ SQLITE_PRIVATE int sqlite3WhereIsDistinct(WhereInfo *pWInfo){
|
|
|
155635
155712
|
** block sorting is required.
|
|
155636
155713
|
*/
|
|
155637
155714
|
SQLITE_PRIVATE int sqlite3WhereIsOrdered(WhereInfo *pWInfo){
|
|
155638
|
-
return pWInfo->nOBSat;
|
|
155715
|
+
return pWInfo->nOBSat<0 ? 0 : pWInfo->nOBSat;
|
|
155639
155716
|
}
|
|
155640
155717
|
|
|
155641
155718
|
/*
|
|
@@ -174543,7 +174620,7 @@ SQLITE_API int sqlite3_overload_function(
|
|
|
174543
174620
|
rc = sqlite3FindFunction(db, zName, nArg, SQLITE_UTF8, 0)!=0;
|
|
174544
174621
|
sqlite3_mutex_leave(db->mutex);
|
|
174545
174622
|
if( rc ) return SQLITE_OK;
|
|
174546
|
-
zCopy = sqlite3_mprintf(zName);
|
|
174623
|
+
zCopy = sqlite3_mprintf("%s", zName);
|
|
174547
174624
|
if( zCopy==0 ) return SQLITE_NOMEM;
|
|
174548
174625
|
return sqlite3_create_function_v2(db, zName, nArg, SQLITE_UTF8,
|
|
174549
174626
|
zCopy, sqlite3InvalidFunction, 0, 0, sqlite3_free);
|
|
@@ -176375,6 +176452,9 @@ SQLITE_API int sqlite3_file_control(sqlite3 *db, const char *zDbName, int op, vo
|
|
|
176375
176452
|
sqlite3BtreeSetPageSize(pBtree, 0, iNew, 0);
|
|
176376
176453
|
}
|
|
176377
176454
|
rc = SQLITE_OK;
|
|
176455
|
+
}else if( op==SQLITE_FCNTL_RESET_CACHE ){
|
|
176456
|
+
sqlite3BtreeClearCache(pBtree);
|
|
176457
|
+
rc = SQLITE_OK;
|
|
176378
176458
|
}else{
|
|
176379
176459
|
int nSave = db->busyHandler.nBusy;
|
|
176380
176460
|
rc = sqlite3OsFileControl(fd, op, pArg);
|
|
@@ -217790,6 +217870,22 @@ static int sessionChangesetNextOne(
|
|
|
217790
217870
|
if( p->op==SQLITE_INSERT ) p->op = SQLITE_DELETE;
|
|
217791
217871
|
else if( p->op==SQLITE_DELETE ) p->op = SQLITE_INSERT;
|
|
217792
217872
|
}
|
|
217873
|
+
|
|
217874
|
+
/* If this is an UPDATE that is part of a changeset, then check that
|
|
217875
|
+
** there are no fields in the old.* record that are not (a) PK fields,
|
|
217876
|
+
** or (b) also present in the new.* record.
|
|
217877
|
+
**
|
|
217878
|
+
** Such records are technically corrupt, but the rebaser was at one
|
|
217879
|
+
** point generating them. Under most circumstances this is benign, but
|
|
217880
|
+
** can cause spurious SQLITE_RANGE errors when applying the changeset. */
|
|
217881
|
+
if( p->bPatchset==0 && p->op==SQLITE_UPDATE){
|
|
217882
|
+
for(i=0; i<p->nCol; i++){
|
|
217883
|
+
if( p->abPK[i]==0 && p->apValue[i+p->nCol]==0 ){
|
|
217884
|
+
sqlite3ValueFree(p->apValue[i]);
|
|
217885
|
+
p->apValue[i] = 0;
|
|
217886
|
+
}
|
|
217887
|
+
}
|
|
217888
|
+
}
|
|
217793
217889
|
}
|
|
217794
217890
|
|
|
217795
217891
|
return SQLITE_ROW;
|
|
@@ -219986,7 +220082,7 @@ static void sessionAppendPartialUpdate(
|
|
|
219986
220082
|
if( !pIter->abPK[i] && a1[0] ) bData = 1;
|
|
219987
220083
|
memcpy(pOut, a1, n1);
|
|
219988
220084
|
pOut += n1;
|
|
219989
|
-
}else if( a2[0]!=0xFF ){
|
|
220085
|
+
}else if( a2[0]!=0xFF && a1[0] ){
|
|
219990
220086
|
bData = 1;
|
|
219991
220087
|
memcpy(pOut, a2, n2);
|
|
219992
220088
|
pOut += n2;
|
|
@@ -236016,7 +236112,7 @@ static void fts5CheckTransactionState(Fts5FullTable *p, int op, int iSavepoint){
|
|
|
236016
236112
|
break;
|
|
236017
236113
|
|
|
236018
236114
|
case FTS5_SYNC:
|
|
236019
|
-
assert( p->ts.eState==1 );
|
|
236115
|
+
assert( p->ts.eState==1 || p->ts.eState==2 );
|
|
236020
236116
|
p->ts.eState = 2;
|
|
236021
236117
|
break;
|
|
236022
236118
|
|
|
@@ -236031,21 +236127,21 @@ static void fts5CheckTransactionState(Fts5FullTable *p, int op, int iSavepoint){
|
|
|
236031
236127
|
break;
|
|
236032
236128
|
|
|
236033
236129
|
case FTS5_SAVEPOINT:
|
|
236034
|
-
assert( p->ts.eState
|
|
236130
|
+
assert( p->ts.eState>=1 );
|
|
236035
236131
|
assert( iSavepoint>=0 );
|
|
236036
236132
|
assert( iSavepoint>=p->ts.iSavepoint );
|
|
236037
236133
|
p->ts.iSavepoint = iSavepoint;
|
|
236038
236134
|
break;
|
|
236039
236135
|
|
|
236040
236136
|
case FTS5_RELEASE:
|
|
236041
|
-
assert( p->ts.eState
|
|
236137
|
+
assert( p->ts.eState>=1 );
|
|
236042
236138
|
assert( iSavepoint>=0 );
|
|
236043
236139
|
assert( iSavepoint<=p->ts.iSavepoint );
|
|
236044
236140
|
p->ts.iSavepoint = iSavepoint-1;
|
|
236045
236141
|
break;
|
|
236046
236142
|
|
|
236047
236143
|
case FTS5_ROLLBACKTO:
|
|
236048
|
-
assert( p->ts.eState
|
|
236144
|
+
assert( p->ts.eState>=1 );
|
|
236049
236145
|
assert( iSavepoint>=-1 );
|
|
236050
236146
|
/* The following assert() can fail if another vtab strikes an error
|
|
236051
236147
|
** within an xSavepoint() call then SQLite calls xRollbackTo() - without
|
|
@@ -237381,7 +237477,7 @@ static int fts5UpdateMethod(
|
|
|
237381
237477
|
int rc = SQLITE_OK; /* Return code */
|
|
237382
237478
|
|
|
237383
237479
|
/* A transaction must be open when this is called. */
|
|
237384
|
-
assert( pTab->ts.eState==1 );
|
|
237480
|
+
assert( pTab->ts.eState==1 || pTab->ts.eState==2 );
|
|
237385
237481
|
|
|
237386
237482
|
assert( pVtab->zErrMsg==0 );
|
|
237387
237483
|
assert( nArg==1 || nArg==(2+pConfig->nCol+2) );
|
|
@@ -238549,7 +238645,7 @@ static void fts5SourceIdFunc(
|
|
|
238549
238645
|
){
|
|
238550
238646
|
assert( nArg==0 );
|
|
238551
238647
|
UNUSED_PARAM2(nArg, apUnused);
|
|
238552
|
-
sqlite3_result_text(pCtx, "fts5: 2022-
|
|
238648
|
+
sqlite3_result_text(pCtx, "fts5: 2022-12-28 14:03:47 df5c253c0b3dd24916e4ec7cf77d3db5294cc9fd45ae7b9c5e82ad8197f38a24", -1, SQLITE_TRANSIENT);
|
|
238553
238649
|
}
|
|
238554
238650
|
|
|
238555
238651
|
/*
|