jsql-neo 4.0.2 → 4.1.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/bin/jsql +69 -0
- package/bin/jsql-server +90 -0
- package/bin/jsql-server-control.js +177 -0
- package/lib/database.js +98 -9
- package/lib/errors.js +6 -0
- package/lib/jsql_format.js +33 -14
- package/lib/mod.js +43 -67
- package/lib/mysql_compat.js +134 -17
- package/lib/mysql_server.js +315 -22
- package/lib/native_client.js +95 -32
- package/lib/sql.js +646 -122
- package/lib/table.js +114 -12
- package/lib/wasm_client.js +59 -6
- package/native/jsql-neo-native.node +0 -0
- package/nativesrc/jsql-neo-core/Cargo.lock +455 -0
- package/nativesrc/jsql-neo-core/src/engine/hybrid.rs +12 -6
- package/nativesrc/jsql-neo-core/src/engine/memory.rs +28 -7
- package/nativesrc/jsql-neo-core/src/engine/mod.rs +22 -1
- package/nativesrc/jsql-neo-core/src/engine/table.rs +53 -23
- package/nativesrc/jsql-neo-core/src/storage/mod.rs +2 -1
- package/nativesrc/jsql-neo-core/src/storage/wal.rs +1 -0
- package/nativesrc/jsql-neo-native/build.rs +3 -0
- package/nativesrc/jsql-neo-native/jsql-neo-native.node +0 -0
- package/nativesrc/jsql-neo-native/src/lib.rs +75 -87
- package/nativesrc/jsql-neo-wasm/Cargo.lock +465 -0
- package/nativesrc/jsql-neo-wasm/Cargo.toml +15 -0
- package/nativesrc/jsql-neo-wasm/src/lib.rs +423 -0
- package/package.json +8 -1
- package/wasm/jsql_neo_wasm.d.ts +2 -0
- package/wasm/jsql_neo_wasm.js +5 -0
- package/wasm/jsql_neo_wasm_bg.wasm +0 -0
- package/wasm/jsql_neo_wasm_bg.wasm.d.ts +1 -0
|
@@ -104,7 +104,7 @@ pub struct Table {
|
|
|
104
104
|
pub pk_index: FxHashMap<u64, usize>,
|
|
105
105
|
}
|
|
106
106
|
|
|
107
|
-
fn default_value(ft: &FieldType) -> FieldValue {
|
|
107
|
+
pub fn default_value(ft: &FieldType) -> FieldValue {
|
|
108
108
|
match ft {
|
|
109
109
|
FieldType::Integer => FieldValue::Int(0),
|
|
110
110
|
FieldType::Float => FieldValue::Float(0.0),
|
|
@@ -230,32 +230,49 @@ impl Table {
|
|
|
230
230
|
});
|
|
231
231
|
|
|
232
232
|
for mut fields in fields_batch {
|
|
233
|
-
let
|
|
233
|
+
let auto_id = self.next_id;
|
|
234
234
|
self.next_id += 1;
|
|
235
|
+
let mut id = auto_id;
|
|
235
236
|
|
|
236
237
|
if let Some(ref pk_key) = pk_auto_key {
|
|
237
238
|
match fields.get(pk_key) {
|
|
238
|
-
Some(v) if v.is_null()
|
|
239
|
-
fields.insert(pk_key.clone(), serde_json::Value::Number(
|
|
239
|
+
Some(v) if v.is_null() => {
|
|
240
|
+
fields.insert(pk_key.clone(), serde_json::Value::Number(auto_id.into()));
|
|
240
241
|
}
|
|
241
242
|
Some(v) => {
|
|
242
243
|
if let Some(n) = v.as_i64() {
|
|
243
|
-
if n > 0 {
|
|
244
|
+
if n > 0 {
|
|
245
|
+
id = n as u64;
|
|
246
|
+
self.next_id = self.next_id.max(id + 1);
|
|
247
|
+
}
|
|
244
248
|
}
|
|
245
249
|
}
|
|
246
250
|
None => {
|
|
247
|
-
fields.insert(pk_key.clone(), serde_json::Value::Number(
|
|
251
|
+
fields.insert(pk_key.clone(), serde_json::Value::Number(auto_id.into()));
|
|
248
252
|
}
|
|
249
253
|
}
|
|
250
254
|
}
|
|
251
255
|
|
|
252
256
|
let values_start = self.values.len();
|
|
253
257
|
if fields.len() < self.schema.len() {
|
|
254
|
-
for
|
|
258
|
+
for name in &self.field_order {
|
|
255
259
|
if let Some(v) = fields.remove(name) {
|
|
256
260
|
self.values.push(FieldValue::from_json(v));
|
|
257
|
-
|
|
258
|
-
|
|
261
|
+
continue;
|
|
262
|
+
}
|
|
263
|
+
match self.schema.get(name).and_then(|fs| fs.default.clone()) {
|
|
264
|
+
Some(dv) => self.values.push(FieldValue::from_json(dv)),
|
|
265
|
+
None => {
|
|
266
|
+
if let Some(fs) = self.schema.get(name) {
|
|
267
|
+
if !fs.nullable {
|
|
268
|
+
self.values.push(default_value(&fs.field_type));
|
|
269
|
+
} else {
|
|
270
|
+
self.values.push(FieldValue::Null);
|
|
271
|
+
}
|
|
272
|
+
} else {
|
|
273
|
+
self.values.push(FieldValue::Null);
|
|
274
|
+
}
|
|
275
|
+
}
|
|
259
276
|
}
|
|
260
277
|
}
|
|
261
278
|
} else {
|
|
@@ -299,17 +316,19 @@ impl Table {
|
|
|
299
316
|
{
|
|
300
317
|
let pk_idx = pk_auto_key.as_ref().and_then(|pk| self.field_index.get(pk.as_str()).copied());
|
|
301
318
|
for mut row_vals in batch {
|
|
302
|
-
let
|
|
319
|
+
let auto_id = self.next_id;
|
|
303
320
|
self.next_id += 1;
|
|
321
|
+
let mut id = auto_id;
|
|
304
322
|
if row_vals.len() < self.field_order.len() {
|
|
305
323
|
row_vals.resize(self.field_order.len(), FieldValue::Null);
|
|
306
324
|
}
|
|
307
325
|
if let Some(pi) = pk_idx {
|
|
308
326
|
if pi < row_vals.len() {
|
|
309
327
|
match row_vals[pi] {
|
|
310
|
-
FieldValue::Null
|
|
328
|
+
FieldValue::Null => row_vals[pi] = FieldValue::Int(auto_id as i64),
|
|
311
329
|
FieldValue::Int(e) if e > 0 => {
|
|
312
|
-
|
|
330
|
+
id = e as u64;
|
|
331
|
+
self.next_id = self.next_id.max(id + 1);
|
|
313
332
|
}
|
|
314
333
|
_ => {}
|
|
315
334
|
}
|
|
@@ -331,26 +350,25 @@ impl Table {
|
|
|
331
350
|
.collect();
|
|
332
351
|
let explicit_pk_si = pk_auto_key.as_ref()
|
|
333
352
|
.and_then(|pk| field_names.iter().position(|n| n == pk));
|
|
353
|
+
let pk_idx = pk_auto_key.as_ref().and_then(|pk| self.field_index.get(pk.as_str()).copied());
|
|
334
354
|
|
|
335
355
|
for mut row_vals in batch {
|
|
336
|
-
let
|
|
356
|
+
let auto_id = self.next_id;
|
|
337
357
|
self.next_id += 1;
|
|
358
|
+
let mut id = auto_id;
|
|
338
359
|
if let Some(si) = explicit_pk_si {
|
|
339
360
|
if let Some(FieldValue::Int(e)) = row_vals.get(si) {
|
|
340
|
-
if *e > 0 {
|
|
361
|
+
if *e > 0 {
|
|
362
|
+
id = *e as u64;
|
|
363
|
+
self.next_id = self.next_id.max(id + 1);
|
|
364
|
+
}
|
|
341
365
|
}
|
|
342
366
|
}
|
|
343
367
|
let values_start = self.values.len();
|
|
344
368
|
for (i, remapped_si) in remap.iter().enumerate() {
|
|
345
369
|
if let Some(si) = *remapped_si {
|
|
346
370
|
if si < row_vals.len() {
|
|
347
|
-
|
|
348
|
-
let is_auto_pk = pk_auto_key.is_some() && self.field_order[i] == *pk_auto_key.as_ref().unwrap();
|
|
349
|
-
if is_auto_pk && matches!(v, FieldValue::Null | FieldValue::Int(0)) {
|
|
350
|
-
self.values.push(FieldValue::Int(id as i64));
|
|
351
|
-
} else {
|
|
352
|
-
self.values.push(v);
|
|
353
|
-
}
|
|
371
|
+
self.values.push(std::mem::take(&mut row_vals[si]));
|
|
354
372
|
continue;
|
|
355
373
|
}
|
|
356
374
|
}
|
|
@@ -374,6 +392,14 @@ impl Table {
|
|
|
374
392
|
}
|
|
375
393
|
}
|
|
376
394
|
}
|
|
395
|
+
// 显式传入 null 的主键:回填自动 id,保证 pk 值与行 id 一致
|
|
396
|
+
if let Some(pi) = pk_idx {
|
|
397
|
+
if let Some(v) = self.values.get_mut(values_start + pi) {
|
|
398
|
+
if *v == FieldValue::Null {
|
|
399
|
+
*v = FieldValue::Int(id as i64);
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
}
|
|
377
403
|
let idx = self.rows.len();
|
|
378
404
|
self.pk_index.insert(id, idx);
|
|
379
405
|
self.rows.push(RowStore { id, values_start, num_values: self.field_order.len(), created_at: now, updated_at: now });
|
|
@@ -433,7 +459,7 @@ impl Table {
|
|
|
433
459
|
|
|
434
460
|
fn to_row_json_string(&self, rs: &RowStore) -> String {
|
|
435
461
|
let vals = self.get_row_values(rs);
|
|
436
|
-
let mut out = String::with_capacity(
|
|
462
|
+
let mut out = String::with_capacity(160);
|
|
437
463
|
out.push_str(r#"{"id":"#);
|
|
438
464
|
out.push_str(itoa::Buffer::new().format(rs.id));
|
|
439
465
|
out.push_str(r#","fields":{"#);
|
|
@@ -447,7 +473,11 @@ impl Table {
|
|
|
447
473
|
out.push_str("null");
|
|
448
474
|
}
|
|
449
475
|
}
|
|
450
|
-
out.push_str("}
|
|
476
|
+
out.push_str(r#"},"created_at":"#);
|
|
477
|
+
write_json_string(&mut out, &millis_to_string(rs.created_at));
|
|
478
|
+
out.push_str(r#","updated_at":"#);
|
|
479
|
+
write_json_string(&mut out, &millis_to_string(rs.updated_at));
|
|
480
|
+
out.push_str("}");
|
|
451
481
|
out
|
|
452
482
|
}
|
|
453
483
|
|
|
@@ -1 +1,2 @@
|
|
|
1
|
-
pub mod persistent;
|
|
1
|
+
pub mod persistent;
|
|
2
|
+
pub mod wal;
|
|
Binary file
|
|
@@ -9,6 +9,26 @@ thread_local! {
|
|
|
9
9
|
static ENGINE: RefCell<HybridEngine> = RefCell::new(HybridEngine::new());
|
|
10
10
|
}
|
|
11
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
|
+
|
|
12
32
|
fn safe_json_result(result: Result<String, String>) -> String {
|
|
13
33
|
match result {
|
|
14
34
|
Ok(s) => s,
|
|
@@ -18,11 +38,11 @@ fn safe_json_result(result: Result<String, String>) -> String {
|
|
|
18
38
|
|
|
19
39
|
#[napi]
|
|
20
40
|
pub fn jsql_open(dir: String, mode: String) -> String {
|
|
21
|
-
|
|
22
|
-
let open_res = eng.
|
|
41
|
+
with_engine_mut(|eng| {
|
|
42
|
+
let open_res = eng.open(&dir, &mode);
|
|
23
43
|
match open_res {
|
|
24
44
|
Ok(()) => {
|
|
25
|
-
let names = eng.
|
|
45
|
+
let names = eng.list_tables();
|
|
26
46
|
let mut out = serde_json::Map::new();
|
|
27
47
|
out.insert("ok".into(), serde_json::Value::Bool(true));
|
|
28
48
|
out.insert("tables".into(), serde_json::Value::Array(
|
|
@@ -30,11 +50,7 @@ pub fn jsql_open(dir: String, mode: String) -> String {
|
|
|
30
50
|
));
|
|
31
51
|
let mut schemas = serde_json::Map::new();
|
|
32
52
|
for n in &names {
|
|
33
|
-
let s = {
|
|
34
|
-
let eng_ref = eng.borrow();
|
|
35
|
-
eng_ref.table_schema(n)
|
|
36
|
-
};
|
|
37
|
-
if let Some(s) = s {
|
|
53
|
+
if let Some(s) = eng.table_schema(n) {
|
|
38
54
|
let mut v = serde_json::Map::new();
|
|
39
55
|
for (k, fs) in &s {
|
|
40
56
|
if let Ok(fv) = serde_json::to_value(fs) {
|
|
@@ -54,8 +70,8 @@ pub fn jsql_open(dir: String, mode: String) -> String {
|
|
|
54
70
|
|
|
55
71
|
#[napi]
|
|
56
72
|
pub fn jsql_flush_dirty() -> String {
|
|
57
|
-
|
|
58
|
-
match eng.
|
|
73
|
+
with_engine_mut(|eng| {
|
|
74
|
+
match eng.flush_dirty() {
|
|
59
75
|
Ok(n) => format!(r#"{{"ok":true,"flushed":{}}}"#, n),
|
|
60
76
|
Err(e) => format!(r#"{{"ok":false,"error":"{}"}}"#, e.replace('"', r#"\""#)),
|
|
61
77
|
}
|
|
@@ -64,9 +80,9 @@ pub fn jsql_flush_dirty() -> String {
|
|
|
64
80
|
|
|
65
81
|
#[napi]
|
|
66
82
|
pub fn jsql_evict() -> String {
|
|
67
|
-
|
|
68
|
-
match eng.
|
|
69
|
-
Some(name) => format!(r#"{{"ok":true,"evicted":"{}","remaining":{}}}"#, name, eng.
|
|
83
|
+
with_engine_mut(|eng| {
|
|
84
|
+
match eng.evict_one() {
|
|
85
|
+
Some(name) => format!(r#"{{"ok":true,"evicted":"{}","remaining":{}}}"#, name, eng.mem_count()),
|
|
70
86
|
None => r#"{"ok":true,"evicted":null,"remaining":0}"#.to_string(),
|
|
71
87
|
}
|
|
72
88
|
})
|
|
@@ -74,8 +90,8 @@ pub fn jsql_evict() -> String {
|
|
|
74
90
|
|
|
75
91
|
#[napi]
|
|
76
92
|
pub fn jsql_close() -> String {
|
|
77
|
-
|
|
78
|
-
eng.
|
|
93
|
+
with_engine_mut(|eng| {
|
|
94
|
+
eng.close();
|
|
79
95
|
r#"{"ok":true}"#.to_string()
|
|
80
96
|
})
|
|
81
97
|
}
|
|
@@ -89,7 +105,7 @@ pub fn jsql_create_table(name: String, schema_json: String) -> String {
|
|
|
89
105
|
Err(e) => return format!(r#"{{"ok":false,"error":"invalid schema: {}"}}"#, e),
|
|
90
106
|
};
|
|
91
107
|
let def = TableDefinition { name: name.clone(), schema };
|
|
92
|
-
|
|
108
|
+
with_engine_mut(|eng| match eng.create_table(def) {
|
|
93
109
|
Ok(()) => r#"{"ok":true}"#.to_string(),
|
|
94
110
|
Err(e) => format!(r#"{{"ok":false,"error":"{}"}}"#, e),
|
|
95
111
|
})
|
|
@@ -97,7 +113,7 @@ pub fn jsql_create_table(name: String, schema_json: String) -> String {
|
|
|
97
113
|
|
|
98
114
|
#[napi]
|
|
99
115
|
pub fn jsql_drop_table(name: String) -> String {
|
|
100
|
-
|
|
116
|
+
with_engine_mut(|eng| match eng.drop_table(&name) {
|
|
101
117
|
Ok(()) => r#"{"ok":true}"#.to_string(),
|
|
102
118
|
Err(e) => format!(r#"{{"ok":false,"error":"{}"}}"#, e),
|
|
103
119
|
})
|
|
@@ -105,77 +121,27 @@ pub fn jsql_drop_table(name: String) -> String {
|
|
|
105
121
|
|
|
106
122
|
#[napi]
|
|
107
123
|
pub fn jsql_insert(table: String, data_json: String) -> String {
|
|
108
|
-
|
|
124
|
+
with_engine_mut(|eng| {
|
|
109
125
|
let data: Vec<HashMap<String, serde_json::Value>> = match serde_json::from_str(&data_json) {
|
|
110
126
|
Ok(d) => d,
|
|
111
127
|
Err(e) => return format!(r#"{{"error":"invalid data: {}"}}"#, e),
|
|
112
128
|
};
|
|
113
|
-
match eng.
|
|
129
|
+
match eng.insert(&table, data) {
|
|
114
130
|
Ok(ids) => serde_json::to_string(&ids).unwrap_or_else(|_| "[]".to_string()),
|
|
115
131
|
Err(e) => format!(r#"{{"error":"{}"}}"#, e),
|
|
116
132
|
}
|
|
117
133
|
})
|
|
118
134
|
}
|
|
119
135
|
|
|
120
|
-
#[inline(always)]
|
|
121
|
-
unsafe fn parse_field_value_unsafe(data: &[u8], off: &mut usize) -> FieldValue {
|
|
122
|
-
let tag = *data.get_unchecked(*off); *off += 1;
|
|
123
|
-
match tag {
|
|
124
|
-
0 => FieldValue::Null,
|
|
125
|
-
1 => {
|
|
126
|
-
let n = i64::from_le_bytes([
|
|
127
|
-
*data.get_unchecked(*off), *data.get_unchecked(*off+1),
|
|
128
|
-
*data.get_unchecked(*off+2), *data.get_unchecked(*off+3),
|
|
129
|
-
*data.get_unchecked(*off+4), *data.get_unchecked(*off+5),
|
|
130
|
-
*data.get_unchecked(*off+6), *data.get_unchecked(*off+7),
|
|
131
|
-
]);
|
|
132
|
-
*off += 8;
|
|
133
|
-
FieldValue::Int(n)
|
|
134
|
-
}
|
|
135
|
-
2 => {
|
|
136
|
-
let n = f64::from_le_bytes([
|
|
137
|
-
*data.get_unchecked(*off), *data.get_unchecked(*off+1),
|
|
138
|
-
*data.get_unchecked(*off+2), *data.get_unchecked(*off+3),
|
|
139
|
-
*data.get_unchecked(*off+4), *data.get_unchecked(*off+5),
|
|
140
|
-
*data.get_unchecked(*off+6), *data.get_unchecked(*off+7),
|
|
141
|
-
]);
|
|
142
|
-
*off += 8;
|
|
143
|
-
FieldValue::Float(n)
|
|
144
|
-
}
|
|
145
|
-
3 => {
|
|
146
|
-
let len = u32::from_le_bytes([
|
|
147
|
-
*data.get_unchecked(*off), *data.get_unchecked(*off+1),
|
|
148
|
-
*data.get_unchecked(*off+2), *data.get_unchecked(*off+3),
|
|
149
|
-
]) as usize;
|
|
150
|
-
*off += 4;
|
|
151
|
-
let s = std::str::from_utf8_unchecked(std::slice::from_raw_parts(
|
|
152
|
-
data.as_ptr().add(*off), len
|
|
153
|
-
));
|
|
154
|
-
*off += len;
|
|
155
|
-
FieldValue::String(s.to_string())
|
|
156
|
-
}
|
|
157
|
-
4 => { let b = *data.get_unchecked(*off) != 0; *off += 1; FieldValue::Bool(b) }
|
|
158
|
-
5 => {
|
|
159
|
-
let n = i32::from_le_bytes([
|
|
160
|
-
*data.get_unchecked(*off), *data.get_unchecked(*off+1),
|
|
161
|
-
*data.get_unchecked(*off+2), *data.get_unchecked(*off+3),
|
|
162
|
-
]) as i64;
|
|
163
|
-
*off += 4;
|
|
164
|
-
FieldValue::Int(n)
|
|
165
|
-
}
|
|
166
|
-
_ => FieldValue::Null,
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
|
|
170
136
|
#[napi]
|
|
171
137
|
pub fn jsql_insert_buf(table: String, data: JsBuffer) -> String {
|
|
172
138
|
let buf_val = match data.into_value() {
|
|
173
139
|
Ok(v) => v,
|
|
174
140
|
Err(_) => return r#"{"error":"invalid buffer"}"#.to_string(),
|
|
175
141
|
};
|
|
176
|
-
|
|
142
|
+
with_engine_mut(|eng| {
|
|
177
143
|
let buf: &[u8] = buf_val.as_ref();
|
|
178
|
-
let res = eng.
|
|
144
|
+
let res = eng.insert_buf(&table, buf)
|
|
179
145
|
.map(|ids| serde_json::to_string(&ids).unwrap_or_else(|_| "[]".to_string()));
|
|
180
146
|
safe_json_result(res.map_err(|e| e))
|
|
181
147
|
})
|
|
@@ -183,10 +149,10 @@ pub fn jsql_insert_buf(table: String, data: JsBuffer) -> String {
|
|
|
183
149
|
|
|
184
150
|
#[napi]
|
|
185
151
|
pub fn jsql_find(table: String, filter_json: String, limit: i32, offset: i32) -> String {
|
|
186
|
-
|
|
152
|
+
with_engine_ro(|eng| {
|
|
187
153
|
let filter: Option<HashMap<String, serde_json::Value>> =
|
|
188
154
|
if filter_json.is_empty() { None } else { serde_json::from_str(&filter_json).ok() };
|
|
189
|
-
match eng.
|
|
155
|
+
match eng.find(&table, &filter, Some(limit as usize), Some(offset as usize), None, &None, &None) {
|
|
190
156
|
Ok((rows, _, _)) => serde_json::to_string(&rows).unwrap_or_else(|_| "[]".to_string()),
|
|
191
157
|
Err(e) => format!(r#"{{"error":"{}"}}"#, e),
|
|
192
158
|
}
|
|
@@ -195,8 +161,8 @@ pub fn jsql_find(table: String, filter_json: String, limit: i32, offset: i32) ->
|
|
|
195
161
|
|
|
196
162
|
#[napi]
|
|
197
163
|
pub fn jsql_find_by_id(table: String, id: i64) -> String {
|
|
198
|
-
|
|
199
|
-
match eng.
|
|
164
|
+
with_engine_ro(|eng| {
|
|
165
|
+
match eng.find_by_id_json(&table, id as u64) {
|
|
200
166
|
Ok(Some(s)) => s,
|
|
201
167
|
Ok(None) => "null".to_string(),
|
|
202
168
|
Err(e) => format!(r#"{{"error":"{}"}}"#, e),
|
|
@@ -204,11 +170,9 @@ pub fn jsql_find_by_id(table: String, id: i64) -> String {
|
|
|
204
170
|
})
|
|
205
171
|
}
|
|
206
172
|
|
|
207
|
-
|
|
208
|
-
|
|
209
173
|
#[napi]
|
|
210
174
|
pub fn jsql_count(table: String) -> String {
|
|
211
|
-
|
|
175
|
+
with_engine_ro(|eng| match eng.count(&table) {
|
|
212
176
|
Ok(c) => format!("{}", c),
|
|
213
177
|
Err(e) => format!(r#"{{"error":"{}"}}"#, e),
|
|
214
178
|
})
|
|
@@ -216,12 +180,12 @@ pub fn jsql_count(table: String) -> String {
|
|
|
216
180
|
|
|
217
181
|
#[napi]
|
|
218
182
|
pub fn jsql_update_by_id(table: String, id: i64, data_json: String) -> String {
|
|
219
|
-
|
|
183
|
+
with_engine_mut(|eng| {
|
|
220
184
|
let data: HashMap<String, serde_json::Value> = match serde_json::from_str(&data_json) {
|
|
221
185
|
Ok(d) => d,
|
|
222
186
|
Err(e) => return format!(r#"{{"ok":false,"error":"invalid data: {}"}}"#, e),
|
|
223
187
|
};
|
|
224
|
-
match eng.
|
|
188
|
+
match eng.update_by_id(&table, id as u64, data) {
|
|
225
189
|
Ok(true) => r#"{"ok":true}"#.to_string(),
|
|
226
190
|
Ok(false) => r#"{"ok":false,"error":"not found"}"#.to_string(),
|
|
227
191
|
Err(e) => format!(r#"{{"ok":false,"error":"{}"}}"#, e),
|
|
@@ -231,7 +195,7 @@ pub fn jsql_update_by_id(table: String, id: i64, data_json: String) -> String {
|
|
|
231
195
|
|
|
232
196
|
#[napi]
|
|
233
197
|
pub fn jsql_remove_by_id(table: String, id: i64) -> String {
|
|
234
|
-
|
|
198
|
+
with_engine_mut(|eng| match eng.remove_by_id(&table, id as u64) {
|
|
235
199
|
Ok(true) => r#"{"ok":true}"#.to_string(),
|
|
236
200
|
Ok(false) => r#"{"ok":false,"error":"not found"}"#.to_string(),
|
|
237
201
|
Err(e) => format!(r#"{{"ok":false,"error":"{}"}}"#, e),
|
|
@@ -240,12 +204,12 @@ pub fn jsql_remove_by_id(table: String, id: i64) -> String {
|
|
|
240
204
|
|
|
241
205
|
#[napi]
|
|
242
206
|
pub fn jsql_remove_by_ids(table: String, ids_json: String) -> String {
|
|
243
|
-
|
|
207
|
+
with_engine_mut(|eng| {
|
|
244
208
|
let ids: Vec<u64> = match serde_json::from_str(&ids_json) {
|
|
245
209
|
Ok(v) => v,
|
|
246
210
|
Err(e) => return format!(r#"{{"error":"invalid ids: {}"}}"#, e),
|
|
247
211
|
};
|
|
248
|
-
match eng.
|
|
212
|
+
match eng.remove_by_ids(&table, &ids) {
|
|
249
213
|
Ok(n) => format!(r#"{{"ok":true,"count":{}}}"#, n),
|
|
250
214
|
Err(e) => format!(r#"{{"ok":false,"error":"{}"}}"#, e),
|
|
251
215
|
}
|
|
@@ -254,12 +218,12 @@ pub fn jsql_remove_by_ids(table: String, ids_json: String) -> String {
|
|
|
254
218
|
|
|
255
219
|
#[napi]
|
|
256
220
|
pub fn jsql_update_by_ids(table: String, batch_json: String) -> String {
|
|
257
|
-
|
|
221
|
+
with_engine_mut(|eng| {
|
|
258
222
|
let batch: Vec<(u64, HashMap<String, serde_json::Value>)> = match serde_json::from_str(&batch_json) {
|
|
259
223
|
Ok(v) => v,
|
|
260
224
|
Err(e) => return format!(r#"{{"error":"invalid batch: {}"}}"#, e),
|
|
261
225
|
};
|
|
262
|
-
match eng.
|
|
226
|
+
match eng.update_by_ids(&table, batch) {
|
|
263
227
|
Ok(n) => format!(r#"{{"ok":true,"count":{}}}"#, n),
|
|
264
228
|
Err(e) => format!(r#"{{"ok":false,"error":"{}"}}"#, e),
|
|
265
229
|
}
|
|
@@ -268,14 +232,38 @@ pub fn jsql_update_by_ids(table: String, batch_json: String) -> String {
|
|
|
268
232
|
|
|
269
233
|
#[napi]
|
|
270
234
|
pub fn jsql_find_by_ids(table: String, ids_json: String) -> String {
|
|
271
|
-
|
|
235
|
+
with_engine_ro(|eng| {
|
|
272
236
|
let ids: Vec<u64> = match serde_json::from_str(&ids_json) {
|
|
273
237
|
Ok(v) => v,
|
|
274
238
|
Err(e) => return format!(r#"{{"error":"invalid ids: {}"}}"#, e),
|
|
275
239
|
};
|
|
276
|
-
match eng.
|
|
240
|
+
match eng.find_by_ids_json(&table, &ids) {
|
|
277
241
|
Ok(s) => s,
|
|
278
242
|
Err(e) => format!(r#"{{"error":"{}"}}"#, e),
|
|
279
243
|
}
|
|
280
244
|
})
|
|
281
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
|
+
}
|