sqlmath 2025.8.30 → 2025.12.28
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/.npmignore +4 -1
- package/CHANGELOG.md +22 -0
- package/README.md +6 -9
- package/_sqlmath.cp310-win_amd64.pyd +0 -0
- package/_sqlmath.cp311-win_amd64.pyd +0 -0
- package/_sqlmath.cp312-win_amd64.pyd +0 -0
- package/_sqlmath.cp313-win_amd64.pyd +0 -0
- package/_sqlmath.cp314-win_amd64.pyd +0 -0
- package/_sqlmath.cpython-310-darwin.so +0 -0
- package/_sqlmath.cpython-311-darwin.so +0 -0
- package/_sqlmath.cpython-312-darwin.so +0 -0
- package/_sqlmath.cpython-312-x86_64-linux-gnu.so +0 -0
- package/_sqlmath.cpython-313-darwin.so +0 -0
- package/_sqlmath.cpython-314-darwin.so +0 -0
- package/_sqlmath.cpython-314t-darwin.so +0 -0
- package/_sqlmath.napi6_darwin_arm64.node +0 -0
- package/_sqlmath.napi6_linux_x64.node +0 -0
- package/_sqlmath.napi6_win32_x64.node +0 -0
- package/_sqlmath.shell_darwin_arm64 +0 -0
- package/_sqlmath.shell_linux_x64 +0 -0
- package/_sqlmath.shell_win32_x64.exe +0 -0
- package/jslint.mjs +82 -18
- package/package.json +2 -2
- package/sqlmath.mjs +287 -162
- package/sqlmath_browser.mjs +4769 -0
- package/test.mjs +4176 -0
package/sqlmath.mjs
CHANGED
|
@@ -84,7 +84,13 @@ const SQLITE_OPEN_TRANSIENT_DB = 0x00000400; /* VFS only */
|
|
|
84
84
|
const SQLITE_OPEN_URI = 0x00000040; /* Ok for sqlite3_open_v2() */
|
|
85
85
|
const SQLITE_OPEN_WAL = 0x00080000; /* VFS only */
|
|
86
86
|
|
|
87
|
+
let DB_EXEC_PROFILE_DICT = {};
|
|
88
|
+
let DB_EXEC_PROFILE_MODE;
|
|
89
|
+
let DB_EXEC_PROFILE_SQL_LENGTH;
|
|
90
|
+
let DB_OPEN_INIT;
|
|
87
91
|
let IS_BROWSER;
|
|
92
|
+
let SQLMATH_EXE;
|
|
93
|
+
let SQLMATH_NODE;
|
|
88
94
|
let cModule;
|
|
89
95
|
let cModulePath;
|
|
90
96
|
let consoleError = console.error;
|
|
@@ -122,7 +128,7 @@ let {
|
|
|
122
128
|
let sqlMessageDict = {}; // dict of web-worker-callbacks
|
|
123
129
|
let sqlMessageId = 0;
|
|
124
130
|
let sqlWorker;
|
|
125
|
-
let version = "v2025.
|
|
131
|
+
let version = "v2025.12.28";
|
|
126
132
|
|
|
127
133
|
async function assertErrorThrownAsync(asyncFunc, regexp) {
|
|
128
134
|
|
|
@@ -213,7 +219,7 @@ async function childProcessSpawn2(command, args, option) {
|
|
|
213
219
|
let {
|
|
214
220
|
modeCapture,
|
|
215
221
|
modeDebug,
|
|
216
|
-
stdio
|
|
222
|
+
stdio = []
|
|
217
223
|
} = option;
|
|
218
224
|
if (modeDebug) {
|
|
219
225
|
consoleError(
|
|
@@ -273,43 +279,86 @@ async function childProcessSpawn2(command, args, option) {
|
|
|
273
279
|
if (npm_config_mode_test) {
|
|
274
280
|
resolve = resolve0;
|
|
275
281
|
}
|
|
276
|
-
[
|
|
282
|
+
[
|
|
283
|
+
stdout, stderr
|
|
284
|
+
] = bufList.slice(1).map(function (buf) {
|
|
277
285
|
return (
|
|
278
286
|
typeof modeCapture === "string"
|
|
279
287
|
? Buffer.concat(buf).toString(modeCapture)
|
|
280
288
|
: Buffer.concat(buf)
|
|
281
289
|
);
|
|
282
290
|
});
|
|
283
|
-
resolve(
|
|
291
|
+
resolve([
|
|
292
|
+
exitCode, stdout, stderr
|
|
293
|
+
]);
|
|
284
294
|
});
|
|
285
295
|
});
|
|
286
|
-
|
|
287
296
|
}
|
|
288
297
|
|
|
289
298
|
async function ciBuildExt({
|
|
290
|
-
modeSkip,
|
|
291
299
|
process
|
|
292
300
|
}) {
|
|
293
301
|
|
|
294
302
|
// This function will build sqlmath from c.
|
|
295
303
|
|
|
296
|
-
let
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
304
|
+
let binNodegyp;
|
|
305
|
+
let exitCode;
|
|
306
|
+
binNodegyp = modulePath.resolve(
|
|
307
|
+
modulePath.dirname(process.execPath || ""),
|
|
308
|
+
"node_modules/npm/node_modules/node-gyp/bin/node-gyp.js"
|
|
309
|
+
).replace("/bin/node_modules/", "/lib/node_modules/");
|
|
310
|
+
if (!noop(
|
|
311
|
+
await fsExistsUnlessTest(cModulePath)
|
|
312
|
+
)) {
|
|
313
|
+
await ciBuildExt1NodejsConfigure({
|
|
314
|
+
binNodegyp,
|
|
315
|
+
process
|
|
316
|
+
});
|
|
317
|
+
}
|
|
318
|
+
consoleError(
|
|
319
|
+
`ciBuildExt2Nodejs - linking lib ${modulePath.resolve(cModulePath)}`
|
|
320
|
+
);
|
|
321
|
+
[
|
|
322
|
+
exitCode
|
|
323
|
+
] = await childProcessSpawn2(
|
|
324
|
+
"sh",
|
|
325
|
+
[
|
|
326
|
+
"-c",
|
|
327
|
+
(`
|
|
328
|
+
(set -e
|
|
329
|
+
# rebuild binding
|
|
330
|
+
rm -rf build/Release/obj/SRC_SQLMATH_CUSTOM/
|
|
331
|
+
node "${binNodegyp}" build --release
|
|
332
|
+
# node "${binNodegyp}" build --release --loglevel=verbose
|
|
333
|
+
mv build/Release/binding.node "${cModulePath}"
|
|
334
|
+
mv build/Release/shell "${SQLMATH_EXE}"
|
|
335
|
+
# ugly-hack - win32-sqlite-shell doesn't like nodejs-builtin-zlib,
|
|
336
|
+
# so link with external-zlib.
|
|
337
|
+
if (uname | grep -q "MING\\|MSYS")
|
|
338
|
+
then
|
|
339
|
+
rm -f ${SQLMATH_EXE}
|
|
340
|
+
python setup.py exe_link \
|
|
341
|
+
./build/Release/SRC_SQLITE_BASE.lib \
|
|
342
|
+
./build/Release/SRC_SQLMATH_CUSTOM.lib \
|
|
343
|
+
./build/Release/obj/shell/sqlmath_external_sqlite.obj \
|
|
344
|
+
./zlib.v1.3.1.vcpkg.x64-windows-static.lib \
|
|
345
|
+
\
|
|
346
|
+
-ltcg \
|
|
347
|
+
-nologo \
|
|
348
|
+
-out:${SQLMATH_EXE} \
|
|
349
|
+
-subsystem:console
|
|
350
|
+
fi
|
|
351
|
+
)
|
|
352
|
+
`)
|
|
353
|
+
],
|
|
354
|
+
{modeDebug: npm_config_mode_debug, stdio: ["ignore", 1, 2]}
|
|
355
|
+
);
|
|
356
|
+
assertOrThrow(!exitCode, `ciBuildExt - exitCode=${exitCode}`);
|
|
308
357
|
}
|
|
309
358
|
|
|
310
359
|
async function ciBuildExt1NodejsConfigure({
|
|
311
|
-
binNodegyp
|
|
312
|
-
|
|
360
|
+
binNodegyp
|
|
361
|
+
// process
|
|
313
362
|
}) {
|
|
314
363
|
|
|
315
364
|
// This function will setup posix/win32 env for building c-extension.
|
|
@@ -340,82 +389,82 @@ SQLMATH_CFLAG_WNO_LIST=" \\
|
|
|
340
389
|
consoleError(`ciBuildExt1Nodejs - configure binding.gyp`);
|
|
341
390
|
await fsWriteFileUnlessTest("binding.gyp", JSON.stringify({
|
|
342
391
|
"target_defaults": {
|
|
343
|
-
"cflags":
|
|
344
|
-
// https://github.com/nodejs/node-gyp/blob/
|
|
392
|
+
"cflags": cflagWallList,
|
|
393
|
+
// https://github.com/nodejs/node-gyp/blob/v10.3.1/gyp/pylib/gyp/MSVSSettings.py
|
|
345
394
|
"msvs_settings": {
|
|
346
395
|
"VCCLCompilerTool": {
|
|
347
396
|
"WarnAsError": 1,
|
|
348
|
-
"WarningLevel":
|
|
397
|
+
"WarningLevel": 4
|
|
349
398
|
}
|
|
350
399
|
},
|
|
351
400
|
"xcode_settings": {
|
|
352
|
-
"OTHER_CFLAGS":
|
|
401
|
+
"OTHER_CFLAGS": cflagWallList
|
|
353
402
|
}
|
|
354
403
|
},
|
|
355
404
|
"targets": [
|
|
356
405
|
{
|
|
406
|
+
"cflags": cflagWnoList,
|
|
357
407
|
"defines": [
|
|
358
|
-
"SRC_SQLITE_BASE_C2"
|
|
359
|
-
"SRC_ZLIB_C2"
|
|
408
|
+
"SRC_SQLITE_BASE_C2"
|
|
360
409
|
],
|
|
410
|
+
"msvs_settings": {
|
|
411
|
+
"VCCLCompilerTool": {
|
|
412
|
+
"WarnAsError": 1,
|
|
413
|
+
"WarningLevel": 2
|
|
414
|
+
}
|
|
415
|
+
},
|
|
361
416
|
"sources": [
|
|
362
|
-
"sqlmath_external_sqlite.c"
|
|
363
|
-
"sqlmath_external_zlib.c"
|
|
417
|
+
"sqlmath_external_sqlite.c"
|
|
364
418
|
],
|
|
365
419
|
"target_name": "SRC_SQLITE_BASE",
|
|
366
|
-
"type": "static_library"
|
|
420
|
+
"type": "static_library",
|
|
421
|
+
"xcode_settings": {
|
|
422
|
+
"OTHER_CFLAGS": cflagWnoList
|
|
423
|
+
}
|
|
367
424
|
},
|
|
368
425
|
{
|
|
369
|
-
"cflags": cflagWallList,
|
|
370
426
|
"defines": [
|
|
371
427
|
"SRC_SQLMATH_BASE_C2",
|
|
372
428
|
"SRC_SQLMATH_CUSTOM_C2"
|
|
373
429
|
],
|
|
374
|
-
"
|
|
375
|
-
"
|
|
376
|
-
|
|
377
|
-
"WarningLevel": 4
|
|
378
|
-
}
|
|
379
|
-
},
|
|
430
|
+
"dependencies": [
|
|
431
|
+
"SRC_SQLITE_BASE"
|
|
432
|
+
],
|
|
380
433
|
"sources": [
|
|
381
434
|
"sqlmath_base.c",
|
|
382
435
|
"sqlmath_custom.c"
|
|
383
436
|
],
|
|
384
437
|
"target_name": "SRC_SQLMATH_CUSTOM",
|
|
385
|
-
"type": "static_library"
|
|
386
|
-
"xcode_settings": {
|
|
387
|
-
"OTHER_CFLAGS": cflagWallList
|
|
388
|
-
}
|
|
438
|
+
"type": "static_library"
|
|
389
439
|
},
|
|
390
440
|
{
|
|
391
|
-
"cflags": cflagWallList,
|
|
392
441
|
"defines": [
|
|
393
442
|
"SRC_SQLMATH_NODEJS_C2"
|
|
394
443
|
],
|
|
395
444
|
"dependencies": [
|
|
396
|
-
"SRC_SQLITE_BASE",
|
|
397
445
|
"SRC_SQLMATH_CUSTOM"
|
|
398
446
|
],
|
|
399
|
-
"msvs_settings": {
|
|
400
|
-
"VCCLCompilerTool": {
|
|
401
|
-
"WarnAsError": 1,
|
|
402
|
-
"WarningLevel": 4
|
|
403
|
-
}
|
|
404
|
-
},
|
|
405
447
|
"sources": [
|
|
406
448
|
"sqlmath_base.c"
|
|
407
449
|
],
|
|
408
|
-
"target_name": "binding"
|
|
409
|
-
"xcode_settings": {
|
|
410
|
-
"OTHER_CFLAGS": cflagWallList
|
|
411
|
-
}
|
|
450
|
+
"target_name": "binding"
|
|
412
451
|
},
|
|
413
452
|
{
|
|
453
|
+
"conditions": [
|
|
454
|
+
[
|
|
455
|
+
"OS==\"win\"",
|
|
456
|
+
{},
|
|
457
|
+
{
|
|
458
|
+
"libraries": [
|
|
459
|
+
"-lz"
|
|
460
|
+
]
|
|
461
|
+
}
|
|
462
|
+
]
|
|
463
|
+
],
|
|
414
464
|
"defines": [
|
|
415
465
|
"SRC_SQLITE_SHELL_C2"
|
|
416
466
|
],
|
|
417
467
|
"dependencies": [
|
|
418
|
-
"SRC_SQLITE_BASE",
|
|
419
468
|
"SRC_SQLMATH_CUSTOM"
|
|
420
469
|
],
|
|
421
470
|
"sources": [
|
|
@@ -437,66 +486,25 @@ SQLMATH_CFLAG_WNO_LIST=" \\
|
|
|
437
486
|
)
|
|
438
487
|
`)
|
|
439
488
|
],
|
|
440
|
-
{modeDebug, stdio: ["ignore", 1, 2]}
|
|
441
|
-
);
|
|
442
|
-
}
|
|
443
|
-
|
|
444
|
-
async function ciBuildExt2NodejsBuild({
|
|
445
|
-
binNodegyp,
|
|
446
|
-
modeDebug
|
|
447
|
-
}) {
|
|
448
|
-
|
|
449
|
-
// This function will archive <fileObj> into <fileLib>
|
|
450
|
-
|
|
451
|
-
if (!noop(
|
|
452
|
-
await fsExistsUnlessTest(cModulePath)
|
|
453
|
-
)) {
|
|
454
|
-
await ciBuildExt1NodejsConfigure({
|
|
455
|
-
binNodegyp,
|
|
456
|
-
modeDebug
|
|
457
|
-
});
|
|
458
|
-
}
|
|
459
|
-
consoleError(
|
|
460
|
-
`ciBuildExt2Nodejs - linking lib ${modulePath.resolve(cModulePath)}`
|
|
461
|
-
);
|
|
462
|
-
await childProcessSpawn2(
|
|
463
|
-
"sh",
|
|
464
|
-
[
|
|
465
|
-
"-c",
|
|
466
|
-
(`
|
|
467
|
-
(set -e
|
|
468
|
-
# rebuild binding
|
|
469
|
-
rm -rf build/Release/obj/SRC_SQLMATH_CUSTOM/
|
|
470
|
-
node "${binNodegyp}" build --release
|
|
471
|
-
mv build/Release/binding.node "${cModulePath}"
|
|
472
|
-
if [ "${process.platform}" = "win32" ]
|
|
473
|
-
then
|
|
474
|
-
mv build/Release/shell \
|
|
475
|
-
"_sqlmath.shell_${process.platform}_${process.arch}.exe"
|
|
476
|
-
else
|
|
477
|
-
mv build/Release/shell \
|
|
478
|
-
"_sqlmath.shell_${process.platform}_${process.arch}"
|
|
479
|
-
fi
|
|
480
|
-
)
|
|
481
|
-
`)
|
|
482
|
-
],
|
|
483
|
-
{modeDebug, stdio: ["ignore", 1, 2]}
|
|
489
|
+
{modeDebug: npm_config_mode_debug, stdio: ["ignore", 1, 2]}
|
|
484
490
|
);
|
|
485
491
|
}
|
|
486
492
|
|
|
487
|
-
async function dbCallAsync(baton, argList, mode) {
|
|
493
|
+
async function dbCallAsync(baton, argList, mode, db) {
|
|
488
494
|
|
|
489
495
|
// This function will call c-function dbXxx() with given <funcname>
|
|
490
496
|
// and return [<baton>, ...argList].
|
|
491
497
|
|
|
492
|
-
let db;
|
|
493
498
|
let errStack;
|
|
494
499
|
let funcname;
|
|
495
500
|
let id;
|
|
501
|
+
let profileObj;
|
|
502
|
+
let profileStart;
|
|
496
503
|
let result;
|
|
504
|
+
let sql;
|
|
497
505
|
let timeElapsed;
|
|
498
506
|
// If argList contains <db>, then mark it as busy.
|
|
499
|
-
if (mode === "
|
|
507
|
+
if (mode === "modeDbExec" || mode === "modeDbFile") {
|
|
500
508
|
// init db
|
|
501
509
|
db = argList[0];
|
|
502
510
|
assertOrThrow(
|
|
@@ -507,8 +515,44 @@ async function dbCallAsync(baton, argList, mode) {
|
|
|
507
515
|
db.ptr = db.connPool[db.ii][0];
|
|
508
516
|
// increment db.busy
|
|
509
517
|
db.busy += 1;
|
|
518
|
+
// init profileObj
|
|
519
|
+
if (DB_EXEC_PROFILE_MODE && mode === "modeDbExec") {
|
|
520
|
+
profileStart = Date.now();
|
|
521
|
+
sql = String(argList[1]);
|
|
522
|
+
// sql-hash - remove comment
|
|
523
|
+
sql = sql.replace((/(?:^|\s+?)--.*/gm), "");
|
|
524
|
+
// sql-hash - remove vowel
|
|
525
|
+
sql = sql.replace((/[aeiou]\b/gi), "\u0000$&");
|
|
526
|
+
sql = sql.replace((/([bcdfghjklmnpqrstvwxyz])[aeiou]+/gi), "$1");
|
|
527
|
+
sql = sql.replace((/\u0000([aeiou])\b/gi), "$1");
|
|
528
|
+
// sql-hash - remove underscore
|
|
529
|
+
sql = sql.replace((/_+/g), "");
|
|
530
|
+
// sql-hash - truncate long text
|
|
531
|
+
sql = sql.replace((/(\S{16})\S+/g), "$1");
|
|
532
|
+
// sql-hash - remove whitespace
|
|
533
|
+
sql = sql.replace((/\s+/g), " ");
|
|
534
|
+
sql = sql.trim().slice(0, DB_EXEC_PROFILE_SQL_LENGTH);
|
|
535
|
+
DB_EXEC_PROFILE_DICT[sql] = DB_EXEC_PROFILE_DICT[sql] || {
|
|
536
|
+
busy: 0,
|
|
537
|
+
count: 0,
|
|
538
|
+
sql,
|
|
539
|
+
timeElapsed: 0
|
|
540
|
+
};
|
|
541
|
+
profileObj = DB_EXEC_PROFILE_DICT[sql];
|
|
542
|
+
// increment profileObj.busy
|
|
543
|
+
profileObj.busy += 1;
|
|
544
|
+
profileObj.count += 1;
|
|
545
|
+
}
|
|
510
546
|
try {
|
|
511
|
-
return await dbCallAsync(
|
|
547
|
+
return await dbCallAsync(
|
|
548
|
+
baton,
|
|
549
|
+
[
|
|
550
|
+
db.ptr,
|
|
551
|
+
...argList.slice(1)
|
|
552
|
+
],
|
|
553
|
+
undefined,
|
|
554
|
+
db
|
|
555
|
+
);
|
|
512
556
|
} finally {
|
|
513
557
|
// decrement db.busy
|
|
514
558
|
db.busy -= 1;
|
|
@@ -516,6 +560,18 @@ async function dbCallAsync(baton, argList, mode) {
|
|
|
516
560
|
db.busy >= 0,
|
|
517
561
|
`dbCallAsync - invalid db.busy = ${db.busy}`
|
|
518
562
|
);
|
|
563
|
+
// update profileObj
|
|
564
|
+
if (profileObj) {
|
|
565
|
+
// decrement profileObj.busy
|
|
566
|
+
profileObj.busy -= 1;
|
|
567
|
+
assertOrThrow(
|
|
568
|
+
profileObj.busy >= 0,
|
|
569
|
+
`dbCallAsync - invalid profileObj.busy = ${profileObj.busy}`
|
|
570
|
+
);
|
|
571
|
+
if (profileObj.busy === 0) {
|
|
572
|
+
profileObj.timeElapsed += Date.now() - profileStart;
|
|
573
|
+
}
|
|
574
|
+
}
|
|
519
575
|
}
|
|
520
576
|
}
|
|
521
577
|
// copy argList to avoid side-effect
|
|
@@ -636,6 +692,10 @@ async function dbCallAsync(baton, argList, mode) {
|
|
|
636
692
|
// prepend baton to argList
|
|
637
693
|
return [result.baton, ...result.argList];
|
|
638
694
|
} catch (err) {
|
|
695
|
+
// debug db.filename
|
|
696
|
+
if (db?.filename2 || db?.filename) {
|
|
697
|
+
err.message += ` (from ${db?.filename2 || db?.filename})`;
|
|
698
|
+
}
|
|
639
699
|
err.stack += errStack;
|
|
640
700
|
assertOrThrow(undefined, err);
|
|
641
701
|
}
|
|
@@ -654,71 +714,55 @@ async function dbCloseAsync(db) {
|
|
|
654
714
|
await Promise.all(db.connPool.map(async function (ptr) {
|
|
655
715
|
let val = ptr[0];
|
|
656
716
|
ptr[0] = 0n;
|
|
657
|
-
await dbCallAsync(
|
|
717
|
+
await dbCallAsync(
|
|
718
|
+
jsbatonCreate("_dbClose"),
|
|
719
|
+
[
|
|
720
|
+
val,
|
|
721
|
+
db.filename
|
|
722
|
+
]
|
|
723
|
+
);
|
|
658
724
|
}));
|
|
659
725
|
}
|
|
660
726
|
|
|
661
|
-
function dbExecAndReturnLastBlob({
|
|
662
|
-
bindList = [],
|
|
663
|
-
db,
|
|
664
|
-
sql
|
|
665
|
-
}) {
|
|
727
|
+
function dbExecAndReturnLastBlob(option) {
|
|
666
728
|
|
|
667
729
|
// This function will exec <sql> in <db>,
|
|
668
730
|
// and return last-value retrieved from execution as raw blob/buffer.
|
|
669
731
|
|
|
670
|
-
return dbExecAsync({
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
responseType: "lastblob",
|
|
674
|
-
sql
|
|
675
|
-
});
|
|
732
|
+
return dbExecAsync(Object.assign({
|
|
733
|
+
responseType: "lastblob"
|
|
734
|
+
}, option));
|
|
676
735
|
}
|
|
677
736
|
|
|
678
|
-
async function dbExecAndReturnLastRow({
|
|
679
|
-
bindList = [],
|
|
680
|
-
db,
|
|
681
|
-
sql
|
|
682
|
-
}) {
|
|
737
|
+
async function dbExecAndReturnLastRow(option) {
|
|
683
738
|
|
|
684
739
|
// This function will exec <sql> in <db>,
|
|
685
740
|
// and return last-row or empty-object.
|
|
686
741
|
|
|
687
|
-
let result = await dbExecAsync(
|
|
742
|
+
let result = await dbExecAsync(option);
|
|
688
743
|
result = result[result.length - 1] || [];
|
|
689
744
|
result = result[result.length - 1] || {};
|
|
690
745
|
return result;
|
|
691
746
|
}
|
|
692
747
|
|
|
693
|
-
async function dbExecAndReturnLastTable({
|
|
694
|
-
bindList = [],
|
|
695
|
-
db,
|
|
696
|
-
sql
|
|
697
|
-
}) {
|
|
748
|
+
async function dbExecAndReturnLastTable(option) {
|
|
698
749
|
|
|
699
750
|
// This function will exec <sql> in <db>,
|
|
700
751
|
// and return last-table or empty-list.
|
|
701
752
|
|
|
702
|
-
let result = await dbExecAsync(
|
|
753
|
+
let result = await dbExecAsync(option);
|
|
703
754
|
result = result[result.length - 1] || [];
|
|
704
755
|
return result;
|
|
705
756
|
}
|
|
706
757
|
|
|
707
|
-
function dbExecAndReturnLastValue({
|
|
708
|
-
bindList = [],
|
|
709
|
-
db,
|
|
710
|
-
sql
|
|
711
|
-
}) {
|
|
758
|
+
function dbExecAndReturnLastValue(option) {
|
|
712
759
|
|
|
713
760
|
// This function will exec <sql> in <db>,
|
|
714
761
|
// and return last-json-value.
|
|
715
762
|
|
|
716
|
-
return dbExecAsync({
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
responseType: "lastvalue",
|
|
720
|
-
sql
|
|
721
|
-
});
|
|
763
|
+
return dbExecAsync(Object.assign({
|
|
764
|
+
responseType: "lastvalue"
|
|
765
|
+
}, option));
|
|
722
766
|
}
|
|
723
767
|
|
|
724
768
|
async function dbExecAsync({
|
|
@@ -761,7 +805,9 @@ async function dbExecAsync({
|
|
|
761
805
|
);
|
|
762
806
|
});
|
|
763
807
|
}
|
|
764
|
-
[
|
|
808
|
+
[
|
|
809
|
+
baton, ...result
|
|
810
|
+
] = await dbCallAsync(
|
|
765
811
|
baton,
|
|
766
812
|
[
|
|
767
813
|
// 0. db
|
|
@@ -785,7 +831,7 @@ async function dbExecAsync({
|
|
|
785
831
|
: 0
|
|
786
832
|
)
|
|
787
833
|
],
|
|
788
|
-
"
|
|
834
|
+
"modeDbExec"
|
|
789
835
|
);
|
|
790
836
|
result = result[0];
|
|
791
837
|
if (!IS_BROWSER) {
|
|
@@ -800,12 +846,13 @@ async function dbExecAsync({
|
|
|
800
846
|
switch (responseType) {
|
|
801
847
|
case "arraybuffer":
|
|
802
848
|
case "lastblob":
|
|
803
|
-
|
|
849
|
+
break;
|
|
804
850
|
case "lastvalue":
|
|
805
851
|
case "list":
|
|
806
|
-
|
|
852
|
+
result = jsonParseArraybuffer(result);
|
|
853
|
+
break;
|
|
807
854
|
default:
|
|
808
|
-
|
|
855
|
+
result = jsonParseArraybuffer(result).map(function (table) {
|
|
809
856
|
let colList = table.shift();
|
|
810
857
|
return table.map(function (row) {
|
|
811
858
|
let dict = {};
|
|
@@ -816,6 +863,52 @@ async function dbExecAsync({
|
|
|
816
863
|
});
|
|
817
864
|
});
|
|
818
865
|
}
|
|
866
|
+
return result;
|
|
867
|
+
}
|
|
868
|
+
|
|
869
|
+
function dbExecProfile({
|
|
870
|
+
limit = 20,
|
|
871
|
+
lineLength = 80,
|
|
872
|
+
modeInit,
|
|
873
|
+
sqlLength = 256
|
|
874
|
+
}) {
|
|
875
|
+
|
|
876
|
+
// This function will profile dbExecAsync.
|
|
877
|
+
|
|
878
|
+
let result;
|
|
879
|
+
if (modeInit && !DB_EXEC_PROFILE_MODE) {
|
|
880
|
+
DB_EXEC_PROFILE_MODE = Date.now();
|
|
881
|
+
DB_EXEC_PROFILE_SQL_LENGTH = sqlLength;
|
|
882
|
+
process.on("exit", function () {
|
|
883
|
+
console.error(dbExecProfile({
|
|
884
|
+
limit,
|
|
885
|
+
lineLength
|
|
886
|
+
}));
|
|
887
|
+
});
|
|
888
|
+
return;
|
|
889
|
+
}
|
|
890
|
+
result = Object.values(DB_EXEC_PROFILE_DICT);
|
|
891
|
+
result.sort(function (aa, bb) {
|
|
892
|
+
return ((bb.timeElapsed - aa.timeElapsed) || (bb.count - aa.count));
|
|
893
|
+
});
|
|
894
|
+
result = result.slice(0, limit).map(function ({
|
|
895
|
+
count,
|
|
896
|
+
sql,
|
|
897
|
+
timeElapsed
|
|
898
|
+
}, ii) {
|
|
899
|
+
return String(
|
|
900
|
+
`${Number(ii + 1).toFixed(0).padStart(2, " ")}.`
|
|
901
|
+
+ ` ${timeElapsed.toFixed(0).padStart(4)}`
|
|
902
|
+
+ ` ${count.toFixed(0).padStart(3)}`
|
|
903
|
+
+ " " + JSON.stringify(sql)
|
|
904
|
+
).slice(0, lineLength);
|
|
905
|
+
}).join("\n");
|
|
906
|
+
result = (
|
|
907
|
+
`\ndbExecProfile:\n`
|
|
908
|
+
+ ` # time cnt sql\n`
|
|
909
|
+
+ `${result}\n`
|
|
910
|
+
);
|
|
911
|
+
return result;
|
|
819
912
|
}
|
|
820
913
|
|
|
821
914
|
async function dbFileLoadAsync({
|
|
@@ -844,7 +937,7 @@ async function dbFileLoadAsync({
|
|
|
844
937
|
// 4. dbData - same position as dbOpenAsync
|
|
845
938
|
dbData
|
|
846
939
|
],
|
|
847
|
-
"
|
|
940
|
+
"modeDbFile"
|
|
848
941
|
);
|
|
849
942
|
}
|
|
850
943
|
if (modeNoop) {
|
|
@@ -857,6 +950,7 @@ async function dbFileLoadAsync({
|
|
|
857
950
|
typeof filename === "string" && filename,
|
|
858
951
|
`invalid filename ${filename}`
|
|
859
952
|
);
|
|
953
|
+
db.filename2 = filename;
|
|
860
954
|
// Save to tmpfile and then atomically-rename to actual-filename.
|
|
861
955
|
if (moduleFs && modeSave) {
|
|
862
956
|
filename2 = filename;
|
|
@@ -898,15 +992,19 @@ async function dbNoopAsync(...argList) {
|
|
|
898
992
|
|
|
899
993
|
// This function will do nothing except return <argList>.
|
|
900
994
|
|
|
901
|
-
return await dbCallAsync(
|
|
995
|
+
return await dbCallAsync(
|
|
996
|
+
jsbatonCreate("_dbNoop"),
|
|
997
|
+
argList
|
|
998
|
+
);
|
|
902
999
|
}
|
|
903
1000
|
|
|
904
1001
|
async function dbOpenAsync({
|
|
905
1002
|
afterFinalization,
|
|
906
1003
|
dbData,
|
|
907
|
-
filename,
|
|
1004
|
+
filename = ":memory:",
|
|
908
1005
|
flags,
|
|
909
|
-
threadCount = 1
|
|
1006
|
+
threadCount = 1,
|
|
1007
|
+
timeoutBusy = 5000
|
|
910
1008
|
}) {
|
|
911
1009
|
|
|
912
1010
|
// This function will open and return sqlite-database-connection <db>.
|
|
@@ -919,7 +1017,7 @@ async function dbOpenAsync({
|
|
|
919
1017
|
// );
|
|
920
1018
|
let connPool;
|
|
921
1019
|
let db = {busy: 0, filename, ii: 0};
|
|
922
|
-
let
|
|
1020
|
+
let libLgbm;
|
|
923
1021
|
assertOrThrow(typeof filename === "string", `invalid filename ${filename}`);
|
|
924
1022
|
assertOrThrow(
|
|
925
1023
|
!dbData || isExternalBuffer(dbData),
|
|
@@ -950,19 +1048,21 @@ async function dbOpenAsync({
|
|
|
950
1048
|
return ptr;
|
|
951
1049
|
}));
|
|
952
1050
|
db.connPool = connPool;
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
1051
|
+
if (!IS_BROWSER && !DB_OPEN_INIT) {
|
|
1052
|
+
DB_OPEN_INIT = true;
|
|
1053
|
+
// init lgbm
|
|
1054
|
+
libLgbm = process.platform;
|
|
1055
|
+
libLgbm = libLgbm.replace("darwin", "lib_lightgbm.dylib");
|
|
1056
|
+
libLgbm = libLgbm.replace("win32", "lib_lightgbm.dll");
|
|
1057
|
+
libLgbm = libLgbm.replace(process.platform, "lib_lightgbm.so");
|
|
1058
|
+
libLgbm = `${import.meta.dirname}/sqlmath/${libLgbm}`;
|
|
1059
|
+
await dbExecAsync({
|
|
1060
|
+
db,
|
|
1061
|
+
sql: (`
|
|
1062
|
+
PRAGMA busy_timeout = ${timeoutBusy};
|
|
1063
|
+
SELECT LGBM_DLOPEN('${libLgbm}');
|
|
1064
|
+
`)
|
|
1065
|
+
});
|
|
966
1066
|
}
|
|
967
1067
|
return db;
|
|
968
1068
|
}
|
|
@@ -1609,6 +1709,17 @@ async function moduleFsInit() {
|
|
|
1609
1709
|
while (moduleFsInitResolveList.length > 0) {
|
|
1610
1710
|
moduleFsInitResolveList.shift()();
|
|
1611
1711
|
}
|
|
1712
|
+
SQLMATH_NODE = `_sqlmath.napi6_${process.platform}_${process.arch}.node`;
|
|
1713
|
+
SQLMATH_EXE = (
|
|
1714
|
+
`_sqlmath.shell_${process.platform}_${process.arch}`
|
|
1715
|
+
+ process.platform.replace(
|
|
1716
|
+
"win32",
|
|
1717
|
+
".exe"
|
|
1718
|
+
).replace(
|
|
1719
|
+
process.platform,
|
|
1720
|
+
""
|
|
1721
|
+
)
|
|
1722
|
+
);
|
|
1612
1723
|
}
|
|
1613
1724
|
|
|
1614
1725
|
function noop(val) {
|
|
@@ -1654,7 +1765,12 @@ async function sqlmathInit() {
|
|
|
1654
1765
|
// This function will auto-close any open sqlite3-db-pointer,
|
|
1655
1766
|
// after its js-wrapper has been garbage-collected.
|
|
1656
1767
|
|
|
1657
|
-
dbCallAsync(
|
|
1768
|
+
dbCallAsync(
|
|
1769
|
+
jsbatonCreate("_dbClose"),
|
|
1770
|
+
[
|
|
1771
|
+
ptr[0]
|
|
1772
|
+
]
|
|
1773
|
+
);
|
|
1658
1774
|
if (afterFinalization) {
|
|
1659
1775
|
afterFinalization();
|
|
1660
1776
|
}
|
|
@@ -1683,7 +1799,7 @@ async function sqlmathInit() {
|
|
|
1683
1799
|
moduleChildProcessSpawn = moduleChildProcess.spawn;
|
|
1684
1800
|
cModulePath = moduleUrl.fileURLToPath(import.meta.url).replace(
|
|
1685
1801
|
(/\bsqlmath\.mjs$/),
|
|
1686
|
-
|
|
1802
|
+
SQLMATH_NODE
|
|
1687
1803
|
);
|
|
1688
1804
|
|
|
1689
1805
|
// Import napi c-addon.
|
|
@@ -1755,7 +1871,12 @@ function sqlmathWebworkerInit({
|
|
|
1755
1871
|
});
|
|
1756
1872
|
};
|
|
1757
1873
|
// test dbCallAsync handling-behavior
|
|
1758
|
-
dbCallAsync(
|
|
1874
|
+
dbCallAsync(
|
|
1875
|
+
jsbatonCreate("testTimeElapsed"),
|
|
1876
|
+
[
|
|
1877
|
+
true
|
|
1878
|
+
]
|
|
1879
|
+
);
|
|
1759
1880
|
// test dbFileLoadAsync handling-behavior
|
|
1760
1881
|
dbFileLoadAsync({db, filename: "aa", modeTest});
|
|
1761
1882
|
// test jsonParseArraybuffer handling-behavior
|
|
@@ -1779,6 +1900,7 @@ await sqlmathInit();
|
|
|
1779
1900
|
sqlmathInit(); // coverage-hack
|
|
1780
1901
|
|
|
1781
1902
|
export {
|
|
1903
|
+
DB_EXEC_PROFILE_DICT,
|
|
1782
1904
|
LGBM_DTYPE_FLOAT32,
|
|
1783
1905
|
LGBM_DTYPE_FLOAT64,
|
|
1784
1906
|
LGBM_DTYPE_INT32,
|
|
@@ -1812,6 +1934,8 @@ export {
|
|
|
1812
1934
|
SQLITE_OPEN_TRANSIENT_DB,
|
|
1813
1935
|
SQLITE_OPEN_URI,
|
|
1814
1936
|
SQLITE_OPEN_WAL,
|
|
1937
|
+
SQLMATH_EXE,
|
|
1938
|
+
SQLMATH_NODE,
|
|
1815
1939
|
assertErrorThrownAsync,
|
|
1816
1940
|
assertInt64,
|
|
1817
1941
|
assertJsonEqual,
|
|
@@ -1825,6 +1949,7 @@ export {
|
|
|
1825
1949
|
dbExecAndReturnLastTable,
|
|
1826
1950
|
dbExecAndReturnLastValue,
|
|
1827
1951
|
dbExecAsync,
|
|
1952
|
+
dbExecProfile,
|
|
1828
1953
|
dbFileLoadAsync,
|
|
1829
1954
|
dbFileSaveAsync,
|
|
1830
1955
|
dbNoopAsync,
|