sqlmath 0.0.5 → 2022.4.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/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "email": "kaizhu256@gmail.com",
4
4
  "name": "kai zhu"
5
5
  },
6
- "counter": 1,
6
+ "counter": 10,
7
7
  "cpu": [
8
8
  "x64"
9
9
  ],
@@ -11,7 +11,7 @@
11
11
  "engines": {
12
12
  "node": ">=14"
13
13
  },
14
- "fileCount": 22,
14
+ "fileCount": 28,
15
15
  "homepage": "https://github.com/sqlmath/sqlmath",
16
16
  "keywords": [
17
17
  "data-science",
@@ -32,10 +32,10 @@
32
32
  "url": "https://github.com/sqlmath/sqlmath"
33
33
  },
34
34
  "scripts": {
35
- "build": "sh jslint_ci.sh shCiBuild",
36
- "test": "sh jslint_ci.sh shCiTest",
35
+ "build": "sh jslint_ci.sh shCiBuildNodejs",
36
+ "test": "sh jslint_ci.sh shCiTestNodejs",
37
37
  "test2": "sh jslint_ci.sh shCiBase",
38
38
  "test_win32": "node -e \"require('child_process').spawn('C:\\\\Program Files\\\\Git\\\\bin\\\\bash.exe',['-c','npm run test' + ' ' + process.argv.slice(1).join(' ')],{stdio:['ignore',1,2]});\""
39
39
  },
40
- "version": "0.0.5"
40
+ "version": "2022.4.28"
41
41
  }
package/sqlmath.mjs CHANGED
@@ -8,7 +8,8 @@ let {
8
8
  assertJsonEqual,
9
9
  assertOrThrow,
10
10
  debugInline,
11
- noop
11
+ noop,
12
+ objectDeepCopyWithKeysSorted
12
13
  } = jslint;
13
14
  let local = Object.assign({}, jslint);
14
15
 
@@ -17,7 +18,7 @@ function assertNumericalEqual(aa, bb, message) {
17
18
  // This function will assert aa - bb <= Number.EPSILON
18
19
 
19
20
  assertOrThrow(aa, "value cannot be 0 or falsy");
20
- if (!(Math.abs(aa - bb) <= Number.EPSILON)) {
21
+ if (!(Math.abs((aa - bb) / Math.max(aa, bb)) <= 256 * Number.EPSILON)) {
21
22
  throw new Error(
22
23
  JSON.stringify(aa) + " != " + JSON.stringify(bb) + (
23
24
  message
@@ -58,10 +59,10 @@ file sqlmath.js
58
59
  let SQLITE_OPEN_URI = 0x00000040; /* Ok for sqlite3_open_v2() */
59
60
  let SQLITE_OPEN_WAL = 0x00080000; /* VFS only */
60
61
  let addon;
61
- let dbDict = new WeakMap();
62
+ let consoleError = console.error;
63
+ let dbDict = new WeakMap(); // private map of sqlite-database-connections
62
64
  let requireCjs = createRequire(import.meta.url);
63
65
  let testList;
64
- // private map of sqlite-database-connections
65
66
 
66
67
  function cCall(func, argList) {
67
68
  // this function will serialize <argList> to a c <baton>,
@@ -168,8 +169,12 @@ file sqlmath.js
168
169
  bindList = [],
169
170
  db,
170
171
  responseType,
171
- rowList,
172
- sql
172
+ sql,
173
+ tmpColList,
174
+ tmpColListPriority,
175
+ tmpCsv,
176
+ tmpRowList,
177
+ tmpTableName
173
178
  }) {
174
179
  // this function will exec <sql> in <db> and return <result>
175
180
  let bindByKey = !Array.isArray(bindList);
@@ -180,10 +185,14 @@ file sqlmath.js
180
185
  );
181
186
  let result;
182
187
  let serialize = jsToSqlSerializer();
183
- if (rowList) {
188
+ if (tmpCsv || tmpRowList) {
184
189
  await dbTableInsertAsync({
190
+ colList: tmpColList,
191
+ colListPriority: tmpColListPriority,
192
+ csv: tmpCsv,
185
193
  db,
186
- rowList
194
+ rowList: tmpRowList,
195
+ tableName: tmpTableName
187
196
  });
188
197
  }
189
198
  Object.entries(bindList).forEach(function ([
@@ -202,8 +211,6 @@ file sqlmath.js
202
211
  (
203
212
  responseType === "lastBlob"
204
213
  ? 1
205
- : responseType === "lastMatrixDouble"
206
- ? 2
207
214
  : 0
208
215
  )
209
216
  ].concat(serialize.bufSharedList));
@@ -212,8 +219,6 @@ file sqlmath.js
212
219
  case "arraybuffer":
213
220
  case "lastBlob":
214
221
  return result;
215
- case "lastMatrixDouble":
216
- return new Float64Array(result);
217
222
  case "list":
218
223
  return JSON.parse(new TextDecoder().decode(result));
219
224
  default:
@@ -231,6 +236,25 @@ file sqlmath.js
231
236
  }
232
237
  }
233
238
 
239
+ async function dbExecWithRetryAsync(option) {
240
+ // this function will exec <sql> in <db> and return <result> with <retryLimit>
241
+ let retry = option.retryLimit || 1;
242
+ while (true) {
243
+ try {
244
+ return await dbExecAsync(option);
245
+ } catch (err) {
246
+ assertOrThrow(retry > 0, err);
247
+ consoleError(err);
248
+ consoleError(
249
+ "dbExecWithRetryAsync - retry failed sql-query with "
250
+ + retry
251
+ + " remaining retry"
252
+ );
253
+ retry -= 1;
254
+ }
255
+ }
256
+ }
257
+
234
258
  function dbGetLastBlobAsync({
235
259
  bindList = [],
236
260
  db,
@@ -246,21 +270,6 @@ file sqlmath.js
246
270
  });
247
271
  }
248
272
 
249
- function dbGetLastMatrixDouble({
250
- bindList = [],
251
- db,
252
- sql
253
- }) {
254
- // this function will exec <sql> in <db> and return last SELECT-statement
255
- // from execution as row x col matrix of doubles
256
- return dbExecAsync({
257
- bindList,
258
- db,
259
- responseType: "lastMatrixDouble",
260
- sql
261
- });
262
- }
263
-
264
273
  async function dbMemoryLoadAsync({
265
274
  db,
266
275
  filename
@@ -306,9 +315,12 @@ file sqlmath.js
306
315
  ), async function () {
307
316
  let finalizer;
308
317
  let ptr = await cCall("__dbOpenAsync", [
309
- String(filename), undefined, flags ?? (
318
+ String(filename),
319
+ undefined,
320
+ flags ?? (
310
321
  SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE | SQLITE_OPEN_URI
311
- ), undefined
322
+ ),
323
+ undefined
312
324
  ]);
313
325
  ptr = ptr[0][0];
314
326
  finalizer = new BigInt64Array(addon.__dbFinalizerCreate());
@@ -330,13 +342,14 @@ file sqlmath.js
330
342
  csv,
331
343
  db,
332
344
  rowList,
333
- tableName = "tmp1"
345
+ tableName
334
346
  }) {
335
347
  // this function will create-or-replace temp <tablename> with <rowList>
336
348
  let serialize = jsToSqlSerializer();
337
349
  let sqlCreateTable;
338
350
  let sqlInsertRow;
339
351
  // normalize and validate tableName
352
+ tableName = tableName || "__tmp1";
340
353
  tableName = "temp." + JSON.stringify(tableName.replace((
341
354
  /^temp\./
342
355
  ), ""));
@@ -429,9 +442,6 @@ file sqlmath.js
429
442
  }
430
443
  function bufferSetBuffer(aa, bb, offset) {
431
444
  // this function will set buffer <bb> to buffer <aa> at <offset>
432
- if (typeof bb === "string") {
433
- bb = new TextEncoder().encode(bb);
434
- }
435
445
  aa = new Uint8Array(aa.buffer, aa.byteOffset, aa.byteLength);
436
446
  bb = new Uint8Array(bb.buffer, bb.byteOffset, bb.byteLength);
437
447
  aa.set(bb, offset);
@@ -1013,50 +1023,6 @@ Definition of the CSV Format
1013
1023
  dd
1014
1024
  });
1015
1025
  });
1016
- // test dbGetLastMatrixDouble's bind handling-behavior
1017
- [
1018
- aa
1019
- ].forEach(async function (aa) {
1020
- let cc = Number(
1021
- typeof aa === "symbol"
1022
- ? 0
1023
- : aa
1024
- ) || 0;
1025
- let dd = await dbGetLastMatrixDouble({
1026
- bindList: [
1027
- aa
1028
- ],
1029
- db,
1030
- sql: "SELECT 1, 2, 3; SELECT 1, 2, ?"
1031
- });
1032
- switch (typeof(aa)) {
1033
- case "bigint":
1034
- aa = String(aa);
1035
- break;
1036
- case "object":
1037
- if (typeof aa?.getUTCFullYear === "function") {
1038
- cc = aa.getUTCFullYear();
1039
- }
1040
- break;
1041
- }
1042
- cc = new Float64Array([
1043
- 1, 3, 1, 2, cc
1044
- ]);
1045
- // debugInline(ii, aa, bb, cc, dd);
1046
- cc.forEach(function (val, jj) {
1047
- assertJsonEqual(
1048
- val,
1049
- dd[jj],
1050
- {
1051
- ii,
1052
- aa, //jslint-quiet
1053
- bb,
1054
- cc,
1055
- dd
1056
- }
1057
- );
1058
- });
1059
- });
1060
1026
  // test dbExecAsync's responseType handling-behavior
1061
1027
  [
1062
1028
  "arraybuffer",
@@ -1212,19 +1178,15 @@ Definition of the CSV Format
1212
1178
  colListPriority,
1213
1179
  rowList
1214
1180
  }, jj) {
1215
- let cc;
1216
- await dbTableInsertAsync({
1217
- colList,
1218
- colListPriority,
1219
- db,
1220
- rowList,
1221
- tableName: "datatype_" + ii + "_" + jj
1222
- });
1223
- cc = noop(
1181
+ let cc = noop(
1224
1182
  await dbExecAsync({
1225
1183
  db,
1226
1184
  responseType: "list",
1227
- sql: "SELECT * FROM datatype_" + ii + "_" + jj
1185
+ sql: `SELECT * FROM datatype_${ii}_${jj}`,
1186
+ tmpColList: colList,
1187
+ tmpColListPriority: colListPriority,
1188
+ tmpRowList: rowList,
1189
+ tmpTableName: "datatype_" + ii + "_" + jj
1228
1190
  })
1229
1191
  )[0];
1230
1192
  // debugInline(ii, jj, aa, bb, cc);
@@ -1282,12 +1244,14 @@ Definition of the CSV Format
1282
1244
  sql: (`
1283
1245
  CREATE TABLE testDbExecAsync1 AS
1284
1246
  SELECT 101 AS c101, 102 AS c102
1247
+ --
1285
1248
  UNION ALL
1286
1249
  VALUES
1287
1250
  (201, 202),
1288
1251
  (301, NULL);
1289
1252
  CREATE TABLE testDbExecAsync2 AS
1290
1253
  SELECT 401 AS c401, 402 AS c402, 403 AS c403
1254
+ --
1291
1255
  UNION ALL
1292
1256
  VALUES
1293
1257
  (501, 502.0123, 5030123456789),
@@ -1350,18 +1314,27 @@ SELECT * FROM testDbExecAsync2;
1350
1314
  ));
1351
1315
  // test sqlmath-defined-func handling-behavior
1352
1316
  [
1317
+ "COT(NULL)", null,
1353
1318
  "COT('-1')", -0.642092615934331,
1354
1319
  "COT('0')", null,
1355
1320
  "COT('1')", 0.642092615934331,
1356
1321
  "COT(-1)", -0.642092615934331,
1357
1322
  "COT(0)", null,
1358
1323
  "COT(1)", 0.642092615934331,
1324
+ "COTH(NULL)", null,
1359
1325
  "COTH('-1')", -1.31303528549933,
1360
1326
  "COTH('0')", null,
1361
1327
  "COTH('1')", 1.31303528549933,
1362
1328
  "COTH(-1)", -1.31303528549933,
1363
1329
  "COTH(0)", null,
1364
1330
  "COTH(1)", 1.31303528549933,
1331
+ "ROUNDORZERO(NULL, NULL)", 0,
1332
+ "ROUNDORZERO(NULL, 0)", 0,
1333
+ "ROUNDORZERO(NULL, 0.5)", 0,
1334
+ "ROUNDORZERO(0.5, NULL)", 1,
1335
+ "ROUNDORZERO(0.5, 0.5)", 1,
1336
+ "ROUNDORZERO(0.5, 1)", 0.5,
1337
+ "SIGN(NULL)", null,
1365
1338
  "SIGN('-1')", -1,
1366
1339
  "SIGN('0')", 0,
1367
1340
  "SIGN('1')", 1,
@@ -1374,7 +1347,6 @@ SELECT * FROM testDbExecAsync2;
1374
1347
  "SIGN(0xffffffffffffffff)", -1,
1375
1348
  "SIGN(1)", 1,
1376
1349
  "SIGN(1e999)", 1,
1377
- "SIGN(NULL)", null,
1378
1350
  // sentinel
1379
1351
  "NULL", null
1380
1352
  ].forEach(async function (sql, ii, list) {
@@ -1388,15 +1360,26 @@ SELECT * FROM testDbExecAsync2;
1388
1360
  await dbExecAsync({
1389
1361
  db,
1390
1362
  responseType: "dict",
1391
- sql: "SELECT " + sql + " AS val"
1363
+ sql: `SELECT ${sql} AS val`
1392
1364
  })
1393
1365
  )[0][0].val;
1394
- assertOrThrow(bb === cc, JSON.stringify([
1395
- ii, sql, bb, cc
1396
- ]));
1366
+ assertJsonEqual(bb, cc, {
1367
+ bb,
1368
+ cc,
1369
+ ii,
1370
+ sql
1371
+ });
1397
1372
  });
1398
1373
  }
1399
1374
 
1375
+ function testDbExecWithRetryAsync() {
1376
+ // this function will test dbExecWithRetryAsync's handling-behavior
1377
+ // test null-case handling-behavior
1378
+ assertErrorThrownAsync(function () {
1379
+ return dbExecWithRetryAsync({});
1380
+ }, "invalid or closed db");
1381
+ }
1382
+
1400
1383
  async function testDbMemoryXxx() {
1401
1384
  // this function will test dbMemoryXxx's handling-behavior
1402
1385
  let data;
@@ -1480,11 +1463,15 @@ SELECT * FROM testDbExecAsync2;
1480
1463
  ].forEach(function ([
1481
1464
  rowList, rgx
1482
1465
  ]) {
1483
- assertErrorThrownAsync(function () {
1484
- return dbTableInsertAsync({
1485
- rowList
1486
- });
1487
- }, rgx);
1466
+ assertErrorThrownAsync(
1467
+ dbTableInsertAsync.bind(
1468
+ undefined,
1469
+ {
1470
+ rowList
1471
+ }
1472
+ ),
1473
+ rgx
1474
+ );
1488
1475
  });
1489
1476
  // test csv handling-behavior
1490
1477
  [
@@ -1526,17 +1513,13 @@ SELECT * FROM testDbExecAsync2;
1526
1513
  ].forEach(async function ([
1527
1514
  aa, bb
1528
1515
  ], ii) {
1529
- let cc;
1530
- await dbTableInsertAsync({
1531
- csv: aa,
1532
- db,
1533
- tableName: "csv_" + ii
1534
- });
1535
- cc = noop(
1516
+ let cc = noop(
1536
1517
  await dbExecAsync({
1537
1518
  db,
1538
1519
  responseType: "list",
1539
- sql: "SELECT * FROM temp.csv_" + ii
1520
+ sql: `SELECT * FROM temp.csv_${ii}`,
1521
+ tmpCsv: aa,
1522
+ tmpTableName: "csv_" + ii
1540
1523
  })
1541
1524
  )[0];
1542
1525
  assertOrThrow(
@@ -1590,7 +1573,7 @@ SELECT * FROM testDbExecAsync2;
1590
1573
  return;
1591
1574
  }
1592
1575
  ii *= 0.5;
1593
- sql = "SELECT throwerror(" + sql + ")";
1576
+ sql = `SELECT throwerror(${sql})`;
1594
1577
  assertErrorThrownAsync(function () {
1595
1578
  return dbExecAsync({
1596
1579
  db,
@@ -1653,6 +1636,101 @@ SELECT * FROM testDbExecAsync2;
1653
1636
  });
1654
1637
  }
1655
1638
 
1639
+ async function testSqlKthpercentile() {
1640
+ // this function will test sql-kthpercentile's handling-behavior
1641
+ let db = await dbOpenAsync({
1642
+ filename: ":memory:"
1643
+ });
1644
+ [
1645
+ [
1646
+ [], -99, 1
1647
+ ], [
1648
+ [], 0, 1
1649
+ ], [
1650
+ [], 0.125, 1
1651
+ ], [
1652
+ [], 0.25, 2
1653
+ ], [
1654
+ [], 0.375, 3
1655
+ ], [
1656
+ [], 0.5, 4
1657
+ ], [
1658
+ [], 0.625, 5
1659
+ ], [
1660
+ [], 0.75, 6
1661
+ ], [
1662
+ [], 0.875, 7
1663
+ ], [
1664
+ [], 1, 8
1665
+ ], [
1666
+ [], 99, 8
1667
+ ], [
1668
+ [
1669
+ 0.5
1670
+ ], 0, 0.5
1671
+ ], [
1672
+ [
1673
+ 0.5
1674
+ ], 0.125, 0.5
1675
+ ], [
1676
+ [
1677
+ 1.5
1678
+ ], 0.25, 1.5
1679
+ ], [
1680
+ [
1681
+ 2.5
1682
+ ], 0.375, 2.5
1683
+ ], [
1684
+ [
1685
+ 3.5
1686
+ ], 0.5, 3.5
1687
+ ], [
1688
+ [
1689
+ 4.5
1690
+ ], 0.625, 4.5
1691
+ ], [
1692
+ [
1693
+ 5.5
1694
+ ], 0.75, 5.5
1695
+ ], [
1696
+ [
1697
+ 6.5
1698
+ ], 0.875, 6.5
1699
+ ], [
1700
+ [
1701
+ 7.5
1702
+ ], 1, 8
1703
+ ]
1704
+ ].forEach(async function ([
1705
+ data, kk, expected
1706
+ ], ii) {
1707
+ let actual;
1708
+ data = data.concat([
1709
+ undefined, undefined, 8, 7, 6, 5, 4, 3, 2, 1, undefined
1710
+ ]);
1711
+ actual = noop(
1712
+ await dbExecAsync({
1713
+ db,
1714
+ sql: (`
1715
+ SELECT kthpercentile(val, ${kk}) AS val FROM __tmp${ii};
1716
+ -- test null-case handling-behavior
1717
+ SELECT kthpercentile(val, ${kk}) AS val FROM __tmp${ii} WHERE 0;
1718
+ `),
1719
+ tmpRowList: data.map(function (val) {
1720
+ return {
1721
+ val
1722
+ };
1723
+ }),
1724
+ tmpTableName: `__tmp${ii}`
1725
+ })
1726
+ )[0][0].val;
1727
+ assertJsonEqual(actual, expected, {
1728
+ data,
1729
+ kk
1730
+ });
1731
+ });
1732
+ }
1733
+
1656
1734
  addon = requireCjs(
1657
1735
  "./_binary_sqlmath"
1658
1736
  + "_napi8"
@@ -1666,11 +1744,13 @@ SELECT * FROM testDbExecAsync2;
1666
1744
  testDbBind,
1667
1745
  testDbCloseAsync,
1668
1746
  testDbExecAsync,
1747
+ testDbExecWithRetryAsync,
1669
1748
  testDbMemoryXxx,
1670
1749
  testDbOpenAsync,
1671
1750
  testDbTableInsertAsync,
1672
1751
  testSqlError,
1673
- testSqlExt
1752
+ testSqlExt,
1753
+ testSqlKthpercentile
1674
1754
  ];
1675
1755
  Object.assign(local, {
1676
1756
  SQLITE_MAX_LENGTH2,
@@ -1699,15 +1779,21 @@ SELECT * FROM testDbExecAsync2;
1699
1779
  assertNumericalEqual,
1700
1780
  dbCloseAsync,
1701
1781
  dbExecAsync,
1782
+ dbExecWithRetryAsync,
1702
1783
  dbGetLastBlobAsync,
1703
1784
  dbMemoryLoadAsync,
1704
1785
  dbMemorySaveAsync,
1705
1786
  dbOpenAsync,
1706
1787
  dbTableInsertAsync,
1707
1788
  debugInline,
1789
+ objectDeepCopyWithKeysSorted,
1708
1790
  testAll,
1709
1791
  testList
1710
1792
  });
1793
+ if (process.env.npm_config_mode_test) {
1794
+ // mock consoleError
1795
+ consoleError = noop;
1796
+ }
1711
1797
  }());
1712
1798
 
1713
1799
  export default Object.freeze(local);
@@ -0,0 +1,4 @@
1
+ /*jslint node, beta*/
2
+ import sqlmath from "./sqlmath.mjs";
3
+ let exportDict = {};
4
+ export default Object.freeze(Object.assign({}, sqlmath, exportDict));