@photostructure/sqlite 0.0.1 → 0.2.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 +36 -2
- package/README.md +45 -484
- package/SECURITY.md +27 -84
- package/binding.gyp +69 -22
- package/dist/index.cjs +185 -18
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +552 -100
- package/dist/index.d.mts +552 -100
- package/dist/index.d.ts +552 -100
- package/dist/index.mjs +183 -18
- package/dist/index.mjs.map +1 -1
- package/package.json +51 -41
- 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-x64/@photostructure+sqlite.glibc.node +0 -0
- package/src/aggregate_function.cpp +503 -235
- package/src/aggregate_function.h +57 -42
- package/src/binding.cpp +117 -14
- package/src/dirname.ts +1 -1
- package/src/index.ts +122 -332
- package/src/lru-cache.ts +84 -0
- package/src/shims/env-inl.h +6 -15
- package/src/shims/node_errors.h +4 -0
- package/src/shims/sqlite_errors.h +162 -0
- package/src/shims/util.h +29 -4
- package/src/sql-tag-store.ts +140 -0
- package/src/sqlite_exception.h +49 -0
- package/src/sqlite_impl.cpp +711 -127
- package/src/sqlite_impl.h +84 -6
- package/src/{stack_path.ts → stack-path.ts} +7 -1
- package/src/types/aggregate-options.ts +22 -0
- package/src/types/changeset-apply-options.ts +18 -0
- package/src/types/database-sync-instance.ts +203 -0
- package/src/types/database-sync-options.ts +69 -0
- package/src/types/session-options.ts +10 -0
- package/src/types/sql-tag-store-instance.ts +51 -0
- package/src/types/sqlite-authorization-actions.ts +77 -0
- package/src/types/sqlite-authorization-results.ts +15 -0
- package/src/types/sqlite-changeset-conflict-types.ts +19 -0
- package/src/types/sqlite-changeset-resolution.ts +15 -0
- package/src/types/sqlite-open-flags.ts +50 -0
- package/src/types/statement-sync-instance.ts +73 -0
- package/src/types/user-functions-options.ts +14 -0
- package/src/upstream/node_sqlite.cc +960 -259
- package/src/upstream/node_sqlite.h +127 -2
- package/src/upstream/sqlite.js +1 -14
- package/src/upstream/sqlite3.c +4510 -1411
- package/src/upstream/sqlite3.h +390 -195
- package/src/upstream/sqlite3ext.h +7 -0
- package/src/user_function.cpp +88 -36
- package/src/user_function.h +2 -1
|
@@ -24,7 +24,9 @@ using v8::BigInt;
|
|
|
24
24
|
using v8::Boolean;
|
|
25
25
|
using v8::ConstructorBehavior;
|
|
26
26
|
using v8::Context;
|
|
27
|
+
using v8::DictionaryTemplate;
|
|
27
28
|
using v8::DontDelete;
|
|
29
|
+
using v8::EscapableHandleScope;
|
|
28
30
|
using v8::Exception;
|
|
29
31
|
using v8::Function;
|
|
30
32
|
using v8::FunctionCallback;
|
|
@@ -35,11 +37,14 @@ using v8::HandleScope;
|
|
|
35
37
|
using v8::Int32;
|
|
36
38
|
using v8::Integer;
|
|
37
39
|
using v8::Isolate;
|
|
40
|
+
using v8::JustVoid;
|
|
38
41
|
using v8::Local;
|
|
39
42
|
using v8::LocalVector;
|
|
43
|
+
using v8::Maybe;
|
|
40
44
|
using v8::MaybeLocal;
|
|
41
45
|
using v8::Name;
|
|
42
46
|
using v8::NewStringType;
|
|
47
|
+
using v8::Nothing;
|
|
43
48
|
using v8::Null;
|
|
44
49
|
using v8::Number;
|
|
45
50
|
using v8::Object;
|
|
@@ -116,6 +121,18 @@ using v8::Value;
|
|
|
116
121
|
} \
|
|
117
122
|
} while (0)
|
|
118
123
|
|
|
124
|
+
namespace {
|
|
125
|
+
Local<DictionaryTemplate> getLazyIterTemplate(Environment* env) {
|
|
126
|
+
auto iter_template = env->iter_template();
|
|
127
|
+
if (iter_template.IsEmpty()) {
|
|
128
|
+
static constexpr std::string_view iter_keys[] = {"done", "value"};
|
|
129
|
+
iter_template = DictionaryTemplate::New(env->isolate(), iter_keys);
|
|
130
|
+
env->set_iter_template(iter_template);
|
|
131
|
+
}
|
|
132
|
+
return iter_template;
|
|
133
|
+
}
|
|
134
|
+
} // namespace
|
|
135
|
+
|
|
119
136
|
inline MaybeLocal<Object> CreateSQLiteError(Isolate* isolate,
|
|
120
137
|
const char* message) {
|
|
121
138
|
Local<String> js_msg;
|
|
@@ -507,8 +524,7 @@ class BackupJob : public ThreadPoolWork {
|
|
|
507
524
|
|
|
508
525
|
Local<Value> argv[] = {progress_info};
|
|
509
526
|
TryCatch try_catch(env()->isolate());
|
|
510
|
-
fn->Call(env()->context(), Null(env()->isolate()), 1, argv)
|
|
511
|
-
.FromMaybe(Local<Value>());
|
|
527
|
+
USE(fn->Call(env()->context(), Null(env()->isolate()), 1, argv));
|
|
512
528
|
if (try_catch.HasCaught()) {
|
|
513
529
|
Finalize();
|
|
514
530
|
resolver->Reject(env()->context(), try_catch.Exception()).ToChecked();
|
|
@@ -737,6 +753,14 @@ bool DatabaseSync::Open() {
|
|
|
737
753
|
CHECK_ERROR_OR_THROW(env()->isolate(), this, r, SQLITE_OK, false);
|
|
738
754
|
CHECK_EQ(foreign_keys_enabled, open_config_.get_enable_foreign_keys());
|
|
739
755
|
|
|
756
|
+
int defensive_enabled;
|
|
757
|
+
r = sqlite3_db_config(connection_,
|
|
758
|
+
SQLITE_DBCONFIG_DEFENSIVE,
|
|
759
|
+
static_cast<int>(open_config_.get_enable_defensive()),
|
|
760
|
+
&defensive_enabled);
|
|
761
|
+
CHECK_ERROR_OR_THROW(env()->isolate(), this, r, SQLITE_OK, false);
|
|
762
|
+
CHECK_EQ(defensive_enabled, open_config_.get_enable_defensive());
|
|
763
|
+
|
|
740
764
|
sqlite3_busy_timeout(connection_, open_config_.get_timeout());
|
|
741
765
|
|
|
742
766
|
if (allow_load_extension_) {
|
|
@@ -794,6 +818,29 @@ bool DatabaseSync::ShouldIgnoreSQLiteError() {
|
|
|
794
818
|
return ignore_next_sqlite_error_;
|
|
795
819
|
}
|
|
796
820
|
|
|
821
|
+
void DatabaseSync::CreateTagStore(const FunctionCallbackInfo<Value>& args) {
|
|
822
|
+
DatabaseSync* db = BaseObject::Unwrap<DatabaseSync>(args.This());
|
|
823
|
+
Environment* env = Environment::GetCurrent(args);
|
|
824
|
+
|
|
825
|
+
if (!db->IsOpen()) {
|
|
826
|
+
THROW_ERR_INVALID_STATE(env, "database is not open");
|
|
827
|
+
return;
|
|
828
|
+
}
|
|
829
|
+
int capacity = 1000;
|
|
830
|
+
if (args.Length() > 0 && args[0]->IsNumber()) {
|
|
831
|
+
capacity = args[0].As<Number>()->Value();
|
|
832
|
+
}
|
|
833
|
+
|
|
834
|
+
BaseObjectPtr<SQLTagStore> session =
|
|
835
|
+
SQLTagStore::Create(env, BaseObjectWeakPtr<DatabaseSync>(db), capacity);
|
|
836
|
+
if (!session) {
|
|
837
|
+
// Handle error if creation failed
|
|
838
|
+
THROW_ERR_SQLITE_ERROR(env->isolate(), "Failed to create SQLTagStore");
|
|
839
|
+
return;
|
|
840
|
+
}
|
|
841
|
+
args.GetReturnValue().Set(session->object());
|
|
842
|
+
}
|
|
843
|
+
|
|
797
844
|
std::optional<std::string> ValidateDatabasePath(Environment* env,
|
|
798
845
|
Local<Value> path,
|
|
799
846
|
const std::string& field_name) {
|
|
@@ -966,6 +1013,81 @@ void DatabaseSync::New(const FunctionCallbackInfo<Value>& args) {
|
|
|
966
1013
|
|
|
967
1014
|
open_config.set_timeout(timeout_v.As<Int32>()->Value());
|
|
968
1015
|
}
|
|
1016
|
+
|
|
1017
|
+
Local<Value> read_bigints_v;
|
|
1018
|
+
if (options->Get(env->context(), env->read_bigints_string())
|
|
1019
|
+
.ToLocal(&read_bigints_v)) {
|
|
1020
|
+
if (!read_bigints_v->IsUndefined()) {
|
|
1021
|
+
if (!read_bigints_v->IsBoolean()) {
|
|
1022
|
+
THROW_ERR_INVALID_ARG_TYPE(
|
|
1023
|
+
env->isolate(),
|
|
1024
|
+
R"(The "options.readBigInts" argument must be a boolean.)");
|
|
1025
|
+
return;
|
|
1026
|
+
}
|
|
1027
|
+
open_config.set_use_big_ints(read_bigints_v.As<Boolean>()->Value());
|
|
1028
|
+
}
|
|
1029
|
+
}
|
|
1030
|
+
|
|
1031
|
+
Local<Value> return_arrays_v;
|
|
1032
|
+
if (options->Get(env->context(), env->return_arrays_string())
|
|
1033
|
+
.ToLocal(&return_arrays_v)) {
|
|
1034
|
+
if (!return_arrays_v->IsUndefined()) {
|
|
1035
|
+
if (!return_arrays_v->IsBoolean()) {
|
|
1036
|
+
THROW_ERR_INVALID_ARG_TYPE(
|
|
1037
|
+
env->isolate(),
|
|
1038
|
+
R"(The "options.returnArrays" argument must be a boolean.)");
|
|
1039
|
+
return;
|
|
1040
|
+
}
|
|
1041
|
+
open_config.set_return_arrays(return_arrays_v.As<Boolean>()->Value());
|
|
1042
|
+
}
|
|
1043
|
+
}
|
|
1044
|
+
|
|
1045
|
+
Local<Value> allow_bare_named_params_v;
|
|
1046
|
+
if (options->Get(env->context(), env->allow_bare_named_params_string())
|
|
1047
|
+
.ToLocal(&allow_bare_named_params_v)) {
|
|
1048
|
+
if (!allow_bare_named_params_v->IsUndefined()) {
|
|
1049
|
+
if (!allow_bare_named_params_v->IsBoolean()) {
|
|
1050
|
+
THROW_ERR_INVALID_ARG_TYPE(
|
|
1051
|
+
env->isolate(),
|
|
1052
|
+
R"(The "options.allowBareNamedParameters" )"
|
|
1053
|
+
"argument must be a boolean.");
|
|
1054
|
+
return;
|
|
1055
|
+
}
|
|
1056
|
+
open_config.set_allow_bare_named_params(
|
|
1057
|
+
allow_bare_named_params_v.As<Boolean>()->Value());
|
|
1058
|
+
}
|
|
1059
|
+
}
|
|
1060
|
+
|
|
1061
|
+
Local<Value> allow_unknown_named_params_v;
|
|
1062
|
+
if (options->Get(env->context(), env->allow_unknown_named_params_string())
|
|
1063
|
+
.ToLocal(&allow_unknown_named_params_v)) {
|
|
1064
|
+
if (!allow_unknown_named_params_v->IsUndefined()) {
|
|
1065
|
+
if (!allow_unknown_named_params_v->IsBoolean()) {
|
|
1066
|
+
THROW_ERR_INVALID_ARG_TYPE(
|
|
1067
|
+
env->isolate(),
|
|
1068
|
+
R"(The "options.allowUnknownNamedParameters" )"
|
|
1069
|
+
"argument must be a boolean.");
|
|
1070
|
+
return;
|
|
1071
|
+
}
|
|
1072
|
+
open_config.set_allow_unknown_named_params(
|
|
1073
|
+
allow_unknown_named_params_v.As<Boolean>()->Value());
|
|
1074
|
+
}
|
|
1075
|
+
}
|
|
1076
|
+
|
|
1077
|
+
Local<Value> defensive_v;
|
|
1078
|
+
if (!options->Get(env->context(), env->defensive_string())
|
|
1079
|
+
.ToLocal(&defensive_v)) {
|
|
1080
|
+
return;
|
|
1081
|
+
}
|
|
1082
|
+
if (!defensive_v->IsUndefined()) {
|
|
1083
|
+
if (!defensive_v->IsBoolean()) {
|
|
1084
|
+
THROW_ERR_INVALID_ARG_TYPE(
|
|
1085
|
+
env->isolate(),
|
|
1086
|
+
"The \"options.defensive\" argument must be a boolean.");
|
|
1087
|
+
return;
|
|
1088
|
+
}
|
|
1089
|
+
open_config.set_enable_defensive(defensive_v.As<Boolean>()->Value());
|
|
1090
|
+
}
|
|
969
1091
|
}
|
|
970
1092
|
|
|
971
1093
|
new DatabaseSync(
|
|
@@ -1005,6 +1127,14 @@ void DatabaseSync::Close(const FunctionCallbackInfo<Value>& args) {
|
|
|
1005
1127
|
db->connection_ = nullptr;
|
|
1006
1128
|
}
|
|
1007
1129
|
|
|
1130
|
+
void DatabaseSync::Dispose(const v8::FunctionCallbackInfo<v8::Value>& args) {
|
|
1131
|
+
v8::TryCatch try_catch(args.GetIsolate());
|
|
1132
|
+
Close(args);
|
|
1133
|
+
if (try_catch.HasCaught()) {
|
|
1134
|
+
CHECK(try_catch.CanContinue());
|
|
1135
|
+
}
|
|
1136
|
+
}
|
|
1137
|
+
|
|
1008
1138
|
void DatabaseSync::Prepare(const FunctionCallbackInfo<Value>& args) {
|
|
1009
1139
|
DatabaseSync* db;
|
|
1010
1140
|
ASSIGN_OR_RETURN_UNWRAP(&db, args.This());
|
|
@@ -1020,6 +1150,7 @@ void DatabaseSync::Prepare(const FunctionCallbackInfo<Value>& args) {
|
|
|
1020
1150
|
Utf8Value sql(env->isolate(), args[0].As<String>());
|
|
1021
1151
|
sqlite3_stmt* s = nullptr;
|
|
1022
1152
|
int r = sqlite3_prepare_v2(db->connection_, *sql, -1, &s, 0);
|
|
1153
|
+
|
|
1023
1154
|
CHECK_ERROR_OR_THROW(env->isolate(), db, r, SQLITE_OK, void());
|
|
1024
1155
|
BaseObjectPtr<StatementSync> stmt =
|
|
1025
1156
|
StatementSync::Create(env, BaseObjectPtr<DatabaseSync>(db), s);
|
|
@@ -1157,9 +1288,7 @@ void DatabaseSync::CustomFunction(const FunctionCallbackInfo<Value>& args) {
|
|
|
1157
1288
|
argc = -1;
|
|
1158
1289
|
} else {
|
|
1159
1290
|
Local<Value> js_len;
|
|
1160
|
-
if (!fn->Get(env->context(),
|
|
1161
|
-
FIXED_ONE_BYTE_STRING(env->isolate(), "length"))
|
|
1162
|
-
.ToLocal(&js_len)) {
|
|
1291
|
+
if (!fn->Get(env->context(), env->length_string()).ToLocal(&js_len)) {
|
|
1163
1292
|
return;
|
|
1164
1293
|
}
|
|
1165
1294
|
argc = js_len.As<Int32>()->Value();
|
|
@@ -1390,7 +1519,7 @@ void DatabaseSync::CreateSession(const FunctionCallbackInfo<Value>& args) {
|
|
|
1390
1519
|
|
|
1391
1520
|
Local<Object> options = args[0].As<Object>();
|
|
1392
1521
|
|
|
1393
|
-
Local<String> table_key =
|
|
1522
|
+
Local<String> table_key = env->table_string();
|
|
1394
1523
|
bool hasIt;
|
|
1395
1524
|
if (!options->HasOwnProperty(env->context(), table_key).To(&hasIt)) {
|
|
1396
1525
|
return;
|
|
@@ -1402,8 +1531,7 @@ void DatabaseSync::CreateSession(const FunctionCallbackInfo<Value>& args) {
|
|
|
1402
1531
|
}
|
|
1403
1532
|
|
|
1404
1533
|
if (table_value->IsString()) {
|
|
1405
|
-
|
|
1406
|
-
table = *str;
|
|
1534
|
+
table = Utf8Value(env->isolate(), table_value).ToString();
|
|
1407
1535
|
} else {
|
|
1408
1536
|
THROW_ERR_INVALID_ARG_TYPE(
|
|
1409
1537
|
env->isolate(), "The \"options.table\" argument must be a string.");
|
|
@@ -1423,8 +1551,7 @@ void DatabaseSync::CreateSession(const FunctionCallbackInfo<Value>& args) {
|
|
|
1423
1551
|
return;
|
|
1424
1552
|
}
|
|
1425
1553
|
if (db_value->IsString()) {
|
|
1426
|
-
|
|
1427
|
-
db_name = std::string(*str);
|
|
1554
|
+
db_name = Utf8Value(env->isolate(), db_value).ToString();
|
|
1428
1555
|
} else {
|
|
1429
1556
|
THROW_ERR_INVALID_ARG_TYPE(
|
|
1430
1557
|
env->isolate(), "The \"options.db\" argument must be a string.");
|
|
@@ -1564,26 +1691,28 @@ void Backup(const FunctionCallbackInfo<Value>& args) {
|
|
|
1564
1691
|
job->ScheduleBackup();
|
|
1565
1692
|
}
|
|
1566
1693
|
|
|
1694
|
+
struct ConflictCallbackContext {
|
|
1695
|
+
std::function<bool(std::string_view)> filterCallback;
|
|
1696
|
+
std::function<int(int)> conflictCallback;
|
|
1697
|
+
};
|
|
1698
|
+
|
|
1567
1699
|
// the reason for using static functions here is that SQLite needs a
|
|
1568
1700
|
// function pointer
|
|
1569
|
-
static std::function<int(int)> conflictCallback;
|
|
1570
1701
|
|
|
1571
1702
|
static int xConflict(void* pCtx, int eConflict, sqlite3_changeset_iter* pIter) {
|
|
1572
|
-
|
|
1573
|
-
|
|
1703
|
+
auto ctx = static_cast<ConflictCallbackContext*>(pCtx);
|
|
1704
|
+
if (!ctx->conflictCallback) return SQLITE_CHANGESET_ABORT;
|
|
1705
|
+
return ctx->conflictCallback(eConflict);
|
|
1574
1706
|
}
|
|
1575
1707
|
|
|
1576
|
-
static std::function<bool(std::string)> filterCallback;
|
|
1577
|
-
|
|
1578
1708
|
static int xFilter(void* pCtx, const char* zTab) {
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
return filterCallback(zTab) ? 1 : 0;
|
|
1709
|
+
auto ctx = static_cast<ConflictCallbackContext*>(pCtx);
|
|
1710
|
+
if (!ctx->filterCallback) return 1;
|
|
1711
|
+
return ctx->filterCallback(zTab) ? 1 : 0;
|
|
1582
1712
|
}
|
|
1583
1713
|
|
|
1584
1714
|
void DatabaseSync::ApplyChangeset(const FunctionCallbackInfo<Value>& args) {
|
|
1585
|
-
|
|
1586
|
-
filterCallback = nullptr;
|
|
1715
|
+
ConflictCallbackContext context;
|
|
1587
1716
|
|
|
1588
1717
|
DatabaseSync* db;
|
|
1589
1718
|
ASSIGN_OR_RETURN_UNWRAP(&db, args.This());
|
|
@@ -1619,7 +1748,7 @@ void DatabaseSync::ApplyChangeset(const FunctionCallbackInfo<Value>& args) {
|
|
|
1619
1748
|
return;
|
|
1620
1749
|
}
|
|
1621
1750
|
Local<Function> conflictFunc = conflictValue.As<Function>();
|
|
1622
|
-
conflictCallback = [env, conflictFunc](int conflictType) -> int {
|
|
1751
|
+
context.conflictCallback = [env, conflictFunc](int conflictType) -> int {
|
|
1623
1752
|
Local<Value> argv[] = {Integer::New(env->isolate(), conflictType)};
|
|
1624
1753
|
TryCatch try_catch(env->isolate());
|
|
1625
1754
|
Local<Value> result =
|
|
@@ -1657,18 +1786,27 @@ void DatabaseSync::ApplyChangeset(const FunctionCallbackInfo<Value>& args) {
|
|
|
1657
1786
|
|
|
1658
1787
|
Local<Function> filterFunc = filterValue.As<Function>();
|
|
1659
1788
|
|
|
1660
|
-
filterCallback = [
|
|
1661
|
-
//
|
|
1662
|
-
//
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1789
|
+
context.filterCallback = [&](std::string_view item) -> bool {
|
|
1790
|
+
// If there was an error in the previous call to the filter's
|
|
1791
|
+
// callback, we skip calling it again.
|
|
1792
|
+
if (db->ignore_next_sqlite_error_) {
|
|
1793
|
+
return false;
|
|
1794
|
+
}
|
|
1795
|
+
|
|
1796
|
+
Local<Value> argv[1];
|
|
1797
|
+
if (!ToV8Value(env->context(), item, env->isolate())
|
|
1798
|
+
.ToLocal(&argv[0])) {
|
|
1799
|
+
db->SetIgnoreNextSQLiteError(true);
|
|
1800
|
+
return false;
|
|
1801
|
+
}
|
|
1802
|
+
|
|
1803
|
+
Local<Value> result;
|
|
1804
|
+
if (!filterFunc->Call(env->context(), Null(env->isolate()), 1, argv)
|
|
1805
|
+
.ToLocal(&result)) {
|
|
1806
|
+
db->SetIgnoreNextSQLiteError(true);
|
|
1807
|
+
return false;
|
|
1808
|
+
}
|
|
1809
|
+
|
|
1672
1810
|
return result->BooleanValue(env->isolate());
|
|
1673
1811
|
};
|
|
1674
1812
|
}
|
|
@@ -1681,7 +1819,7 @@ void DatabaseSync::ApplyChangeset(const FunctionCallbackInfo<Value>& args) {
|
|
|
1681
1819
|
const_cast<void*>(static_cast<const void*>(buf.data())),
|
|
1682
1820
|
xFilter,
|
|
1683
1821
|
xConflict,
|
|
1684
|
-
|
|
1822
|
+
static_cast<void*>(&context));
|
|
1685
1823
|
if (r == SQLITE_OK) {
|
|
1686
1824
|
args.GetReturnValue().Set(true);
|
|
1687
1825
|
return;
|
|
@@ -1698,15 +1836,14 @@ void DatabaseSync::EnableLoadExtension(
|
|
|
1698
1836
|
const FunctionCallbackInfo<Value>& args) {
|
|
1699
1837
|
DatabaseSync* db;
|
|
1700
1838
|
ASSIGN_OR_RETURN_UNWRAP(&db, args.This());
|
|
1701
|
-
|
|
1839
|
+
auto isolate = args.GetIsolate();
|
|
1702
1840
|
if (!args[0]->IsBoolean()) {
|
|
1703
|
-
THROW_ERR_INVALID_ARG_TYPE(
|
|
1841
|
+
THROW_ERR_INVALID_ARG_TYPE(isolate,
|
|
1704
1842
|
"The \"allow\" argument must be a boolean.");
|
|
1705
1843
|
return;
|
|
1706
1844
|
}
|
|
1707
1845
|
|
|
1708
1846
|
const int enable = args[0].As<Boolean>()->Value();
|
|
1709
|
-
auto isolate = env->isolate();
|
|
1710
1847
|
|
|
1711
1848
|
if (db->allow_load_extension_ == false && enable == true) {
|
|
1712
1849
|
THROW_ERR_INVALID_STATE(
|
|
@@ -1721,6 +1858,26 @@ void DatabaseSync::EnableLoadExtension(
|
|
|
1721
1858
|
CHECK_ERROR_OR_THROW(isolate, db, load_extension_ret, SQLITE_OK, void());
|
|
1722
1859
|
}
|
|
1723
1860
|
|
|
1861
|
+
void DatabaseSync::EnableDefensive(const FunctionCallbackInfo<Value>& args) {
|
|
1862
|
+
DatabaseSync* db;
|
|
1863
|
+
ASSIGN_OR_RETURN_UNWRAP(&db, args.This());
|
|
1864
|
+
Environment* env = Environment::GetCurrent(args);
|
|
1865
|
+
THROW_AND_RETURN_ON_BAD_STATE(env, !db->IsOpen(), "database is not open");
|
|
1866
|
+
|
|
1867
|
+
auto isolate = args.GetIsolate();
|
|
1868
|
+
if (!args[0]->IsBoolean()) {
|
|
1869
|
+
THROW_ERR_INVALID_ARG_TYPE(isolate,
|
|
1870
|
+
"The \"active\" argument must be a boolean.");
|
|
1871
|
+
return;
|
|
1872
|
+
}
|
|
1873
|
+
|
|
1874
|
+
const int enable = args[0].As<Boolean>()->Value();
|
|
1875
|
+
int defensive_enabled;
|
|
1876
|
+
const int defensive_ret = sqlite3_db_config(
|
|
1877
|
+
db->connection_, SQLITE_DBCONFIG_DEFENSIVE, enable, &defensive_enabled);
|
|
1878
|
+
CHECK_ERROR_OR_THROW(isolate, db, defensive_ret, SQLITE_OK, void());
|
|
1879
|
+
}
|
|
1880
|
+
|
|
1724
1881
|
void DatabaseSync::LoadExtension(const FunctionCallbackInfo<Value>& args) {
|
|
1725
1882
|
DatabaseSync* db;
|
|
1726
1883
|
ASSIGN_OR_RETURN_UNWRAP(&db, args.This());
|
|
@@ -1757,6 +1914,113 @@ void DatabaseSync::LoadExtension(const FunctionCallbackInfo<Value>& args) {
|
|
|
1757
1914
|
}
|
|
1758
1915
|
}
|
|
1759
1916
|
|
|
1917
|
+
void DatabaseSync::SetAuthorizer(const FunctionCallbackInfo<Value>& args) {
|
|
1918
|
+
DatabaseSync* db;
|
|
1919
|
+
ASSIGN_OR_RETURN_UNWRAP(&db, args.This());
|
|
1920
|
+
Environment* env = Environment::GetCurrent(args);
|
|
1921
|
+
Isolate* isolate = env->isolate();
|
|
1922
|
+
|
|
1923
|
+
if (args[0]->IsNull()) {
|
|
1924
|
+
// Clear the authorizer
|
|
1925
|
+
sqlite3_set_authorizer(db->connection_, nullptr, nullptr);
|
|
1926
|
+
db->object()->SetInternalField(kAuthorizerCallback, Null(isolate));
|
|
1927
|
+
return;
|
|
1928
|
+
}
|
|
1929
|
+
|
|
1930
|
+
if (!args[0]->IsFunction()) {
|
|
1931
|
+
THROW_ERR_INVALID_ARG_TYPE(
|
|
1932
|
+
isolate, "The \"callback\" argument must be a function or null.");
|
|
1933
|
+
return;
|
|
1934
|
+
}
|
|
1935
|
+
|
|
1936
|
+
Local<Function> fn = args[0].As<Function>();
|
|
1937
|
+
|
|
1938
|
+
db->object()->SetInternalField(kAuthorizerCallback, fn);
|
|
1939
|
+
|
|
1940
|
+
int r = sqlite3_set_authorizer(
|
|
1941
|
+
db->connection_, DatabaseSync::AuthorizerCallback, db);
|
|
1942
|
+
|
|
1943
|
+
if (r != SQLITE_OK) {
|
|
1944
|
+
CHECK_ERROR_OR_THROW(isolate, db, r, SQLITE_OK, void());
|
|
1945
|
+
}
|
|
1946
|
+
}
|
|
1947
|
+
|
|
1948
|
+
int DatabaseSync::AuthorizerCallback(void* user_data,
|
|
1949
|
+
int action_code,
|
|
1950
|
+
const char* param1,
|
|
1951
|
+
const char* param2,
|
|
1952
|
+
const char* param3,
|
|
1953
|
+
const char* param4) {
|
|
1954
|
+
DatabaseSync* db = static_cast<DatabaseSync*>(user_data);
|
|
1955
|
+
Environment* env = db->env();
|
|
1956
|
+
Isolate* isolate = env->isolate();
|
|
1957
|
+
HandleScope handle_scope(isolate);
|
|
1958
|
+
Local<Context> context = env->context();
|
|
1959
|
+
|
|
1960
|
+
Local<Value> cb =
|
|
1961
|
+
db->object()->GetInternalField(kAuthorizerCallback).template As<Value>();
|
|
1962
|
+
|
|
1963
|
+
CHECK(cb->IsFunction());
|
|
1964
|
+
|
|
1965
|
+
Local<Function> callback = cb.As<Function>();
|
|
1966
|
+
LocalVector<Value> js_argv(isolate);
|
|
1967
|
+
|
|
1968
|
+
// Convert SQLite authorizer parameters to JavaScript values
|
|
1969
|
+
js_argv.emplace_back(Integer::New(isolate, action_code));
|
|
1970
|
+
js_argv.emplace_back(
|
|
1971
|
+
NullableSQLiteStringToValue(isolate, param1).ToLocalChecked());
|
|
1972
|
+
js_argv.emplace_back(
|
|
1973
|
+
NullableSQLiteStringToValue(isolate, param2).ToLocalChecked());
|
|
1974
|
+
js_argv.emplace_back(
|
|
1975
|
+
NullableSQLiteStringToValue(isolate, param3).ToLocalChecked());
|
|
1976
|
+
js_argv.emplace_back(
|
|
1977
|
+
NullableSQLiteStringToValue(isolate, param4).ToLocalChecked());
|
|
1978
|
+
|
|
1979
|
+
MaybeLocal<Value> retval = callback->Call(
|
|
1980
|
+
context, Undefined(isolate), js_argv.size(), js_argv.data());
|
|
1981
|
+
|
|
1982
|
+
Local<Value> result;
|
|
1983
|
+
|
|
1984
|
+
if (!retval.ToLocal(&result)) {
|
|
1985
|
+
db->SetIgnoreNextSQLiteError(true);
|
|
1986
|
+
return SQLITE_DENY;
|
|
1987
|
+
}
|
|
1988
|
+
|
|
1989
|
+
Local<String> error_message;
|
|
1990
|
+
|
|
1991
|
+
if (!result->IsInt32()) {
|
|
1992
|
+
if (!String::NewFromUtf8(
|
|
1993
|
+
isolate,
|
|
1994
|
+
"Authorizer callback must return an integer authorization code")
|
|
1995
|
+
.ToLocal(&error_message)) {
|
|
1996
|
+
return SQLITE_DENY;
|
|
1997
|
+
}
|
|
1998
|
+
|
|
1999
|
+
Local<Value> err = Exception::TypeError(error_message);
|
|
2000
|
+
isolate->ThrowException(err);
|
|
2001
|
+
db->SetIgnoreNextSQLiteError(true);
|
|
2002
|
+
return SQLITE_DENY;
|
|
2003
|
+
}
|
|
2004
|
+
|
|
2005
|
+
int32_t int_result = result.As<Int32>()->Value();
|
|
2006
|
+
if (int_result != SQLITE_OK && int_result != SQLITE_DENY &&
|
|
2007
|
+
int_result != SQLITE_IGNORE) {
|
|
2008
|
+
if (!String::NewFromUtf8(
|
|
2009
|
+
isolate,
|
|
2010
|
+
"Authorizer callback returned a invalid authorization code")
|
|
2011
|
+
.ToLocal(&error_message)) {
|
|
2012
|
+
return SQLITE_DENY;
|
|
2013
|
+
}
|
|
2014
|
+
|
|
2015
|
+
Local<Value> err = Exception::RangeError(error_message);
|
|
2016
|
+
isolate->ThrowException(err);
|
|
2017
|
+
db->SetIgnoreNextSQLiteError(true);
|
|
2018
|
+
return SQLITE_DENY;
|
|
2019
|
+
}
|
|
2020
|
+
|
|
2021
|
+
return int_result;
|
|
2022
|
+
}
|
|
2023
|
+
|
|
1760
2024
|
StatementSync::StatementSync(Environment* env,
|
|
1761
2025
|
Local<Object> object,
|
|
1762
2026
|
BaseObjectPtr<DatabaseSync> db,
|
|
@@ -1764,12 +2028,11 @@ StatementSync::StatementSync(Environment* env,
|
|
|
1764
2028
|
: BaseObject(env, object), db_(std::move(db)) {
|
|
1765
2029
|
MakeWeak();
|
|
1766
2030
|
statement_ = stmt;
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
allow_unknown_named_params_ = false;
|
|
2031
|
+
use_big_ints_ = db_->use_big_ints();
|
|
2032
|
+
return_arrays_ = db_->return_arrays();
|
|
2033
|
+
allow_bare_named_params_ = db_->allow_bare_named_params();
|
|
2034
|
+
allow_unknown_named_params_ = db_->allow_unknown_named_params();
|
|
2035
|
+
|
|
1773
2036
|
bare_named_params_ = std::nullopt;
|
|
1774
2037
|
}
|
|
1775
2038
|
|
|
@@ -1798,7 +2061,7 @@ bool StatementSync::BindParams(const FunctionCallbackInfo<Value>& args) {
|
|
|
1798
2061
|
|
|
1799
2062
|
if (args[0]->IsObject() && !args[0]->IsArrayBufferView()) {
|
|
1800
2063
|
Local<Object> obj = args[0].As<Object>();
|
|
1801
|
-
Local<Context> context =
|
|
2064
|
+
Local<Context> context = Isolate::GetCurrent()->GetCurrentContext();
|
|
1802
2065
|
Local<Array> keys;
|
|
1803
2066
|
if (!obj->GetOwnPropertyNames(context).ToLocal(&keys)) {
|
|
1804
2067
|
return false;
|
|
@@ -1856,7 +2119,7 @@ bool StatementSync::BindParams(const FunctionCallbackInfo<Value>& args) {
|
|
|
1856
2119
|
continue;
|
|
1857
2120
|
} else {
|
|
1858
2121
|
THROW_ERR_INVALID_STATE(
|
|
1859
|
-
env(), "Unknown named parameter '%s'",
|
|
2122
|
+
env(), "Unknown named parameter '%s'", utf8_key);
|
|
1860
2123
|
return false;
|
|
1861
2124
|
}
|
|
1862
2125
|
}
|
|
@@ -1875,7 +2138,9 @@ bool StatementSync::BindParams(const FunctionCallbackInfo<Value>& args) {
|
|
|
1875
2138
|
}
|
|
1876
2139
|
|
|
1877
2140
|
for (int i = anon_start; i < args.Length(); ++i) {
|
|
1878
|
-
while (
|
|
2141
|
+
while (1) {
|
|
2142
|
+
const char* param = sqlite3_bind_parameter_name(statement_, anon_idx);
|
|
2143
|
+
if (param == nullptr || param[0] == '?') break;
|
|
1879
2144
|
anon_idx++;
|
|
1880
2145
|
}
|
|
1881
2146
|
|
|
@@ -1930,11 +2195,8 @@ bool StatementSync::BindValue(const Local<Value>& value, const int index) {
|
|
|
1930
2195
|
}
|
|
1931
2196
|
|
|
1932
2197
|
MaybeLocal<Value> StatementSync::ColumnToValue(const int column) {
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
SQLITE_VALUE_TO_JS(
|
|
1936
|
-
column, isolate, use_big_ints_, js_val, statement_, column);
|
|
1937
|
-
return js_val;
|
|
2198
|
+
return StatementExecutionHelper::ColumnToValue(
|
|
2199
|
+
env(), statement_, column, use_big_ints_);
|
|
1938
2200
|
}
|
|
1939
2201
|
|
|
1940
2202
|
MaybeLocal<Name> StatementSync::ColumnNameToName(const int column) {
|
|
@@ -1947,60 +2209,82 @@ MaybeLocal<Name> StatementSync::ColumnNameToName(const int column) {
|
|
|
1947
2209
|
return String::NewFromUtf8(env()->isolate(), col_name).As<Name>();
|
|
1948
2210
|
}
|
|
1949
2211
|
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
ASSIGN_OR_RETURN_UNWRAP(&stmt, args.This());
|
|
1955
|
-
Environment* env = Environment::GetCurrent(args);
|
|
1956
|
-
THROW_AND_RETURN_ON_BAD_STATE(
|
|
1957
|
-
env, stmt->IsFinalized(), "statement has been finalized");
|
|
2212
|
+
MaybeLocal<Value> StatementExecutionHelper::ColumnToValue(Environment* env,
|
|
2213
|
+
sqlite3_stmt* stmt,
|
|
2214
|
+
const int column,
|
|
2215
|
+
bool use_big_ints) {
|
|
1958
2216
|
Isolate* isolate = env->isolate();
|
|
1959
|
-
|
|
1960
|
-
|
|
2217
|
+
MaybeLocal<Value> js_val = MaybeLocal<Value>();
|
|
2218
|
+
SQLITE_VALUE_TO_JS(column, isolate, use_big_ints, js_val, stmt, column);
|
|
2219
|
+
return js_val;
|
|
2220
|
+
}
|
|
1961
2221
|
|
|
1962
|
-
|
|
1963
|
-
|
|
2222
|
+
MaybeLocal<Name> StatementExecutionHelper::ColumnNameToName(Environment* env,
|
|
2223
|
+
sqlite3_stmt* stmt,
|
|
2224
|
+
const int column) {
|
|
2225
|
+
const char* col_name = sqlite3_column_name(stmt, column);
|
|
2226
|
+
if (col_name == nullptr) {
|
|
2227
|
+
THROW_ERR_INVALID_STATE(env, "Cannot get name of column %d", column);
|
|
2228
|
+
return MaybeLocal<Name>();
|
|
1964
2229
|
}
|
|
1965
2230
|
|
|
1966
|
-
|
|
1967
|
-
|
|
2231
|
+
return String::NewFromUtf8(env->isolate(), col_name).As<Name>();
|
|
2232
|
+
}
|
|
2233
|
+
|
|
2234
|
+
void StatementSync::MemoryInfo(MemoryTracker* tracker) const {}
|
|
2235
|
+
|
|
2236
|
+
Maybe<void> ExtractRowValues(Environment* env,
|
|
2237
|
+
sqlite3_stmt* stmt,
|
|
2238
|
+
int num_cols,
|
|
2239
|
+
bool use_big_ints,
|
|
2240
|
+
LocalVector<Value>* row_values) {
|
|
2241
|
+
row_values->clear();
|
|
2242
|
+
row_values->reserve(num_cols);
|
|
2243
|
+
for (int i = 0; i < num_cols; ++i) {
|
|
2244
|
+
Local<Value> val;
|
|
2245
|
+
if (!StatementExecutionHelper::ColumnToValue(env, stmt, i, use_big_ints)
|
|
2246
|
+
.ToLocal(&val)) {
|
|
2247
|
+
return Nothing<void>();
|
|
2248
|
+
}
|
|
2249
|
+
row_values->emplace_back(val);
|
|
2250
|
+
}
|
|
2251
|
+
return JustVoid();
|
|
2252
|
+
}
|
|
2253
|
+
|
|
2254
|
+
MaybeLocal<Value> StatementExecutionHelper::All(Environment* env,
|
|
2255
|
+
DatabaseSync* db,
|
|
2256
|
+
sqlite3_stmt* stmt,
|
|
2257
|
+
bool return_arrays,
|
|
2258
|
+
bool use_big_ints) {
|
|
2259
|
+
Isolate* isolate = env->isolate();
|
|
2260
|
+
EscapableHandleScope scope(isolate);
|
|
2261
|
+
int r;
|
|
2262
|
+
int num_cols = sqlite3_column_count(stmt);
|
|
1968
2263
|
LocalVector<Value> rows(isolate);
|
|
2264
|
+
LocalVector<Value> row_values(isolate);
|
|
2265
|
+
LocalVector<Name> row_keys(isolate);
|
|
1969
2266
|
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
for (int i = 0; i < num_cols; ++i) {
|
|
1975
|
-
Local<Value> val;
|
|
1976
|
-
if (!stmt->ColumnToValue(i).ToLocal(&val)) return;
|
|
1977
|
-
array_values.emplace_back(val);
|
|
1978
|
-
}
|
|
1979
|
-
Local<Array> row_array =
|
|
1980
|
-
Array::New(isolate, array_values.data(), array_values.size());
|
|
1981
|
-
rows.emplace_back(row_array);
|
|
2267
|
+
while ((r = sqlite3_step(stmt)) == SQLITE_ROW) {
|
|
2268
|
+
if (ExtractRowValues(env, stmt, num_cols, use_big_ints, &row_values)
|
|
2269
|
+
.IsNothing()) {
|
|
2270
|
+
return MaybeLocal<Value>();
|
|
1982
2271
|
}
|
|
1983
|
-
} else {
|
|
1984
|
-
LocalVector<Name> row_keys(isolate);
|
|
1985
2272
|
|
|
1986
|
-
|
|
2273
|
+
if (return_arrays) {
|
|
2274
|
+
Local<Array> row_array =
|
|
2275
|
+
Array::New(isolate, row_values.data(), row_values.size());
|
|
2276
|
+
rows.emplace_back(row_array);
|
|
2277
|
+
} else {
|
|
1987
2278
|
if (row_keys.size() == 0) {
|
|
1988
2279
|
row_keys.reserve(num_cols);
|
|
1989
2280
|
for (int i = 0; i < num_cols; ++i) {
|
|
1990
2281
|
Local<Name> key;
|
|
1991
|
-
if (!
|
|
2282
|
+
if (!ColumnNameToName(env, stmt, i).ToLocal(&key)) {
|
|
2283
|
+
return MaybeLocal<Value>();
|
|
2284
|
+
}
|
|
1992
2285
|
row_keys.emplace_back(key);
|
|
1993
2286
|
}
|
|
1994
2287
|
}
|
|
1995
|
-
|
|
1996
|
-
LocalVector<Value> row_values(isolate);
|
|
1997
|
-
row_values.reserve(num_cols);
|
|
1998
|
-
for (int i = 0; i < num_cols; ++i) {
|
|
1999
|
-
Local<Value> val;
|
|
2000
|
-
if (!stmt->ColumnToValue(i).ToLocal(&val)) return;
|
|
2001
|
-
row_values.emplace_back(val);
|
|
2002
|
-
}
|
|
2003
|
-
|
|
2004
2288
|
DCHECK_EQ(row_keys.size(), row_values.size());
|
|
2005
2289
|
Local<Object> row_obj = Object::New(
|
|
2006
2290
|
isolate, Null(isolate), row_keys.data(), row_values.data(), num_cols);
|
|
@@ -2008,52 +2292,128 @@ void StatementSync::All(const FunctionCallbackInfo<Value>& args) {
|
|
|
2008
2292
|
}
|
|
2009
2293
|
}
|
|
2010
2294
|
|
|
2011
|
-
CHECK_ERROR_OR_THROW(isolate,
|
|
2012
|
-
|
|
2295
|
+
CHECK_ERROR_OR_THROW(isolate, db, r, SQLITE_DONE, MaybeLocal<Value>());
|
|
2296
|
+
return scope.Escape(Array::New(isolate, rows.data(), rows.size()));
|
|
2013
2297
|
}
|
|
2014
2298
|
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2299
|
+
MaybeLocal<Object> StatementExecutionHelper::Run(Environment* env,
|
|
2300
|
+
DatabaseSync* db,
|
|
2301
|
+
sqlite3_stmt* stmt,
|
|
2302
|
+
bool use_big_ints) {
|
|
2303
|
+
Isolate* isolate = env->isolate();
|
|
2304
|
+
EscapableHandleScope scope(isolate);
|
|
2305
|
+
sqlite3_step(stmt);
|
|
2306
|
+
int r = sqlite3_reset(stmt);
|
|
2307
|
+
CHECK_ERROR_OR_THROW(isolate, db, r, SQLITE_OK, MaybeLocal<Object>());
|
|
2308
|
+
Local<Object> result = Object::New(isolate);
|
|
2309
|
+
sqlite3_int64 last_insert_rowid = sqlite3_last_insert_rowid(db->Connection());
|
|
2310
|
+
sqlite3_int64 changes = sqlite3_changes64(db->Connection());
|
|
2311
|
+
Local<Value> last_insert_rowid_val;
|
|
2312
|
+
Local<Value> changes_val;
|
|
2025
2313
|
|
|
2026
|
-
if (
|
|
2027
|
-
|
|
2314
|
+
if (use_big_ints) {
|
|
2315
|
+
last_insert_rowid_val = BigInt::New(isolate, last_insert_rowid);
|
|
2316
|
+
changes_val = BigInt::New(isolate, changes);
|
|
2317
|
+
} else {
|
|
2318
|
+
last_insert_rowid_val = Number::New(isolate, last_insert_rowid);
|
|
2319
|
+
changes_val = Number::New(isolate, changes);
|
|
2028
2320
|
}
|
|
2029
2321
|
|
|
2322
|
+
if (result
|
|
2323
|
+
->Set(env->context(),
|
|
2324
|
+
env->last_insert_rowid_string(),
|
|
2325
|
+
last_insert_rowid_val)
|
|
2326
|
+
.IsNothing() ||
|
|
2327
|
+
result->Set(env->context(), env->changes_string(), changes_val)
|
|
2328
|
+
.IsNothing()) {
|
|
2329
|
+
return MaybeLocal<Object>();
|
|
2330
|
+
}
|
|
2331
|
+
|
|
2332
|
+
return scope.Escape(result);
|
|
2333
|
+
}
|
|
2334
|
+
|
|
2335
|
+
BaseObjectPtr<StatementSyncIterator> StatementExecutionHelper::Iterate(
|
|
2336
|
+
Environment* env, BaseObjectPtr<StatementSync> stmt) {
|
|
2337
|
+
Local<Context> context = env->context();
|
|
2030
2338
|
Local<Object> global = context->Global();
|
|
2031
2339
|
Local<Value> js_iterator;
|
|
2032
2340
|
Local<Value> js_iterator_prototype;
|
|
2033
2341
|
if (!global->Get(context, env->iterator_string()).ToLocal(&js_iterator)) {
|
|
2034
|
-
return;
|
|
2342
|
+
return BaseObjectPtr<StatementSyncIterator>();
|
|
2035
2343
|
}
|
|
2036
2344
|
if (!js_iterator.As<Object>()
|
|
2037
2345
|
->Get(context, env->prototype_string())
|
|
2038
2346
|
.ToLocal(&js_iterator_prototype)) {
|
|
2039
|
-
return;
|
|
2347
|
+
return BaseObjectPtr<StatementSyncIterator>();
|
|
2040
2348
|
}
|
|
2041
2349
|
|
|
2042
2350
|
BaseObjectPtr<StatementSyncIterator> iter =
|
|
2043
|
-
StatementSyncIterator::Create(env,
|
|
2351
|
+
StatementSyncIterator::Create(env, stmt);
|
|
2352
|
+
|
|
2353
|
+
if (!iter) {
|
|
2354
|
+
// Error in iterator creation, likely already threw in Create
|
|
2355
|
+
return BaseObjectPtr<StatementSyncIterator>();
|
|
2356
|
+
}
|
|
2044
2357
|
|
|
2045
2358
|
if (iter->object()
|
|
2046
|
-
->
|
|
2359
|
+
->GetPrototypeV2()
|
|
2047
2360
|
.As<Object>()
|
|
2048
|
-
->
|
|
2361
|
+
->SetPrototypeV2(context, js_iterator_prototype)
|
|
2049
2362
|
.IsNothing()) {
|
|
2050
|
-
return;
|
|
2363
|
+
return BaseObjectPtr<StatementSyncIterator>();
|
|
2051
2364
|
}
|
|
2052
2365
|
|
|
2053
|
-
|
|
2366
|
+
return iter;
|
|
2054
2367
|
}
|
|
2055
2368
|
|
|
2056
|
-
|
|
2369
|
+
MaybeLocal<Value> StatementExecutionHelper::Get(Environment* env,
|
|
2370
|
+
DatabaseSync* db,
|
|
2371
|
+
sqlite3_stmt* stmt,
|
|
2372
|
+
bool return_arrays,
|
|
2373
|
+
bool use_big_ints) {
|
|
2374
|
+
Isolate* isolate = env->isolate();
|
|
2375
|
+
EscapableHandleScope scope(isolate);
|
|
2376
|
+
auto reset = OnScopeLeave([&]() { sqlite3_reset(stmt); });
|
|
2377
|
+
|
|
2378
|
+
int r = sqlite3_step(stmt);
|
|
2379
|
+
if (r == SQLITE_DONE) return scope.Escape(Undefined(isolate));
|
|
2380
|
+
if (r != SQLITE_ROW) {
|
|
2381
|
+
THROW_ERR_SQLITE_ERROR(isolate, db);
|
|
2382
|
+
return MaybeLocal<Value>();
|
|
2383
|
+
}
|
|
2384
|
+
|
|
2385
|
+
int num_cols = sqlite3_column_count(stmt);
|
|
2386
|
+
if (num_cols == 0) {
|
|
2387
|
+
return Undefined(isolate);
|
|
2388
|
+
}
|
|
2389
|
+
|
|
2390
|
+
LocalVector<Value> row_values(isolate);
|
|
2391
|
+
if (ExtractRowValues(env, stmt, num_cols, use_big_ints, &row_values)
|
|
2392
|
+
.IsNothing()) {
|
|
2393
|
+
return MaybeLocal<Value>();
|
|
2394
|
+
}
|
|
2395
|
+
|
|
2396
|
+
if (return_arrays) {
|
|
2397
|
+
return scope.Escape(
|
|
2398
|
+
Array::New(isolate, row_values.data(), row_values.size()));
|
|
2399
|
+
} else {
|
|
2400
|
+
LocalVector<Name> keys(isolate);
|
|
2401
|
+
keys.reserve(num_cols);
|
|
2402
|
+
for (int i = 0; i < num_cols; ++i) {
|
|
2403
|
+
Local<Name> key;
|
|
2404
|
+
if (!ColumnNameToName(env, stmt, i).ToLocal(&key)) {
|
|
2405
|
+
return MaybeLocal<Value>();
|
|
2406
|
+
}
|
|
2407
|
+
keys.emplace_back(key);
|
|
2408
|
+
}
|
|
2409
|
+
|
|
2410
|
+
DCHECK_EQ(keys.size(), row_values.size());
|
|
2411
|
+
return scope.Escape(Object::New(
|
|
2412
|
+
isolate, Null(isolate), keys.data(), row_values.data(), num_cols));
|
|
2413
|
+
}
|
|
2414
|
+
}
|
|
2415
|
+
|
|
2416
|
+
void StatementSync::All(const FunctionCallbackInfo<Value>& args) {
|
|
2057
2417
|
StatementSync* stmt;
|
|
2058
2418
|
ASSIGN_OR_RETURN_UNWRAP(&stmt, args.This());
|
|
2059
2419
|
Environment* env = Environment::GetCurrent(args);
|
|
@@ -2068,48 +2428,61 @@ void StatementSync::Get(const FunctionCallbackInfo<Value>& args) {
|
|
|
2068
2428
|
}
|
|
2069
2429
|
|
|
2070
2430
|
auto reset = OnScopeLeave([&]() { sqlite3_reset(stmt->statement_); });
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
if (
|
|
2074
|
-
|
|
2431
|
+
|
|
2432
|
+
Local<Value> result;
|
|
2433
|
+
if (StatementExecutionHelper::All(env,
|
|
2434
|
+
stmt->db_.get(),
|
|
2435
|
+
stmt->statement_,
|
|
2436
|
+
stmt->return_arrays_,
|
|
2437
|
+
stmt->use_big_ints_)
|
|
2438
|
+
.ToLocal(&result)) {
|
|
2439
|
+
args.GetReturnValue().Set(result);
|
|
2440
|
+
}
|
|
2441
|
+
}
|
|
2442
|
+
|
|
2443
|
+
void StatementSync::Iterate(const FunctionCallbackInfo<Value>& args) {
|
|
2444
|
+
StatementSync* stmt;
|
|
2445
|
+
ASSIGN_OR_RETURN_UNWRAP(&stmt, args.This());
|
|
2446
|
+
Environment* env = Environment::GetCurrent(args);
|
|
2447
|
+
THROW_AND_RETURN_ON_BAD_STATE(
|
|
2448
|
+
env, stmt->IsFinalized(), "statement has been finalized");
|
|
2449
|
+
int r = sqlite3_reset(stmt->statement_);
|
|
2450
|
+
CHECK_ERROR_OR_THROW(env->isolate(), stmt->db_.get(), r, SQLITE_OK, void());
|
|
2451
|
+
|
|
2452
|
+
if (!stmt->BindParams(args)) {
|
|
2075
2453
|
return;
|
|
2076
2454
|
}
|
|
2077
2455
|
|
|
2078
|
-
|
|
2079
|
-
|
|
2456
|
+
BaseObjectPtr<StatementSyncIterator> iter = StatementExecutionHelper::Iterate(
|
|
2457
|
+
env, BaseObjectPtr<StatementSync>(stmt));
|
|
2458
|
+
|
|
2459
|
+
if (!iter) {
|
|
2080
2460
|
return;
|
|
2081
2461
|
}
|
|
2082
2462
|
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
array_values.reserve(num_cols);
|
|
2086
|
-
for (int i = 0; i < num_cols; ++i) {
|
|
2087
|
-
Local<Value> val;
|
|
2088
|
-
if (!stmt->ColumnToValue(i).ToLocal(&val)) return;
|
|
2089
|
-
array_values.emplace_back(val);
|
|
2090
|
-
}
|
|
2091
|
-
Local<Array> result =
|
|
2092
|
-
Array::New(isolate, array_values.data(), array_values.size());
|
|
2093
|
-
args.GetReturnValue().Set(result);
|
|
2094
|
-
} else {
|
|
2095
|
-
LocalVector<Name> keys(isolate);
|
|
2096
|
-
keys.reserve(num_cols);
|
|
2097
|
-
LocalVector<Value> values(isolate);
|
|
2098
|
-
values.reserve(num_cols);
|
|
2463
|
+
args.GetReturnValue().Set(iter->object());
|
|
2464
|
+
}
|
|
2099
2465
|
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2466
|
+
void StatementSync::Get(const FunctionCallbackInfo<Value>& args) {
|
|
2467
|
+
StatementSync* stmt;
|
|
2468
|
+
ASSIGN_OR_RETURN_UNWRAP(&stmt, args.This());
|
|
2469
|
+
Environment* env = Environment::GetCurrent(args);
|
|
2470
|
+
THROW_AND_RETURN_ON_BAD_STATE(
|
|
2471
|
+
env, stmt->IsFinalized(), "statement has been finalized");
|
|
2472
|
+
int r = sqlite3_reset(stmt->statement_);
|
|
2473
|
+
CHECK_ERROR_OR_THROW(env->isolate(), stmt->db_.get(), r, SQLITE_OK, void());
|
|
2108
2474
|
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2475
|
+
if (!stmt->BindParams(args)) {
|
|
2476
|
+
return;
|
|
2477
|
+
}
|
|
2112
2478
|
|
|
2479
|
+
Local<Value> result;
|
|
2480
|
+
if (StatementExecutionHelper::Get(env,
|
|
2481
|
+
stmt->db_.get(),
|
|
2482
|
+
stmt->statement_,
|
|
2483
|
+
stmt->return_arrays_,
|
|
2484
|
+
stmt->use_big_ints_)
|
|
2485
|
+
.ToLocal(&result)) {
|
|
2113
2486
|
args.GetReturnValue().Set(result);
|
|
2114
2487
|
}
|
|
2115
2488
|
}
|
|
@@ -2127,35 +2500,12 @@ void StatementSync::Run(const FunctionCallbackInfo<Value>& args) {
|
|
|
2127
2500
|
return;
|
|
2128
2501
|
}
|
|
2129
2502
|
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
sqlite3_last_insert_rowid(stmt->db_->Connection());
|
|
2136
|
-
sqlite3_int64 changes = sqlite3_changes64(stmt->db_->Connection());
|
|
2137
|
-
Local<Value> last_insert_rowid_val;
|
|
2138
|
-
Local<Value> changes_val;
|
|
2139
|
-
|
|
2140
|
-
if (stmt->use_big_ints_) {
|
|
2141
|
-
last_insert_rowid_val = BigInt::New(env->isolate(), last_insert_rowid);
|
|
2142
|
-
changes_val = BigInt::New(env->isolate(), changes);
|
|
2143
|
-
} else {
|
|
2144
|
-
last_insert_rowid_val = Number::New(env->isolate(), last_insert_rowid);
|
|
2145
|
-
changes_val = Number::New(env->isolate(), changes);
|
|
2146
|
-
}
|
|
2147
|
-
|
|
2148
|
-
if (result
|
|
2149
|
-
->Set(env->context(),
|
|
2150
|
-
env->last_insert_rowid_string(),
|
|
2151
|
-
last_insert_rowid_val)
|
|
2152
|
-
.IsNothing() ||
|
|
2153
|
-
result->Set(env->context(), env->changes_string(), changes_val)
|
|
2154
|
-
.IsNothing()) {
|
|
2155
|
-
return;
|
|
2503
|
+
Local<Object> result;
|
|
2504
|
+
if (StatementExecutionHelper::Run(
|
|
2505
|
+
env, stmt->db_.get(), stmt->statement_, stmt->use_big_ints_)
|
|
2506
|
+
.ToLocal(&result)) {
|
|
2507
|
+
args.GetReturnValue().Set(result);
|
|
2156
2508
|
}
|
|
2157
|
-
|
|
2158
|
-
args.GetReturnValue().Set(result);
|
|
2159
2509
|
}
|
|
2160
2510
|
|
|
2161
2511
|
void StatementSync::Columns(const FunctionCallbackInfo<Value>& args) {
|
|
@@ -2167,58 +2517,35 @@ void StatementSync::Columns(const FunctionCallbackInfo<Value>& args) {
|
|
|
2167
2517
|
int num_cols = sqlite3_column_count(stmt->statement_);
|
|
2168
2518
|
Isolate* isolate = env->isolate();
|
|
2169
2519
|
LocalVector<Value> cols(isolate);
|
|
2170
|
-
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
|
|
2520
|
+
auto sqlite_column_template = env->sqlite_column_template();
|
|
2521
|
+
if (sqlite_column_template.IsEmpty()) {
|
|
2522
|
+
static constexpr std::string_view col_keys[] = {
|
|
2523
|
+
"column", "database", "name", "table", "type"};
|
|
2524
|
+
sqlite_column_template = DictionaryTemplate::New(isolate, col_keys);
|
|
2525
|
+
env->set_sqlite_column_template(sqlite_column_template);
|
|
2526
|
+
}
|
|
2177
2527
|
|
|
2178
2528
|
cols.reserve(num_cols);
|
|
2179
2529
|
for (int i = 0; i < num_cols; ++i) {
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
|
|
2530
|
+
MaybeLocal<Value> values[] = {
|
|
2531
|
+
NullableSQLiteStringToValue(
|
|
2532
|
+
isolate, sqlite3_column_origin_name(stmt->statement_, i)),
|
|
2533
|
+
NullableSQLiteStringToValue(
|
|
2534
|
+
isolate, sqlite3_column_database_name(stmt->statement_, i)),
|
|
2535
|
+
stmt->ColumnNameToName(i),
|
|
2536
|
+
NullableSQLiteStringToValue(
|
|
2537
|
+
isolate, sqlite3_column_table_name(stmt->statement_, i)),
|
|
2538
|
+
NullableSQLiteStringToValue(
|
|
2539
|
+
isolate, sqlite3_column_decltype(stmt->statement_, i)),
|
|
2540
|
+
};
|
|
2541
|
+
|
|
2542
|
+
Local<Object> col;
|
|
2543
|
+
if (!NewDictionaryInstanceNullProto(
|
|
2544
|
+
env->context(), sqlite_column_template, values)
|
|
2545
|
+
.ToLocal(&col)) {
|
|
2186
2546
|
return;
|
|
2187
2547
|
}
|
|
2188
|
-
|
|
2189
|
-
|
|
2190
|
-
if (!NullableSQLiteStringToValue(
|
|
2191
|
-
isolate, sqlite3_column_database_name(stmt->statement_, i))
|
|
2192
|
-
.ToLocal(&value)) {
|
|
2193
|
-
return;
|
|
2194
|
-
}
|
|
2195
|
-
col_values.emplace_back(value);
|
|
2196
|
-
|
|
2197
|
-
if (!stmt->ColumnNameToName(i).ToLocal(&value)) {
|
|
2198
|
-
return;
|
|
2199
|
-
}
|
|
2200
|
-
col_values.emplace_back(value);
|
|
2201
|
-
|
|
2202
|
-
if (!NullableSQLiteStringToValue(
|
|
2203
|
-
isolate, sqlite3_column_table_name(stmt->statement_, i))
|
|
2204
|
-
.ToLocal(&value)) {
|
|
2205
|
-
return;
|
|
2206
|
-
}
|
|
2207
|
-
col_values.emplace_back(value);
|
|
2208
|
-
|
|
2209
|
-
if (!NullableSQLiteStringToValue(
|
|
2210
|
-
isolate, sqlite3_column_decltype(stmt->statement_, i))
|
|
2211
|
-
.ToLocal(&value)) {
|
|
2212
|
-
return;
|
|
2213
|
-
}
|
|
2214
|
-
col_values.emplace_back(value);
|
|
2215
|
-
|
|
2216
|
-
Local<Object> column = Object::New(isolate,
|
|
2217
|
-
Null(isolate),
|
|
2218
|
-
col_keys.data(),
|
|
2219
|
-
col_values.data(),
|
|
2220
|
-
col_keys.size());
|
|
2221
|
-
cols.emplace_back(column);
|
|
2548
|
+
cols.emplace_back(col);
|
|
2222
2549
|
}
|
|
2223
2550
|
|
|
2224
2551
|
args.GetReturnValue().Set(Array::New(isolate, cols.data(), cols.size()));
|
|
@@ -2331,6 +2658,17 @@ void IllegalConstructor(const FunctionCallbackInfo<Value>& args) {
|
|
|
2331
2658
|
THROW_ERR_ILLEGAL_CONSTRUCTOR(Environment::GetCurrent(args));
|
|
2332
2659
|
}
|
|
2333
2660
|
|
|
2661
|
+
SQLTagStore::SQLTagStore(Environment* env,
|
|
2662
|
+
Local<Object> object,
|
|
2663
|
+
BaseObjectWeakPtr<DatabaseSync> database,
|
|
2664
|
+
int capacity)
|
|
2665
|
+
: BaseObject(env, object),
|
|
2666
|
+
database_(std::move(database)),
|
|
2667
|
+
sql_tags_(capacity),
|
|
2668
|
+
capacity_(capacity) {
|
|
2669
|
+
MakeWeak();
|
|
2670
|
+
}
|
|
2671
|
+
|
|
2334
2672
|
static inline void SetSideEffectFreeGetter(
|
|
2335
2673
|
Isolate* isolate,
|
|
2336
2674
|
Local<FunctionTemplate> class_template,
|
|
@@ -2348,6 +2686,299 @@ static inline void SetSideEffectFreeGetter(
|
|
|
2348
2686
|
name, getter, Local<FunctionTemplate>(), DontDelete);
|
|
2349
2687
|
}
|
|
2350
2688
|
|
|
2689
|
+
SQLTagStore::~SQLTagStore() {}
|
|
2690
|
+
|
|
2691
|
+
Local<FunctionTemplate> SQLTagStore::GetConstructorTemplate(Environment* env) {
|
|
2692
|
+
Isolate* isolate = env->isolate();
|
|
2693
|
+
Local<FunctionTemplate> tmpl =
|
|
2694
|
+
NewFunctionTemplate(isolate, IllegalConstructor);
|
|
2695
|
+
tmpl->SetClassName(FIXED_ONE_BYTE_STRING(isolate, "SQLTagStore"));
|
|
2696
|
+
tmpl->InstanceTemplate()->SetInternalFieldCount(
|
|
2697
|
+
SQLTagStore::kInternalFieldCount);
|
|
2698
|
+
SetProtoMethod(isolate, tmpl, "get", Get);
|
|
2699
|
+
SetProtoMethod(isolate, tmpl, "all", All);
|
|
2700
|
+
SetProtoMethod(isolate, tmpl, "iterate", Iterate);
|
|
2701
|
+
SetProtoMethod(isolate, tmpl, "run", Run);
|
|
2702
|
+
SetProtoMethod(isolate, tmpl, "clear", Clear);
|
|
2703
|
+
SetProtoMethod(isolate, tmpl, "size", Size);
|
|
2704
|
+
SetSideEffectFreeGetter(
|
|
2705
|
+
isolate, tmpl, FIXED_ONE_BYTE_STRING(isolate, "capacity"), Capacity);
|
|
2706
|
+
SetSideEffectFreeGetter(
|
|
2707
|
+
isolate, tmpl, FIXED_ONE_BYTE_STRING(isolate, "db"), DatabaseGetter);
|
|
2708
|
+
return tmpl;
|
|
2709
|
+
}
|
|
2710
|
+
|
|
2711
|
+
BaseObjectPtr<SQLTagStore> SQLTagStore::Create(
|
|
2712
|
+
Environment* env, BaseObjectWeakPtr<DatabaseSync> database, int capacity) {
|
|
2713
|
+
Local<Object> obj;
|
|
2714
|
+
if (!GetConstructorTemplate(env)
|
|
2715
|
+
->InstanceTemplate()
|
|
2716
|
+
->NewInstance(env->context())
|
|
2717
|
+
.ToLocal(&obj)) {
|
|
2718
|
+
return nullptr;
|
|
2719
|
+
}
|
|
2720
|
+
return MakeBaseObject<SQLTagStore>(env, obj, std::move(database), capacity);
|
|
2721
|
+
}
|
|
2722
|
+
|
|
2723
|
+
void SQLTagStore::DatabaseGetter(const FunctionCallbackInfo<Value>& args) {
|
|
2724
|
+
SQLTagStore* store;
|
|
2725
|
+
ASSIGN_OR_RETURN_UNWRAP(&store, args.This());
|
|
2726
|
+
args.GetReturnValue().Set(store->database_->object());
|
|
2727
|
+
}
|
|
2728
|
+
|
|
2729
|
+
void SQLTagStore::Run(const FunctionCallbackInfo<Value>& info) {
|
|
2730
|
+
SQLTagStore* session;
|
|
2731
|
+
ASSIGN_OR_RETURN_UNWRAP(&session, info.This());
|
|
2732
|
+
Environment* env = Environment::GetCurrent(info);
|
|
2733
|
+
|
|
2734
|
+
THROW_AND_RETURN_ON_BAD_STATE(
|
|
2735
|
+
env, !session->database_->IsOpen(), "database is not open");
|
|
2736
|
+
|
|
2737
|
+
BaseObjectPtr<StatementSync> stmt = PrepareStatement(info);
|
|
2738
|
+
|
|
2739
|
+
if (!stmt) {
|
|
2740
|
+
return;
|
|
2741
|
+
}
|
|
2742
|
+
|
|
2743
|
+
uint32_t n_params = info.Length() - 1;
|
|
2744
|
+
int r = sqlite3_reset(stmt->statement_);
|
|
2745
|
+
CHECK_ERROR_OR_THROW(env->isolate(), stmt->db_.get(), r, SQLITE_OK, void());
|
|
2746
|
+
int param_count = sqlite3_bind_parameter_count(stmt->statement_);
|
|
2747
|
+
for (int i = 0; i < static_cast<int>(n_params) && i < param_count; ++i) {
|
|
2748
|
+
Local<Value> value = info[i + 1];
|
|
2749
|
+
if (!stmt->BindValue(value, i + 1)) {
|
|
2750
|
+
return;
|
|
2751
|
+
}
|
|
2752
|
+
}
|
|
2753
|
+
|
|
2754
|
+
Local<Object> result;
|
|
2755
|
+
if (StatementExecutionHelper::Run(
|
|
2756
|
+
env, stmt->db_.get(), stmt->statement_, stmt->use_big_ints_)
|
|
2757
|
+
.ToLocal(&result)) {
|
|
2758
|
+
info.GetReturnValue().Set(result);
|
|
2759
|
+
}
|
|
2760
|
+
}
|
|
2761
|
+
|
|
2762
|
+
void SQLTagStore::Iterate(const FunctionCallbackInfo<Value>& args) {
|
|
2763
|
+
SQLTagStore* session;
|
|
2764
|
+
ASSIGN_OR_RETURN_UNWRAP(&session, args.This());
|
|
2765
|
+
Environment* env = Environment::GetCurrent(args);
|
|
2766
|
+
|
|
2767
|
+
THROW_AND_RETURN_ON_BAD_STATE(
|
|
2768
|
+
env, !session->database_->IsOpen(), "database is not open");
|
|
2769
|
+
|
|
2770
|
+
BaseObjectPtr<StatementSync> stmt = PrepareStatement(args);
|
|
2771
|
+
|
|
2772
|
+
if (!stmt) {
|
|
2773
|
+
return;
|
|
2774
|
+
}
|
|
2775
|
+
|
|
2776
|
+
uint32_t n_params = args.Length() - 1;
|
|
2777
|
+
int r = sqlite3_reset(stmt->statement_);
|
|
2778
|
+
CHECK_ERROR_OR_THROW(env->isolate(), stmt->db_.get(), r, SQLITE_OK, void());
|
|
2779
|
+
int param_count = sqlite3_bind_parameter_count(stmt->statement_);
|
|
2780
|
+
for (int i = 0; i < static_cast<int>(n_params) && i < param_count; ++i) {
|
|
2781
|
+
Local<Value> value = args[i + 1];
|
|
2782
|
+
if (!stmt->BindValue(value, i + 1)) {
|
|
2783
|
+
return;
|
|
2784
|
+
}
|
|
2785
|
+
}
|
|
2786
|
+
|
|
2787
|
+
BaseObjectPtr<StatementSyncIterator> iter = StatementExecutionHelper::Iterate(
|
|
2788
|
+
env, BaseObjectPtr<StatementSync>(stmt));
|
|
2789
|
+
|
|
2790
|
+
if (!iter) {
|
|
2791
|
+
return;
|
|
2792
|
+
}
|
|
2793
|
+
|
|
2794
|
+
args.GetReturnValue().Set(iter->object());
|
|
2795
|
+
}
|
|
2796
|
+
|
|
2797
|
+
void SQLTagStore::Get(const FunctionCallbackInfo<Value>& args) {
|
|
2798
|
+
SQLTagStore* session;
|
|
2799
|
+
ASSIGN_OR_RETURN_UNWRAP(&session, args.This());
|
|
2800
|
+
Environment* env = Environment::GetCurrent(args);
|
|
2801
|
+
|
|
2802
|
+
THROW_AND_RETURN_ON_BAD_STATE(
|
|
2803
|
+
env, !session->database_->IsOpen(), "database is not open");
|
|
2804
|
+
|
|
2805
|
+
BaseObjectPtr<StatementSync> stmt = PrepareStatement(args);
|
|
2806
|
+
|
|
2807
|
+
if (!stmt) {
|
|
2808
|
+
return;
|
|
2809
|
+
}
|
|
2810
|
+
|
|
2811
|
+
uint32_t n_params = args.Length() - 1;
|
|
2812
|
+
Isolate* isolate = env->isolate();
|
|
2813
|
+
|
|
2814
|
+
int r = sqlite3_reset(stmt->statement_);
|
|
2815
|
+
CHECK_ERROR_OR_THROW(isolate, stmt->db_.get(), r, SQLITE_OK, void());
|
|
2816
|
+
|
|
2817
|
+
int param_count = sqlite3_bind_parameter_count(stmt->statement_);
|
|
2818
|
+
for (int i = 0; i < static_cast<int>(n_params) && i < param_count; ++i) {
|
|
2819
|
+
Local<Value> value = args[i + 1];
|
|
2820
|
+
if (!stmt->BindValue(value, i + 1)) {
|
|
2821
|
+
return;
|
|
2822
|
+
}
|
|
2823
|
+
}
|
|
2824
|
+
|
|
2825
|
+
Local<Value> result;
|
|
2826
|
+
if (StatementExecutionHelper::Get(env,
|
|
2827
|
+
stmt->db_.get(),
|
|
2828
|
+
stmt->statement_,
|
|
2829
|
+
stmt->return_arrays_,
|
|
2830
|
+
stmt->use_big_ints_)
|
|
2831
|
+
.ToLocal(&result)) {
|
|
2832
|
+
args.GetReturnValue().Set(result);
|
|
2833
|
+
}
|
|
2834
|
+
}
|
|
2835
|
+
|
|
2836
|
+
void SQLTagStore::All(const FunctionCallbackInfo<Value>& args) {
|
|
2837
|
+
SQLTagStore* session;
|
|
2838
|
+
ASSIGN_OR_RETURN_UNWRAP(&session, args.This());
|
|
2839
|
+
Environment* env = Environment::GetCurrent(args);
|
|
2840
|
+
|
|
2841
|
+
THROW_AND_RETURN_ON_BAD_STATE(
|
|
2842
|
+
env, !session->database_->IsOpen(), "database is not open");
|
|
2843
|
+
|
|
2844
|
+
BaseObjectPtr<StatementSync> stmt = PrepareStatement(args);
|
|
2845
|
+
|
|
2846
|
+
if (!stmt) {
|
|
2847
|
+
return;
|
|
2848
|
+
}
|
|
2849
|
+
|
|
2850
|
+
uint32_t n_params = args.Length() - 1;
|
|
2851
|
+
Isolate* isolate = env->isolate();
|
|
2852
|
+
|
|
2853
|
+
int r = sqlite3_reset(stmt->statement_);
|
|
2854
|
+
CHECK_ERROR_OR_THROW(isolate, stmt->db_.get(), r, SQLITE_OK, void());
|
|
2855
|
+
|
|
2856
|
+
int param_count = sqlite3_bind_parameter_count(stmt->statement_);
|
|
2857
|
+
for (int i = 0; i < static_cast<int>(n_params) && i < param_count; ++i) {
|
|
2858
|
+
Local<Value> value = args[i + 1];
|
|
2859
|
+
if (!stmt->BindValue(value, i + 1)) {
|
|
2860
|
+
return;
|
|
2861
|
+
}
|
|
2862
|
+
}
|
|
2863
|
+
|
|
2864
|
+
auto reset = OnScopeLeave([&]() { sqlite3_reset(stmt->statement_); });
|
|
2865
|
+
Local<Value> result;
|
|
2866
|
+
if (StatementExecutionHelper::All(env,
|
|
2867
|
+
stmt->db_.get(),
|
|
2868
|
+
stmt->statement_,
|
|
2869
|
+
stmt->return_arrays_,
|
|
2870
|
+
stmt->use_big_ints_)
|
|
2871
|
+
.ToLocal(&result)) {
|
|
2872
|
+
args.GetReturnValue().Set(result);
|
|
2873
|
+
}
|
|
2874
|
+
}
|
|
2875
|
+
|
|
2876
|
+
void SQLTagStore::Size(const FunctionCallbackInfo<Value>& info) {
|
|
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) {
|
|
2884
|
+
SQLTagStore* store;
|
|
2885
|
+
ASSIGN_OR_RETURN_UNWRAP(&store, info.This());
|
|
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());
|
|
2893
|
+
store->sql_tags_.Clear();
|
|
2894
|
+
}
|
|
2895
|
+
|
|
2896
|
+
BaseObjectPtr<StatementSync> SQLTagStore::PrepareStatement(
|
|
2897
|
+
const FunctionCallbackInfo<Value>& args) {
|
|
2898
|
+
SQLTagStore* session = BaseObject::FromJSObject<SQLTagStore>(args.This());
|
|
2899
|
+
if (!session) {
|
|
2900
|
+
THROW_ERR_INVALID_ARG_TYPE(
|
|
2901
|
+
Environment::GetCurrent(args)->isolate(),
|
|
2902
|
+
"This method can only be called on SQLTagStore instances.");
|
|
2903
|
+
return BaseObjectPtr<StatementSync>();
|
|
2904
|
+
}
|
|
2905
|
+
Environment* env = Environment::GetCurrent(args);
|
|
2906
|
+
Isolate* isolate = env->isolate();
|
|
2907
|
+
Local<Context> context = isolate->GetCurrentContext();
|
|
2908
|
+
|
|
2909
|
+
if (args.Length() < 1 || !args[0]->IsArray()) {
|
|
2910
|
+
THROW_ERR_INVALID_ARG_TYPE(
|
|
2911
|
+
isolate,
|
|
2912
|
+
"First argument must be an array of strings (template literal).");
|
|
2913
|
+
return BaseObjectPtr<StatementSync>();
|
|
2914
|
+
}
|
|
2915
|
+
|
|
2916
|
+
Local<Array> strings = args[0].As<Array>();
|
|
2917
|
+
uint32_t n_strings = strings->Length();
|
|
2918
|
+
uint32_t n_params = args.Length() - 1;
|
|
2919
|
+
|
|
2920
|
+
std::string sql;
|
|
2921
|
+
for (uint32_t i = 0; i < n_strings; ++i) {
|
|
2922
|
+
Local<Value> str_val;
|
|
2923
|
+
if (!strings->Get(context, i).ToLocal(&str_val) || !str_val->IsString()) {
|
|
2924
|
+
THROW_ERR_INVALID_ARG_TYPE(isolate,
|
|
2925
|
+
"Template literal parts must be strings.");
|
|
2926
|
+
return BaseObjectPtr<StatementSync>();
|
|
2927
|
+
}
|
|
2928
|
+
Utf8Value part(isolate, str_val);
|
|
2929
|
+
sql += part.ToStringView();
|
|
2930
|
+
if (i < n_params) {
|
|
2931
|
+
sql += "?";
|
|
2932
|
+
}
|
|
2933
|
+
}
|
|
2934
|
+
|
|
2935
|
+
BaseObjectPtr<StatementSync> stmt = nullptr;
|
|
2936
|
+
if (session->sql_tags_.Exists(sql)) {
|
|
2937
|
+
stmt = session->sql_tags_.Get(sql);
|
|
2938
|
+
if (stmt->IsFinalized()) {
|
|
2939
|
+
session->sql_tags_.Erase(sql);
|
|
2940
|
+
stmt = nullptr;
|
|
2941
|
+
}
|
|
2942
|
+
}
|
|
2943
|
+
|
|
2944
|
+
if (stmt == nullptr) {
|
|
2945
|
+
sqlite3_stmt* s = nullptr;
|
|
2946
|
+
int r = sqlite3_prepare_v2(
|
|
2947
|
+
session->database_->connection_, sql.data(), sql.size(), &s, 0);
|
|
2948
|
+
|
|
2949
|
+
if (r != SQLITE_OK) {
|
|
2950
|
+
THROW_ERR_SQLITE_ERROR(isolate, "Failed to prepare statement");
|
|
2951
|
+
sqlite3_finalize(s);
|
|
2952
|
+
return BaseObjectPtr<StatementSync>();
|
|
2953
|
+
}
|
|
2954
|
+
|
|
2955
|
+
BaseObjectPtr<StatementSync> stmt_obj = StatementSync::Create(
|
|
2956
|
+
env, BaseObjectPtr<DatabaseSync>(session->database_), s);
|
|
2957
|
+
|
|
2958
|
+
if (!stmt_obj) {
|
|
2959
|
+
THROW_ERR_SQLITE_ERROR(isolate, "Failed to create StatementSync");
|
|
2960
|
+
sqlite3_finalize(s);
|
|
2961
|
+
return BaseObjectPtr<StatementSync>();
|
|
2962
|
+
}
|
|
2963
|
+
|
|
2964
|
+
session->sql_tags_.Put(sql, stmt_obj);
|
|
2965
|
+
stmt = stmt_obj;
|
|
2966
|
+
}
|
|
2967
|
+
|
|
2968
|
+
return stmt;
|
|
2969
|
+
}
|
|
2970
|
+
|
|
2971
|
+
void SQLTagStore::MemoryInfo(MemoryTracker* tracker) const {
|
|
2972
|
+
tracker->TrackFieldWithSize(MemoryInfoName(), SelfSize());
|
|
2973
|
+
tracker->TrackField("database", database_);
|
|
2974
|
+
size_t cache_content_size = 0;
|
|
2975
|
+
for (const auto& pair : sql_tags_) {
|
|
2976
|
+
cache_content_size += pair.first.capacity();
|
|
2977
|
+
cache_content_size += sizeof(pair.second);
|
|
2978
|
+
}
|
|
2979
|
+
tracker->TrackFieldWithSize("sql_tags_cache", cache_content_size);
|
|
2980
|
+
}
|
|
2981
|
+
|
|
2351
2982
|
Local<FunctionTemplate> StatementSync::GetConstructorTemplate(
|
|
2352
2983
|
Environment* env) {
|
|
2353
2984
|
Local<FunctionTemplate> tmpl =
|
|
@@ -2450,15 +3081,19 @@ void StatementSyncIterator::Next(const FunctionCallbackInfo<Value>& args) {
|
|
|
2450
3081
|
THROW_AND_RETURN_ON_BAD_STATE(
|
|
2451
3082
|
env, iter->stmt_->IsFinalized(), "statement has been finalized");
|
|
2452
3083
|
Isolate* isolate = env->isolate();
|
|
2453
|
-
|
|
3084
|
+
|
|
3085
|
+
auto iter_template = getLazyIterTemplate(env);
|
|
2454
3086
|
|
|
2455
3087
|
if (iter->done_) {
|
|
2456
|
-
|
|
2457
|
-
|
|
2458
|
-
|
|
2459
|
-
|
|
2460
|
-
|
|
2461
|
-
|
|
3088
|
+
MaybeLocal<Value> values[]{
|
|
3089
|
+
Boolean::New(isolate, true),
|
|
3090
|
+
Null(isolate),
|
|
3091
|
+
};
|
|
3092
|
+
Local<Object> result;
|
|
3093
|
+
if (NewDictionaryInstanceNullProto(env->context(), iter_template, values)
|
|
3094
|
+
.ToLocal(&result)) {
|
|
3095
|
+
args.GetReturnValue().Set(result);
|
|
3096
|
+
}
|
|
2462
3097
|
return;
|
|
2463
3098
|
}
|
|
2464
3099
|
|
|
@@ -2467,39 +3102,37 @@ void StatementSyncIterator::Next(const FunctionCallbackInfo<Value>& args) {
|
|
|
2467
3102
|
CHECK_ERROR_OR_THROW(
|
|
2468
3103
|
env->isolate(), iter->stmt_->db_.get(), r, SQLITE_DONE, void());
|
|
2469
3104
|
sqlite3_reset(iter->stmt_->statement_);
|
|
2470
|
-
|
|
2471
|
-
|
|
2472
|
-
|
|
2473
|
-
|
|
2474
|
-
|
|
2475
|
-
|
|
3105
|
+
MaybeLocal<Value> values[] = {Boolean::New(isolate, true), Null(isolate)};
|
|
3106
|
+
Local<Object> result;
|
|
3107
|
+
if (NewDictionaryInstanceNullProto(env->context(), iter_template, values)
|
|
3108
|
+
.ToLocal(&result)) {
|
|
3109
|
+
args.GetReturnValue().Set(result);
|
|
3110
|
+
}
|
|
2476
3111
|
return;
|
|
2477
3112
|
}
|
|
2478
3113
|
|
|
2479
3114
|
int num_cols = sqlite3_column_count(iter->stmt_->statement_);
|
|
2480
3115
|
Local<Value> row_value;
|
|
3116
|
+
LocalVector<Name> row_keys(isolate);
|
|
3117
|
+
LocalVector<Value> row_values(isolate);
|
|
3118
|
+
|
|
3119
|
+
if (ExtractRowValues(env,
|
|
3120
|
+
iter->stmt_->statement_,
|
|
3121
|
+
num_cols,
|
|
3122
|
+
iter->stmt_->use_big_ints_,
|
|
3123
|
+
&row_values)
|
|
3124
|
+
.IsNothing()) {
|
|
3125
|
+
return;
|
|
3126
|
+
}
|
|
2481
3127
|
|
|
2482
3128
|
if (iter->stmt_->return_arrays_) {
|
|
2483
|
-
|
|
2484
|
-
array_values.reserve(num_cols);
|
|
2485
|
-
for (int i = 0; i < num_cols; ++i) {
|
|
2486
|
-
Local<Value> val;
|
|
2487
|
-
if (!iter->stmt_->ColumnToValue(i).ToLocal(&val)) return;
|
|
2488
|
-
array_values.emplace_back(val);
|
|
2489
|
-
}
|
|
2490
|
-
row_value = Array::New(isolate, array_values.data(), array_values.size());
|
|
3129
|
+
row_value = Array::New(isolate, row_values.data(), row_values.size());
|
|
2491
3130
|
} else {
|
|
2492
|
-
LocalVector<Name> row_keys(isolate);
|
|
2493
|
-
LocalVector<Value> row_values(isolate);
|
|
2494
3131
|
row_keys.reserve(num_cols);
|
|
2495
|
-
row_values.reserve(num_cols);
|
|
2496
3132
|
for (int i = 0; i < num_cols; ++i) {
|
|
2497
3133
|
Local<Name> key;
|
|
2498
3134
|
if (!iter->stmt_->ColumnNameToName(i).ToLocal(&key)) return;
|
|
2499
|
-
Local<Value> val;
|
|
2500
|
-
if (!iter->stmt_->ColumnToValue(i).ToLocal(&val)) return;
|
|
2501
3135
|
row_keys.emplace_back(key);
|
|
2502
|
-
row_values.emplace_back(val);
|
|
2503
3136
|
}
|
|
2504
3137
|
|
|
2505
3138
|
DCHECK_EQ(row_keys.size(), row_values.size());
|
|
@@ -2507,11 +3140,12 @@ void StatementSyncIterator::Next(const FunctionCallbackInfo<Value>& args) {
|
|
|
2507
3140
|
isolate, Null(isolate), row_keys.data(), row_values.data(), num_cols);
|
|
2508
3141
|
}
|
|
2509
3142
|
|
|
2510
|
-
|
|
2511
|
-
|
|
2512
|
-
|
|
2513
|
-
|
|
2514
|
-
|
|
3143
|
+
MaybeLocal<Value> values[] = {Boolean::New(isolate, false), row_value};
|
|
3144
|
+
Local<Object> result;
|
|
3145
|
+
if (NewDictionaryInstanceNullProto(env->context(), iter_template, values)
|
|
3146
|
+
.ToLocal(&result)) {
|
|
3147
|
+
args.GetReturnValue().Set(result);
|
|
3148
|
+
}
|
|
2515
3149
|
}
|
|
2516
3150
|
|
|
2517
3151
|
void StatementSyncIterator::Return(const FunctionCallbackInfo<Value>& args) {
|
|
@@ -2524,14 +3158,15 @@ void StatementSyncIterator::Return(const FunctionCallbackInfo<Value>& args) {
|
|
|
2524
3158
|
|
|
2525
3159
|
sqlite3_reset(iter->stmt_->statement_);
|
|
2526
3160
|
iter->done_ = true;
|
|
2527
|
-
LocalVector<Name> keys(isolate, {env->done_string(), env->value_string()});
|
|
2528
|
-
LocalVector<Value> values(isolate,
|
|
2529
|
-
{Boolean::New(isolate, true), Null(isolate)});
|
|
2530
3161
|
|
|
2531
|
-
|
|
2532
|
-
|
|
2533
|
-
|
|
2534
|
-
|
|
3162
|
+
auto iter_template = getLazyIterTemplate(env);
|
|
3163
|
+
MaybeLocal<Value> values[] = {Boolean::New(isolate, true), Null(isolate)};
|
|
3164
|
+
|
|
3165
|
+
Local<Object> result;
|
|
3166
|
+
if (NewDictionaryInstanceNullProto(env->context(), iter_template, values)
|
|
3167
|
+
.ToLocal(&result)) {
|
|
3168
|
+
args.GetReturnValue().Set(result);
|
|
3169
|
+
}
|
|
2535
3170
|
}
|
|
2536
3171
|
|
|
2537
3172
|
Session::Session(Environment* env,
|
|
@@ -2577,6 +3212,7 @@ Local<FunctionTemplate> Session::GetConstructorTemplate(Environment* env) {
|
|
|
2577
3212
|
SetProtoMethod(
|
|
2578
3213
|
isolate, tmpl, "patchset", Session::Changeset<sqlite3session_patchset>);
|
|
2579
3214
|
SetProtoMethod(isolate, tmpl, "close", Session::Close);
|
|
3215
|
+
SetProtoDispose(isolate, tmpl, Session::Dispose);
|
|
2580
3216
|
env->set_sqlite_session_constructor_template(tmpl);
|
|
2581
3217
|
}
|
|
2582
3218
|
return tmpl;
|
|
@@ -2621,6 +3257,14 @@ void Session::Close(const FunctionCallbackInfo<Value>& args) {
|
|
|
2621
3257
|
session->Delete();
|
|
2622
3258
|
}
|
|
2623
3259
|
|
|
3260
|
+
void Session::Dispose(const v8::FunctionCallbackInfo<v8::Value>& args) {
|
|
3261
|
+
v8::TryCatch try_catch(args.GetIsolate());
|
|
3262
|
+
Close(args);
|
|
3263
|
+
if (try_catch.HasCaught()) {
|
|
3264
|
+
CHECK(try_catch.CanContinue());
|
|
3265
|
+
}
|
|
3266
|
+
}
|
|
3267
|
+
|
|
2624
3268
|
void Session::Delete() {
|
|
2625
3269
|
if (!database_ || !database_->connection_ || session_ == nullptr) return;
|
|
2626
3270
|
sqlite3session_delete(session_);
|
|
@@ -2638,6 +3282,47 @@ void DefineConstants(Local<Object> target) {
|
|
|
2638
3282
|
NODE_DEFINE_CONSTANT(target, SQLITE_CHANGESET_CONFLICT);
|
|
2639
3283
|
NODE_DEFINE_CONSTANT(target, SQLITE_CHANGESET_CONSTRAINT);
|
|
2640
3284
|
NODE_DEFINE_CONSTANT(target, SQLITE_CHANGESET_FOREIGN_KEY);
|
|
3285
|
+
|
|
3286
|
+
// Authorization result codes
|
|
3287
|
+
NODE_DEFINE_CONSTANT(target, SQLITE_OK);
|
|
3288
|
+
NODE_DEFINE_CONSTANT(target, SQLITE_DENY);
|
|
3289
|
+
NODE_DEFINE_CONSTANT(target, SQLITE_IGNORE);
|
|
3290
|
+
|
|
3291
|
+
// Authorization action codes
|
|
3292
|
+
NODE_DEFINE_CONSTANT(target, SQLITE_CREATE_INDEX);
|
|
3293
|
+
NODE_DEFINE_CONSTANT(target, SQLITE_CREATE_TABLE);
|
|
3294
|
+
NODE_DEFINE_CONSTANT(target, SQLITE_CREATE_TEMP_INDEX);
|
|
3295
|
+
NODE_DEFINE_CONSTANT(target, SQLITE_CREATE_TEMP_TABLE);
|
|
3296
|
+
NODE_DEFINE_CONSTANT(target, SQLITE_CREATE_TEMP_TRIGGER);
|
|
3297
|
+
NODE_DEFINE_CONSTANT(target, SQLITE_CREATE_TEMP_VIEW);
|
|
3298
|
+
NODE_DEFINE_CONSTANT(target, SQLITE_CREATE_TRIGGER);
|
|
3299
|
+
NODE_DEFINE_CONSTANT(target, SQLITE_CREATE_VIEW);
|
|
3300
|
+
NODE_DEFINE_CONSTANT(target, SQLITE_DELETE);
|
|
3301
|
+
NODE_DEFINE_CONSTANT(target, SQLITE_DROP_INDEX);
|
|
3302
|
+
NODE_DEFINE_CONSTANT(target, SQLITE_DROP_TABLE);
|
|
3303
|
+
NODE_DEFINE_CONSTANT(target, SQLITE_DROP_TEMP_INDEX);
|
|
3304
|
+
NODE_DEFINE_CONSTANT(target, SQLITE_DROP_TEMP_TABLE);
|
|
3305
|
+
NODE_DEFINE_CONSTANT(target, SQLITE_DROP_TEMP_TRIGGER);
|
|
3306
|
+
NODE_DEFINE_CONSTANT(target, SQLITE_DROP_TEMP_VIEW);
|
|
3307
|
+
NODE_DEFINE_CONSTANT(target, SQLITE_DROP_TRIGGER);
|
|
3308
|
+
NODE_DEFINE_CONSTANT(target, SQLITE_DROP_VIEW);
|
|
3309
|
+
NODE_DEFINE_CONSTANT(target, SQLITE_INSERT);
|
|
3310
|
+
NODE_DEFINE_CONSTANT(target, SQLITE_PRAGMA);
|
|
3311
|
+
NODE_DEFINE_CONSTANT(target, SQLITE_READ);
|
|
3312
|
+
NODE_DEFINE_CONSTANT(target, SQLITE_SELECT);
|
|
3313
|
+
NODE_DEFINE_CONSTANT(target, SQLITE_TRANSACTION);
|
|
3314
|
+
NODE_DEFINE_CONSTANT(target, SQLITE_UPDATE);
|
|
3315
|
+
NODE_DEFINE_CONSTANT(target, SQLITE_ATTACH);
|
|
3316
|
+
NODE_DEFINE_CONSTANT(target, SQLITE_DETACH);
|
|
3317
|
+
NODE_DEFINE_CONSTANT(target, SQLITE_ALTER_TABLE);
|
|
3318
|
+
NODE_DEFINE_CONSTANT(target, SQLITE_REINDEX);
|
|
3319
|
+
NODE_DEFINE_CONSTANT(target, SQLITE_ANALYZE);
|
|
3320
|
+
NODE_DEFINE_CONSTANT(target, SQLITE_CREATE_VTABLE);
|
|
3321
|
+
NODE_DEFINE_CONSTANT(target, SQLITE_DROP_VTABLE);
|
|
3322
|
+
NODE_DEFINE_CONSTANT(target, SQLITE_FUNCTION);
|
|
3323
|
+
NODE_DEFINE_CONSTANT(target, SQLITE_SAVEPOINT);
|
|
3324
|
+
NODE_DEFINE_CONSTANT(target, SQLITE_COPY);
|
|
3325
|
+
NODE_DEFINE_CONSTANT(target, SQLITE_RECURSIVE);
|
|
2641
3326
|
}
|
|
2642
3327
|
|
|
2643
3328
|
static void Initialize(Local<Object> target,
|
|
@@ -2656,9 +3341,12 @@ static void Initialize(Local<Object> target,
|
|
|
2656
3341
|
|
|
2657
3342
|
SetProtoMethod(isolate, db_tmpl, "open", DatabaseSync::Open);
|
|
2658
3343
|
SetProtoMethod(isolate, db_tmpl, "close", DatabaseSync::Close);
|
|
3344
|
+
SetProtoDispose(isolate, db_tmpl, DatabaseSync::Dispose);
|
|
2659
3345
|
SetProtoMethod(isolate, db_tmpl, "prepare", DatabaseSync::Prepare);
|
|
2660
3346
|
SetProtoMethod(isolate, db_tmpl, "exec", DatabaseSync::Exec);
|
|
2661
3347
|
SetProtoMethod(isolate, db_tmpl, "function", DatabaseSync::CustomFunction);
|
|
3348
|
+
SetProtoMethod(
|
|
3349
|
+
isolate, db_tmpl, "createTagStore", DatabaseSync::CreateTagStore);
|
|
2662
3350
|
SetProtoMethodNoSideEffect(
|
|
2663
3351
|
isolate, db_tmpl, "location", DatabaseSync::Location);
|
|
2664
3352
|
SetProtoMethod(
|
|
@@ -2671,8 +3359,12 @@ static void Initialize(Local<Object> target,
|
|
|
2671
3359
|
db_tmpl,
|
|
2672
3360
|
"enableLoadExtension",
|
|
2673
3361
|
DatabaseSync::EnableLoadExtension);
|
|
3362
|
+
SetProtoMethod(
|
|
3363
|
+
isolate, db_tmpl, "enableDefensive", DatabaseSync::EnableDefensive);
|
|
2674
3364
|
SetProtoMethod(
|
|
2675
3365
|
isolate, db_tmpl, "loadExtension", DatabaseSync::LoadExtension);
|
|
3366
|
+
SetProtoMethod(
|
|
3367
|
+
isolate, db_tmpl, "setAuthorizer", DatabaseSync::SetAuthorizer);
|
|
2676
3368
|
SetSideEffectFreeGetter(isolate,
|
|
2677
3369
|
db_tmpl,
|
|
2678
3370
|
FIXED_ONE_BYTE_STRING(isolate, "isOpen"),
|
|
@@ -2681,11 +3373,20 @@ static void Initialize(Local<Object> target,
|
|
|
2681
3373
|
db_tmpl,
|
|
2682
3374
|
FIXED_ONE_BYTE_STRING(isolate, "isTransaction"),
|
|
2683
3375
|
DatabaseSync::IsTransactionGetter);
|
|
3376
|
+
Local<String> sqlite_type_key = FIXED_ONE_BYTE_STRING(isolate, "sqlite-type");
|
|
3377
|
+
Local<v8::Symbol> sqlite_type_symbol =
|
|
3378
|
+
v8::Symbol::For(isolate, sqlite_type_key);
|
|
3379
|
+
Local<String> database_sync_string =
|
|
3380
|
+
FIXED_ONE_BYTE_STRING(isolate, "node:sqlite");
|
|
3381
|
+
db_tmpl->InstanceTemplate()->Set(sqlite_type_symbol, database_sync_string);
|
|
3382
|
+
|
|
2684
3383
|
SetConstructorFunction(context, target, "DatabaseSync", db_tmpl);
|
|
2685
3384
|
SetConstructorFunction(context,
|
|
2686
3385
|
target,
|
|
2687
3386
|
"StatementSync",
|
|
2688
3387
|
StatementSync::GetConstructorTemplate(env));
|
|
3388
|
+
SetConstructorFunction(
|
|
3389
|
+
context, target, "Session", Session::GetConstructorTemplate(env));
|
|
2689
3390
|
|
|
2690
3391
|
target->Set(context, env->constants_string(), constants).Check();
|
|
2691
3392
|
|