sqlmath 2026.4.31 → 2026.7.30
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 +29 -0
- package/README.md +6 -6
- package/_sqlmath.napi6_darwin_arm64.node +0 -0
- package/_sqlmath.napi6_darwin_x64.node +0 -0
- package/_sqlmath.napi6_win32_x64.node +0 -0
- package/_sqlmath.shell_darwin_arm64 +0 -0
- package/_sqlmath.shell_darwin_x64 +0 -0
- package/_sqlmath.shell_win32_x64.exe +0 -0
- package/jslint.mjs +3353 -2683
- package/package.json +1 -1
- package/sqlmath.mjs +265 -179
- package/sqlmath_browser.mjs +10 -59
- package/sqlmath_wasm.js +2 -2
- package/test.mjs +23 -13
package/package.json
CHANGED
package/sqlmath.mjs
CHANGED
|
@@ -20,12 +20,36 @@
|
|
|
20
20
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
21
|
// SOFTWARE.
|
|
22
22
|
|
|
23
|
+
/*
|
|
24
|
+
sh one-liner:
|
|
25
|
+
sh jslint_ci.sh shCiBuildWasm
|
|
26
|
+
sh jslint_ci.sh shSqlmathUpdate
|
|
27
|
+
*/
|
|
23
28
|
|
|
24
29
|
/*jslint beta, bitwise, name, node*/
|
|
25
30
|
/*global FinalizationRegistry*/
|
|
26
31
|
"use strict";
|
|
27
32
|
|
|
28
|
-
|
|
33
|
+
// init debugInline
|
|
34
|
+
const debugInline = (function () {
|
|
35
|
+
let consoleError = Object;
|
|
36
|
+
function debug(...argList) {
|
|
37
|
+
|
|
38
|
+
// This function will print <argList> to stderr and then return <argList>[0].
|
|
39
|
+
|
|
40
|
+
consoleError("\n\ndebugInline");
|
|
41
|
+
consoleError(...argList);
|
|
42
|
+
consoleError("\n");
|
|
43
|
+
if (consoleError === Object) {
|
|
44
|
+
consoleError = console.error;
|
|
45
|
+
}
|
|
46
|
+
return argList[0];
|
|
47
|
+
}
|
|
48
|
+
return debug;
|
|
49
|
+
}());
|
|
50
|
+
debugInline(); // coverage-hack
|
|
51
|
+
|
|
52
|
+
const JSBATON_ARGC = 8; //jslint-ignore-line
|
|
29
53
|
const JSBATON_OFFSET_ALL = 256;
|
|
30
54
|
const JSBATON_OFFSET_ARGV = 128;
|
|
31
55
|
const JSBATON_OFFSET_BUFV = 192;
|
|
@@ -84,10 +108,11 @@ const SQLITE_OPEN_TRANSIENT_DB = 0x00000400; /* VFS only */
|
|
|
84
108
|
const SQLITE_OPEN_URI = 0x00000040; /* Ok for sqlite3_open_v2() */
|
|
85
109
|
const SQLITE_OPEN_WAL = 0x00080000; /* VFS only */
|
|
86
110
|
|
|
87
|
-
|
|
111
|
+
const DB_EXEC_PROFILE_DICT = {}; //jslint-ignore-line
|
|
112
|
+
const DB_STATE = {};
|
|
113
|
+
const version = "v2026.7.30";
|
|
88
114
|
let DB_EXEC_PROFILE_MODE;
|
|
89
115
|
let DB_EXEC_PROFILE_SQL_LENGTH;
|
|
90
|
-
let DB_STATE = {};
|
|
91
116
|
let IS_BROWSER;
|
|
92
117
|
let SQLMATH_EXE;
|
|
93
118
|
let SQLMATH_NODE;
|
|
@@ -95,24 +120,6 @@ let cModule;
|
|
|
95
120
|
let cModulePath;
|
|
96
121
|
let consoleError = console.error;
|
|
97
122
|
let dbFinalizationRegistry;
|
|
98
|
-
// init debugInline
|
|
99
|
-
let debugInline = (function () {
|
|
100
|
-
let __consoleError = function () {
|
|
101
|
-
return;
|
|
102
|
-
};
|
|
103
|
-
function debug(...argv) {
|
|
104
|
-
|
|
105
|
-
// This function will print <argv> to stderr and then return <argv>[0].
|
|
106
|
-
|
|
107
|
-
__consoleError("\n\ndebugInline");
|
|
108
|
-
__consoleError(...argv);
|
|
109
|
-
__consoleError("\n");
|
|
110
|
-
return argv[0];
|
|
111
|
-
}
|
|
112
|
-
debug(); // Coverage-hack.
|
|
113
|
-
__consoleError = console.error; //jslint-ignore-line
|
|
114
|
-
return debug;
|
|
115
|
-
}());
|
|
116
123
|
let moduleChildProcess;
|
|
117
124
|
let moduleChildProcessSpawn;
|
|
118
125
|
let moduleCrypto;
|
|
@@ -128,7 +135,6 @@ let {
|
|
|
128
135
|
let sqlMessageDict = {}; // dict of web-worker-callbacks
|
|
129
136
|
let sqlMessageId = 0;
|
|
130
137
|
let sqlWorker;
|
|
131
|
-
let version = "v2026.4.31";
|
|
132
138
|
|
|
133
139
|
async function assertErrorThrownAsync(asyncFunc, regexp) {
|
|
134
140
|
|
|
@@ -487,6 +493,197 @@ SQLMATH_CFLAG_WNO_LIST=" \\
|
|
|
487
493
|
);
|
|
488
494
|
}
|
|
489
495
|
|
|
496
|
+
function csvFromListofList({
|
|
497
|
+
colList,
|
|
498
|
+
rowList
|
|
499
|
+
}) {
|
|
500
|
+
// this function will convert json <rowList> to csv with given <colList>
|
|
501
|
+
let data = JSON.stringify([[colList], rowList].flat(), undefined, 1);
|
|
502
|
+
// convert data to csv
|
|
503
|
+
data = data.replace((
|
|
504
|
+
/\n /g
|
|
505
|
+
), "");
|
|
506
|
+
data = data.replace((
|
|
507
|
+
/\n \[/g
|
|
508
|
+
), "");
|
|
509
|
+
data = data.replace((
|
|
510
|
+
/\n \],?/g
|
|
511
|
+
), "\r\n");
|
|
512
|
+
data = data.slice(1, -2);
|
|
513
|
+
// sqlite-strings are c-strings which should never contain null-char
|
|
514
|
+
data = data.replace((
|
|
515
|
+
/\u0000/g
|
|
516
|
+
), "");
|
|
517
|
+
// hide double-backslash `\\\\` as null-char
|
|
518
|
+
data = data.replace((
|
|
519
|
+
/\\\\/g
|
|
520
|
+
), "\u0000");
|
|
521
|
+
// escape double-quote `\\"` to `""`
|
|
522
|
+
data = data.replace((
|
|
523
|
+
/\\"/g
|
|
524
|
+
), "\"\"");
|
|
525
|
+
// replace newline with space
|
|
526
|
+
data = data.replace((
|
|
527
|
+
/\\r\\n|\\r|\\n/g
|
|
528
|
+
), " ");
|
|
529
|
+
// restore double-backslash `\\\\` from null-char
|
|
530
|
+
data = data.replace((
|
|
531
|
+
/\u0000/g
|
|
532
|
+
), "\\\\");
|
|
533
|
+
return data;
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
function csvToListofList({
|
|
537
|
+
csv
|
|
538
|
+
}) {
|
|
539
|
+
// This function will convert <csv>-text to json list-of-list.
|
|
540
|
+
//
|
|
541
|
+
// https://tools.ietf.org/html/rfc4180#section-2
|
|
542
|
+
// Definition of the CSV Format
|
|
543
|
+
// While there are various specifications and implementations for the
|
|
544
|
+
// CSV format (for ex. [4], [5], [6] and [7]), there is no formal
|
|
545
|
+
// specification in existence, which allows for a wide variety of
|
|
546
|
+
// interpretations of CSV files. This section documents the format that
|
|
547
|
+
// seems to be followed by most implementations:
|
|
548
|
+
//
|
|
549
|
+
// 1. Each record is located on a separate line, delimited by a line
|
|
550
|
+
// break (CRLF). For example:
|
|
551
|
+
// aaa,bbb,ccc CRLF
|
|
552
|
+
// zzz,yyy,xxx CRLF
|
|
553
|
+
//
|
|
554
|
+
// 2. The last record in the file may or may not have an ending line
|
|
555
|
+
// break. For example:
|
|
556
|
+
// aaa,bbb,ccc CRLF
|
|
557
|
+
// zzz,yyy,xxx
|
|
558
|
+
//
|
|
559
|
+
// 3. There maybe an optional header line appearing as the first line
|
|
560
|
+
// of the file with the same format as normal record lines. This
|
|
561
|
+
// header will contain names corresponding to the fields in the file
|
|
562
|
+
// and should contain the same number of fields as the records in
|
|
563
|
+
// the rest of the file (the presence or absence of the header line
|
|
564
|
+
// should be indicated via the optional "header" parameter of this
|
|
565
|
+
// MIME type). For example:
|
|
566
|
+
// field_name,field_name,field_name CRLF
|
|
567
|
+
// aaa,bbb,ccc CRLF
|
|
568
|
+
// zzz,yyy,xxx CRLF
|
|
569
|
+
//
|
|
570
|
+
// 4. Within the header and each record, there may be one or more
|
|
571
|
+
// fields, separated by commas. Each line should contain the same
|
|
572
|
+
// number of fields throughout the file. Spaces are considered part
|
|
573
|
+
// of a field and should not be ignored. The last field in the
|
|
574
|
+
// record must not be followed by a comma. For example:
|
|
575
|
+
// aaa,bbb,ccc
|
|
576
|
+
//
|
|
577
|
+
// 5. Each field may or may not be enclosed in double quotes (however
|
|
578
|
+
// some programs, such as Microsoft Excel, do not use double quotes
|
|
579
|
+
// at all). If fields are not enclosed with double quotes, then
|
|
580
|
+
// double quotes may not appear inside the fields. For example:
|
|
581
|
+
// "aaa","bbb","ccc" CRLF
|
|
582
|
+
// zzz,yyy,xxx
|
|
583
|
+
//
|
|
584
|
+
// 6. Fields containing line breaks (CRLF), double quotes, and commas
|
|
585
|
+
// should be enclosed in double-quotes. For example:
|
|
586
|
+
// "aaa","b CRLF
|
|
587
|
+
// bb","ccc" CRLF
|
|
588
|
+
// zzz,yyy,xxx
|
|
589
|
+
//
|
|
590
|
+
// 7. If double-quotes are used to enclose fields, then a double-quote
|
|
591
|
+
// appearing inside a field must be escaped by preceding it with
|
|
592
|
+
// another double quote. For example:
|
|
593
|
+
// "aaa","b""bb","ccc"
|
|
594
|
+
let match;
|
|
595
|
+
let quote;
|
|
596
|
+
let rgx;
|
|
597
|
+
let row;
|
|
598
|
+
let rowList;
|
|
599
|
+
let val;
|
|
600
|
+
// normalize "\r\n" to "\n"
|
|
601
|
+
csv = csv.trimEnd().replace((
|
|
602
|
+
/\r\n?/gu
|
|
603
|
+
), "\n") + "\n";
|
|
604
|
+
rgx = (
|
|
605
|
+
/(.*?)(""|"|,|\n)/gu
|
|
606
|
+
);
|
|
607
|
+
rowList = [];
|
|
608
|
+
// reset row
|
|
609
|
+
row = [];
|
|
610
|
+
val = "";
|
|
611
|
+
while (true) {
|
|
612
|
+
match = rgx.exec(csv);
|
|
613
|
+
if (!match) {
|
|
614
|
+
// 2. The last record in the file may or may not have an ending line
|
|
615
|
+
// break. For example:
|
|
616
|
+
// aaa,bbb,ccc CRLF
|
|
617
|
+
// zzz,yyy,xxx
|
|
618
|
+
if (!row.length) {
|
|
619
|
+
break;
|
|
620
|
+
}
|
|
621
|
+
// // if eof missing crlf, then mock it
|
|
622
|
+
// rgx.lastIndex = csv.length;
|
|
623
|
+
// match = [
|
|
624
|
+
// "\n", "", "\n"
|
|
625
|
+
// ];
|
|
626
|
+
}
|
|
627
|
+
// build val
|
|
628
|
+
val += match[1];
|
|
629
|
+
if (match[2] === "\"") {
|
|
630
|
+
// 5. Each field may or may not be enclosed in double quotes (however
|
|
631
|
+
// some programs, such as Microsoft Excel, do not use double quotes
|
|
632
|
+
// at all). If fields are not enclosed with double quotes, then
|
|
633
|
+
// double quotes may not appear inside the fields. For example:
|
|
634
|
+
// "aaa","bbb","ccc" CRLF
|
|
635
|
+
// zzz,yyy,xxx
|
|
636
|
+
quote = !quote;
|
|
637
|
+
} else if (quote) {
|
|
638
|
+
// 7. If double-quotes are used to enclose fields, then a double-quote
|
|
639
|
+
// appearing inside a field must be escaped by preceding it with
|
|
640
|
+
// another double quote. For example:
|
|
641
|
+
// "aaa","b""bb","ccc"
|
|
642
|
+
if (match[2] === "\"\"") {
|
|
643
|
+
val += "\"";
|
|
644
|
+
// 6. Fields containing line breaks (CRLF), double quotes, and commas
|
|
645
|
+
// should be enclosed in double-quotes. For example:
|
|
646
|
+
// "aaa","b CRLF
|
|
647
|
+
// bb","ccc" CRLF
|
|
648
|
+
// zzz,yyy,xxx
|
|
649
|
+
} else {
|
|
650
|
+
val += match[2];
|
|
651
|
+
}
|
|
652
|
+
} else if (match[2] === ",") {
|
|
653
|
+
// 4. Within the header and each record, there may be one or more
|
|
654
|
+
// fields, separated by commas. Each line should contain the same
|
|
655
|
+
// number of fields throughout the file. Spaces are considered part
|
|
656
|
+
// of a field and should not be ignored. The last field in the
|
|
657
|
+
// record must not be followed by a comma. For example:
|
|
658
|
+
// aaa,bbb,ccc
|
|
659
|
+
// delimit val
|
|
660
|
+
row.push(val);
|
|
661
|
+
val = "";
|
|
662
|
+
} else if (match[2] === "\n") {
|
|
663
|
+
// 1. Each record is located on a separate line, delimited by a line
|
|
664
|
+
// break (CRLF). For example:
|
|
665
|
+
// aaa,bbb,ccc CRLF
|
|
666
|
+
// zzz,yyy,xxx CRLF
|
|
667
|
+
// delimit val
|
|
668
|
+
row.push(val);
|
|
669
|
+
val = "";
|
|
670
|
+
// append row
|
|
671
|
+
rowList.push(row);
|
|
672
|
+
// reset row
|
|
673
|
+
row = [];
|
|
674
|
+
}
|
|
675
|
+
}
|
|
676
|
+
// // append val
|
|
677
|
+
// if (val) {
|
|
678
|
+
// row.push(val);
|
|
679
|
+
// }
|
|
680
|
+
// // append row
|
|
681
|
+
// if (row.length) {
|
|
682
|
+
// rowList.push(row);
|
|
683
|
+
// }
|
|
684
|
+
return rowList;
|
|
685
|
+
}
|
|
686
|
+
|
|
490
687
|
async function dbCallAsync(baton, argList, mode, db) {
|
|
491
688
|
|
|
492
689
|
// This function will call c-function dbXxx() with given <funcname>
|
|
@@ -517,7 +714,7 @@ async function dbCallAsync(baton, argList, mode, db) {
|
|
|
517
714
|
profileStart = Date.now();
|
|
518
715
|
sql = String(argList[1]);
|
|
519
716
|
// sql-hash - remove comment
|
|
520
|
-
sql = sql.replace((
|
|
717
|
+
sql = sql.replace((/\s*?--.*?$/gm), "");
|
|
521
718
|
// sql-hash - remove vowel
|
|
522
719
|
sql = sql.replace((/[aeiou]\b/gi), "\u0000$&");
|
|
523
720
|
sql = sql.replace((/([bcdfghjklmnpqrstvwxyz])[aeiou]+/gi), "$1");
|
|
@@ -1093,7 +1290,7 @@ async function dbTableImportAsync({
|
|
|
1093
1290
|
}
|
|
1094
1291
|
switch (mode) {
|
|
1095
1292
|
case "csv":
|
|
1096
|
-
rowList =
|
|
1293
|
+
rowList = csvToListofList({
|
|
1097
1294
|
csv: textData
|
|
1098
1295
|
});
|
|
1099
1296
|
break;
|
|
@@ -1215,7 +1412,7 @@ async function fsExistsUnlessTest(file, mode) {
|
|
|
1215
1412
|
return false;
|
|
1216
1413
|
}
|
|
1217
1414
|
try {
|
|
1218
|
-
await moduleFs.promises.access(file);
|
|
1415
|
+
await moduleFs.promises.access(file, moduleFs.promises.constants.F_OK);
|
|
1219
1416
|
return true;
|
|
1220
1417
|
} catch (ignore) {
|
|
1221
1418
|
return false;
|
|
@@ -1521,157 +1718,6 @@ function jsonParseArraybuffer(buf) {
|
|
|
1521
1718
|
);
|
|
1522
1719
|
}
|
|
1523
1720
|
|
|
1524
|
-
function jsonRowListFromCsv({
|
|
1525
|
-
csv
|
|
1526
|
-
}) {
|
|
1527
|
-
// This function will convert <csv>-text to json list-of-list.
|
|
1528
|
-
//
|
|
1529
|
-
// https://tools.ietf.org/html/rfc4180#section-2
|
|
1530
|
-
// Definition of the CSV Format
|
|
1531
|
-
// While there are various specifications and implementations for the
|
|
1532
|
-
// CSV format (for ex. [4], [5], [6] and [7]), there is no formal
|
|
1533
|
-
// specification in existence, which allows for a wide variety of
|
|
1534
|
-
// interpretations of CSV files. This section documents the format that
|
|
1535
|
-
// seems to be followed by most implementations:
|
|
1536
|
-
//
|
|
1537
|
-
// 1. Each record is located on a separate line, delimited by a line
|
|
1538
|
-
// break (CRLF). For example:
|
|
1539
|
-
// aaa,bbb,ccc CRLF
|
|
1540
|
-
// zzz,yyy,xxx CRLF
|
|
1541
|
-
//
|
|
1542
|
-
// 2. The last record in the file may or may not have an ending line
|
|
1543
|
-
// break. For example:
|
|
1544
|
-
// aaa,bbb,ccc CRLF
|
|
1545
|
-
// zzz,yyy,xxx
|
|
1546
|
-
//
|
|
1547
|
-
// 3. There maybe an optional header line appearing as the first line
|
|
1548
|
-
// of the file with the same format as normal record lines. This
|
|
1549
|
-
// header will contain names corresponding to the fields in the file
|
|
1550
|
-
// and should contain the same number of fields as the records in
|
|
1551
|
-
// the rest of the file (the presence or absence of the header line
|
|
1552
|
-
// should be indicated via the optional "header" parameter of this
|
|
1553
|
-
// MIME type). For example:
|
|
1554
|
-
// field_name,field_name,field_name CRLF
|
|
1555
|
-
// aaa,bbb,ccc CRLF
|
|
1556
|
-
// zzz,yyy,xxx CRLF
|
|
1557
|
-
//
|
|
1558
|
-
// 4. Within the header and each record, there may be one or more
|
|
1559
|
-
// fields, separated by commas. Each line should contain the same
|
|
1560
|
-
// number of fields throughout the file. Spaces are considered part
|
|
1561
|
-
// of a field and should not be ignored. The last field in the
|
|
1562
|
-
// record must not be followed by a comma. For example:
|
|
1563
|
-
// aaa,bbb,ccc
|
|
1564
|
-
//
|
|
1565
|
-
// 5. Each field may or may not be enclosed in double quotes (however
|
|
1566
|
-
// some programs, such as Microsoft Excel, do not use double quotes
|
|
1567
|
-
// at all). If fields are not enclosed with double quotes, then
|
|
1568
|
-
// double quotes may not appear inside the fields. For example:
|
|
1569
|
-
// "aaa","bbb","ccc" CRLF
|
|
1570
|
-
// zzz,yyy,xxx
|
|
1571
|
-
//
|
|
1572
|
-
// 6. Fields containing line breaks (CRLF), double quotes, and commas
|
|
1573
|
-
// should be enclosed in double-quotes. For example:
|
|
1574
|
-
// "aaa","b CRLF
|
|
1575
|
-
// bb","ccc" CRLF
|
|
1576
|
-
// zzz,yyy,xxx
|
|
1577
|
-
//
|
|
1578
|
-
// 7. If double-quotes are used to enclose fields, then a double-quote
|
|
1579
|
-
// appearing inside a field must be escaped by preceding it with
|
|
1580
|
-
// another double quote. For example:
|
|
1581
|
-
// "aaa","b""bb","ccc"
|
|
1582
|
-
let match;
|
|
1583
|
-
let quote;
|
|
1584
|
-
let rgx;
|
|
1585
|
-
let row;
|
|
1586
|
-
let rowList;
|
|
1587
|
-
let val;
|
|
1588
|
-
// normalize "\r\n" to "\n"
|
|
1589
|
-
csv = csv.trimEnd().replace((
|
|
1590
|
-
/\r\n?/gu
|
|
1591
|
-
), "\n") + "\n";
|
|
1592
|
-
rgx = (
|
|
1593
|
-
/(.*?)(""|"|,|\n)/gu
|
|
1594
|
-
);
|
|
1595
|
-
rowList = [];
|
|
1596
|
-
// reset row
|
|
1597
|
-
row = [];
|
|
1598
|
-
val = "";
|
|
1599
|
-
while (true) {
|
|
1600
|
-
match = rgx.exec(csv);
|
|
1601
|
-
if (!match) {
|
|
1602
|
-
// 2. The last record in the file may or may not have an ending line
|
|
1603
|
-
// break. For example:
|
|
1604
|
-
// aaa,bbb,ccc CRLF
|
|
1605
|
-
// zzz,yyy,xxx
|
|
1606
|
-
if (!row.length) {
|
|
1607
|
-
break;
|
|
1608
|
-
}
|
|
1609
|
-
// // if eof missing crlf, then mock it
|
|
1610
|
-
// rgx.lastIndex = csv.length;
|
|
1611
|
-
// match = [
|
|
1612
|
-
// "\n", "", "\n"
|
|
1613
|
-
// ];
|
|
1614
|
-
}
|
|
1615
|
-
// build val
|
|
1616
|
-
val += match[1];
|
|
1617
|
-
if (match[2] === "\"") {
|
|
1618
|
-
// 5. Each field may or may not be enclosed in double quotes (however
|
|
1619
|
-
// some programs, such as Microsoft Excel, do not use double quotes
|
|
1620
|
-
// at all). If fields are not enclosed with double quotes, then
|
|
1621
|
-
// double quotes may not appear inside the fields. For example:
|
|
1622
|
-
// "aaa","bbb","ccc" CRLF
|
|
1623
|
-
// zzz,yyy,xxx
|
|
1624
|
-
quote = !quote;
|
|
1625
|
-
} else if (quote) {
|
|
1626
|
-
// 7. If double-quotes are used to enclose fields, then a double-quote
|
|
1627
|
-
// appearing inside a field must be escaped by preceding it with
|
|
1628
|
-
// another double quote. For example:
|
|
1629
|
-
// "aaa","b""bb","ccc"
|
|
1630
|
-
if (match[2] === "\"\"") {
|
|
1631
|
-
val += "\"";
|
|
1632
|
-
// 6. Fields containing line breaks (CRLF), double quotes, and commas
|
|
1633
|
-
// should be enclosed in double-quotes. For example:
|
|
1634
|
-
// "aaa","b CRLF
|
|
1635
|
-
// bb","ccc" CRLF
|
|
1636
|
-
// zzz,yyy,xxx
|
|
1637
|
-
} else {
|
|
1638
|
-
val += match[2];
|
|
1639
|
-
}
|
|
1640
|
-
} else if (match[2] === ",") {
|
|
1641
|
-
// 4. Within the header and each record, there may be one or more
|
|
1642
|
-
// fields, separated by commas. Each line should contain the same
|
|
1643
|
-
// number of fields throughout the file. Spaces are considered part
|
|
1644
|
-
// of a field and should not be ignored. The last field in the
|
|
1645
|
-
// record must not be followed by a comma. For example:
|
|
1646
|
-
// aaa,bbb,ccc
|
|
1647
|
-
// delimit val
|
|
1648
|
-
row.push(val);
|
|
1649
|
-
val = "";
|
|
1650
|
-
} else if (match[2] === "\n") {
|
|
1651
|
-
// 1. Each record is located on a separate line, delimited by a line
|
|
1652
|
-
// break (CRLF). For example:
|
|
1653
|
-
// aaa,bbb,ccc CRLF
|
|
1654
|
-
// zzz,yyy,xxx CRLF
|
|
1655
|
-
// delimit val
|
|
1656
|
-
row.push(val);
|
|
1657
|
-
val = "";
|
|
1658
|
-
// append row
|
|
1659
|
-
rowList.push(row);
|
|
1660
|
-
// reset row
|
|
1661
|
-
row = [];
|
|
1662
|
-
}
|
|
1663
|
-
}
|
|
1664
|
-
// // append val
|
|
1665
|
-
// if (val) {
|
|
1666
|
-
// row.push(val);
|
|
1667
|
-
// }
|
|
1668
|
-
// // append row
|
|
1669
|
-
// if (row.length) {
|
|
1670
|
-
// rowList.push(row);
|
|
1671
|
-
// }
|
|
1672
|
-
return rowList;
|
|
1673
|
-
}
|
|
1674
|
-
|
|
1675
1721
|
function libPlatformArchExt() {
|
|
1676
1722
|
let libArch = process.arch;
|
|
1677
1723
|
let libExt = process.platform;
|
|
@@ -1740,11 +1786,11 @@ async function moduleFsInit() {
|
|
|
1740
1786
|
);
|
|
1741
1787
|
}
|
|
1742
1788
|
|
|
1743
|
-
function noop(
|
|
1789
|
+
function noop(value) {
|
|
1744
1790
|
|
|
1745
|
-
// This function will do nothing except return <
|
|
1791
|
+
// This function will do nothing except return <value>.
|
|
1746
1792
|
|
|
1747
|
-
return
|
|
1793
|
+
return value;
|
|
1748
1794
|
}
|
|
1749
1795
|
|
|
1750
1796
|
function objectDeepCopyWithKeysSorted(obj) {
|
|
@@ -1904,6 +1950,43 @@ function sqlmathWebworkerInit({
|
|
|
1904
1950
|
}
|
|
1905
1951
|
}
|
|
1906
1952
|
|
|
1953
|
+
async function uvthreadpoolsizeGet() {
|
|
1954
|
+
|
|
1955
|
+
// This function will guess how many logical-processors on current-host.
|
|
1956
|
+
|
|
1957
|
+
let uvthreadpoolsize;
|
|
1958
|
+
await new Promise(function (resolve) {
|
|
1959
|
+
let child;
|
|
1960
|
+
child = moduleChildProcess.spawn(
|
|
1961
|
+
"sh",
|
|
1962
|
+
["-c", (`
|
|
1963
|
+
case "$(uname)" in
|
|
1964
|
+
Darwin)
|
|
1965
|
+
sysctl -n hw.logicalcpu
|
|
1966
|
+
;;
|
|
1967
|
+
Linux)
|
|
1968
|
+
nproc
|
|
1969
|
+
;;
|
|
1970
|
+
*NT*)
|
|
1971
|
+
wmic cpu get NumberOfLogicalProcessors | \
|
|
1972
|
+
grep -v "NumberOfLogicalProcessors"
|
|
1973
|
+
;;
|
|
1974
|
+
esac
|
|
1975
|
+
`)],
|
|
1976
|
+
{stdio: ["ignore", "pipe", "ignore"]}
|
|
1977
|
+
);
|
|
1978
|
+
child.stdout.setEncoding("utf8");
|
|
1979
|
+
child.stdout.on("data", function (chunk) {
|
|
1980
|
+
uvthreadpoolsize = Number(chunk);
|
|
1981
|
+
});
|
|
1982
|
+
child.on("exit", resolve);
|
|
1983
|
+
});
|
|
1984
|
+
if (npm_config_mode_test) {
|
|
1985
|
+
uvthreadpoolsize = undefined;
|
|
1986
|
+
}
|
|
1987
|
+
return uvthreadpoolsize || 4;
|
|
1988
|
+
}
|
|
1989
|
+
|
|
1907
1990
|
function waitAsync(timeout) {
|
|
1908
1991
|
|
|
1909
1992
|
// This function will wait <timeout> ms.
|
|
@@ -1966,6 +2049,8 @@ export {
|
|
|
1966
2049
|
assertOrThrow,
|
|
1967
2050
|
childProcessSpawn2,
|
|
1968
2051
|
ciBuildExt,
|
|
2052
|
+
csvFromListofList,
|
|
2053
|
+
csvToListofList,
|
|
1969
2054
|
dbCloseAsync,
|
|
1970
2055
|
dbExecAndReturnLastBlob,
|
|
1971
2056
|
dbExecAndReturnLastRow,
|
|
@@ -1990,6 +2075,7 @@ export {
|
|
|
1990
2075
|
noop,
|
|
1991
2076
|
objectDeepCopyWithKeysSorted,
|
|
1992
2077
|
sqlmathWebworkerInit,
|
|
2078
|
+
uvthreadpoolsizeGet,
|
|
1993
2079
|
version,
|
|
1994
2080
|
waitAsync
|
|
1995
2081
|
};
|
package/sqlmath_browser.mjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/*jslint beta, bitwise, browser, devel, nomen*/
|
|
2
2
|
import {
|
|
3
3
|
assertOrThrow,
|
|
4
|
+
csvFromListofList,
|
|
4
5
|
dbCloseAsync,
|
|
5
6
|
dbExecAsync,
|
|
6
7
|
dbFileSaveAsync,
|
|
@@ -337,22 +338,11 @@ INSERT INTO tradebot_tech_intra_day
|
|
|
337
338
|
*
|
|
338
339
|
FROM (
|
|
339
340
|
SELECT
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
JOIN (
|
|
346
|
-
SELECT '1a_stk_pct' AS tname
|
|
347
|
-
--
|
|
348
|
-
UNION ALL
|
|
349
|
-
--
|
|
350
|
-
SELECT '1b_stk_lmt' AS tname
|
|
351
|
-
)
|
|
352
|
-
--
|
|
353
|
-
UNION ALL
|
|
354
|
-
--
|
|
355
|
-
SELECT '1a_stk_pct', xdate, xdate2, stk_pct FROM tradebot_tech_intra
|
|
341
|
+
'1a_stk_pct' AS tname,
|
|
342
|
+
xdate,
|
|
343
|
+
xdate2,
|
|
344
|
+
stk_pct AS tval
|
|
345
|
+
FROM tradebot_tech_intra
|
|
356
346
|
--
|
|
357
347
|
UNION ALL
|
|
358
348
|
--
|
|
@@ -984,7 +974,7 @@ INSERT INTO chart._{{ii}}_tradebot_buysell_history (
|
|
|
984
974
|
? "unixepochToTimeutc"
|
|
985
975
|
: "juliandayToDate"
|
|
986
976
|
),
|
|
987
|
-
yaxisTitle: "percent
|
|
977
|
+
yaxisTitle: "percent gain",
|
|
988
978
|
yvalueSuffix: " %"
|
|
989
979
|
};
|
|
990
980
|
return (`
|
|
@@ -1574,7 +1564,8 @@ async function onDbAction(evt) {
|
|
|
1574
1564
|
case "dbtableRename":
|
|
1575
1565
|
title = target.textContent.trim().replace(/\s+/g, " ");
|
|
1576
1566
|
UI_CRUD.querySelector(".modalTitle").innerHTML = (
|
|
1577
|
-
`${stringHtmlSafe(baton.dbtableFullname)}<br
|
|
1567
|
+
`${stringHtmlSafe(baton.dbtableFullname)}<br>` +
|
|
1568
|
+
`${stringHtmlSafe(title)}`
|
|
1578
1569
|
);
|
|
1579
1570
|
UI_CRUD.querySelector("tbody").innerHTML = (
|
|
1580
1571
|
(`
|
|
@@ -1839,7 +1830,7 @@ DELETE FROM ${baton.dbtableName} WHERE rowid = ${baton.rowid};
|
|
|
1839
1830
|
});
|
|
1840
1831
|
data = data[0] || [];
|
|
1841
1832
|
data.shift();
|
|
1842
|
-
data =
|
|
1833
|
+
data = csvFromListofList({
|
|
1843
1834
|
colList: baton.colList,
|
|
1844
1835
|
rowList: data
|
|
1845
1836
|
});
|
|
@@ -2101,46 +2092,6 @@ function onResize() {
|
|
|
2101
2092
|
uitableInitWithinView({});
|
|
2102
2093
|
}
|
|
2103
2094
|
|
|
2104
|
-
function rowListToCsv({
|
|
2105
|
-
colList,
|
|
2106
|
-
rowList
|
|
2107
|
-
}) {
|
|
2108
|
-
// this function will convert json <rowList> to csv with given <colList>
|
|
2109
|
-
let data = JSON.stringify([[colList], rowList].flat(), undefined, 1);
|
|
2110
|
-
// convert data to csv
|
|
2111
|
-
data = data.replace((
|
|
2112
|
-
/\n /g
|
|
2113
|
-
), "");
|
|
2114
|
-
data = data.replace((
|
|
2115
|
-
/\n \[/g
|
|
2116
|
-
), "");
|
|
2117
|
-
data = data.replace((
|
|
2118
|
-
/\n \],?/g
|
|
2119
|
-
), "\r\n");
|
|
2120
|
-
data = data.slice(1, -2);
|
|
2121
|
-
// sqlite-strings are c-strings which should never contain null-char
|
|
2122
|
-
data = data.replace((
|
|
2123
|
-
/\u0000/g
|
|
2124
|
-
), "");
|
|
2125
|
-
// hide double-backslash `\\\\` as null-char
|
|
2126
|
-
data = data.replace((
|
|
2127
|
-
/\\\\/g
|
|
2128
|
-
), "\u0000");
|
|
2129
|
-
// escape double-quote `\\"` to `""`
|
|
2130
|
-
data = data.replace((
|
|
2131
|
-
/\\"/g
|
|
2132
|
-
), "\"\"");
|
|
2133
|
-
// replace newline with space
|
|
2134
|
-
data = data.replace((
|
|
2135
|
-
/\\r\\n|\\r|\\n/g
|
|
2136
|
-
), " ");
|
|
2137
|
-
// restore double-backslash `\\\\` from null-char
|
|
2138
|
-
data = data.replace((
|
|
2139
|
-
/\u0000/g
|
|
2140
|
-
), "\\\\");
|
|
2141
|
-
return data;
|
|
2142
|
-
}
|
|
2143
|
-
|
|
2144
2095
|
function stringHtmlSafe(str) {
|
|
2145
2096
|
// this function will make <str> html-safe
|
|
2146
2097
|
// https://stackoverflow.com/questions/7381974
|
package/sqlmath_wasm.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
/*jslint-disable*/
|
|
2
2
|
// Copyright (c) 2021 Kai Zhu
|
|
3
3
|
// SPDX-License-Identifier: MIT
|
|
4
|
-
// 2026-
|
|
4
|
+
// 2026-08-01T00:48:14+0000
|
|
5
5
|
(function () {
|
|
6
6
|
"use strict";
|
|
7
7
|
|
|
8
|
-
var g;g||(g=typeof Module !== 'undefined' ? Module : {});var aa=Object.assign;
|
|
8
|
+
var g;g||(g=typeof Module !== 'undefined' ? Module : {});var aa=Object.assign;function ba(a){return a&&a.constructor===ArrayBuffer}
|
|
9
9
|
(async function(){let a=h("dbFileLoadOrSave","number",["number","string","number"]),b=h("jsbatonGetErrmsg","string",["number"]),c=h("jsbatonGetString","string",["number","number"]),d=h("sqlite3_errmsg","string",["number"]),e;globalThis.onmessage=async function({data:f}){await e;f.batonPtr=0;try{a:{let G=f.FILENAME_DBTMP;var k=f.JSBATON_OFFSET_ALL;let Rb=f.JSBATON_OFFSET_BUFV,P=f.argList,Q=new Uint8Array(f.baton.buffer),C=0,A=P[4],Sb=0,ea="",W=f.funcname,Va=P[2];switch(W){case "_dbClose":case "_dbExec":case "_dbFileLoad":case "_dbNoop":case "_dbOpen":C=
|
|
10
10
|
ca(Q.byteLength);f.batonPtr=C;l.set(Q,C);switch(W){case "_dbClose":console.error(`_dbClose("${c(C,1)}")`);break;case "_dbFileLoad":Va||da(G,new Uint8Array(A));break;case "_dbOpen":console.error(`_dbOpen("${c(C,0)}")`)}fa(C);ea=b(C);Q.set(l.subarray(C,C+k));switch(!ea&&W){case "_dbExec":A=new BigInt64Array(Q.buffer,Rb);P[0]=l.slice(Number(A[0]),Number(A[0]+A[1])).buffer;ha(Number(A[0]));break;case "_dbFileLoad":if(Va){k=G;var m=m||0;var p=p||"binary";if("utf8"!==p&&"binary"!==p)throw Error('Invalid encoding type "'+
|
|
11
11
|
p+'"');var q,t=n(k,m),v=r(k).size,H=new Uint8Array(v);ia(t,H,0,v,0);"utf8"===p?q=u(H,0):"binary"===p&&(q=H);ja(t);P[0]=q.buffer;ka(G)}break;case "_dbOpen":A&&(da(G,new Uint8Array(A)),A=Number(la(C,0)),(Sb=a(A,G,0))&&(ea=d(A)),ka(G))}postMessage({argList:P,baton:new DataView(Q.buffer),errmsg:ea,funcname:W,id:f.id},[Q.buffer,...P.filter(ba)]);var Tb=void 0;break a}throw Error(`invalid funcname "${W}"`);}await Tb}catch(G){postMessage({errmsg:G.stack,id:f.id})}finally{ha(f.batonPtr)}};e=new Promise(function(f){g.postRun=
|