sqlmath 2026.7.30 → 2026.8.31

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
@@ -7,6 +7,15 @@
7
7
  - sqlite - Add similar error-handling from builtin-sql-function PERCENTILE() into custom-sql-function QUANTILE().
8
8
  - none
9
9
 
10
+ # v2026.8.31
11
+ - jslint-ci - Update ci-shell-function shGitLsTree() to include sha256 hash of files.
12
+ - sqlmath - Cleanup c-function winSinefitSnr().
13
+ - sqlmath - Update sql-function WIN_SINEFIT2() argument modeSnr with bitmask, allowing selective sine-fit of each column, to avoid wasting cpu on columns that don't need it.
14
+ - lgbm - Upgrade to lightgbm-v4.7.0.
15
+ - sqlite - Upgrade to sqlite-v3.51.3.
16
+ - sqlmath - Remove obsolete sql-functions MEDIAN2(), QUANTILE(), superseded by sqlite-builtins.
17
+ - sqlmath - Fix c-header conflict between dlfcn.h and Python.h.
18
+
10
19
  # v2026.7.30
11
20
  - jslint-ecma - Add ES2015-feature for..of.
12
21
  - jslint - Change scope from scope_function to scope_block:
package/README.md CHANGED
@@ -9,7 +9,7 @@
9
9
 
10
10
  # Status
11
11
 
12
- | Branch | [master<br>(v2026.7.30)](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) |
12
+ | Branch | [master<br>(v2026.8.31)](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) |
13
13
  |--:|:--:|:--:|:--:|
14
14
  | 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) |
15
15
  | 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) |
@@ -398,7 +398,7 @@ Full notebook with fraud detection, intraday trading signals, and model persiste
398
398
  **Kaggle Environment:**
399
399
  - Linux x64, Python 3.12, Node.js 24
400
400
  - Datasets: [Credit Card Fraud](https://www.kaggle.com/datasets/mlg-ulb/creditcardfraud) (284K transactions), SPY intraday OHLCV
401
- - sqlmath installs via `pip install sqlmath==2026.7.30`
401
+ - sqlmath installs via `pip install sqlmath==2026.8.31`
402
402
 
403
403
 
404
404
  <br><br>
@@ -643,11 +643,11 @@ PORT=8080 sh jslint_ci.sh shHttpFileServer
643
643
  ```shell
644
644
  python -m build
645
645
  #
646
- twine upload --repository testpypi dist/sqlmath-2026.7.30*
647
- py -m pip install --index-url https://test.pypi.org/simple/ sqlmath==2026.7.30
646
+ twine upload --repository testpypi dist/sqlmath-2026.8.31*
647
+ py -m pip install --index-url https://test.pypi.org/simple/ sqlmath==2026.8.31
648
648
  #
649
- twine upload dist/sqlmath-2026.7.30*
650
- pip install sqlmath==2026.7.30
649
+ twine upload dist/sqlmath-2026.8.31*
650
+ pip install sqlmath==2026.8.31
651
651
  ```
652
652
 
653
653
 
@@ -658,11 +658,11 @@ pip install sqlmath==2026.7.30
658
658
  (set -e
659
659
  #
660
660
  # lgbm
661
- sh jslint_ci.sh shRollupUpgrade "v4.5.0" "v4.6.0" ".ci.sh sqlmath_base.h"
661
+ sh jslint_ci.sh shRollupUpgrade "v4.6.0" "v4.7.0" ".ci.sh sqlmath_base.h"
662
662
  #
663
663
  # sqlite
664
- sh jslint_ci.sh shRollupUpgrade "3.50.3" "3.50.4" ".ci.sh sqlmath_external_sqlite.c"
665
- sh jslint_ci.sh shRollupUpgrade "3500300" "3500400" ".ci.sh sqlmath_external_sqlite.c"
664
+ sh jslint_ci.sh shRollupUpgrade "3.50.4" "3.51.3" ".ci.sh sqlmath_external_sqlite.c"
665
+ sh jslint_ci.sh shRollupUpgrade "3500400" "3510300" ".ci.sh sqlmath_external_sqlite.c"
666
666
  #
667
667
  # shSqlmathUpdate
668
668
  read -p "Press Enter to shSqlmathUpdate:"
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
package/jslint.mjs CHANGED
@@ -435,7 +435,7 @@ const jslint_charset_ascii = ( //jslint-ignore-line
435
435
  + "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_"
436
436
  + "`abcdefghijklmnopqrstuvwxyz{|}~\u007f"
437
437
  );
438
- const jslint_edition = "v2026.7.30";
438
+ const jslint_edition = "v2026.8.31";
439
439
  const jslint_fudge = 1; // Fudge starting line and starting
440
440
  // ... column to 1.
441
441
  const jslint_global_dict_all = {
package/package.json CHANGED
@@ -32,5 +32,5 @@
32
32
  },
33
33
  "shCiArtifactUpload": 1,
34
34
  "shCiPublishNpm": 1,
35
- "version": "2026.7.30"
35
+ "version": "2026.8.31"
36
36
  }
Binary file
Binary file
package/sqlmath.mjs CHANGED
@@ -22,6 +22,7 @@
22
22
 
23
23
  /*
24
24
  sh one-liner:
25
+ npm_config_mode_test_save=1 npm run test && git diff
25
26
  sh jslint_ci.sh shCiBuildWasm
26
27
  sh jslint_ci.sh shSqlmathUpdate
27
28
  */
@@ -110,7 +111,7 @@ const SQLITE_OPEN_WAL = 0x00080000; /* VFS only */
110
111
 
111
112
  const DB_EXEC_PROFILE_DICT = {}; //jslint-ignore-line
112
113
  const DB_STATE = {};
113
- const version = "v2026.7.30";
114
+ const version = "v2026.8.31";
114
115
  let DB_EXEC_PROFILE_MODE;
115
116
  let DB_EXEC_PROFILE_SQL_LENGTH;
116
117
  let IS_BROWSER;
package/sqlmath_wasm.js CHANGED
@@ -1,7 +1,7 @@
1
1
  /*jslint-disable*/
2
2
  // Copyright (c) 2021 Kai Zhu
3
3
  // SPDX-License-Identifier: MIT
4
- // 2026-08-01T00:48:14+0000
4
+ // 2026-08-31T22:53:43+0000
5
5
  (function () {
6
6
  "use strict";
7
7
 
package/sqlmath_wasm.wasm CHANGED
Binary file
package/test.mjs CHANGED
@@ -20,11 +20,6 @@
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
- * example usage:
25
- npm_config_mode_test_save2=1 npm test
26
- */
27
-
28
23
  /*jslint beta, node*/
29
24
  import moduleChildProcess from "child_process";
30
25
  import modulePath from "path";
@@ -2155,15 +2150,13 @@ DROP TABLE IF EXISTS __tmp1;
2155
2150
  CREATE TEMP TABLE __tmp1 (val REAL);
2156
2151
  SELECT
2157
2152
  1 AS id,
2158
- MEDIAN2(val) AS mdn,
2159
- QUANTILE(val, 0.5) AS qnt,
2160
2153
  STDEV(val) AS std
2161
2154
  FROM __tmp1;
2162
2155
  `)
2163
2156
  });
2164
2157
  assertJsonEqual(
2165
2158
  valActual,
2166
- [{id: 1, mdn: null, qnt: null, std: null}]
2159
+ [{id: 1, std: null}]
2167
2160
  );
2168
2161
  }());
2169
2162
  await Promise.all([
@@ -2226,20 +2219,12 @@ SELECT
2226
2219
  ]) {
2227
2220
  let avg = 0;
2228
2221
  let data2;
2229
- let valExpectMdn;
2230
2222
  let valExpectStd = 0;
2231
2223
  data2 = data.map(function (elem) {
2232
2224
  return Number(elem);
2233
2225
  }).filter(function (elem) {
2234
2226
  return Number.isFinite(elem);
2235
2227
  }).sort();
2236
- valExpectMdn = (
2237
- data2.length % 2 === 0
2238
- ? 0.5 * (
2239
- data2[0.5 * data2.length - 1] + data2[0.5 * data2.length]
2240
- )
2241
- : data2[0.5 * (data2.length - 1)]
2242
- );
2243
2228
  data2.forEach(function (elem) {
2244
2229
  avg += elem;
2245
2230
  });
@@ -2267,12 +2252,8 @@ SELECT
2267
2252
  },
2268
2253
  db,
2269
2254
  sql: (`
2270
- -- test null-case handling-behavior
2271
- SELECT QUANTILE(value, ${qq}) AS qnt FROM JSON_EACH($tmp1) WHERE 0;
2272
2255
  -- test last-row handling-behavior
2273
2256
  SELECT
2274
- MEDIAN2(value) AS mdn,
2275
- QUANTILE(value, ${qq}) AS qnt,
2276
2257
  ROUND(stdev(value), 8) AS std
2277
2258
  FROM JSON_EACH($tmp1);
2278
2259
  `)
@@ -2280,8 +2261,6 @@ SELECT
2280
2261
  assertJsonEqual(
2281
2262
  valActual,
2282
2263
  {
2283
- mdn: valExpectMdn,
2284
- qnt: valExpect ?? null,
2285
2264
  std: valExpectStd
2286
2265
  },
2287
2266
  {
@@ -2289,7 +2268,6 @@ SELECT
2289
2268
  qq,
2290
2269
  valActual,
2291
2270
  valExpect,
2292
- valExpectMdn,
2293
2271
  valExpectStd
2294
2272
  }
2295
2273
  );
@@ -3269,7 +3247,7 @@ SELECT
3269
3247
  "id2": 3,
3270
3248
  "laa": -4.5,
3271
3249
  "lbb": 2.5,
3272
- "lee": 0.40824829,
3250
+ "lee": 0.70710678,
3273
3251
  "lxy": 0.94491118,
3274
3252
  "lyy": 3,
3275
3253
  "mee": 1.52752523,
@@ -3289,7 +3267,7 @@ SELECT
3289
3267
  "id2": 4,
3290
3268
  "laa": -3,
3291
3269
  "lbb": 1.81818182,
3292
- "lee": 0.47673129,
3270
+ "lee": 0.67419986,
3293
3271
  "lxy": 0.95346259,
3294
3272
  "lyy": 4.27272727,
3295
3273
  "mee": 1.82574186,
@@ -3309,7 +3287,7 @@ SELECT
3309
3287
  "id2": 5,
3310
3288
  "laa": -2.29411765,
3311
3289
  "lbb": 1.52941176,
3312
- "lee": 0.50874702,
3290
+ "lee": 0.65678958,
3313
3291
  "lxy": 0.96164474,
3314
3292
  "lyy": 5.35294118,
3315
3293
  "mee": 2.07364414,
@@ -3329,7 +3307,7 @@ SELECT
3329
3307
  "id2": 6,
3330
3308
  "laa": -2.54385965,
3331
3309
  "lbb": 1.63157895,
3332
- "lee": 0.50725727,
3310
+ "lee": 0.62126074,
3333
3311
  "lxy": 0.97080629,
3334
3312
  "lyy": 5.61403509,
3335
3313
  "mee": 2.31660671,
@@ -3349,7 +3327,7 @@ SELECT
3349
3327
  "id2": 7,
3350
3328
  "laa": -2.65,
3351
3329
  "lbb": 1.675,
3352
- "lee": 0.48550416,
3330
+ "lee": 0.57445626,
3353
3331
  "lxy": 0.9752227,
3354
3332
  "lyy": 5.725,
3355
3333
  "mee": 2.37045304,
@@ -3369,7 +3347,7 @@ SELECT
3369
3347
  "id2": 8,
3370
3348
  "laa": -2.5,
3371
3349
  "lbb": 1.625,
3372
- "lee": 0.46770717,
3350
+ "lee": 0.54006172,
3373
3351
  "lxy": 0.97991187,
3374
3352
  "lyy": 7.25,
3375
3353
  "mee": 2.50713268,
@@ -3389,7 +3367,7 @@ SELECT
3389
3367
  "id2": 9,
3390
3368
  "laa": 0.75,
3391
3369
  "lbb": 0.85,
3392
- "lee": 0.94207218,
3370
+ "lee": 1.08781126,
3393
3371
  "lxy": 0.89597867,
3394
3372
  "lyy": 9.25,
3395
3373
  "mee": 2.26778684,
@@ -3409,7 +3387,7 @@ SELECT
3409
3387
  "id2": 10,
3410
3388
  "laa": 2.75,
3411
3389
  "lbb": 0.55,
3412
- "lee": 0.8587782,
3390
+ "lee": 0.99163165,
3413
3391
  "lxy": 0.81989159,
3414
3392
  "lyy": 3.85,
3415
3393
  "mee": 1.60356745,
@@ -3451,6 +3429,15 @@ SELECT WIN_SINEFIT2(1, 2, 3) FROM (SELECT 1);
3451
3429
  `)
3452
3430
  });
3453
3431
  }, "wrong number of arguments");
3432
+ // test win_sinefit2-modeSnr-bitmask-overflow handling-behavior
3433
+ await assertErrorThrownAsync(function () {
3434
+ return dbExecAsync({
3435
+ db,
3436
+ sql: (`
3437
+ SELECT WIN_SINEFIT2(1, 2${", 3, 4".repeat(31)}) FROM (SELECT 1);
3438
+ `)
3439
+ });
3440
+ }, "too many columns");
3454
3441
  // test win_sinefit2-null-case handling-behavior
3455
3442
  valActual = await dbExecAndReturnLastTable({
3456
3443
  db,
@@ -3465,6 +3452,323 @@ SELECT DOUBLEARRAY_JSONTO(WIN_SINEFIT2(1, 2, 3, 4)) FROM __tmp1;
3465
3452
  });
3466
3453
  assertJsonEqual(valActual, [null]);
3467
3454
  }()),
3455
+ (async function () {
3456
+ let valActual;
3457
+ let valSine = JSON.stringify(Array.from({
3458
+ length: 64
3459
+ }, function (ignore, ii) {
3460
+ return [ii + 1, Math.sin(0.5 * (ii + 1)) + 0.1 * ii];
3461
+ }));
3462
+ // test win_sinefit2-modeSnr-bitmask handling-behavior
3463
+ // Mask 0b110 is inverted on purpose - column 0 must NOT be
3464
+ // sine-fit. A build that re-hardcodes column 0, or that
3465
+ // treats modeSnr as an all-or-nothing flag, fails here.
3466
+ valActual = await dbExecAndReturnLastTable({
3467
+ bindList: {
3468
+ valSine
3469
+ },
3470
+ db,
3471
+ sql: (`
3472
+ SELECT
3473
+ SINEFIT_EXTRACT(__wsf, 0, 'sww', 0) = 0 AS sww0_off,
3474
+ SINEFIT_EXTRACT(__wsf, 1, 'sww', 0) > 0 AS sww1_on,
3475
+ SINEFIT_EXTRACT(__wsf, 2, 'sww', 0) > 0 AS sww2_on,
3476
+ SINEFIT_EXTRACT(__wsf, 0, 'rrb', 0) IS NOT NULL AS lnr0_on
3477
+ FROM (
3478
+ SELECT
3479
+ key,
3480
+ WIN_SINEFIT2(
3481
+ 6, NULL,
3482
+ value->>0, value->>1,
3483
+ value->>0, value->>1,
3484
+ value->>0, value->>1
3485
+ ) OVER (
3486
+ ORDER BY key ASC
3487
+ ROWS BETWEEN 31 PRECEDING AND 0 FOLLOWING
3488
+ ) AS __wsf
3489
+ FROM JSON_EACH($valSine)
3490
+ )
3491
+ WHERE key = 63;
3492
+ `)
3493
+ });
3494
+ valActual = valActual.map(function (elem) {
3495
+ return [
3496
+ elem.sww0_off,
3497
+ elem.sww1_on,
3498
+ elem.sww2_on,
3499
+ elem.lnr0_on
3500
+ ];
3501
+ });
3502
+ assertJsonEqual(valActual, [[1, 1, 1, 1]]);
3503
+ }()),
3504
+ (async function () {
3505
+ let valActual;
3506
+ let valSine = JSON.stringify(Array.from({
3507
+ length: 64
3508
+ }, function (ignore, ii) {
3509
+ return [ii + 1, Math.sin(0.5 * (ii + 1)) + 0.1 * ii];
3510
+ }));
3511
+ // test sinefit_extract-dof handling-behavior
3512
+ // lee divides by nnn-2 (laa, lbb) and see by nnn-5 (those
3513
+ // plus saa, spp, sww). Pin the divisors by comparing a
3514
+ // 32-row window against an 8-row one - the ratio of the
3515
+ // two is free of the unknown residual sum-of-squares only
3516
+ // if we instead check the small-window NULL boundaries,
3517
+ // which is what this does: lee goes NULL at nnn <= 2 and
3518
+ // see at nnn <= 5, and both are finite one row later.
3519
+ valActual = await dbExecAndReturnLastTable({
3520
+ bindList: {
3521
+ valSine
3522
+ },
3523
+ db,
3524
+ sql: (`
3525
+ SELECT
3526
+ SINEFIT_EXTRACT(__wsf02, 0, 'lee', 0) IS NULL AS lee_null_at_2,
3527
+ SINEFIT_EXTRACT(__wsf03, 0, 'lee', 0) > 0 AS lee_ok_at_3,
3528
+ SINEFIT_EXTRACT(__wsf05, 0, 'see', 0) IS NULL AS see_null_at_5,
3529
+ SINEFIT_EXTRACT(__wsf06, 0, 'see', 0) >= 0 AS see_ok_at_6
3530
+ FROM (
3531
+ SELECT
3532
+ key,
3533
+ WIN_SINEFIT2(1, NULL, value->>0, value->>1) OVER (
3534
+ ORDER BY key ASC ROWS BETWEEN 1 PRECEDING AND 0 FOLLOWING
3535
+ ) AS __wsf02,
3536
+ WIN_SINEFIT2(1, NULL, value->>0, value->>1) OVER (
3537
+ ORDER BY key ASC ROWS BETWEEN 2 PRECEDING AND 0 FOLLOWING
3538
+ ) AS __wsf03,
3539
+ WIN_SINEFIT2(1, NULL, value->>0, value->>1) OVER (
3540
+ ORDER BY key ASC ROWS BETWEEN 4 PRECEDING AND 0 FOLLOWING
3541
+ ) AS __wsf05,
3542
+ WIN_SINEFIT2(1, NULL, value->>0, value->>1) OVER (
3543
+ ORDER BY key ASC ROWS BETWEEN 5 PRECEDING AND 0 FOLLOWING
3544
+ ) AS __wsf06
3545
+ FROM JSON_EACH($valSine)
3546
+ )
3547
+ WHERE key = 63;
3548
+ `)
3549
+ });
3550
+ valActual = valActual.map(function (elem) {
3551
+ return [
3552
+ elem.lee_null_at_2,
3553
+ elem.lee_ok_at_3,
3554
+ elem.see_null_at_5,
3555
+ elem.see_ok_at_6
3556
+ ];
3557
+ });
3558
+ assertJsonEqual(valActual, [[1, 1, 1, 1]]);
3559
+ }()),
3560
+ // test win_sinefit2-empty-frame handling-behavior
3561
+ (async function () {
3562
+ // WIN_SINEFIT_N = 23 doubles = 184 bytes per column
3563
+ const nhead = 23 * 8;
3564
+ // Frame "5 PRECEDING AND 3 PRECEDING" is empty for rows 1-3, so
3565
+ // sqlite calls xValue before the first xStep. Regression-test that
3566
+ // xValue does not allocate an aggregate-context with nhead=0, which
3567
+ // would pin nhead=0 for the life of the aggregate and alias
3568
+ // doublewinHead() onto doublewinBody(). ncol=2 additionally
3569
+ // overflows the 304-byte nhead=0 allocation, needing 2*184+48 = 416
3570
+ // bytes of head.
3571
+ assertJsonEqual(
3572
+ noop(
3573
+ await dbExecAsync({
3574
+ db,
3575
+ sql: (`
3576
+ CREATE TABLE testWinSinefit2Emptyframe AS
3577
+ SELECT 1 AS xx, 1 AS yy
3578
+ --
3579
+ UNION ALL VALUES
3580
+ (2, 2),
3581
+ (3, 3),
3582
+ (4, 4),
3583
+ (5, 5),
3584
+ (6, 6),
3585
+ (7, 7),
3586
+ (8, 8);
3587
+
3588
+ -- empty-window-frame
3589
+ SELECT
3590
+ LENGTH(WIN_SINEFIT2(0, NULL, xx, yy) OVER (
3591
+ ORDER BY xx
3592
+ ROWS BETWEEN 5 PRECEDING AND 3 PRECEDING
3593
+ )) AS nhead
3594
+ FROM testWinSinefit2Emptyframe;
3595
+
3596
+ -- empty-window-frame multi-column
3597
+ SELECT
3598
+ LENGTH(WIN_SINEFIT2(0, NULL, xx, yy, xx, yy * 2) OVER (
3599
+ ORDER BY xx
3600
+ ROWS BETWEEN 5 PRECEDING AND 3 PRECEDING
3601
+ )) AS nhead
3602
+ FROM testWinSinefit2Emptyframe;
3603
+ -- non-empty-window-frame control
3604
+ SELECT
3605
+ LENGTH(WIN_SINEFIT2(0, NULL, xx, yy) OVER (
3606
+ ORDER BY xx
3607
+ ROWS BETWEEN 5 PRECEDING AND CURRENT ROW
3608
+ )) AS nhead
3609
+ FROM testWinSinefit2Emptyframe;
3610
+
3611
+ -- sinefit-object is well-formed
3612
+ -- row 8 frame = rows 3-5, so nnn = 3
3613
+ WITH tmp1 AS (
3614
+ SELECT
3615
+ xx,
3616
+ win_sinefit2(0, NULL, xx, yy, xx, yy * 2) OVER (
3617
+ ORDER BY xx
3618
+ ROWS BETWEEN 5 PRECEDING AND 3 PRECEDING
3619
+ ) AS wsf
3620
+ FROM testWinSinefit2Emptyframe
3621
+ )
3622
+ SELECT
3623
+ SINEFIT_EXTRACT(wsf, 0, 'nnn', 0) AS nnn0,
3624
+ SINEFIT_EXTRACT(wsf, 1, 'nnn', 0) AS nnn1,
3625
+ SINEFIT_EXTRACT(wsf, 0, 'lbb', 0) AS lbb0,
3626
+ SINEFIT_EXTRACT(wsf, 1, 'lbb', 0) AS lbb1
3627
+ FROM tmp1
3628
+ WHERE xx = 8;
3629
+ -- empty-table xFinal
3630
+ SELECT LENGTH(WIN_SINEFIT2(0, NULL, xx, yy)) AS nhead
3631
+ FROM testWinSinefit2Emptyframe
3632
+ WHERE 0;
3633
+ `)
3634
+ })
3635
+ ),
3636
+ [
3637
+ [
3638
+ {nhead: 0},
3639
+ {nhead: 0},
3640
+ {nhead: 0},
3641
+ {nhead},
3642
+ {nhead},
3643
+ {nhead},
3644
+ {nhead},
3645
+ {nhead}
3646
+ ],
3647
+ [
3648
+ {nhead: 0},
3649
+ {nhead: 0},
3650
+ {nhead: 0},
3651
+ {nhead: 2 * nhead},
3652
+ {nhead: 2 * nhead},
3653
+ {nhead: 2 * nhead},
3654
+ {nhead: 2 * nhead},
3655
+ {nhead: 2 * nhead}
3656
+ ],
3657
+ [
3658
+ {nhead},
3659
+ {nhead},
3660
+ {nhead},
3661
+ {nhead},
3662
+ {nhead},
3663
+ {nhead},
3664
+ {nhead},
3665
+ {nhead}
3666
+ ],
3667
+ [
3668
+ {lbb0: 1, lbb1: 2, nnn0: 3, nnn1: 3}
3669
+ ],
3670
+ [
3671
+ {nhead: 0}
3672
+ ]
3673
+ ]
3674
+ );
3675
+ }()),
3676
+ // test sinefit_refitlast malformed-blob handling-behavior
3677
+ (async function () {
3678
+ // WinSinefit field-offsets, in bytes
3679
+ let offsetNnn = 5 * 8;
3680
+ let offsetWbb = 16 * 8;
3681
+ function blobMalformed(nnn, wbb) {
3682
+ // ncol=1 header = WIN_SINEFIT_N * 8 = 184 bytes
3683
+ let buf = new ArrayBuffer(184);
3684
+ let dv = new DataView(buf);
3685
+ dv.setFloat64(offsetNnn, nnn, true);
3686
+ dv.setFloat64(offsetWbb, wbb, true);
3687
+ return new Uint8Array(buf);
3688
+ }
3689
+ // test malformed-nnn handling-behavior
3690
+ await Promise.all([
3691
+ 0 / 0, // nan
3692
+ 1 / 0, // inf
3693
+ -1 / 0, // -inf
3694
+ 1e300, // overflows (int)
3695
+ -1, // negative
3696
+ 0, // empty
3697
+ 1.5 // non-integral
3698
+ ].map(function (nnn) {
3699
+ return assertErrorThrownAsync(function () {
3700
+ return dbExecAsync({
3701
+ bindList: [blobMalformed(nnn, 0)],
3702
+ db,
3703
+ sql: "SELECT sinefit_refitlast(?1, 0, 0)"
3704
+ });
3705
+ }, "sinefit_refitlast");
3706
+ }));
3707
+ // test malformed-wbb handling-behavior
3708
+ // nnn=1 implies nbody = 3, so any wbb but 0 is invalid.
3709
+ await Promise.all([
3710
+ 0 / 0, 1 / 0, 1e300, -1, 1, 2, 3, 1.5
3711
+ ].map(function (wbb) {
3712
+ return assertErrorThrownAsync(function () {
3713
+ return dbExecAsync({
3714
+ bindList: [blobMalformed(1, wbb)],
3715
+ db,
3716
+ sql: "SELECT sinefit_refitlast(?1, 0, 0)"
3717
+ });
3718
+ }, "sinefit_refitlast");
3719
+ }));
3720
+ // test truncated-blob handling-behavior
3721
+ await assertErrorThrownAsync(function () {
3722
+ return dbExecAsync({
3723
+ bindList: [new Uint8Array(100)],
3724
+ db,
3725
+ sql: "SELECT sinefit_refitlast(?1, 0, 0)"
3726
+ });
3727
+ }, "sinefit_refitlast");
3728
+ // test wrong-argc handling-behavior
3729
+ await assertErrorThrownAsync(function () {
3730
+ return dbExecAsync({
3731
+ bindList: [blobMalformed(1, 0)],
3732
+ db,
3733
+ sql: "SELECT sinefit_refitlast(?1, 0)"
3734
+ });
3735
+ }, "sinefit_refitlast");
3736
+ }()),
3737
+ // test sinefit_extract non-blob 1st-argument handling-behavior
3738
+ (async function () {
3739
+ await Promise.all([
3740
+ "'hello'",
3741
+ "123",
3742
+ "1.5",
3743
+ "NULL",
3744
+ "zeroblob(0)"
3745
+ ].map(function (arg) {
3746
+ return assertErrorThrownAsync(function () {
3747
+ return dbExecAsync({
3748
+ db,
3749
+ sql: `SELECT sinefit_extract(${arg}, 0, 'nnn', 0)`
3750
+ });
3751
+ }, "sinefit_extract");
3752
+ }));
3753
+ }()),
3754
+ // test win_sinefit2-aggregate-normal handling-behavior
3755
+ (async function () {
3756
+ // test non-blob 1st-argument handling-behavior
3757
+ await Promise.all([
3758
+ "'hello'",
3759
+ "123",
3760
+ "1.5",
3761
+ "NULL",
3762
+ "zeroblob(0)"
3763
+ ].map(function (arg) {
3764
+ return assertErrorThrownAsync(function () {
3765
+ return dbExecAsync({
3766
+ db,
3767
+ sql: `SELECT sinefit_extract(${arg}, 0, 'nnn', 0)`
3768
+ });
3769
+ }, "sinefit_extract");
3770
+ }));
3771
+ }()),
3468
3772
  // test win_sinefit2-aggregate-normal handling-behavior
3469
3773
  (async function () {
3470
3774
  let valActual;
@@ -3494,7 +3798,7 @@ SELECT
3494
3798
  "gyy": 0.19611614,
3495
3799
  "laa": 0.77941176,
3496
3800
  "lbb": 0.84558824,
3497
- "lee": 1.40010504,
3801
+ "lee": 1.56536502,
3498
3802
  "lxy": 0.81541829,
3499
3803
  "lyy": 2.47058824,
3500
3804
  "mee": 2.54950976,
@@ -3520,7 +3824,7 @@ SELECT
3520
3824
  "gyy": -1.02062073,
3521
3825
  "laa": -0.82025678,
3522
3826
  "lbb": 0.14621969,
3523
- "lee": 2.23885734,
3827
+ "lee": 2.74202904,
3524
3828
  "lxy": 0.865665,
3525
3829
  "lyy": 6.63694722,
3526
3830
  "mee": 4.89897949,
@@ -3566,7 +3870,7 @@ SELECT
3566
3870
  "id2": id3,
3567
3871
  "laa": 5.25,
3568
3872
  "lbb": -0.275,
3569
- "lee": 2.49624718,
3873
+ "lee": 2.88241797,
3570
3874
  "lxy": -0.23918696,
3571
3875
  "lyy": 2.5,
3572
3876
  "mee": 2.74837614,
@@ -3586,7 +3890,7 @@ SELECT
3586
3890
  "id2": id4,
3587
3891
  "laa": 7.25,
3588
3892
  "lbb": -0.575,
3589
- "lee": 1.95735791,
3893
+ "lee": 2.26016224,
3590
3894
  "lxy": -0.5490214,
3591
3895
  "lyy": 6.1,
3592
3896
  "mee": 2.50356888,
@@ -3918,7 +4222,7 @@ SELECT
3918
4222
  FROM __sinefit_csv
3919
4223
  JOIN (
3920
4224
  SELECT
3921
- MEDIAN2(rr) AS rr_avg,
4225
+ MEDIAN(rr) AS rr_avg,
3922
4226
  STDEV(rr) AS rr_err
3923
4227
  FROM __sinefit_csv
3924
4228
  )