sqlmath 2023.12.20 → 2024.3.25

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,18 @@
4
4
  - sqlmath - Add sqlite-extension for lightgbm.
5
5
  - none
6
6
 
7
+ # v2024.3.25
8
+ - jslint-ci - Add shell-functions shGitPullrequestCleanup(), shGitPullrequest() to automatically cleanup or create-and-push github-pull-commit to origin/alpha.
9
+ - ci - Fix tmpdir in shell-function shBrowserScreenshot().
10
+ - webdemo - Update tables tradebot_intraday_xxx.
11
+ - migration - Rename prm ydate to xdate, ytime to xtime.
12
+ - sqlmath - Move function dbTableImportAsync from file sqlmath_browser.mjs to sqlmath.mjs.
13
+ - ci - Update github-ci for actions/cache, actions/setup-python from nodejs v16 to nodejs v20.
14
+ - ci - Update shell-function shRollupFetch() to fix blank date-committed.
15
+
16
+ # v2024.1.21
17
+ - sqlmath - Add function assertErrorThrownAsync().
18
+
7
19
  # v2023.12.20
8
20
  - chart - Improve ergonomics with import tsv.
9
21
  - betadog - bugfix - Remove over-complicated prm ttt from table y_historical.
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
 
4
4
  # Status
5
- | Branch | [master<br>(v2023.12.20)](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.3.25)](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) |
@@ -122,11 +122,11 @@ PORT=8080 sh jslint_ci.sh shHttpFileServer
122
122
  ```shell
123
123
  python -m build
124
124
  #
125
- twine upload --repository testpypi dist/sqlmath-2023.12.20*
126
- py -m pip install --index-url https://test.pypi.org/simple/ sqlmath==2023.12.20
125
+ twine upload --repository testpypi dist/sqlmath-2024.3.25*
126
+ py -m pip install --index-url https://test.pypi.org/simple/ sqlmath==2024.3.25
127
127
  #
128
- twine upload dist/sqlmath-2023.12.20*
129
- pip install sqlmath==2023.12.20
128
+ twine upload dist/sqlmath-2024.3.25*
129
+ pip install sqlmath==2024.3.25
130
130
  ```
131
131
 
132
132
 
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.3.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
@@ -38,5 +38,5 @@
38
38
  },
39
39
  "shCiArtifactUpload": 1,
40
40
  "shCiPublishNpm": 1,
41
- "version": "2023.12.20"
41
+ "version": "2024.3.25"
42
42
  }
package/sqlmath.mjs CHANGED
@@ -104,7 +104,24 @@ let {
104
104
  let sqlMessageDict = {}; // dict of web-worker-callbacks
105
105
  let sqlMessageId = 0;
106
106
  let sqlWorker;
107
- let version = "v2023.12.20";
107
+ let version = "v2024.3.25";
108
+
109
+ async function assertErrorThrownAsync(asyncFunc, regexp) {
110
+
111
+ // This function will assert calling <asyncFunc> throws an error.
112
+
113
+ let err;
114
+ try {
115
+ await asyncFunc();
116
+ } catch (errCaught) {
117
+ err = errCaught;
118
+ }
119
+ assertOrThrow(err, "No error thrown.");
120
+ assertOrThrow(
121
+ !regexp || new RegExp(regexp).test(err.message),
122
+ err
123
+ );
124
+ }
108
125
 
109
126
  function assertInt64(val) {
110
127
  // This function will assert <val> is within range of c99-signed-long-long.
@@ -758,7 +775,8 @@ async function dbFileLoadAsync({
758
775
  async function dbFileSaveAsync({
759
776
  db,
760
777
  dbData,
761
- filename
778
+ filename,
779
+ modeNoop
762
780
  }) {
763
781
 
764
782
  // This function will save <db> to <filename>.
@@ -767,6 +785,7 @@ async function dbFileSaveAsync({
767
785
  db,
768
786
  dbData,
769
787
  filename,
788
+ modeNoop,
770
789
  modeSave: 1
771
790
  });
772
791
  }
@@ -829,6 +848,117 @@ async function dbOpenAsync({
829
848
  return db;
830
849
  }
831
850
 
851
+ async function dbTableImportAsync({
852
+ db,
853
+ mode,
854
+ tableName,
855
+ textData
856
+ }) {
857
+ // this function will create table from imported csv/json <textData>
858
+ let colList;
859
+ let rowList;
860
+ let rowidList;
861
+ let tmp;
862
+ switch (mode) {
863
+ case "csv":
864
+ rowList = jsonRowListFromCsv({
865
+ csv: textData
866
+ });
867
+ break;
868
+ case "tsv":
869
+ rowList = [];
870
+ textData.trimEnd().replace((/.+/g), function (line) {
871
+ rowList.push(line.split("\t"));
872
+ });
873
+ break;
874
+ // case "json":
875
+ default:
876
+ rowList = JSON.parse(textData);
877
+ }
878
+ if (!(typeof rowList === "object" && rowList)) {
879
+ rowList = [];
880
+ }
881
+ // normalize rowList to list
882
+ if (!Array.isArray(rowList)) {
883
+ rowidList = [];
884
+ rowList = Object.entries(rowList).map(function ([
885
+ key, val
886
+ ]) {
887
+ rowidList.push(key);
888
+ return val;
889
+ });
890
+ }
891
+ // normalize rowList[ii] to list
892
+ if (rowList.length === 0) {
893
+ rowList.push([
894
+ "undefined"
895
+ ]);
896
+ }
897
+ if (!Array.isArray(rowList[0])) {
898
+ colList = Array.from(
899
+ new Set(
900
+ rowList.map(function (obj) {
901
+ return Object.keys(obj);
902
+ }).flat()
903
+ )
904
+ );
905
+ rowList = rowList.map(function (obj) {
906
+ return colList.map(function (key) {
907
+ return obj[key];
908
+ });
909
+ });
910
+ rowList.unshift(colList);
911
+ }
912
+ // init colList
913
+ colList = rowList.shift();
914
+ // preserve rowid
915
+ if (rowidList) {
916
+ colList.unshift("rowid");
917
+ rowList.forEach(function (row, ii) {
918
+ row.unshift(rowidList[ii]);
919
+ });
920
+ }
921
+ // normalize colList
922
+ tmp = new Set();
923
+ colList = colList.map(function (colName) {
924
+ let colName2;
925
+ let duplicate = 0;
926
+ colName = "c_" + colName.toLowerCase().replace((
927
+ /\W/g
928
+ ), "_");
929
+ while (true) {
930
+ duplicate += 1;
931
+ colName2 = (
932
+ duplicate === 1
933
+ ? colName
934
+ : colName + "_" + duplicate
935
+ );
936
+ if (!tmp.has(colName2)) {
937
+ tmp.add(colName2);
938
+ return colName2;
939
+ }
940
+ }
941
+ });
942
+ // create dbtable from rowList
943
+ await dbExecAsync({
944
+ bindList: {
945
+ rowList: JSON.stringify(rowList)
946
+ },
947
+ db,
948
+ sql: (
949
+ rowList.length === 0
950
+ ? `CREATE TABLE ${tableName} (${colList.join(",")});`
951
+ : (
952
+ `CREATE TABLE ${tableName} AS SELECT `
953
+ + colList.map(function (colName, ii) {
954
+ return "value->>" + ii + " AS " + colName;
955
+ }).join(",")
956
+ + " FROM JSON_EACH($rowList);"
957
+ )
958
+ )
959
+ });
960
+ }
961
+
832
962
  async function fsCopyFileUnlessTest(file1, file2, mode) {
833
963
 
834
964
  // This function will copy <file1> to <file2> unless <npm_config_mode_test> = 1.
@@ -1150,6 +1280,157 @@ function jsonParseArraybuffer(buf) {
1150
1280
  );
1151
1281
  }
1152
1282
 
1283
+ function jsonRowListFromCsv({
1284
+ csv
1285
+ }) {
1286
+ // this function will convert <csv>-text to json list-of-list
1287
+ //
1288
+ // https://tools.ietf.org/html/rfc4180#section-2
1289
+ // Definition of the CSV Format
1290
+ // While there are various specifications and implementations for the
1291
+ // CSV format (for ex. [4], [5], [6] and [7]), there is no formal
1292
+ // specification in existence, which allows for a wide variety of
1293
+ // interpretations of CSV files. This section documents the format that
1294
+ // seems to be followed by most implementations:
1295
+ //
1296
+ // 1. Each record is located on a separate line, delimited by a line
1297
+ // break (CRLF). For example:
1298
+ // aaa,bbb,ccc CRLF
1299
+ // zzz,yyy,xxx CRLF
1300
+ //
1301
+ // 2. The last record in the file may or may not have an ending line
1302
+ // break. For example:
1303
+ // aaa,bbb,ccc CRLF
1304
+ // zzz,yyy,xxx
1305
+ //
1306
+ // 3. There maybe an optional header line appearing as the first line
1307
+ // of the file with the same format as normal record lines. This
1308
+ // header will contain names corresponding to the fields in the file
1309
+ // and should contain the same number of fields as the records in
1310
+ // the rest of the file (the presence or absence of the header line
1311
+ // should be indicated via the optional "header" parameter of this
1312
+ // MIME type). For example:
1313
+ // field_name,field_name,field_name CRLF
1314
+ // aaa,bbb,ccc CRLF
1315
+ // zzz,yyy,xxx CRLF
1316
+ //
1317
+ // 4. Within the header and each record, there may be one or more
1318
+ // fields, separated by commas. Each line should contain the same
1319
+ // number of fields throughout the file. Spaces are considered part
1320
+ // of a field and should not be ignored. The last field in the
1321
+ // record must not be followed by a comma. For example:
1322
+ // aaa,bbb,ccc
1323
+ //
1324
+ // 5. Each field may or may not be enclosed in double quotes (however
1325
+ // some programs, such as Microsoft Excel, do not use double quotes
1326
+ // at all). If fields are not enclosed with double quotes, then
1327
+ // double quotes may not appear inside the fields. For example:
1328
+ // "aaa","bbb","ccc" CRLF
1329
+ // zzz,yyy,xxx
1330
+ //
1331
+ // 6. Fields containing line breaks (CRLF), double quotes, and commas
1332
+ // should be enclosed in double-quotes. For example:
1333
+ // "aaa","b CRLF
1334
+ // bb","ccc" CRLF
1335
+ // zzz,yyy,xxx
1336
+ //
1337
+ // 7. If double-quotes are used to enclose fields, then a double-quote
1338
+ // appearing inside a field must be escaped by preceding it with
1339
+ // another double quote. For example:
1340
+ // "aaa","b""bb","ccc"
1341
+ let match;
1342
+ let quote;
1343
+ let rgx;
1344
+ let row;
1345
+ let rowList;
1346
+ let val;
1347
+ // normalize "\r\n" to "\n"
1348
+ csv = csv.trimEnd().replace((
1349
+ /\r\n?/gu
1350
+ ), "\n") + "\n";
1351
+ rgx = (
1352
+ /(.*?)(""|"|,|\n)/gu
1353
+ );
1354
+ rowList = [];
1355
+ // reset row
1356
+ row = [];
1357
+ val = "";
1358
+ while (true) {
1359
+ match = rgx.exec(csv);
1360
+ if (!match) {
1361
+ // 2. The last record in the file may or may not have an ending line
1362
+ // break. For example:
1363
+ // aaa,bbb,ccc CRLF
1364
+ // zzz,yyy,xxx
1365
+ if (!row.length) {
1366
+ break;
1367
+ }
1368
+ // // if eof missing crlf, then mock it
1369
+ // rgx.lastIndex = csv.length;
1370
+ // match = [
1371
+ // "\n", "", "\n"
1372
+ // ];
1373
+ }
1374
+ // build val
1375
+ val += match[1];
1376
+ if (match[2] === "\"") {
1377
+ // 5. Each field may or may not be enclosed in double quotes (however
1378
+ // some programs, such as Microsoft Excel, do not use double quotes
1379
+ // at all). If fields are not enclosed with double quotes, then
1380
+ // double quotes may not appear inside the fields. For example:
1381
+ // "aaa","bbb","ccc" CRLF
1382
+ // zzz,yyy,xxx
1383
+ quote = !quote;
1384
+ } else if (quote) {
1385
+ // 7. If double-quotes are used to enclose fields, then a double-quote
1386
+ // appearing inside a field must be escaped by preceding it with
1387
+ // another double quote. For example:
1388
+ // "aaa","b""bb","ccc"
1389
+ if (match[2] === "\"\"") {
1390
+ val += "\"";
1391
+ // 6. Fields containing line breaks (CRLF), double quotes, and commas
1392
+ // should be enclosed in double-quotes. For example:
1393
+ // "aaa","b CRLF
1394
+ // bb","ccc" CRLF
1395
+ // zzz,yyy,xxx
1396
+ } else {
1397
+ val += match[2];
1398
+ }
1399
+ } else if (match[2] === ",") {
1400
+ // 4. Within the header and each record, there may be one or more
1401
+ // fields, separated by commas. Each line should contain the same
1402
+ // number of fields throughout the file. Spaces are considered part
1403
+ // of a field and should not be ignored. The last field in the
1404
+ // record must not be followed by a comma. For example:
1405
+ // aaa,bbb,ccc
1406
+ // delimit val
1407
+ row.push(val);
1408
+ val = "";
1409
+ } else if (match[2] === "\n") {
1410
+ // 1. Each record is located on a separate line, delimited by a line
1411
+ // break (CRLF). For example:
1412
+ // aaa,bbb,ccc CRLF
1413
+ // zzz,yyy,xxx CRLF
1414
+ // delimit val
1415
+ row.push(val);
1416
+ val = "";
1417
+ // append row
1418
+ rowList.push(row);
1419
+ // reset row
1420
+ row = [];
1421
+ }
1422
+ }
1423
+ // // append val
1424
+ // if (val) {
1425
+ // row.push(val);
1426
+ // }
1427
+ // // append row
1428
+ // if (row.length) {
1429
+ // rowList.push(row);
1430
+ // }
1431
+ return rowList;
1432
+ }
1433
+
1153
1434
  async function moduleFsInit() {
1154
1435
 
1155
1436
  // This function will import nodejs builtin-modules if they have not yet been
@@ -1368,6 +1649,7 @@ export {
1368
1649
  SQLITE_OPEN_TRANSIENT_DB,
1369
1650
  SQLITE_OPEN_URI,
1370
1651
  SQLITE_OPEN_WAL,
1652
+ assertErrorThrownAsync,
1371
1653
  assertInt64,
1372
1654
  assertJsonEqual,
1373
1655
  assertNumericalEqual,
@@ -1381,6 +1663,7 @@ export {
1381
1663
  dbFileSaveAsync,
1382
1664
  dbNoopAsync,
1383
1665
  dbOpenAsync,
1666
+ dbTableImportAsync,
1384
1667
  debugInline,
1385
1668
  fsCopyFileUnlessTest,
1386
1669
  fsExistsUnlessTest,