jsql-neo 5.4.2 → 5.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +202 -202
- package/README.md +8097 -7971
- package/bin/jsql +320 -320
- package/bin/jsql-server +90 -90
- package/bin/jsql-server-control.js +177 -177
- package/index.d.ts +385 -357
- package/index.js +124 -118
- package/lib/ast.js +214 -0
- package/lib/btree.js +413 -413
- package/lib/cache.js +328 -328
- package/lib/client.js +125 -125
- package/lib/database.js +1744 -1744
- package/lib/date-types.js +182 -182
- package/lib/errors.js +89 -89
- package/lib/jsql_format.js +497 -497
- package/lib/migrate.js +254 -254
- package/lib/mod.js +292 -292
- package/lib/mongo_server.js +607 -607
- package/lib/multiserver.js +140 -140
- package/lib/mysql_compat.js +413 -413
- package/lib/mysql_server.js +1237 -1237
- package/lib/native_client.js +732 -732
- package/lib/nedb_compat.js +506 -506
- package/lib/pg_server.js +864 -864
- package/lib/plugin.js +34 -34
- package/lib/query.js +815 -815
- package/lib/redis_server.js +571 -571
- package/lib/sql.js +3460 -2925
- package/lib/sqlite_compat.js +323 -323
- package/lib/sqlite_worker.js +264 -264
- package/lib/table.js +1304 -1304
- package/lib/tui.js +502 -502
- package/lib/wasm.js +1 -1
- package/lib/wasm_client.js +718 -718
- package/lib/web_ui.js +257 -257
- package/native/jsql-neo-native.node +0 -0
- package/nativesrc/jsql-neo-core/Cargo.lock +455 -455
- package/nativesrc/jsql-neo-core/Cargo.toml +24 -24
- package/nativesrc/jsql-neo-core/src/engine/hybrid.rs +455 -455
- package/nativesrc/jsql-neo-core/src/engine/memory.rs +168 -168
- package/nativesrc/jsql-neo-core/src/engine/mod.rs +62 -62
- package/nativesrc/jsql-neo-core/src/engine/table.rs +700 -700
- package/nativesrc/jsql-neo-core/src/lib.rs +2 -2
- package/nativesrc/jsql-neo-core/src/storage/mod.rs +2 -2
- package/nativesrc/jsql-neo-core/src/storage/persistent.rs +1 -1
- package/nativesrc/jsql-neo-core/src/storage/wal.rs +85 -85
- package/nativesrc/jsql-neo-core/src/types.rs +93 -93
- package/nativesrc/jsql-neo-native/Cargo.lock +606 -606
- package/nativesrc/jsql-neo-native/Cargo.toml +16 -16
- package/nativesrc/jsql-neo-native/build.rs +3 -3
- package/nativesrc/jsql-neo-native/package.json +7 -7
- package/nativesrc/jsql-neo-native/src/lib.rs +269 -269
- package/nativesrc/jsql-neo-wasm/Cargo.lock +465 -465
- package/nativesrc/jsql-neo-wasm/Cargo.toml +15 -15
- package/nativesrc/jsql-neo-wasm/src/lib.rs +447 -447
- package/package.json +87 -86
- package/postinstall.js +158 -158
- package/test/btree.test.js +128 -128
- package/test/coverage.js +187 -187
- package/test/join.test.js +110 -110
- package/test/native.test.js +158 -158
- package/test/regress-5.1.0.js +271 -271
- package/test/smoke.js +58 -58
- package/test/sql-parser.test.js +273 -0
- package/test/wasm.test.js +110 -110
- package/wasm/browser.d.ts +89 -89
- package/wasm/browser.mjs +569 -569
- package/wasm/browser_bg.mjs +597 -597
- package/wasm/jsql_neo_wasm.d.ts +38 -38
- package/wasm/jsql_neo_wasm.js +520 -520
- package/wasm/jsql_neo_wasm_bg.wasm.d.ts +26 -26
- package/wasm/package.json +11 -11
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
[package]
|
|
2
|
-
name = "jsql-neo-native"
|
|
3
|
-
version = "5.
|
|
4
|
-
edition = "2021"
|
|
5
|
-
|
|
6
|
-
[lib]
|
|
7
|
-
crate-type = ["cdylib"]
|
|
8
|
-
|
|
9
|
-
[dependencies]
|
|
10
|
-
jsql-neo-core = { path = "../jsql-neo-core" }
|
|
11
|
-
napi = { version = "2", features = ["napi6"] }
|
|
12
|
-
napi-derive = "2"
|
|
13
|
-
serde_json = "1"
|
|
14
|
-
|
|
15
|
-
[build-dependencies]
|
|
16
|
-
napi-build = "2"
|
|
1
|
+
[package]
|
|
2
|
+
name = "jsql-neo-native"
|
|
3
|
+
version = "5.5.0"
|
|
4
|
+
edition = "2021"
|
|
5
|
+
|
|
6
|
+
[lib]
|
|
7
|
+
crate-type = ["cdylib"]
|
|
8
|
+
|
|
9
|
+
[dependencies]
|
|
10
|
+
jsql-neo-core = { path = "../jsql-neo-core" }
|
|
11
|
+
napi = { version = "2", features = ["napi6"] }
|
|
12
|
+
napi-derive = "2"
|
|
13
|
+
serde_json = "1"
|
|
14
|
+
|
|
15
|
+
[build-dependencies]
|
|
16
|
+
napi-build = "2"
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
fn main() {
|
|
2
|
-
napi_build::setup();
|
|
3
|
-
}
|
|
1
|
+
fn main() {
|
|
2
|
+
napi_build::setup();
|
|
3
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "jsql-neo-native",
|
|
3
|
-
"version": "0.1.0",
|
|
4
|
-
"napi": {
|
|
5
|
-
"binaryName": "jsql-neo-native"
|
|
6
|
-
}
|
|
7
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "jsql-neo-native",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"napi": {
|
|
5
|
+
"binaryName": "jsql-neo-native"
|
|
6
|
+
}
|
|
7
|
+
}
|
|
@@ -1,269 +1,269 @@
|
|
|
1
|
-
use std::cell::RefCell;
|
|
2
|
-
use std::collections::HashMap;
|
|
3
|
-
use jsql_neo_core::engine::{Engine, HybridEngine, FieldValue, RowStore};
|
|
4
|
-
use jsql_neo_core::types::{FieldSchema, TableDefinition, schema_order_preserving};
|
|
5
|
-
use napi_derive::napi;
|
|
6
|
-
use napi::JsBuffer;
|
|
7
|
-
|
|
8
|
-
thread_local! {
|
|
9
|
-
static ENGINE: RefCell<HybridEngine> = RefCell::new(HybridEngine::new());
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
fn with_engine_mut<F>(f: F) -> String
|
|
13
|
-
where
|
|
14
|
-
F: FnOnce(&mut HybridEngine) -> String,
|
|
15
|
-
{
|
|
16
|
-
ENGINE.with(|cell| match cell.try_borrow_mut() {
|
|
17
|
-
Ok(mut eng) => f(&mut eng),
|
|
18
|
-
Err(_) => r#"{"ok":false,"error":"engine busy (reentrant call)"}"#.to_string(),
|
|
19
|
-
})
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
fn with_engine_ro<F>(f: F) -> String
|
|
23
|
-
where
|
|
24
|
-
F: FnOnce(&HybridEngine) -> String,
|
|
25
|
-
{
|
|
26
|
-
ENGINE.with(|cell| match cell.try_borrow() {
|
|
27
|
-
Ok(eng) => f(&eng),
|
|
28
|
-
Err(_) => r#"{"ok":false,"error":"engine busy (reentrant call)"}"#.to_string(),
|
|
29
|
-
})
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
fn safe_json_result(result: Result<String, String>) -> String {
|
|
33
|
-
match result {
|
|
34
|
-
Ok(s) => s,
|
|
35
|
-
Err(e) => format!(r#"{{"error":"{}"}}"#, e.replace('"', r#"\""#)),
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
#[napi]
|
|
40
|
-
pub fn jsql_open(dir: String, mode: String) -> String {
|
|
41
|
-
with_engine_mut(|eng| {
|
|
42
|
-
let open_res = eng.open(&dir, &mode);
|
|
43
|
-
match open_res {
|
|
44
|
-
Ok(()) => {
|
|
45
|
-
let names = eng.list_tables();
|
|
46
|
-
let mut out = serde_json::Map::new();
|
|
47
|
-
out.insert("ok".into(), serde_json::Value::Bool(true));
|
|
48
|
-
out.insert("tables".into(), serde_json::Value::Array(
|
|
49
|
-
names.iter().map(|n| serde_json::Value::String(n.clone())).collect()
|
|
50
|
-
));
|
|
51
|
-
let mut schemas = serde_json::Map::new();
|
|
52
|
-
for n in &names {
|
|
53
|
-
if let Some(s) = eng.table_schema(n) {
|
|
54
|
-
let mut v = serde_json::Map::new();
|
|
55
|
-
for (k, fs) in &s {
|
|
56
|
-
if let Ok(fv) = serde_json::to_value(fs) {
|
|
57
|
-
v.insert(k.clone(), fv);
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
schemas.insert(n.clone(), serde_json::Value::Object(v));
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
out.insert("schemas".into(), serde_json::Value::Object(schemas));
|
|
64
|
-
serde_json::to_string(&out).unwrap_or_else(|_| r#"{"ok":true}"#.to_string())
|
|
65
|
-
}
|
|
66
|
-
Err(e) => format!(r#"{{"ok":false,"error":"{}"}}"#, e.replace('"', r#"\""#)),
|
|
67
|
-
}
|
|
68
|
-
})
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
#[napi]
|
|
72
|
-
pub fn jsql_flush_dirty() -> String {
|
|
73
|
-
with_engine_mut(|eng| {
|
|
74
|
-
match eng.flush_dirty() {
|
|
75
|
-
Ok(n) => format!(r#"{{"ok":true,"flushed":{}}}"#, n),
|
|
76
|
-
Err(e) => format!(r#"{{"ok":false,"error":"{}"}}"#, e.replace('"', r#"\""#)),
|
|
77
|
-
}
|
|
78
|
-
})
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
#[napi]
|
|
82
|
-
pub fn jsql_evict() -> String {
|
|
83
|
-
with_engine_mut(|eng| {
|
|
84
|
-
match eng.evict_one() {
|
|
85
|
-
Some(name) => format!(r#"{{"ok":true,"evicted":"{}","remaining":{}}}"#, name, eng.mem_count()),
|
|
86
|
-
None => r#"{"ok":true,"evicted":null,"remaining":0}"#.to_string(),
|
|
87
|
-
}
|
|
88
|
-
})
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
#[napi]
|
|
92
|
-
pub fn jsql_close() -> String {
|
|
93
|
-
with_engine_mut(|eng| {
|
|
94
|
-
eng.close();
|
|
95
|
-
r#"{"ok":true}"#.to_string()
|
|
96
|
-
})
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
#[napi]
|
|
100
|
-
pub fn jsql_create_table(name: String, schema_json: String) -> String {
|
|
101
|
-
use schema_order_preserving;
|
|
102
|
-
let mut d = serde_json::Deserializer::from_str(&schema_json);
|
|
103
|
-
let schema: Vec<(String, FieldSchema)> = match schema_order_preserving::deserialize(&mut d) {
|
|
104
|
-
Ok(s) => s,
|
|
105
|
-
Err(e) => return format!(r#"{{"ok":false,"error":"invalid schema: {}"}}"#, e),
|
|
106
|
-
};
|
|
107
|
-
let def = TableDefinition { name: name.clone(), schema };
|
|
108
|
-
with_engine_mut(|eng| match eng.create_table(def) {
|
|
109
|
-
Ok(()) => r#"{"ok":true}"#.to_string(),
|
|
110
|
-
Err(e) => format!(r#"{{"ok":false,"error":"{}"}}"#, e),
|
|
111
|
-
})
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
#[napi]
|
|
115
|
-
pub fn jsql_drop_table(name: String) -> String {
|
|
116
|
-
with_engine_mut(|eng| match eng.drop_table(&name) {
|
|
117
|
-
Ok(()) => r#"{"ok":true}"#.to_string(),
|
|
118
|
-
Err(e) => format!(r#"{{"ok":false,"error":"{}"}}"#, e),
|
|
119
|
-
})
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
#[napi]
|
|
123
|
-
pub fn jsql_insert(table: String, data_json: String) -> String {
|
|
124
|
-
with_engine_mut(|eng| {
|
|
125
|
-
let data: Vec<HashMap<String, serde_json::Value>> = match serde_json::from_str(&data_json) {
|
|
126
|
-
Ok(d) => d,
|
|
127
|
-
Err(e) => return format!(r#"{{"error":"invalid data: {}"}}"#, e),
|
|
128
|
-
};
|
|
129
|
-
match eng.insert(&table, data) {
|
|
130
|
-
Ok(ids) => serde_json::to_string(&ids).unwrap_or_else(|_| "[]".to_string()),
|
|
131
|
-
Err(e) => format!(r#"{{"error":"{}"}}"#, e),
|
|
132
|
-
}
|
|
133
|
-
})
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
#[napi]
|
|
137
|
-
pub fn jsql_insert_buf(table: String, data: JsBuffer) -> String {
|
|
138
|
-
let buf_val = match data.into_value() {
|
|
139
|
-
Ok(v) => v,
|
|
140
|
-
Err(_) => return r#"{"error":"invalid buffer"}"#.to_string(),
|
|
141
|
-
};
|
|
142
|
-
with_engine_mut(|eng| {
|
|
143
|
-
let buf: &[u8] = buf_val.as_ref();
|
|
144
|
-
let res = eng.insert_buf(&table, buf)
|
|
145
|
-
.map(|ids| serde_json::to_string(&ids).unwrap_or_else(|_| "[]".to_string()));
|
|
146
|
-
safe_json_result(res.map_err(|e| e))
|
|
147
|
-
})
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
#[napi]
|
|
151
|
-
pub fn jsql_find(table: String, filter_json: String, limit: i32, offset: i32) -> String {
|
|
152
|
-
with_engine_ro(|eng| {
|
|
153
|
-
let filter: Option<HashMap<String, serde_json::Value>> =
|
|
154
|
-
if filter_json.is_empty() { None } else { serde_json::from_str(&filter_json).ok() };
|
|
155
|
-
match eng.find(&table, &filter, Some(limit as usize), Some(offset as usize), None, &None, &None) {
|
|
156
|
-
Ok((rows, _, _)) => serde_json::to_string(&rows).unwrap_or_else(|_| "[]".to_string()),
|
|
157
|
-
Err(e) => format!(r#"{{"error":"{}"}}"#, e),
|
|
158
|
-
}
|
|
159
|
-
})
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
#[napi]
|
|
163
|
-
pub fn jsql_find_by_id(table: String, id: i64) -> String {
|
|
164
|
-
with_engine_ro(|eng| {
|
|
165
|
-
match eng.find_by_id_json(&table, id as u64) {
|
|
166
|
-
Ok(Some(s)) => s,
|
|
167
|
-
Ok(None) => "null".to_string(),
|
|
168
|
-
Err(e) => format!(r#"{{"error":"{}"}}"#, e),
|
|
169
|
-
}
|
|
170
|
-
})
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
#[napi]
|
|
174
|
-
pub fn jsql_count(table: String) -> String {
|
|
175
|
-
with_engine_ro(|eng| match eng.count(&table) {
|
|
176
|
-
Ok(c) => format!("{}", c),
|
|
177
|
-
Err(e) => format!(r#"{{"error":"{}"}}"#, e),
|
|
178
|
-
})
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
#[napi]
|
|
182
|
-
pub fn jsql_update_by_id(table: String, id: i64, data_json: String) -> String {
|
|
183
|
-
with_engine_mut(|eng| {
|
|
184
|
-
let data: HashMap<String, serde_json::Value> = match serde_json::from_str(&data_json) {
|
|
185
|
-
Ok(d) => d,
|
|
186
|
-
Err(e) => return format!(r#"{{"ok":false,"error":"invalid data: {}"}}"#, e),
|
|
187
|
-
};
|
|
188
|
-
match eng.update_by_id(&table, id as u64, data) {
|
|
189
|
-
Ok(true) => r#"{"ok":true}"#.to_string(),
|
|
190
|
-
Ok(false) => r#"{"ok":false,"error":"not found"}"#.to_string(),
|
|
191
|
-
Err(e) => format!(r#"{{"ok":false,"error":"{}"}}"#, e),
|
|
192
|
-
}
|
|
193
|
-
})
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
#[napi]
|
|
197
|
-
pub fn jsql_remove_by_id(table: String, id: i64) -> String {
|
|
198
|
-
with_engine_mut(|eng| match eng.remove_by_id(&table, id as u64) {
|
|
199
|
-
Ok(true) => r#"{"ok":true}"#.to_string(),
|
|
200
|
-
Ok(false) => r#"{"ok":false,"error":"not found"}"#.to_string(),
|
|
201
|
-
Err(e) => format!(r#"{{"ok":false,"error":"{}"}}"#, e),
|
|
202
|
-
})
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
#[napi]
|
|
206
|
-
pub fn jsql_remove_by_ids(table: String, ids_json: String) -> String {
|
|
207
|
-
with_engine_mut(|eng| {
|
|
208
|
-
let ids: Vec<u64> = match serde_json::from_str(&ids_json) {
|
|
209
|
-
Ok(v) => v,
|
|
210
|
-
Err(e) => return format!(r#"{{"error":"invalid ids: {}"}}"#, e),
|
|
211
|
-
};
|
|
212
|
-
match eng.remove_by_ids(&table, &ids) {
|
|
213
|
-
Ok(n) => format!(r#"{{"ok":true,"count":{}}}"#, n),
|
|
214
|
-
Err(e) => format!(r#"{{"ok":false,"error":"{}"}}"#, e),
|
|
215
|
-
}
|
|
216
|
-
})
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
#[napi]
|
|
220
|
-
pub fn jsql_update_by_ids(table: String, batch_json: String) -> String {
|
|
221
|
-
with_engine_mut(|eng| {
|
|
222
|
-
let batch: Vec<(u64, HashMap<String, serde_json::Value>)> = match serde_json::from_str(&batch_json) {
|
|
223
|
-
Ok(v) => v,
|
|
224
|
-
Err(e) => return format!(r#"{{"error":"invalid batch: {}"}}"#, e),
|
|
225
|
-
};
|
|
226
|
-
match eng.update_by_ids(&table, batch) {
|
|
227
|
-
Ok(n) => format!(r#"{{"ok":true,"count":{}}}"#, n),
|
|
228
|
-
Err(e) => format!(r#"{{"ok":false,"error":"{}"}}"#, e),
|
|
229
|
-
}
|
|
230
|
-
})
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
#[napi]
|
|
234
|
-
pub fn jsql_find_by_ids(table: String, ids_json: String) -> String {
|
|
235
|
-
with_engine_ro(|eng| {
|
|
236
|
-
let ids: Vec<u64> = match serde_json::from_str(&ids_json) {
|
|
237
|
-
Ok(v) => v,
|
|
238
|
-
Err(e) => return format!(r#"{{"error":"invalid ids: {}"}}"#, e),
|
|
239
|
-
};
|
|
240
|
-
match eng.find_by_ids_json(&table, &ids) {
|
|
241
|
-
Ok(s) => s,
|
|
242
|
-
Err(e) => format!(r#"{{"error":"{}"}}"#, e),
|
|
243
|
-
}
|
|
244
|
-
})
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
#[napi]
|
|
248
|
-
pub fn jsql_begin_tx() -> String {
|
|
249
|
-
with_engine_mut(|eng| match eng.begin_tx() {
|
|
250
|
-
Ok(tx_id) => serde_json::json!({ "ok": true, "txId": tx_id }).to_string(),
|
|
251
|
-
Err(e) => format!(r#"{{"ok":false,"error":"{}"}}"#, e),
|
|
252
|
-
})
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
#[napi]
|
|
256
|
-
pub fn jsql_commit_tx(tx_id: String) -> String {
|
|
257
|
-
with_engine_mut(|eng| match eng.commit_tx(&tx_id) {
|
|
258
|
-
Ok(()) => r#"{"ok":true}"#.to_string(),
|
|
259
|
-
Err(e) => format!(r#"{{"ok":false,"error":"{}"}}"#, e),
|
|
260
|
-
})
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
#[napi]
|
|
264
|
-
pub fn jsql_rollback_tx(tx_id: String) -> String {
|
|
265
|
-
with_engine_mut(|eng| match eng.rollback_tx(&tx_id) {
|
|
266
|
-
Ok(()) => r#"{"ok":true}"#.to_string(),
|
|
267
|
-
Err(e) => format!(r#"{{"ok":false,"error":"{}"}}"#, e),
|
|
268
|
-
})
|
|
269
|
-
}
|
|
1
|
+
use std::cell::RefCell;
|
|
2
|
+
use std::collections::HashMap;
|
|
3
|
+
use jsql_neo_core::engine::{Engine, HybridEngine, FieldValue, RowStore};
|
|
4
|
+
use jsql_neo_core::types::{FieldSchema, TableDefinition, schema_order_preserving};
|
|
5
|
+
use napi_derive::napi;
|
|
6
|
+
use napi::JsBuffer;
|
|
7
|
+
|
|
8
|
+
thread_local! {
|
|
9
|
+
static ENGINE: RefCell<HybridEngine> = RefCell::new(HybridEngine::new());
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
fn with_engine_mut<F>(f: F) -> String
|
|
13
|
+
where
|
|
14
|
+
F: FnOnce(&mut HybridEngine) -> String,
|
|
15
|
+
{
|
|
16
|
+
ENGINE.with(|cell| match cell.try_borrow_mut() {
|
|
17
|
+
Ok(mut eng) => f(&mut eng),
|
|
18
|
+
Err(_) => r#"{"ok":false,"error":"engine busy (reentrant call)"}"#.to_string(),
|
|
19
|
+
})
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
fn with_engine_ro<F>(f: F) -> String
|
|
23
|
+
where
|
|
24
|
+
F: FnOnce(&HybridEngine) -> String,
|
|
25
|
+
{
|
|
26
|
+
ENGINE.with(|cell| match cell.try_borrow() {
|
|
27
|
+
Ok(eng) => f(&eng),
|
|
28
|
+
Err(_) => r#"{"ok":false,"error":"engine busy (reentrant call)"}"#.to_string(),
|
|
29
|
+
})
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
fn safe_json_result(result: Result<String, String>) -> String {
|
|
33
|
+
match result {
|
|
34
|
+
Ok(s) => s,
|
|
35
|
+
Err(e) => format!(r#"{{"error":"{}"}}"#, e.replace('"', r#"\""#)),
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
#[napi]
|
|
40
|
+
pub fn jsql_open(dir: String, mode: String) -> String {
|
|
41
|
+
with_engine_mut(|eng| {
|
|
42
|
+
let open_res = eng.open(&dir, &mode);
|
|
43
|
+
match open_res {
|
|
44
|
+
Ok(()) => {
|
|
45
|
+
let names = eng.list_tables();
|
|
46
|
+
let mut out = serde_json::Map::new();
|
|
47
|
+
out.insert("ok".into(), serde_json::Value::Bool(true));
|
|
48
|
+
out.insert("tables".into(), serde_json::Value::Array(
|
|
49
|
+
names.iter().map(|n| serde_json::Value::String(n.clone())).collect()
|
|
50
|
+
));
|
|
51
|
+
let mut schemas = serde_json::Map::new();
|
|
52
|
+
for n in &names {
|
|
53
|
+
if let Some(s) = eng.table_schema(n) {
|
|
54
|
+
let mut v = serde_json::Map::new();
|
|
55
|
+
for (k, fs) in &s {
|
|
56
|
+
if let Ok(fv) = serde_json::to_value(fs) {
|
|
57
|
+
v.insert(k.clone(), fv);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
schemas.insert(n.clone(), serde_json::Value::Object(v));
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
out.insert("schemas".into(), serde_json::Value::Object(schemas));
|
|
64
|
+
serde_json::to_string(&out).unwrap_or_else(|_| r#"{"ok":true}"#.to_string())
|
|
65
|
+
}
|
|
66
|
+
Err(e) => format!(r#"{{"ok":false,"error":"{}"}}"#, e.replace('"', r#"\""#)),
|
|
67
|
+
}
|
|
68
|
+
})
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
#[napi]
|
|
72
|
+
pub fn jsql_flush_dirty() -> String {
|
|
73
|
+
with_engine_mut(|eng| {
|
|
74
|
+
match eng.flush_dirty() {
|
|
75
|
+
Ok(n) => format!(r#"{{"ok":true,"flushed":{}}}"#, n),
|
|
76
|
+
Err(e) => format!(r#"{{"ok":false,"error":"{}"}}"#, e.replace('"', r#"\""#)),
|
|
77
|
+
}
|
|
78
|
+
})
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
#[napi]
|
|
82
|
+
pub fn jsql_evict() -> String {
|
|
83
|
+
with_engine_mut(|eng| {
|
|
84
|
+
match eng.evict_one() {
|
|
85
|
+
Some(name) => format!(r#"{{"ok":true,"evicted":"{}","remaining":{}}}"#, name, eng.mem_count()),
|
|
86
|
+
None => r#"{"ok":true,"evicted":null,"remaining":0}"#.to_string(),
|
|
87
|
+
}
|
|
88
|
+
})
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
#[napi]
|
|
92
|
+
pub fn jsql_close() -> String {
|
|
93
|
+
with_engine_mut(|eng| {
|
|
94
|
+
eng.close();
|
|
95
|
+
r#"{"ok":true}"#.to_string()
|
|
96
|
+
})
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
#[napi]
|
|
100
|
+
pub fn jsql_create_table(name: String, schema_json: String) -> String {
|
|
101
|
+
use schema_order_preserving;
|
|
102
|
+
let mut d = serde_json::Deserializer::from_str(&schema_json);
|
|
103
|
+
let schema: Vec<(String, FieldSchema)> = match schema_order_preserving::deserialize(&mut d) {
|
|
104
|
+
Ok(s) => s,
|
|
105
|
+
Err(e) => return format!(r#"{{"ok":false,"error":"invalid schema: {}"}}"#, e),
|
|
106
|
+
};
|
|
107
|
+
let def = TableDefinition { name: name.clone(), schema };
|
|
108
|
+
with_engine_mut(|eng| match eng.create_table(def) {
|
|
109
|
+
Ok(()) => r#"{"ok":true}"#.to_string(),
|
|
110
|
+
Err(e) => format!(r#"{{"ok":false,"error":"{}"}}"#, e),
|
|
111
|
+
})
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
#[napi]
|
|
115
|
+
pub fn jsql_drop_table(name: String) -> String {
|
|
116
|
+
with_engine_mut(|eng| match eng.drop_table(&name) {
|
|
117
|
+
Ok(()) => r#"{"ok":true}"#.to_string(),
|
|
118
|
+
Err(e) => format!(r#"{{"ok":false,"error":"{}"}}"#, e),
|
|
119
|
+
})
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
#[napi]
|
|
123
|
+
pub fn jsql_insert(table: String, data_json: String) -> String {
|
|
124
|
+
with_engine_mut(|eng| {
|
|
125
|
+
let data: Vec<HashMap<String, serde_json::Value>> = match serde_json::from_str(&data_json) {
|
|
126
|
+
Ok(d) => d,
|
|
127
|
+
Err(e) => return format!(r#"{{"error":"invalid data: {}"}}"#, e),
|
|
128
|
+
};
|
|
129
|
+
match eng.insert(&table, data) {
|
|
130
|
+
Ok(ids) => serde_json::to_string(&ids).unwrap_or_else(|_| "[]".to_string()),
|
|
131
|
+
Err(e) => format!(r#"{{"error":"{}"}}"#, e),
|
|
132
|
+
}
|
|
133
|
+
})
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
#[napi]
|
|
137
|
+
pub fn jsql_insert_buf(table: String, data: JsBuffer) -> String {
|
|
138
|
+
let buf_val = match data.into_value() {
|
|
139
|
+
Ok(v) => v,
|
|
140
|
+
Err(_) => return r#"{"error":"invalid buffer"}"#.to_string(),
|
|
141
|
+
};
|
|
142
|
+
with_engine_mut(|eng| {
|
|
143
|
+
let buf: &[u8] = buf_val.as_ref();
|
|
144
|
+
let res = eng.insert_buf(&table, buf)
|
|
145
|
+
.map(|ids| serde_json::to_string(&ids).unwrap_or_else(|_| "[]".to_string()));
|
|
146
|
+
safe_json_result(res.map_err(|e| e))
|
|
147
|
+
})
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
#[napi]
|
|
151
|
+
pub fn jsql_find(table: String, filter_json: String, limit: i32, offset: i32) -> String {
|
|
152
|
+
with_engine_ro(|eng| {
|
|
153
|
+
let filter: Option<HashMap<String, serde_json::Value>> =
|
|
154
|
+
if filter_json.is_empty() { None } else { serde_json::from_str(&filter_json).ok() };
|
|
155
|
+
match eng.find(&table, &filter, Some(limit as usize), Some(offset as usize), None, &None, &None) {
|
|
156
|
+
Ok((rows, _, _)) => serde_json::to_string(&rows).unwrap_or_else(|_| "[]".to_string()),
|
|
157
|
+
Err(e) => format!(r#"{{"error":"{}"}}"#, e),
|
|
158
|
+
}
|
|
159
|
+
})
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
#[napi]
|
|
163
|
+
pub fn jsql_find_by_id(table: String, id: i64) -> String {
|
|
164
|
+
with_engine_ro(|eng| {
|
|
165
|
+
match eng.find_by_id_json(&table, id as u64) {
|
|
166
|
+
Ok(Some(s)) => s,
|
|
167
|
+
Ok(None) => "null".to_string(),
|
|
168
|
+
Err(e) => format!(r#"{{"error":"{}"}}"#, e),
|
|
169
|
+
}
|
|
170
|
+
})
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
#[napi]
|
|
174
|
+
pub fn jsql_count(table: String) -> String {
|
|
175
|
+
with_engine_ro(|eng| match eng.count(&table) {
|
|
176
|
+
Ok(c) => format!("{}", c),
|
|
177
|
+
Err(e) => format!(r#"{{"error":"{}"}}"#, e),
|
|
178
|
+
})
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
#[napi]
|
|
182
|
+
pub fn jsql_update_by_id(table: String, id: i64, data_json: String) -> String {
|
|
183
|
+
with_engine_mut(|eng| {
|
|
184
|
+
let data: HashMap<String, serde_json::Value> = match serde_json::from_str(&data_json) {
|
|
185
|
+
Ok(d) => d,
|
|
186
|
+
Err(e) => return format!(r#"{{"ok":false,"error":"invalid data: {}"}}"#, e),
|
|
187
|
+
};
|
|
188
|
+
match eng.update_by_id(&table, id as u64, data) {
|
|
189
|
+
Ok(true) => r#"{"ok":true}"#.to_string(),
|
|
190
|
+
Ok(false) => r#"{"ok":false,"error":"not found"}"#.to_string(),
|
|
191
|
+
Err(e) => format!(r#"{{"ok":false,"error":"{}"}}"#, e),
|
|
192
|
+
}
|
|
193
|
+
})
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
#[napi]
|
|
197
|
+
pub fn jsql_remove_by_id(table: String, id: i64) -> String {
|
|
198
|
+
with_engine_mut(|eng| match eng.remove_by_id(&table, id as u64) {
|
|
199
|
+
Ok(true) => r#"{"ok":true}"#.to_string(),
|
|
200
|
+
Ok(false) => r#"{"ok":false,"error":"not found"}"#.to_string(),
|
|
201
|
+
Err(e) => format!(r#"{{"ok":false,"error":"{}"}}"#, e),
|
|
202
|
+
})
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
#[napi]
|
|
206
|
+
pub fn jsql_remove_by_ids(table: String, ids_json: String) -> String {
|
|
207
|
+
with_engine_mut(|eng| {
|
|
208
|
+
let ids: Vec<u64> = match serde_json::from_str(&ids_json) {
|
|
209
|
+
Ok(v) => v,
|
|
210
|
+
Err(e) => return format!(r#"{{"error":"invalid ids: {}"}}"#, e),
|
|
211
|
+
};
|
|
212
|
+
match eng.remove_by_ids(&table, &ids) {
|
|
213
|
+
Ok(n) => format!(r#"{{"ok":true,"count":{}}}"#, n),
|
|
214
|
+
Err(e) => format!(r#"{{"ok":false,"error":"{}"}}"#, e),
|
|
215
|
+
}
|
|
216
|
+
})
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
#[napi]
|
|
220
|
+
pub fn jsql_update_by_ids(table: String, batch_json: String) -> String {
|
|
221
|
+
with_engine_mut(|eng| {
|
|
222
|
+
let batch: Vec<(u64, HashMap<String, serde_json::Value>)> = match serde_json::from_str(&batch_json) {
|
|
223
|
+
Ok(v) => v,
|
|
224
|
+
Err(e) => return format!(r#"{{"error":"invalid batch: {}"}}"#, e),
|
|
225
|
+
};
|
|
226
|
+
match eng.update_by_ids(&table, batch) {
|
|
227
|
+
Ok(n) => format!(r#"{{"ok":true,"count":{}}}"#, n),
|
|
228
|
+
Err(e) => format!(r#"{{"ok":false,"error":"{}"}}"#, e),
|
|
229
|
+
}
|
|
230
|
+
})
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
#[napi]
|
|
234
|
+
pub fn jsql_find_by_ids(table: String, ids_json: String) -> String {
|
|
235
|
+
with_engine_ro(|eng| {
|
|
236
|
+
let ids: Vec<u64> = match serde_json::from_str(&ids_json) {
|
|
237
|
+
Ok(v) => v,
|
|
238
|
+
Err(e) => return format!(r#"{{"error":"invalid ids: {}"}}"#, e),
|
|
239
|
+
};
|
|
240
|
+
match eng.find_by_ids_json(&table, &ids) {
|
|
241
|
+
Ok(s) => s,
|
|
242
|
+
Err(e) => format!(r#"{{"error":"{}"}}"#, e),
|
|
243
|
+
}
|
|
244
|
+
})
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
#[napi]
|
|
248
|
+
pub fn jsql_begin_tx() -> String {
|
|
249
|
+
with_engine_mut(|eng| match eng.begin_tx() {
|
|
250
|
+
Ok(tx_id) => serde_json::json!({ "ok": true, "txId": tx_id }).to_string(),
|
|
251
|
+
Err(e) => format!(r#"{{"ok":false,"error":"{}"}}"#, e),
|
|
252
|
+
})
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
#[napi]
|
|
256
|
+
pub fn jsql_commit_tx(tx_id: String) -> String {
|
|
257
|
+
with_engine_mut(|eng| match eng.commit_tx(&tx_id) {
|
|
258
|
+
Ok(()) => r#"{"ok":true}"#.to_string(),
|
|
259
|
+
Err(e) => format!(r#"{{"ok":false,"error":"{}"}}"#, e),
|
|
260
|
+
})
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
#[napi]
|
|
264
|
+
pub fn jsql_rollback_tx(tx_id: String) -> String {
|
|
265
|
+
with_engine_mut(|eng| match eng.rollback_tx(&tx_id) {
|
|
266
|
+
Ok(()) => r#"{"ok":true}"#.to_string(),
|
|
267
|
+
Err(e) => format!(r#"{{"ok":false,"error":"{}"}}"#, e),
|
|
268
|
+
})
|
|
269
|
+
}
|