sqlmath 2024.1.21 → 2024.5.26

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 CHANGED
@@ -4,6 +4,26 @@
4
4
  - sqlmath - Add sqlite-extension for lightgbm.
5
5
  - none
6
6
 
7
+ # v2024.5.26
8
+ - webdemo - Replace market-indices .spx/.ndx/.dji with futures .es/.nq/.ym.
9
+ - sqlite - Decouple c-function str99JsonAppendText() from builtin-function jsonAppendString().
10
+ - sqlite - Update to sqlite v3.42.0.
11
+ - sqlmath - Remove little-used sqlean-regexp-extension and file sqlmath_external_pcre2.c.
12
+ - sqlmath - bugfix - Fix off-by-2 root-mean-square-deviation calculation of parameter lee in sql-function win_sinefit2().
13
+ - sqlmath - bugfix - Fix null-case handling-behavior for function dbExecAndReturnLastBlobAsync().
14
+ - sqlmath - Add functions dbExecAndReturnFirstRow(), dbExecAndReturnFirstTable(), listOrEmptyList().
15
+ - jslint - Update jslint to v2024.4.1-beta.
16
+ - ci - bugfix - Fix package.json config-regression breaking ci.
17
+
18
+ # v2024.3.25
19
+ - jslint-ci - Add shell-functions shGitPullrequestCleanup(), shGitPullrequest() to automatically cleanup or create-and-push github-pull-commit to origin/alpha.
20
+ - ci - Fix tmpdir in shell-function shBrowserScreenshot().
21
+ - webdemo - Update tables tradebot_intraday_xxx.
22
+ - migration - Rename prm ydate to xdate, ytime to xtime.
23
+ - sqlmath - Move function dbTableImportAsync from file sqlmath_browser.mjs to sqlmath.mjs.
24
+ - ci - Update github-ci for actions/cache, actions/setup-python from nodejs v16 to nodejs v20.
25
+ - ci - Update shell-function shRollupFetch() to fix blank date-committed.
26
+
7
27
  # v2024.1.21
8
28
  - sqlmath - Add function assertErrorThrownAsync().
9
29
 
@@ -24,7 +44,7 @@
24
44
  - sqlean - Add sqlean-extension regexp with regexp-replacement and pcre2 - increases wasm size to 1.1mb.
25
45
  - zlib - Update to zlib v1.3.
26
46
  - sqlmath - Fix SIGSEGV error when binding external-buffer during db_exec.
27
- - sqlite - Update to sqlite v3.39.4.
47
+ - sqlite - Update to sqlite v3.42.0.
28
48
  - python - Add python-functions db_file_load(), db_file_save().
29
49
  - sqlmath - Revamp how js-arraybuffers are passed to c-api without copying.
30
50
  - python - Revamp python-c-extension to support cp312.
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
 
4
4
  # Status
5
- | Branch | [master<br>(v2024.1.21)](https://github.com/sqlmath/sqlmath/tree/master) | [beta<br>(Web Demo)](https://github.com/sqlmath/sqlmath/tree/beta) | [alpha<br>(Development)](https://github.com/sqlmath/sqlmath/tree/alpha) |
5
+ | Branch | [master<br>(v2024.5.26)](https://github.com/sqlmath/sqlmath/tree/master) | [beta<br>(Web Demo)](https://github.com/sqlmath/sqlmath/tree/beta) | [alpha<br>(Development)](https://github.com/sqlmath/sqlmath/tree/alpha) |
6
6
  |--:|:--:|:--:|:--:|
7
7
  | CI | [![ci](https://github.com/sqlmath/sqlmath/actions/workflows/ci.yml/badge.svg?branch=master)](https://github.com/sqlmath/sqlmath/actions?query=branch%3Amaster) | [![ci](https://github.com/sqlmath/sqlmath/actions/workflows/ci.yml/badge.svg?branch=beta)](https://github.com/sqlmath/sqlmath/actions?query=branch%3Abeta) | [![ci](https://github.com/sqlmath/sqlmath/actions/workflows/ci.yml/badge.svg?branch=alpha)](https://github.com/sqlmath/sqlmath/actions?query=branch%3Aalpha) |
8
8
  | Coverage | [![coverage](https://sqlmath.github.io/sqlmath/branch-master/.artifact/coverage/coverage_badge.svg)](https://sqlmath.github.io/sqlmath/branch-master/.artifact/coverage/index.html) | [![coverage](https://sqlmath.github.io/sqlmath/branch-beta/.artifact/coverage/coverage_badge.svg)](https://sqlmath.github.io/sqlmath/branch-beta/.artifact/coverage/index.html) | [![coverage](https://sqlmath.github.io/sqlmath/branch-alpha/.artifact/coverage/coverage_badge.svg)](https://sqlmath.github.io/sqlmath/branch-alpha/.artifact/coverage/index.html) |
@@ -106,7 +106,6 @@ PORT=8080 sh jslint_ci.sh shHttpFileServer
106
106
  # License
107
107
  - [sqlite](https://github.com/sqlite/sqlite) is under [public domain](https://www.sqlite.org/copyright.html).
108
108
  - [jslint](https://github.com/jslint-org/jslint) is under [Unlicense License](https://github.com/jslint-org/jslint/blob/master/LICENSE).
109
- - [pcre2](https://github.com/PCRE2Project/pcre2) is under [3-Clause BSD License](https://github.com/PCRE2Project/pcre2/blob/pcre2-10.42/LICENCE)
110
109
  - [zlib](https://github.com/madler/zlib) is under [zlib License](https://github.com/madler/zlib/blob/v1.2.13/LICENSE).
111
110
  - [cpplint.py](cpplint.py) is under [3-Clause BSD License](https://github.com/cpplint/cpplint/blob/1.5.5/LICENSE).
112
111
  - [indent.exe](indent.exe) is under [GPLv3 License](https://www.gnu.org/licenses/gpl-3.0.txt).
@@ -122,11 +121,11 @@ PORT=8080 sh jslint_ci.sh shHttpFileServer
122
121
  ```shell
123
122
  python -m build
124
123
  #
125
- twine upload --repository testpypi dist/sqlmath-2024.1.21*
126
- py -m pip install --index-url https://test.pypi.org/simple/ sqlmath==2024.1.21
124
+ twine upload --repository testpypi dist/sqlmath-2024.5.26*
125
+ py -m pip install --index-url https://test.pypi.org/simple/ sqlmath==2024.5.26
127
126
  #
128
- twine upload dist/sqlmath-2024.1.21*
129
- pip install sqlmath==2024.1.21
127
+ twine upload dist/sqlmath-2024.5.26*
128
+ pip install sqlmath==2024.5.26
130
129
  ```
131
130
 
132
131
 
@@ -134,13 +133,16 @@ pip install sqlmath==2024.1.21
134
133
  ### sqlite upgrade
135
134
  - goto https://www.sqlite.org/changes.html
136
135
  ```shell
137
- curl -L https://www.sqlite.org/2023/sqlite-autoconf-3420000.tar.gz | tar -xz
138
- git grep "3\.39\.4\|3390400"
139
- for FILE in .ci.sh sqlite_rollup.c
136
+ curl -L https://www.sqlite.org/2023/sqlite-autoconf-3440200.tar.gz | tar -xz
137
+ mv sqlite-autoconf-3440200 .sqlite-autoconf-3440200
138
+ git grep "3\.42\.0\|3420000"
139
+ for FILE in .ci.sh sqlmath_external_sqlite.c sqlmath_external_zlib.c
140
140
  do
141
- sed -i -e "s|\<3\.39\.4\>|3.42.0|g" "$FILE"
142
- sed -i -e "s|\<3390400\>|3420000|g" "$FILE"
141
+ sed -i -e "s|\<3\.42\.0\>|3.44.2|g" "$FILE"
142
+ sed -i -e "s|\<3420000\>|3440200|g" "$FILE"
143
143
  done
144
- git grep "3\.39\.4\|3390400"
145
- shRollupFetch sqlite_rollup.c
144
+ git grep "3\.42\.0\|3420000"
145
+ shRollupFetch sqlmath_external_sqlite.c
146
+ shRollupFetch sqlmath_external_zlib.c
147
+ sh jslint_ci.sh shSqlmathUpdate
146
148
  ```
package/jslint.mjs CHANGED
@@ -163,7 +163,7 @@ let jslint_charset_ascii = (
163
163
  + "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_"
164
164
  + "`abcdefghijklmnopqrstuvwxyz{|}~\u007f"
165
165
  );
166
- let jslint_edition = "v2023.11.1-beta";
166
+ let jslint_edition = "v2024.4.1-beta";
167
167
  let jslint_export; // The jslint object to be exported.
168
168
  let jslint_fudge = 1; // Fudge starting line and starting
169
169
  // ... column to 1.
@@ -5487,13 +5487,15 @@ function jslint_phase3_parse(state) {
5487
5487
  if (
5488
5488
  token_nxt.id === "."
5489
5489
  || token_nxt.id === "?."
5490
- || token_nxt.id === "["
5490
+
5491
+ // PR-459 - Allow destructuring-assignment after function-definition.
5492
+
5493
+ // || token_nxt.id === "["
5491
5494
  ) {
5492
5495
 
5493
5496
  // test_cause:
5494
5497
  // ["function aa(){}\n.aa", "prefix_function", "unexpected_a", ".", 1]
5495
5498
  // ["function aa(){}\n?.aa", "prefix_function", "unexpected_a", "?.", 1]
5496
- // ["function aa(){}\n[]", "prefix_function", "unexpected_a", "[", 1]
5497
5499
 
5498
5500
  warn("unexpected_a");
5499
5501
  }
@@ -9952,6 +9954,12 @@ async function jstestDescribe(description, testFunction) {
9952
9954
  process.on("exit", jstestOnExit);
9953
9955
  }
9954
9956
 
9957
+ // PR-457 - Wait awhile for imports to initialize.
9958
+
9959
+ await new Promise(function (resolve) {
9960
+ setTimeout(resolve);
9961
+ });
9962
+
9955
9963
  // Init jstestItList.
9956
9964
 
9957
9965
  jstestItList = [];
@@ -10005,9 +10013,7 @@ function jstestIt(description, testFunction, mode) {
10005
10013
  } catch (errCaught) {
10006
10014
  err = errCaught;
10007
10015
  }
10008
- resolve([
10009
- err, description, mode
10010
- ]);
10016
+ resolve([err, description, mode]);
10011
10017
  }));
10012
10018
  }
10013
10019
 
package/package.json CHANGED
@@ -11,7 +11,7 @@
11
11
  "engines": {
12
12
  "node": ">=14"
13
13
  },
14
- "fileCount": 42,
14
+ "fileCount": 41,
15
15
  "homepage": "https://github.com/sqlmath/sqlmath",
16
16
  "keywords": [
17
17
  "data-science",
@@ -29,7 +29,7 @@
29
29
  ],
30
30
  "repository": {
31
31
  "type": "git",
32
- "url": "https://github.com/sqlmath/sqlmath.git"
32
+ "url": "git+https://github.com/sqlmath/sqlmath.git"
33
33
  },
34
34
  "scripts": {
35
35
  "build": "sh jslint_ci.sh shCiBuildNodejs",
@@ -38,5 +38,5 @@
38
38
  },
39
39
  "shCiArtifactUpload": 1,
40
40
  "shCiPublishNpm": 1,
41
- "version": "2024.1.21"
41
+ "version": "2024.5.26"
42
42
  }
package/sqlmath.mjs CHANGED
@@ -92,6 +92,7 @@ let debugInline = (function () {
92
92
  }());
93
93
  let moduleChildProcess;
94
94
  let moduleChildProcessSpawn;
95
+ let moduleCrypto;
95
96
  let moduleFs;
96
97
  let moduleFsInitResolveList;
97
98
  let modulePath;
@@ -104,7 +105,7 @@ let {
104
105
  let sqlMessageDict = {}; // dict of web-worker-callbacks
105
106
  let sqlMessageId = 0;
106
107
  let sqlWorker;
107
- let version = "v2024.1.21";
108
+ let version = "v2024.5.26";
108
109
 
109
110
  async function assertErrorThrownAsync(asyncFunc, regexp) {
110
111
 
@@ -341,7 +342,6 @@ async function ciBuildExt1NodejsConfigure({
341
342
  ],
342
343
  "sources": [
343
344
  "sqlmath_base.c",
344
- "sqlmath_external_pcre2.c",
345
345
  "sqlmath_external_sqlite.c",
346
346
  "sqlmath_external_zlib.c"
347
347
  ],
@@ -626,14 +626,59 @@ async function dbCloseAsync(db) {
626
626
  }));
627
627
  }
628
628
 
629
+ async function dbExecAndReturnFirstRow({
630
+ bindList = [],
631
+ db,
632
+ sql
633
+ }) {
634
+
635
+ // This function will exec <sql> in <db>,
636
+ // and return first-row or empty-object.
637
+
638
+ return (
639
+ noop(
640
+ noop(
641
+ await dbExecAsync({
642
+ bindList,
643
+ db,
644
+ sql
645
+ })
646
+ )[0]
647
+ || []
648
+ )[0]
649
+ || {}
650
+ );
651
+ }
652
+
653
+ async function dbExecAndReturnFirstTable({
654
+ bindList = [],
655
+ db,
656
+ sql
657
+ }) {
658
+
659
+ // This function will exec <sql> in <db>,
660
+ // and return first-table or empty-list.
661
+
662
+ return (
663
+ noop(
664
+ await dbExecAsync({
665
+ bindList,
666
+ db,
667
+ sql
668
+ })
669
+ )[0]
670
+ || []
671
+ );
672
+ }
673
+
629
674
  function dbExecAndReturnLastBlobAsync({
630
675
  bindList = [],
631
676
  db,
632
677
  sql
633
678
  }) {
634
679
 
635
- // This function will exec <sql> in <db> and return last value retrieved
636
- // from execution as raw blob/buffer.
680
+ // This function will exec <sql> in <db>,
681
+ // and return last-value retrieved from execution as raw blob/buffer.
637
682
 
638
683
  return dbExecAsync({
639
684
  bindList,
@@ -743,6 +788,25 @@ async function dbFileLoadAsync({
743
788
 
744
789
  // This function will load <filename> to <db>.
745
790
 
791
+ let filename2;
792
+ async function _dbFileLoad() {
793
+ dbData = await dbCallAsync(
794
+ jsbatonCreate("_dbFileLoad"),
795
+ [
796
+ // 0. sqlite3 * pInMemory
797
+ db,
798
+ // 1. char *zFilename
799
+ filename,
800
+ // 2. const int isSave
801
+ modeSave,
802
+ // 3. undefined
803
+ undefined,
804
+ // 4. dbData - same position as dbOpenAsync
805
+ dbData
806
+ ],
807
+ "modeDb"
808
+ );
809
+ }
746
810
  if (modeNoop) {
747
811
  return;
748
812
  }
@@ -753,29 +817,30 @@ async function dbFileLoadAsync({
753
817
  typeof filename === "string" && filename,
754
818
  `invalid filename ${filename}`
755
819
  );
756
- dbData = await dbCallAsync(
757
- jsbatonCreate("_dbFileLoad"),
758
- [
759
- // 0. sqlite3 * pInMemory
760
- db,
761
- // 1. char *zFilename
762
- filename,
763
- // 2. const int isSave
764
- modeSave,
765
- // 3. undefined
766
- undefined,
767
- // 4. dbData - same position as dbOpenAsync
768
- dbData
769
- ],
770
- "modeDb"
771
- );
820
+ // Save to tmpfile and then atomically-rename to actual-filename.
821
+ if (moduleFs && modeSave) {
822
+ filename2 = filename;
823
+ filename = modulePath.join(
824
+ modulePath.dirname(filename),
825
+ `.dbFileSaveAsync.${moduleCrypto.randomUUID()}`
826
+ );
827
+ try {
828
+ await _dbFileLoad();
829
+ await moduleFs.promises.rename(filename, filename2);
830
+ } finally {
831
+ await moduleFs.promises.unlink(filename).catch(noop);
832
+ }
833
+ } else {
834
+ await _dbFileLoad();
835
+ }
772
836
  return dbData[1 + 0];
773
837
  }
774
838
 
775
839
  async function dbFileSaveAsync({
776
840
  db,
777
841
  dbData,
778
- filename
842
+ filename,
843
+ modeNoop
779
844
  }) {
780
845
 
781
846
  // This function will save <db> to <filename>.
@@ -784,6 +849,7 @@ async function dbFileSaveAsync({
784
849
  db,
785
850
  dbData,
786
851
  filename,
852
+ modeNoop,
787
853
  modeSave: 1
788
854
  });
789
855
  }
@@ -846,6 +912,117 @@ async function dbOpenAsync({
846
912
  return db;
847
913
  }
848
914
 
915
+ async function dbTableImportAsync({
916
+ db,
917
+ mode,
918
+ tableName,
919
+ textData
920
+ }) {
921
+ // this function will create table from imported csv/json <textData>
922
+ let colList;
923
+ let rowList;
924
+ let rowidList;
925
+ let tmp;
926
+ switch (mode) {
927
+ case "csv":
928
+ rowList = jsonRowListFromCsv({
929
+ csv: textData
930
+ });
931
+ break;
932
+ case "tsv":
933
+ rowList = [];
934
+ textData.trimEnd().replace((/.+/g), function (line) {
935
+ rowList.push(line.split("\t"));
936
+ });
937
+ break;
938
+ // case "json":
939
+ default:
940
+ rowList = JSON.parse(textData);
941
+ }
942
+ if (!(typeof rowList === "object" && rowList)) {
943
+ rowList = [];
944
+ }
945
+ // normalize rowList to list
946
+ if (!Array.isArray(rowList)) {
947
+ rowidList = [];
948
+ rowList = Object.entries(rowList).map(function ([
949
+ key, val
950
+ ]) {
951
+ rowidList.push(key);
952
+ return val;
953
+ });
954
+ }
955
+ // normalize rowList[ii] to list
956
+ if (rowList.length === 0) {
957
+ rowList.push([
958
+ "undefined"
959
+ ]);
960
+ }
961
+ if (!Array.isArray(rowList[0])) {
962
+ colList = Array.from(
963
+ new Set(
964
+ rowList.map(function (obj) {
965
+ return Object.keys(obj);
966
+ }).flat()
967
+ )
968
+ );
969
+ rowList = rowList.map(function (obj) {
970
+ return colList.map(function (key) {
971
+ return obj[key];
972
+ });
973
+ });
974
+ rowList.unshift(colList);
975
+ }
976
+ // init colList
977
+ colList = rowList.shift();
978
+ // preserve rowid
979
+ if (rowidList) {
980
+ colList.unshift("rowid");
981
+ rowList.forEach(function (row, ii) {
982
+ row.unshift(rowidList[ii]);
983
+ });
984
+ }
985
+ // normalize colList
986
+ tmp = new Set();
987
+ colList = colList.map(function (colName) {
988
+ let colName2;
989
+ let duplicate = 0;
990
+ colName = "c_" + colName.toLowerCase().replace((
991
+ /\W/g
992
+ ), "_");
993
+ while (true) {
994
+ duplicate += 1;
995
+ colName2 = (
996
+ duplicate === 1
997
+ ? colName
998
+ : colName + "_" + duplicate
999
+ );
1000
+ if (!tmp.has(colName2)) {
1001
+ tmp.add(colName2);
1002
+ return colName2;
1003
+ }
1004
+ }
1005
+ });
1006
+ // create dbtable from rowList
1007
+ await dbExecAsync({
1008
+ bindList: {
1009
+ rowList: JSON.stringify(rowList)
1010
+ },
1011
+ db,
1012
+ sql: (
1013
+ rowList.length === 0
1014
+ ? `CREATE TABLE ${tableName} (${colList.join(",")});`
1015
+ : (
1016
+ `CREATE TABLE ${tableName} AS SELECT `
1017
+ + colList.map(function (colName, ii) {
1018
+ return "value->>" + ii + " AS " + colName;
1019
+ }).join(",")
1020
+ + " FROM JSON_EACH($rowList);"
1021
+ )
1022
+ )
1023
+ });
1024
+ }
1025
+
849
1026
  async function fsCopyFileUnlessTest(file1, file2, mode) {
850
1027
 
851
1028
  // This function will copy <file1> to <file2> unless <npm_config_mode_test> = 1.
@@ -1167,6 +1344,164 @@ function jsonParseArraybuffer(buf) {
1167
1344
  );
1168
1345
  }
1169
1346
 
1347
+ function jsonRowListFromCsv({
1348
+ csv
1349
+ }) {
1350
+ // this function will convert <csv>-text to json list-of-list
1351
+ //
1352
+ // https://tools.ietf.org/html/rfc4180#section-2
1353
+ // Definition of the CSV Format
1354
+ // While there are various specifications and implementations for the
1355
+ // CSV format (for ex. [4], [5], [6] and [7]), there is no formal
1356
+ // specification in existence, which allows for a wide variety of
1357
+ // interpretations of CSV files. This section documents the format that
1358
+ // seems to be followed by most implementations:
1359
+ //
1360
+ // 1. Each record is located on a separate line, delimited by a line
1361
+ // break (CRLF). For example:
1362
+ // aaa,bbb,ccc CRLF
1363
+ // zzz,yyy,xxx CRLF
1364
+ //
1365
+ // 2. The last record in the file may or may not have an ending line
1366
+ // break. For example:
1367
+ // aaa,bbb,ccc CRLF
1368
+ // zzz,yyy,xxx
1369
+ //
1370
+ // 3. There maybe an optional header line appearing as the first line
1371
+ // of the file with the same format as normal record lines. This
1372
+ // header will contain names corresponding to the fields in the file
1373
+ // and should contain the same number of fields as the records in
1374
+ // the rest of the file (the presence or absence of the header line
1375
+ // should be indicated via the optional "header" parameter of this
1376
+ // MIME type). For example:
1377
+ // field_name,field_name,field_name CRLF
1378
+ // aaa,bbb,ccc CRLF
1379
+ // zzz,yyy,xxx CRLF
1380
+ //
1381
+ // 4. Within the header and each record, there may be one or more
1382
+ // fields, separated by commas. Each line should contain the same
1383
+ // number of fields throughout the file. Spaces are considered part
1384
+ // of a field and should not be ignored. The last field in the
1385
+ // record must not be followed by a comma. For example:
1386
+ // aaa,bbb,ccc
1387
+ //
1388
+ // 5. Each field may or may not be enclosed in double quotes (however
1389
+ // some programs, such as Microsoft Excel, do not use double quotes
1390
+ // at all). If fields are not enclosed with double quotes, then
1391
+ // double quotes may not appear inside the fields. For example:
1392
+ // "aaa","bbb","ccc" CRLF
1393
+ // zzz,yyy,xxx
1394
+ //
1395
+ // 6. Fields containing line breaks (CRLF), double quotes, and commas
1396
+ // should be enclosed in double-quotes. For example:
1397
+ // "aaa","b CRLF
1398
+ // bb","ccc" CRLF
1399
+ // zzz,yyy,xxx
1400
+ //
1401
+ // 7. If double-quotes are used to enclose fields, then a double-quote
1402
+ // appearing inside a field must be escaped by preceding it with
1403
+ // another double quote. For example:
1404
+ // "aaa","b""bb","ccc"
1405
+ let match;
1406
+ let quote;
1407
+ let rgx;
1408
+ let row;
1409
+ let rowList;
1410
+ let val;
1411
+ // normalize "\r\n" to "\n"
1412
+ csv = csv.trimEnd().replace((
1413
+ /\r\n?/gu
1414
+ ), "\n") + "\n";
1415
+ rgx = (
1416
+ /(.*?)(""|"|,|\n)/gu
1417
+ );
1418
+ rowList = [];
1419
+ // reset row
1420
+ row = [];
1421
+ val = "";
1422
+ while (true) {
1423
+ match = rgx.exec(csv);
1424
+ if (!match) {
1425
+ // 2. The last record in the file may or may not have an ending line
1426
+ // break. For example:
1427
+ // aaa,bbb,ccc CRLF
1428
+ // zzz,yyy,xxx
1429
+ if (!row.length) {
1430
+ break;
1431
+ }
1432
+ // // if eof missing crlf, then mock it
1433
+ // rgx.lastIndex = csv.length;
1434
+ // match = [
1435
+ // "\n", "", "\n"
1436
+ // ];
1437
+ }
1438
+ // build val
1439
+ val += match[1];
1440
+ if (match[2] === "\"") {
1441
+ // 5. Each field may or may not be enclosed in double quotes (however
1442
+ // some programs, such as Microsoft Excel, do not use double quotes
1443
+ // at all). If fields are not enclosed with double quotes, then
1444
+ // double quotes may not appear inside the fields. For example:
1445
+ // "aaa","bbb","ccc" CRLF
1446
+ // zzz,yyy,xxx
1447
+ quote = !quote;
1448
+ } else if (quote) {
1449
+ // 7. If double-quotes are used to enclose fields, then a double-quote
1450
+ // appearing inside a field must be escaped by preceding it with
1451
+ // another double quote. For example:
1452
+ // "aaa","b""bb","ccc"
1453
+ if (match[2] === "\"\"") {
1454
+ val += "\"";
1455
+ // 6. Fields containing line breaks (CRLF), double quotes, and commas
1456
+ // should be enclosed in double-quotes. For example:
1457
+ // "aaa","b CRLF
1458
+ // bb","ccc" CRLF
1459
+ // zzz,yyy,xxx
1460
+ } else {
1461
+ val += match[2];
1462
+ }
1463
+ } else if (match[2] === ",") {
1464
+ // 4. Within the header and each record, there may be one or more
1465
+ // fields, separated by commas. Each line should contain the same
1466
+ // number of fields throughout the file. Spaces are considered part
1467
+ // of a field and should not be ignored. The last field in the
1468
+ // record must not be followed by a comma. For example:
1469
+ // aaa,bbb,ccc
1470
+ // delimit val
1471
+ row.push(val);
1472
+ val = "";
1473
+ } else if (match[2] === "\n") {
1474
+ // 1. Each record is located on a separate line, delimited by a line
1475
+ // break (CRLF). For example:
1476
+ // aaa,bbb,ccc CRLF
1477
+ // zzz,yyy,xxx CRLF
1478
+ // delimit val
1479
+ row.push(val);
1480
+ val = "";
1481
+ // append row
1482
+ rowList.push(row);
1483
+ // reset row
1484
+ row = [];
1485
+ }
1486
+ }
1487
+ // // append val
1488
+ // if (val) {
1489
+ // row.push(val);
1490
+ // }
1491
+ // // append row
1492
+ // if (row.length) {
1493
+ // rowList.push(row);
1494
+ // }
1495
+ return rowList;
1496
+ }
1497
+
1498
+ function listOrEmptyList(list) {
1499
+
1500
+ // This function will return <list> or empty-list if falsy.
1501
+
1502
+ return list || [];
1503
+ }
1504
+
1170
1505
  async function moduleFsInit() {
1171
1506
 
1172
1507
  // This function will import nodejs builtin-modules if they have not yet been
@@ -1191,11 +1526,13 @@ async function moduleFsInit() {
1191
1526
  moduleFsInitResolveList = [];
1192
1527
  [
1193
1528
  moduleChildProcess,
1529
+ moduleCrypto,
1194
1530
  moduleFs,
1195
1531
  modulePath,
1196
1532
  moduleUrl
1197
1533
  ] = await Promise.all([
1198
1534
  import("child_process"),
1535
+ import("crypto"),
1199
1536
  import("fs"),
1200
1537
  import("path"),
1201
1538
  import("url")
@@ -1359,6 +1696,15 @@ function sqlmathWebworkerInit({
1359
1696
  }
1360
1697
  }
1361
1698
 
1699
+ function waitAsync(timeout) {
1700
+
1701
+ // This function will wait <timeout> ms.
1702
+
1703
+ return new Promise(function (resolve) {
1704
+ setTimeout(resolve, timeout * !npm_config_mode_test);
1705
+ });
1706
+ }
1707
+
1362
1708
  sqlmathInit(); // coverage-hack
1363
1709
  await sqlmathInit();
1364
1710
  sqlmathInit(); // coverage-hack
@@ -1393,12 +1739,15 @@ export {
1393
1739
  childProcessSpawn2,
1394
1740
  ciBuildExt,
1395
1741
  dbCloseAsync,
1742
+ dbExecAndReturnFirstRow,
1743
+ dbExecAndReturnFirstTable,
1396
1744
  dbExecAndReturnLastBlobAsync,
1397
1745
  dbExecAsync,
1398
1746
  dbFileLoadAsync,
1399
1747
  dbFileSaveAsync,
1400
1748
  dbNoopAsync,
1401
1749
  dbOpenAsync,
1750
+ dbTableImportAsync,
1402
1751
  debugInline,
1403
1752
  fsCopyFileUnlessTest,
1404
1753
  fsExistsUnlessTest,
@@ -1406,8 +1755,10 @@ export {
1406
1755
  fsWriteFileUnlessTest,
1407
1756
  jsbatonGetInt64,
1408
1757
  jsbatonGetString,
1758
+ listOrEmptyList,
1409
1759
  noop,
1410
1760
  objectDeepCopyWithKeysSorted,
1411
1761
  sqlmathWebworkerInit,
1412
- version
1762
+ version,
1763
+ waitAsync
1413
1764
  };