V8 Coverage Report
Files covered Lines Remaining
. / sqlmath.mjs
100.00 %
1996 / 1996

0 / 1996
    1.      1// MIT License
    2.      1//
    3.      1// Copyright (c) 2021 Kai Zhu
    4.      1//
    5.      1// Permission is hereby granted, free of charge, to any person obtaining a copy
    6.      1// of this software and associated documentation files (the "Software"), to deal
    7.      1// in the Software without restriction, including without limitation the rights
    8.      1// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    9.      1// copies of the Software, and to permit persons to whom the Software is
   10.      1// furnished to do so, subject to the following conditions:
   11.      1//
   12.      1// The above copyright notice and this permission notice shall be included in
   13.      1// all copies or substantial portions of the Software.
   14.      1//
   15.      1// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   16.      1// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   17.      1// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
   18.      1// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   19.      1// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
   20.      1// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
   21.      1// SOFTWARE.
   22.      1
   23.      1
   24.      1/*jslint beta, bitwise, name, node*/
   25.      1/*global FinalizationRegistry*/
   26.      1"use strict";
   27.      1
   28.      1const JSBATON_ARGC = 8;
   29.      1const JSBATON_OFFSET_ALL = 256;
   30.      1const JSBATON_OFFSET_ARGV = 128;
   31.      1const JSBATON_OFFSET_BUFV = 192;
   32.      1// const JSBATON_OFFSET_ERRMSG = 48;
   33.      1const JSBATON_OFFSET_FUNCNAME = 8;
   34.      1const JS_MAX_SAFE_INTEGER = 0x1f_ffff_ffff_ffff;
   35.      1const JS_MIN_SAFE_INTEGER = -0x1f_ffff_ffff_ffff;
   36.      1const SIZEOF_BLOB_MAX = 1_000_000_000;
   37.      1// const SIZEOF_ERRMSG = 80;
   38.      1const SIZEOF_FUNCNAME = 16;
   39.      1const SQLITE_DATATYPE_BLOB = 0x04;
   40.      1const SQLITE_DATATYPE_EXTERNALBUFFER = 0x71;
   41.      1const SQLITE_DATATYPE_FLOAT = 0x02;
   42.      1const SQLITE_DATATYPE_INTEGER = 0x01;
   43.      1const SQLITE_DATATYPE_INTEGER_0 = 0x00;
   44.      1const SQLITE_DATATYPE_INTEGER_1 = 0x21;
   45.      1const SQLITE_DATATYPE_NULL = 0x05;
   46.      1const SQLITE_DATATYPE_TEXT = 0x03;
   47.      1const SQLITE_DATATYPE_TEXT_0 = 0x13;
   48.      1const SQLITE_RESPONSETYPE_LASTBLOB = 1;
   49.      1const SQLITE_RESPONSETYPE_LASTVALUE = 2;
   50.      1
   51.      1const FILENAME_DBTMP = "/tmp/__dbtmp1"; //jslint-ignore-line
   52.      1
   53.      1const LGBM_DTYPE_FLOAT32 = 0;           /* float32 (single precision float)*/
   54.      1const LGBM_DTYPE_FLOAT64 = 1;           /* float64 (double precision float)*/
   55.      1const LGBM_DTYPE_INT32 = 2;             /* int32*/
   56.      1const LGBM_DTYPE_INT64 = 3;             /* int64*/
   57.      1const LGBM_FEATURE_IMPORTANCE_GAIN = 1; /* Gain type of feature importance*/
   58.      1const LGBM_FEATURE_IMPORTANCE_SPLIT = 0;/* Split type of feature importance*/
   59.      1const LGBM_MATRIX_TYPE_CSC = 1;         /* CSC sparse matrix type*/
   60.      1const LGBM_MATRIX_TYPE_CSR = 0;         /* CSR sparse matrix type*/
   61.      1const LGBM_PREDICT_CONTRIB = 3; /* Predict feature contributions (SHAP values)*/
   62.      1const LGBM_PREDICT_LEAF_INDEX = 2;      /* Predict leaf index*/
   63.      1const LGBM_PREDICT_NORMAL = 0;  /* Normal prediction w/ transform (if needed)*/
   64.      1const LGBM_PREDICT_RAW_SCORE = 1;       /* Predict raw score*/
   65.      1const SQLITE_OPEN_AUTOPROXY = 0x00000020;       /* VFS only */
   66.      1const SQLITE_OPEN_CREATE = 0x00000004;          /* Ok for sqlite3_open_v2() */
   67.      1const SQLITE_OPEN_DELETEONCLOSE = 0x00000008;   /* VFS only */
   68.      1const SQLITE_OPEN_EXCLUSIVE = 0x00000010;       /* VFS only */
   69.      1const SQLITE_OPEN_FULLMUTEX = 0x00010000;       /* Ok for sqlite3_open_v2() */
   70.      1const SQLITE_OPEN_MAIN_DB = 0x00000100;         /* VFS only */
   71.      1const SQLITE_OPEN_MAIN_JOURNAL = 0x00000800;    /* VFS only */
   72.      1const SQLITE_OPEN_MEMORY = 0x00000080;          /* Ok for sqlite3_open_v2() */
   73.      1const SQLITE_OPEN_NOFOLLOW = 0x01000000;        /* Ok for sqlite3_open_v2() */
   74.      1const SQLITE_OPEN_NOMUTEX = 0x00008000;         /* Ok for sqlite3_open_v2() */
   75.      1const SQLITE_OPEN_PRIVATECACHE = 0x00040000;    /* Ok for sqlite3_open_v2() */
   76.      1const SQLITE_OPEN_READONLY = 0x00000001;        /* Ok for sqlite3_open_v2() */
   77.      1const SQLITE_OPEN_READWRITE = 0x00000002;       /* Ok for sqlite3_open_v2() */
   78.      1const SQLITE_OPEN_SHAREDCACHE = 0x00020000;     /* Ok for sqlite3_open_v2() */
   79.      1const SQLITE_OPEN_SUBJOURNAL = 0x00002000;      /* VFS only */
   80.      1const SQLITE_OPEN_SUPER_JOURNAL = 0x00004000;   /* VFS only */
   81.      1const SQLITE_OPEN_TEMP_DB = 0x00000200;         /* VFS only */
   82.      1const SQLITE_OPEN_TEMP_JOURNAL = 0x00001000;    /* VFS only */
   83.      1const SQLITE_OPEN_TRANSIENT_DB = 0x00000400;    /* VFS only */
   84.      1const SQLITE_OPEN_URI = 0x00000040;             /* Ok for sqlite3_open_v2() */
   85.      1const SQLITE_OPEN_WAL = 0x00080000;             /* VFS only */
   86.      1
   87.      1let DB_EXEC_PROFILE_DICT = {};
   88.      1let DB_EXEC_PROFILE_MODE;
   89.      1let DB_EXEC_PROFILE_SQL_LENGTH;
   90.      1let DB_STATE = {};
   91.      1let IS_BROWSER;
   92.      1let SQLMATH_EXE;
   93.      1let SQLMATH_NODE;
   94.      1let cModule;
   95.      1let cModulePath;
   96.      1let consoleError = console.error;
   97.      1let dbFinalizationRegistry;
   98.      1// init debugInline
   99.      1let debugInline = (function () {
  100.      3    let __consoleError = function () {
  101.      3        return;
  102.      3    };
  103.      1    function debug(...argv) {
  104.      1
  105.      1// This function will print <argv> to stderr and then return <argv>[0].
  106.      1
  107.      1        __consoleError("\n\ndebugInline");
  108.      1        __consoleError(...argv);
  109.      1        __consoleError("\n");
  110.      1        return argv[0];
  111.      1    }
  112.      1    debug(); // Coverage-hack.
  113.      1    __consoleError = console.error; //jslint-ignore-line
  114.      1    return debug;
  115.      1}());
  116.      1let moduleChildProcess;
  117.      1let moduleChildProcessSpawn;
  118.      1let moduleCrypto;
  119.      1let moduleFs;
  120.      1let moduleFsInitResolveList;
  121.      1let modulePath;
  122.      1let moduleUrl;
  123.      1let {
  124.      1    npm_config_mode_debug,
  125.      1    npm_config_mode_setup,
  126.      1    npm_config_mode_test
  127.      1} = typeof process === "object" && process?.env;
  128.      1let sqlMessageDict = {}; // dict of web-worker-callbacks
  129.      1let sqlMessageId = 0;
  130.      1let sqlWorker;
  131.      1let version = "v2026.4.31";
  132.      1
  133.     86async function assertErrorThrownAsync(asyncFunc, regexp) {
  134.     86
  135.     86// This function will assert calling <asyncFunc> throws an error.
  136.     86
  137.     86    let err;
  138.     86    try {
  139.      1        await asyncFunc();
  140.     85    } catch (errCaught) {
  141.     85        err = errCaught;
  142.     85    }
  143.     86    assertOrThrow(err, "No error thrown.");
  144.     86    assertOrThrow(
  145.     83        !regexp || new RegExp(regexp).test(err.message),
  146.     86        err
  147.     86    );
  148.     86}
  149.      1
  150.  14024function assertInt64(val) {
  151.  14024    // This function will assert <val> is within range of c99-signed-long-long.
  152.  14024    val = BigInt(val);
  153.  14024    if (!(
  154.  14017        -9_223_372_036_854_775_808n <= val && val <= 9_223_372_036_854_775_807n
  155.     14    )) {
  156.     14        throw new Error(
  157.     14            `integer ${val} outside signed-64-bit inclusive-range`
  158.     14            + " -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807"
  159.     14        );
  160.     14    }
  161.  14024}
  162.      1
  163.   4930function assertJsonEqual(aa, bb, message) {
  164.   4930
  165.   4930// This function will assert JSON.stringify(<aa>) === JSON.stringify(<bb>).
  166.   4930
  167.   4930    aa = JSON.stringify(objectDeepCopyWithKeysSorted(aa), undefined, 1);
  168.   4930    bb = JSON.stringify(objectDeepCopyWithKeysSorted(bb), undefined, 1);
  169.      3    if (aa !== bb) {
  170.      3        throw new Error(
  171.      3            "\n" + aa + "\n!==\n" + bb
  172.      3            + (
  173.      3                typeof message === "string"
  174.      3                ? " - " + message
  175.      3                : message
  176.      3                ? " - " + JSON.stringify(message)
  177.      3                : ""
  178.      3            )
  179.      3        );
  180.      3    }
  181.   4930}
  182.      1
  183.      4function assertNumericalEqual(aa, bb, message) {
  184.      4
  185.      4// This function will assert aa - bb <= Number.EPSILON.
  186.      4
  187.      4    assertOrThrow(aa, "value cannot be 0 or falsy");
  188.      2    if (!(Math.abs((aa - bb) / Math.max(aa, bb)) <= 256 * Number.EPSILON)) {
  189.      2        throw new Error(
  190.      2            JSON.stringify(aa) + " != " + JSON.stringify(bb) + (
  191.      2                message
  192.      2                ? " - " + message
  193.      2                : ""
  194.      2            )
  195.      2        );
  196.      2    }
  197.      4}
  198.      1
  199.  49221function assertOrThrow(condition, message) {
  200.  49221
  201.  49221// This function will throw <message> if <condition> is falsy.
  202.  49221
  203.     70    if (!condition) {
  204.     70        throw (
  205.     70            (!message || typeof message === "string")
  206.     70            ? new Error(String(message).slice(0, 2048))
  207.     70            : message
  208.     70        );
  209.     70    }
  210.  49221}
  211.      1
  212.     15async function childProcessSpawn2(command, args, option) {
  213.     15
  214.     15// This function will run child_process.spawn as a promise.
  215.     15
  216.     15    return await new Promise(function (resolve, reject) {
  217.     15        let bufList = [[], [], []];
  218.     15        let child;
  219.     15        let {
  220.     15            modeCapture,
  221.     15            modeDebug,
  222.     15            stdio = []
  223.     15        } = option;
  224.      1        if (modeDebug) {
  225.      1            consoleError(
  226.      1                `childProcessSpawn2 - ${command} ${JSON.stringify(args)}`
  227.      1            );
  228.      1        }
  229.     15        child = moduleChildProcessSpawn(
  230.     15            command,
  231.     15            args,
  232.     15            Object.assign({}, option, {
  233.     15                stdio: [
  234.     15                    "ignore",
  235.     15                    (
  236.     15                        modeCapture
  237.      1                        ? "pipe"
  238.     14                        : stdio[1]
  239.     15                    ),
  240.     15                    (
  241.     15                        modeCapture
  242.      1                        ? "pipe"
  243.     14                        : stdio[2]
  244.     15                    )
  245.     15                ]
  246.     15            })
  247.     15        );
  248.      1        if (modeCapture) {
  249.      1            [
  250.      1                child.stdin, child.stdout, child.stderr
  251.      3            ].forEach(function (pipe, ii) {
  252.      1                if (ii === 0) {
  253.      1                    return;
  254.      2                }
  255.      2                pipe.on("data", function (chunk) {
  256.      2                    bufList[ii].push(chunk);
  257.      2                    if (stdio[ii] !== "ignore") {
  258.      2                        switch (ii) {
  259.      2                        case 1:
  260.      2                            process.stdout.write(chunk);
  261.      2                            break;
  262.      2                        case 2:
  263.      2                            process.stderr.write(chunk);
  264.      2                            break;
  265.      2                        }
  266.      2                    }
  267.      2                });
  268.      2            });
  269.      1        }
  270.     15        child.on("exit", function (exitCode) {
  271.     15            let resolve0 = resolve;
  272.     15            let stderr;
  273.     15            let stdout;
  274.     15            // coverage-hack
  275.     15            if (exitCode || npm_config_mode_test) {
  276.     15                resolve = reject;
  277.     15            }
  278.     15            // coverage-hack
  279.     15            if (npm_config_mode_test) {
  280.     15                resolve = resolve0;
  281.     15            }
  282.     15            [
  283.     15                stdout, stderr
  284.     30            ] = bufList.slice(1).map(function (buf) {
  285.     30                return (
  286.     30                    typeof modeCapture === "string"
  287.      2                    ? Buffer.concat(buf).toString(modeCapture)
  288.     28                    : Buffer.concat(buf)
  289.     30                );
  290.     30            });
  291.     15            resolve([
  292.     15                exitCode, stdout, stderr
  293.     15            ]);
  294.     15        });
  295.     15    });
  296.     15}
  297.      1
  298.      7async function ciBuildExt({
  299.      7    process
  300.      7}) {
  301.      7
  302.      7// This function will build sqlmath from c.
  303.      7
  304.      7    let binNodegyp;
  305.      7    let exitCode;
  306.      7    binNodegyp = modulePath.resolve(
  307.      7        modulePath.dirname(process.execPath || ""),
  308.      7        "node_modules/npm/node_modules/node-gyp/bin/node-gyp.js"
  309.      7    ).replace("/bin/node_modules/", "/lib/node_modules/");
  310.      7    if (!noop(
  311.      7        await fsExistsUnlessTest(cModulePath)
  312.      7    )) {
  313.      7        await ciBuildExt1NodejsConfigure({
  314.      7            binNodegyp,
  315.      7            process
  316.      7        });
  317.      7    }
  318.      7    consoleError(
  319.      7        `ciBuildExt2Nodejs - linking lib ${modulePath.resolve(cModulePath)}`
  320.      7    );
  321.      7    [
  322.      7        exitCode
  323.      7    ] = await childProcessSpawn2(
  324.      7        "sh",
  325.      7        [
  326.      7            "-c",
  327.      7            (`
  328.      7(set -e
  329.      7    # rebuild binding
  330.      7    node "${binNodegyp}" build --release
  331.      7    # node "${binNodegyp}" build --release --loglevel=verbose
  332.      7    mv build/Release/binding.node "${cModulePath}"
  333.      7    mv build/Release/shell "${SQLMATH_EXE}"
  334.      7    # ugly-hack - win32-sqlite-shell doesn't like nodejs-builtin-zlib,
  335.      7    #             so link with external-zlib.
  336.      7    if (uname | grep -q "MING\\|MSYS")
  337.      7    then
  338.      7        rm -f ${SQLMATH_EXE}
  339.      7        python setup.py exe_link \
  340.      7            ./build/Release/SRC_SQLITE_BASE.lib \
  341.      7            ./build/Release/SRC_SQLMATH_BASE.lib \
  342.      7            ./build/Release/obj/shell/sqlmath_external_sqlite.obj \
  343.      7            ./zlib.v1.3.1.vcpkg.x64-windows-static.lib \
  344.      7            \
  345.      7            -ltcg \
  346.      7            -nologo \
  347.      7            -out:${SQLMATH_EXE} \
  348.      7            -subsystem:console
  349.      7    fi
  350.      7)
  351.      7            `)
  352.      7        ],
  353.      7        {modeDebug: npm_config_mode_debug, stdio: ["ignore", 1, 2]}
  354.      7    );
  355.      7    assertOrThrow(!exitCode, `ciBuildExt - exitCode=${exitCode}`);
  356.      7}
  357.      1
  358.      7async function ciBuildExt1NodejsConfigure({
  359.      7    binNodegyp
  360.      7    // process
  361.      7}) {
  362.      7
  363.      7// This function will setup posix/win32 env for building c-extension.
  364.      7
  365.      7    let cflagWallList = [];
  366.      7    let cflagWnoList = [];
  367.      7    String(
  368.      7        await fsReadFileUnlessTest(".ci.sh", "utf8", (`
  369.      7SQLMATH_CFLAG_WALL_LIST=" \\
  370.      7"
  371.      7SQLMATH_CFLAG_WNO_LIST=" \\
  372.      7"
  373.      7        `))
  374.      7    ).replace((
  375.      7        /(SQLMATH_CFLAG_WALL_LIST|SQLMATH_CFLAG_WNO_LIST)=" \\([\S\s]*?)"/g
  376.     14    ), function (ignore, cflagType, cflagList) {
  377.     14        cflagList = cflagList.split(/[\s\\]/).filter(noop);
  378.     14        switch (cflagType) {
  379.      7        case "SQLMATH_CFLAG_WALL_LIST":
  380.      7            cflagWallList = cflagList;
  381.      7            break;
  382.      7        case "SQLMATH_CFLAG_WNO_LIST":
  383.      7            cflagWnoList = cflagList;
  384.      7            break;
  385.     14        }
  386.     14        return "";
  387.     14    });
  388.      7    consoleError(`ciBuildExt1Nodejs - configure binding.gyp`);
  389.      7    await fsWriteFileUnlessTest("binding.gyp", JSON.stringify({
  390.      7        "target_defaults": {
  391.      7            "cflags": cflagWallList,
  392.      7// https://github.com/nodejs/node-gyp/blob/v10.3.1/gyp/pylib/gyp/MSVSSettings.py
  393.      7            "msvs_settings": {
  394.      7                "VCCLCompilerTool": {
  395.      7                    "WarnAsError": 1,
  396.      7                    "WarningLevel": 4
  397.      7                }
  398.      7            },
  399.      7            "xcode_settings": {
  400.      7                "OTHER_CFLAGS": cflagWallList
  401.      7            }
  402.      7        },
  403.      7        "targets": [
  404.      7            {
  405.      7                "cflags": cflagWnoList,
  406.      7                "defines": [
  407.      7                    "SRC_SQLITE_BASE_C2"
  408.      7                ],
  409.      7                "msvs_settings": {
  410.      7                    "VCCLCompilerTool": {
  411.      7                        "WarnAsError": 1,
  412.      7                        "WarningLevel": 2
  413.      7                    }
  414.      7                },
  415.      7                "sources": [
  416.      7                    "sqlmath_external_sqlite.c"
  417.      7                ],
  418.      7                "target_name": "SRC_SQLITE_BASE",
  419.      7                "type": "static_library",
  420.      7                "xcode_settings": {
  421.      7                    "OTHER_CFLAGS": cflagWnoList
  422.      7                }
  423.      7            },
  424.      7            {
  425.      7                "defines": [
  426.      7                    "SRC_SQLMATH_BASE_C2"
  427.      7                ],
  428.      7                "dependencies": [
  429.      7                    "SRC_SQLITE_BASE"
  430.      7                ],
  431.      7                "sources": [
  432.      7                    "sqlmath_base.c"
  433.      7                ],
  434.      7                "target_name": "SRC_SQLMATH_BASE",
  435.      7                "type": "static_library"
  436.      7            },
  437.      7            {
  438.      7                "defines": [
  439.      7                    "SRC_SQLMATH_NODEJS_C2"
  440.      7                ],
  441.      7                "dependencies": [
  442.      7                    "SRC_SQLMATH_BASE"
  443.      7                ],
  444.      7                "sources": [
  445.      7                    "sqlmath_base.c"
  446.      7                ],
  447.      7                "target_name": "binding"
  448.      7            },
  449.      7            {
  450.      7                "conditions": [
  451.      7                    [
  452.      7                        "OS==\"win\"",
  453.      7                        {},
  454.      7                        {
  455.      7                            "libraries": [
  456.      7                                "-lz"
  457.      7                            ]
  458.      7                        }
  459.      7                    ]
  460.      7                ],
  461.      7                "defines": [
  462.      7                    "SRC_SQLITE_SHELL_C2"
  463.      7                ],
  464.      7                "dependencies": [
  465.      7                    "SRC_SQLMATH_BASE"
  466.      7                ],
  467.      7                "sources": [
  468.      7                    "sqlmath_external_sqlite.c"
  469.      7                ],
  470.      7                "target_name": "shell",
  471.      7                "type": "executable"
  472.      7            }
  473.      7        ]
  474.      7    }, undefined, 4) + "\n");
  475.      7    await childProcessSpawn2(
  476.      7        "sh",
  477.      7        [
  478.      7            "-c",
  479.      7            (`
  480.      7(set -e
  481.      7    # node "${binNodegyp}" clean
  482.      7    node "${binNodegyp}" configure
  483.      7)
  484.      7            `)
  485.      7        ],
  486.      7        {modeDebug: npm_config_mode_debug, stdio: ["ignore", 1, 2]}
  487.      7    );
  488.      7}
  489.      1
  490.   3913async function dbCallAsync(baton, argList, mode, db) {
  491.   3913
  492.   3913// This function will call c-function dbXxx() with given <funcname>
  493.   3913// and return [<baton>, ...argList].
  494.   3913
  495.   3913    let errStack;
  496.   3913    let funcname;
  497.   3913    let id;
  498.   3913    let profileObj;
  499.   3913    let profileStart;
  500.   3913    let result;
  501.   3913    let sql;
  502.   3913    let timeElapsed;
  503.   3913    // If argList contains <db>, then mark it as busy.
  504.   2026    if (mode === "modeDbExec" || mode === "modeDbFile") {
  505.   1902        // init db
  506.   1902        db = argList[0];
  507.   1902        assertOrThrow(
  508.   1902            db.busy >= 0,
  509.   1902            `dbCallAsync - invalid db.busy = ${db.busy}`
  510.   1902        );
  511.   1902        db.ii = (db.ii + 1) % db.connPool.length;
  512.   1902        db.ptr = db.connPool[db.ii][0];
  513.   1902        // increment db.busy
  514.   1902        db.busy += 1;
  515.   1902        // init profileObj
  516.   1902        if (DB_EXEC_PROFILE_MODE && mode === "modeDbExec") {
  517.   1902            profileStart = Date.now();
  518.   1902            sql = String(argList[1]);
  519.   1902            // sql-hash - remove comment
  520.   1902            sql = sql.replace((/(?:^|\s+?)--.*/gm), "");
  521.   1902            // sql-hash - remove vowel
  522.   1902            sql = sql.replace((/[aeiou]\b/gi), "\u0000$&");
  523.   1902            sql = sql.replace((/([bcdfghjklmnpqrstvwxyz])[aeiou]+/gi), "$1");
  524.   1902            sql = sql.replace((/\u0000([aeiou])\b/gi), "$1");
  525.   1902            // sql-hash - remove underscore
  526.   1902            sql = sql.replace((/_+/g), "");
  527.   1902            // sql-hash - truncate long text
  528.   1902            sql = sql.replace((/(\S{16})\S+/g), "$1");
  529.   1902            // sql-hash - remove whitespace
  530.   1902            sql = sql.replace((/\s+/g), " ");
  531.   1902            sql = sql.trim().slice(0, DB_EXEC_PROFILE_SQL_LENGTH);
  532.   1902            DB_EXEC_PROFILE_DICT[sql] = DB_EXEC_PROFILE_DICT[sql] || {
  533.   1902                busy: 0,
  534.   1902                count: 0,
  535.   1902                sql,
  536.   1902                timeElapsed: 0
  537.   1902            };
  538.   1902            profileObj = DB_EXEC_PROFILE_DICT[sql];
  539.   1902            // increment profileObj.busy
  540.   1902            profileObj.busy += 1;
  541.   1902            profileObj.count += 1;
  542.   1902        }
  543.   1902        try {
  544.   1902            return await dbCallAsync(
  545.   1902                baton,
  546.   1902                [
  547.   1902                    db.ptr,
  548.   1902                    ...argList.slice(1)
  549.   1902                ],
  550.   1902                undefined,
  551.   1902                db
  552.   1902            );
  553.   1902        } finally {
  554.   1902            // decrement db.busy
  555.   1902            db.busy -= 1;
  556.   1902            assertOrThrow(
  557.   1902                db.busy >= 0,
  558.   1902                `dbCallAsync - invalid db.busy = ${db.busy}`
  559.   1902            );
  560.   1902            // update profileObj
  561.   1902            if (profileObj) {
  562.   1902                // decrement profileObj.busy
  563.   1902                profileObj.busy -= 1;
  564.   1902                assertOrThrow(
  565.   1902                    profileObj.busy >= 0,
  566.   1902                    `dbCallAsync - invalid profileObj.busy = ${profileObj.busy}`
  567.   1902                );
  568.   1902                if (profileObj.busy === 0) {
  569.   1902                    profileObj.timeElapsed += Date.now() - profileStart;
  570.   1902                }
  571.   1902            }
  572.   1902        }
  573.   2011    }
  574.   2011    // copy argList to avoid side-effect
  575.   2011    argList = [...argList];
  576.   2011    assertOrThrow(
  577.   2011        argList.length <= JSBATON_ARGC,
  578.   2011        `dbCallAsync - argList.length must be less than than ${JSBATON_ARGC}`
  579.   2011    );
  580.   2011    // pad argList to length JSBATON_ARGC
  581.   6228    while (argList.length < JSBATON_ARGC) {
  582.   6228        argList.push(0n);
  583.   6228    }
  584.   2011    // serialize js-value to c-value
  585.  15950    argList = argList.map(function (val, argi) {
  586.  15949        if (val === null || val === undefined) {
  587.   2011            val = 0;
  588.   2011        }
  589.  15950        switch (typeof val) {
  590.   8047        case "bigint":
  591.   9937        case "boolean":
  592.  13992        case "number":
  593.  13992            // check for min/max safe-integer
  594.  13992            assertOrThrow(
  595.  13992                (
  596.  13992                    (JS_MIN_SAFE_INTEGER <= val && val <= JS_MAX_SAFE_INTEGER)
  597.  13992                    || typeof val === "bigint"
  598.  13992                ),
  599.  13992                (
  600.  13992                    "dbCallAsync - "
  601.  13992                    + "non-bigint-integer must be within inclusive-range"
  602.  13992                    + ` ${JS_MIN_SAFE_INTEGER} to ${JS_MAX_SAFE_INTEGER}`
  603.  13992                )
  604.  13992            );
  605.  13992            val = BigInt(val);
  606.  13992            assertInt64(val);
  607.  13992            baton.setBigInt64(JSBATON_OFFSET_ARGV + argi * 8, val, true);
  608.  13992            return val;
  609.  15950        // case "object":
  610.  15950        //     break;
  611.   2011        case "string":
  612.   2011            baton = jsbatonSetValue(baton, argi, (
  613.   2011                val.endsWith("\u0000")
  614.   2011                ? val
  615.   2011                // append null-terminator to string
  616.   2011                : val + "\u0000"
  617.   2011            ));
  618.   2011            return;
  619.   2011        }
  620.   2011        assertOrThrow(
  621.   2011            !ArrayBuffer.isView(val) || val.byteOffset === 0,
  622.  15950            (
  623.  15950                "dbCallAsync - argList cannot contain arraybuffer-views"
  624.  15950                + " with non-zero byteOffset"
  625.  15950            )
  626.  15950        );
  627.   2011        if (isExternalBuffer(val)) {
  628.   2011            return val;
  629.   2011        }
  630.   2011        throw new Error(`dbCallAsync - invalid arg-type "${typeof val}"`);
  631.   2011    });
  632.   2011    // assert byteOffset === 0
  633.  17892    [baton, ...argList].forEach(function (arg) {
  634.   2011        assertOrThrow(!ArrayBuffer.isView(arg) || arg.byteOffset === 0, arg);
  635.  17892    });
  636.   2011    // extract funcname
  637.   2011    funcname = new TextDecoder().decode(
  638.   2011        new DataView(baton.buffer, JSBATON_OFFSET_FUNCNAME, SIZEOF_FUNCNAME)
  639.   2011    ).replace((/\u0000/g), "");
  640.   2011    // preserve stack-trace
  641.   2011    errStack = new Error().stack.replace((/.*$/m), "");
  642.   2011    try {
  643.   2011
  644.   2011// Dispatch to nodejs-napi.
  645.   2011
  646.   2011        if (!IS_BROWSER) {
  647.   1986            await cModule._jspromiseCreate(baton.buffer, argList, funcname);
  648.   1986            // prepend baton to argList
  649.   1986            return [baton, ...argList];
  650.   1986        }
  651.      2
  652.      2// Dispatch to web-worker.
  653.      2
  654.      2        // increment sqlMessageId
  655.      2        sqlMessageId += 1;
  656.      2        id = sqlMessageId;
  657.      2        // postMessage to web-worker
  658.      2        sqlWorker.postMessage(
  659.      2            {
  660.      2                FILENAME_DBTMP,
  661.      2                JSBATON_OFFSET_ALL,
  662.      2                JSBATON_OFFSET_BUFV,
  663.      2                argList,
  664.      2                baton,
  665.      2                funcname,
  666.      2                id
  667.      2            },
  668.      2            // transfer arraybuffer without copying
  669.      2            [baton.buffer, ...argList.filter(isExternalBuffer)]
  670.      2        );
  671.      2        // init timeElapsed
  672.      2        timeElapsed = Date.now();
  673.      2        // await result from web-worker
  674.      2        result = await new Promise(function (resolve) {
  675.      2            sqlMessageDict[id] = resolve;
  676.      2        });
  677.      2        // cleanup sqlMessageDict
  678.      2        delete sqlMessageDict[id];
  679.      2        // debug slow postMessage
  680.      2        timeElapsed = Date.now() - timeElapsed;
  681.      2        if (timeElapsed > 500 || funcname === "testTimeElapsed") {
  682.      1            consoleError(
  683.      1                "sqlMessagePost - "
  684.      1                + JSON.stringify({funcname, timeElapsed})
  685.      1                + errStack
  686.      1            );
  687.      2        }
  688.      2        assertOrThrow(!result.errmsg, result.errmsg);
  689.      2        // prepend baton to argList
  690.      2        return [result.baton, ...result.argList];
  691.     55    } catch (err) {
  692.     55        // debug db.filename
  693.     55        if (db?.filename2 || db?.filename) {
  694.     55            err.message += ` (from ${db?.filename2 || db?.filename})`;
  695.     55        }
  696.     55        err.stack += errStack;
  697.     55        assertOrThrow(undefined, err);
  698.     55    }
  699.   3913}
  700.      1
  701.      3async function dbCloseAsync(db) {
  702.      3
  703.      3// This function will close sqlite-database-connection <db>.
  704.      3
  705.      3    // prevent segfault - do not close db if actions are pending
  706.      3    assertOrThrow(
  707.      3        db.busy === 0,
  708.      3        `dbCloseAsync - cannot close db with ${db.busy} actions pending`
  709.      3    );
  710.      3    // cleanup connPool
  711.      1    await Promise.all(db.connPool.map(async function (ptr) {
  712.      1        let val = ptr[0];
  713.      1        ptr[0] = 0n;
  714.      1        await dbCallAsync(
  715.      1            jsbatonCreate("_dbClose"),
  716.      1            [
  717.      1                val,
  718.      1                db.filename
  719.      1            ]
  720.      1        );
  721.      1    }));
  722.      1}
  723.      1
  724.     58function dbExecAndReturnLastBlob(option) {
  725.     58
  726.     58// This function will exec <sql> in <db>,
  727.     58// and return last-value retrieved from execution as raw blob/buffer.
  728.     58
  729.     58    return dbExecAsync(Object.assign({
  730.     58        responseType: "lastblob"
  731.     58    }, option));
  732.     58}
  733.      1
  734.    115async function dbExecAndReturnLastRow(option) {
  735.    115
  736.    115// This function will exec <sql> in <db>,
  737.    115// and return last-row or empty-object.
  738.    115
  739.    101    let result = await dbExecAsync(option);
  740.    101    result = result[result.length - 1] || [];
  741.      1    result = result[result.length - 1] || {};
  742.    115    return result;
  743.    115}
  744.      1
  745.     65async function dbExecAndReturnLastTable(option) {
  746.     65
  747.     65// This function will exec <sql> in <db>,
  748.     65// and return last-table or empty-list.
  749.     65
  750.     65    let result = await dbExecAsync(option);
  751.      1    result = result[result.length - 1] || [];
  752.     65    return result;
  753.     65}
  754.      1
  755.   1184function dbExecAndReturnLastValue(option) {
  756.   1184
  757.   1184// This function will exec <sql> in <db>,
  758.   1184// and return last-json-value.
  759.   1184
  760.   1184    return dbExecAsync(Object.assign({
  761.   1184        responseType: "lastvalue"
  762.   1184    }, option));
  763.   1184}
  764.      1
  765.   1900async function dbExecAsync({
  766.   1900    bindList = [],
  767.   1900    db,
  768.   1900    modeNoop,
  769.   1900    responseType,
  770.   1900    sql
  771.   1900}) {
  772.   1900
  773.   1900// This function will exec <sql> in <db> and return <result>.
  774.   1900
  775.   1900    let baton = jsbatonCreate("_dbExec");
  776.   1900    let bindByKey = !Array.isArray(bindList);
  777.   1900    let bufi = [0];
  778.   1900    let referenceList = [];
  779.   1900    let result;
  780.      1    if (modeNoop) {
  781.      1        return;
  782.   1899    }
  783.   1899    if (bindByKey) {
  784.   1347        Object.entries(bindList).forEach(function ([key, val]) {
  785.   1347            baton = jsbatonSetValue(baton, undefined, `:${key}\u0000`);
  786.   1347            baton = jsbatonSetValue(
  787.   1347                baton,
  788.   1347                undefined,
  789.   1347                val,
  790.   1347                bufi,
  791.   1347                referenceList
  792.   1347            );
  793.   1347        });
  794.   1235    } else {
  795.    664        bindList.forEach(function (val) {
  796.    664            baton = jsbatonSetValue(
  797.    664                baton,
  798.    664                undefined,
  799.    664                val,
  800.    664                bufi,
  801.    664                referenceList
  802.    664            );
  803.    664        });
  804.   1887    }
  805.   1887    [
  806.   1887        baton, ...result
  807.   1887    ] = await dbCallAsync(
  808.   1887        baton,
  809.   1887        [
  810.   1887            // 0. db
  811.   1887            db,
  812.   1887            // 1. sql
  813.   1887            String(sql) + "\n;\nPRAGMA noop",
  814.   1887            // 2. bindList.length
  815.   1887            (
  816.   1887                bindByKey
  817.   1887                ? Object.keys(bindList).length
  818.    652                : bindList.length
  819.   1900            ),
  820.   1900            // 3. bindByKey
  821.   1900            bindByKey,
  822.   1900            // 4. responseType
  823.   1900            (
  824.   1900                responseType === "lastblob"
  825.     56                ? SQLITE_RESPONSETYPE_LASTBLOB
  826.   1831                : responseType === "lastvalue"
  827.   1831                ? SQLITE_RESPONSETYPE_LASTVALUE
  828.   1831                : 0
  829.   1900            )
  830.   1900        ],
  831.   1900        "modeDbExec"
  832.   1832    );
  833.   1832    result = result[0];
  834.   1832    if (!IS_BROWSER) {
  835.   1832        result = cModule._jsbatonStealCbuffer(
  836.   1832            baton.buffer,
  837.   1832            0,
  838.   1832            Number(
  839.   1832                responseType !== "arraybuffer" && responseType !== "lastblob"
  840.   1832            )
  841.   1832        );
  842.   1832    }
  843.   1832    switch (responseType) {
  844.   1832    case "arraybuffer":
  845.    110    case "lastblob":
  846.    110        break;
  847.   1236    case "lastvalue":
  848.   1403    case "list":
  849.   1403        result = jsonParseArraybuffer(result);
  850.   1403        break;
  851.    319    default:
  852.    345        result = jsonParseArraybuffer(result).map(function (table) {
  853.    345            let colList = table.shift();
  854.  13913            return table.map(function (row) {
  855.  13913                let dict = {};
  856.  43338                colList.forEach(function (key, ii) {
  857.  43338                    dict[key] = row[ii];
  858.  43338                });
  859.  13913                return dict;
  860.  13913            });
  861.    345        });
  862.   1832    }
  863.   1832    return result;
  864.   1832}
  865.      1
  866.      2function dbExecProfile({
  867.      2    limit = 20,
  868.      2    lineLength = 80,
  869.      2    modeInit,
  870.      2    sqlLength = 256
  871.      2}) {
  872.      2
  873.      2// This function will profile dbExecAsync.
  874.      2
  875.      2    let result;
  876.      1    if (modeInit && !DB_EXEC_PROFILE_MODE) {
  877.      1        DB_EXEC_PROFILE_MODE = Date.now();
  878.      1        DB_EXEC_PROFILE_SQL_LENGTH = sqlLength;
  879.      1        process.on("exit", function () {
  880.      1            console.error(dbExecProfile({
  881.      1                limit,
  882.      1                lineLength
  883.      1            }));
  884.      1        });
  885.      1        return;
  886.      1    }
  887.      1    result = Object.values(DB_EXEC_PROFILE_DICT);
  888.   1481    result.sort(function (aa, bb) {
  889.    475        return ((bb.timeElapsed - aa.timeElapsed) || (bb.count - aa.count));
  890.   1481    });
  891.     20    result = result.slice(0, limit).map(function ({
  892.     20        count,
  893.     20        sql,
  894.     20        timeElapsed
  895.     20    }, ii) {
  896.     20        return String(
  897.     20            `${Number(ii + 1).toFixed(0).padStart(2, " ")}.`
  898.     20            + ` ${timeElapsed.toFixed(0).padStart(4)}`
  899.     20            + ` ${count.toFixed(0).padStart(3)}`
  900.     20            + " " + JSON.stringify(sql)
  901.     20        ).slice(0, lineLength);
  902.     20    }).join("\n");
  903.      1    result = (
  904.      1        `\ndbExecProfile:\n`
  905.      1        + ` #  time cnt sql\n`
  906.      1        + `${result}\n`
  907.      1    );
  908.      1    return result;
  909.      1}
  910.      1
  911.     17async function dbFileLoadAsync({
  912.     17    db,
  913.     17    dbData,
  914.     17    filename,
  915.     17    modeNoop,
  916.     17    modeSave = 0
  917.     17}) {
  918.     17
  919.     17// This function will load <filename> to <db>.
  920.     17
  921.     17    let filename2;
  922.     15    async function _dbFileLoad() {
  923.     15        dbData = await dbCallAsync(
  924.     15            jsbatonCreate("_dbFileLoad"),
  925.     15            [
  926.     15                // 0. sqlite3 * pInMemory
  927.     15                db,
  928.     15                // 1. char *zFilename
  929.     15                filename,
  930.     15                // 2. const int isSave
  931.     15                modeSave,
  932.     15                // 3. undefined
  933.     15                undefined,
  934.     15                // 4. dbData - same position as dbOpenAsync
  935.     15                dbData
  936.     15            ],
  937.     15            "modeDbFile"
  938.     15        );
  939.     15    }
  940.      1    if (modeNoop) {
  941.      1        return;
  942.     16    }
  943.     16    if (IS_BROWSER) {
  944.      1        filename = FILENAME_DBTMP;
  945.     16    }
  946.     16    assertOrThrow(
  947.     16        typeof filename === "string" && filename,
  948.     17        `invalid filename ${filename}`
  949.     17    );
  950.     17    db.filename2 = filename;
  951.     17    // Save to tmpfile and then atomically-rename to actual-filename.
  952.     15    if (moduleFs && modeSave) {
  953.     13        filename2 = filename;
  954.     13        filename = modulePath.join(
  955.     13            modulePath.dirname(filename),
  956.     13            `.dbFileSaveAsync.${moduleCrypto.randomUUID()}`
  957.     13        );
  958.     13        try {
  959.     13            await _dbFileLoad();
  960.     13            await moduleFs.promises.rename(filename, filename2);
  961.     13        } finally {
  962.     13            await moduleFs.promises.unlink(filename).catch(noop);
  963.     13        }
  964.     13    } else {
  965.      2        await _dbFileLoad();
  966.     15    }
  967.     15    return dbData[1 + 0];
  968.     15}
  969.      1
  970.     14async function dbFileSaveAsync({
  971.     14    db,
  972.     14    dbData,
  973.     14    filename,
  974.     14    modeNoop
  975.     14}) {
  976.     14
  977.     14// This function will save <db> to <filename>.
  978.     14
  979.     14    return await dbFileLoadAsync({
  980.     14        db,
  981.     14        dbData,
  982.     14        filename,
  983.     14        modeNoop,
  984.     14        modeSave: 1
  985.     14    });
  986.     14}
  987.      1
  988.     56async function dbNoopAsync(...argList) {
  989.     56
  990.     56// This function will do nothing except return <argList>.
  991.     56
  992.     56    return await dbCallAsync(
  993.     56        jsbatonCreate("_dbNoop"),
  994.     56        argList
  995.     56    );
  996.     56}
  997.      1
  998.     32async function dbOpenAsync({
  999.     32    afterFinalization,
 1000.     32    dbData,
 1001.     32    filename = ":memory:",
 1002.     32    flags,
 1003.     32    threadCount = 1,
 1004.     32    timeoutBusy = 5000
 1005.     32}) {
 1006.     32
 1007.     32// This function will open and return sqlite-database-connection <db>.
 1008.     32
 1009.     32// int sqlite3_open_v2(
 1010.     32//   const char *filename,   /* Database filename (UTF-8) */
 1011.     32//   sqlite3 **ppDb,         /* OUT: SQLite db handle */
 1012.     32//   int flags,              /* Flags */
 1013.     32//   const char *zVfs        /* Name of VFS module to use */
 1014.     32// );
 1015.     32    let connPool;
 1016.     32    let db = {busy: 0, filename, ii: 0};
 1017.     32    assertOrThrow(typeof filename === "string", `invalid filename ${filename}`);
 1018.     32    assertOrThrow(
 1019.      1        !dbData || isExternalBuffer(dbData),
 1020.     32        "dbData must be ArrayBuffer"
 1021.     32    );
 1022.     32    connPool = await Promise.all(Array.from(new Array(
 1023.     32        threadCount
 1024.     32    ), async function () {
 1025.     32        let [ptr] = await dbCallAsync(
 1026.     32            jsbatonCreate("_dbOpen"),
 1027.     32            [
 1028.     32                // 0. const char *filename,   Database filename (UTF-8)
 1029.     32                filename,
 1030.     32                // 1. sqlite3 **ppDb,         OUT: SQLite db handle
 1031.     32                undefined,
 1032.     32                // 2. int flags,              Flags
 1033.     32                flags ?? (
 1034.     32                    SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE | SQLITE_OPEN_URI
 1035.     32                ),
 1036.     32                // 3. const char *zVfs        Name of VFS module to use
 1037.     32                undefined,
 1038.     32                // 4. wasm-only - arraybuffer of raw sqlite-database
 1039.     32                dbData
 1040.     32            ]
 1041.     32        );
 1042.     32        ptr = [ptr.getBigInt64(JSBATON_OFFSET_ARGV + 0, true)];
 1043.     32        dbFinalizationRegistry.register(db, {afterFinalization, ptr});
 1044.     32        return ptr;
 1045.     32    }));
 1046.     32    db.connPool = connPool;
 1047.      1    if (!IS_BROWSER && !DB_STATE.init) {
 1048.      1        DB_STATE.init = true;
 1049.      1        await Promise.all([
 1050.      1            // PRAGMA busy_timeout
 1051.      1            dbExecAsync({
 1052.      1                db,
 1053.      1                sql: (`
 1054.      1PRAGMA busy_timeout = ${timeoutBusy};
 1055.      1                `)
 1056.      1            }),
 1057.      1            // LGBM_DLOPEN
 1058.      1            (async function () {
 1059.      1                let libLgbm = `lib_lightgbm_${libPlatformArchExt()}`;
 1060.      1                libLgbm = `${import.meta.dirname}/sqlmath/${libLgbm}`;
 1061.      1                await moduleFs.promises.access(
 1062.      1                    libLgbm
 1063.      1                ).then(async function () {
 1064.      1                    await dbExecAsync({
 1065.      1                        db,
 1066.      1                        sql: (`
 1067.      1SELECT LGBM_DLOPEN('${libLgbm}');
 1068.      1                        `)
 1069.      1                    });
 1070.      1                    DB_STATE.lgbm = true;
 1071.      1                }).catch(noop);
 1072.      1            }())
 1073.      1        ]);
 1074.      1    }
 1075.     32    return db;
 1076.     32}
 1077.      1
 1078.     47async function dbTableImportAsync({
 1079.     47    db,
 1080.     47    filename,
 1081.     47    headerMissing,
 1082.     47    mode,
 1083.     47    tableName,
 1084.     47    textData
 1085.     47}) {
 1086.     47// This function will create table from imported csv/json <textData>.
 1087.     47    let colList;
 1088.     47    let rowList;
 1089.     47    let rowidList;
 1090.     47    let tmp;
 1091.     42    if (filename) {
 1092.     42        textData = await moduleFs.promises.readFile(filename, "utf8");
 1093.     42    }
 1094.     47    switch (mode) {
 1095.      2    case "csv":
 1096.      2        rowList = jsonRowListFromCsv({
 1097.      2            csv: textData
 1098.      2        });
 1099.      2        break;
 1100.     43    case "tsv":
 1101.     43        rowList = [];
 1102.  99001        textData.trimEnd().replace((/.+/g), function (line) {
 1103.  99001            rowList.push(line.split("\t"));
 1104.  99001        });
 1105.     43        break;
 1106.     47    // case "json":
 1107.      2    default:
 1108.      2        rowList = JSON.parse(textData);
 1109.     47    }
 1110.      1    if (!(typeof rowList === "object" && rowList)) {
 1111.      1        rowList = [];
 1112.      1    }
 1113.     47    // normalize rowList to list
 1114.      1    if (!Array.isArray(rowList)) {
 1115.      1        rowidList = [];
 1116.      2        rowList = Object.entries(rowList).map(function ([
 1117.      2            key, val
 1118.      2        ]) {
 1119.      2            rowidList.push(key);
 1120.      2            return val;
 1121.      2        });
 1122.      1    }
 1123.     47    // headerMissing
 1124.     42    if (headerMissing && (rowList.length > 0 && Array.isArray(rowList[0]))) {
 1125.    714        rowList.unshift(Array.from(rowList[0]).map(function (ignore, ii) {
 1126.    714            return String(ii + 1);
 1127.    714        }));
 1128.     42    }
 1129.     47    // normalize rowList[ii] to list
 1130.      1    if (rowList.length === 0) {
 1131.      1        rowList.push([
 1132.      1            "undefined"
 1133.      1        ]);
 1134.      1    }
 1135.      1    if (!Array.isArray(rowList[0])) {
 1136.      1        colList = Array.from(
 1137.      1            new Set(
 1138.      2                rowList.map(function (obj) {
 1139.      2                    return Object.keys(obj);
 1140.      2                }).flat()
 1141.      1            )
 1142.      1        );
 1143.      2        rowList = rowList.map(function (obj) {
 1144.      4            return colList.map(function (key) {
 1145.      4                return obj[key];
 1146.      4            });
 1147.      2        });
 1148.      1        rowList.unshift(colList);
 1149.      1    }
 1150.     47    // init colList
 1151.     47    colList = rowList.shift();
 1152.     47    // preserve rowid
 1153.      1    if (rowidList) {
 1154.      1        colList.unshift("rowid");
 1155.      2        rowList.forEach(function (row, ii) {
 1156.      2            row.unshift(rowidList[ii]);
 1157.      2        });
 1158.      1    }
 1159.     47    // normalize colList
 1160.     47    tmp = new Set();
 1161.    723    colList = colList.map(function (colName) {
 1162.    723        let colName2;
 1163.    723        let duplicate = 0;
 1164.    723        colName = colName.trim();
 1165.    723        colName = colName.replace((/\W/g), "_");
 1166.    723        colName = colName.replace((/^[^A-Z_a-z]|^$/gm), "_$&");
 1167.    724        while (true) {
 1168.    724            duplicate += 1;
 1169.    724            colName2 = (
 1170.    724                duplicate === 1
 1171.    724                ? colName
 1172.    724                : colName + "_" + duplicate
 1173.    724            );
 1174.    724            if (!tmp.has(colName2)) {
 1175.    724                tmp.add(colName2);
 1176.    724                return colName2;
 1177.    724            }
 1178.    724        }
 1179.    723    });
 1180.     47    // create dbtable from rowList
 1181.     47    await dbExecAsync({
 1182.     47        bindList: {
 1183.     47            rowList: JSON.stringify(rowList)
 1184.     47        },
 1185.     47        db,
 1186.     47        sql: (
 1187.     47            rowList.length === 0
 1188.      3            ? `CREATE TABLE ${tableName} (${colList.join(",")});`
 1189.     44            : (
 1190.     44                `CREATE TABLE ${tableName} AS SELECT `
 1191.    719                + colList.map(function (colName, ii) {
 1192.    719                    return "value->>" + ii + " AS " + colName;
 1193.    719                }).join(",")
 1194.     44                + " FROM JSON_EACH($rowList);"
 1195.     44            )
 1196.     47        )
 1197.     47    });
 1198.     47}
 1199.      1
 1200.      2async function fsCopyFileUnlessTest(file1, file2, mode) {
 1201.      2
 1202.      2// This function will copy <file1> to <file2> unless <npm_config_mode_test> = 1.
 1203.      2
 1204.      1    if (npm_config_mode_test && mode !== "force") {
 1205.      1        return;
 1206.      1    }
 1207.      1    await moduleFs.promises.copyFile(file1, file2, mode | 0);
 1208.      1}
 1209.      1
 1210.     10async function fsExistsUnlessTest(file, mode) {
 1211.     10
 1212.     10// This function will test if <file> exists unless <npm_config_mode_test> = 1.
 1213.     10
 1214.      8    if (npm_config_mode_test && mode !== "force") {
 1215.      8        return false;
 1216.      8    }
 1217.      2    try {
 1218.      2        await moduleFs.promises.access(file);
 1219.      1        return true;
 1220.      1    } catch (ignore) {
 1221.      1        return false;
 1222.      1    }
 1223.     10}
 1224.      1
 1225.     22async function fsReadFileUnlessTest(file, mode, defaultData) {
 1226.     22
 1227.     22// This function will read <data> from <file> unless <npm_config_mode_test> = 1.
 1228.     22
 1229.      8    if (npm_config_mode_test && mode !== "force") {
 1230.      8        return defaultData;
 1231.     14    }
 1232.     14    return await moduleFs.promises.readFile(
 1233.     14        file,
 1234.     14        mode && mode.replace("force", "utf8")
 1235.     22    );
 1236.     22}
 1237.      1
 1238.     10async function fsWriteFileUnlessTest(file, data, mode) {
 1239.     10
 1240.     10// This function will write <data> to <file> unless <npm_config_mode_test> = 1.
 1241.     10
 1242.      9    if (npm_config_mode_test && mode !== "force") {
 1243.      9        return;
 1244.      9    }
 1245.      1    await moduleFs.promises.writeFile(file, data);
 1246.      1}
 1247.      1
 1248.     31function isExternalBuffer(buf) {
 1249.     31
 1250.     31// This function will check if <buf> is ArrayBuffer.
 1251.     31
 1252.     17    return buf && buf.constructor === ArrayBuffer;
 1253.     31}
 1254.      1
 1255.   2024function jsbatonCreate(funcname) {
 1256.   2024
 1257.   2024// This function will create buffer <baton>.
 1258.   2024
 1259.   2024    let baton = new DataView(new ArrayBuffer(JSBATON_OFFSET_ALL));
 1260.   2024    // init nallc, nused
 1261.   2024    baton.setInt32(4, JSBATON_OFFSET_ALL, true);
 1262.   2024    // copy funcname into baton
 1263.   2024    new Uint8Array(
 1264.   2024        baton.buffer,
 1265.   2024        baton.byteOffset + JSBATON_OFFSET_FUNCNAME,
 1266.   2024        SIZEOF_FUNCNAME - 1
 1267.   2024    ).set(new TextEncoder().encode(funcname));
 1268.   2024    return baton;
 1269.   2024}
 1270.      1
 1271.     24function jsbatonGetInt64(baton, argi) {
 1272.     24
 1273.     24// This function will return int64-value from <baton> at <argi>.
 1274.     24
 1275.     24    return baton.getBigInt64(JSBATON_OFFSET_ARGV + argi * 8, true);
 1276.     24}
 1277.      1
 1278.      9function jsbatonGetString(baton, argi) {
 1279.      9
 1280.      9// This function will return string-value from <baton> at <argi>.
 1281.      9
 1282.      9    let offset = baton.getInt32(JSBATON_OFFSET_ARGV + argi * 8, true);
 1283.      9    return new TextDecoder().decode(new Uint8Array(
 1284.      9        baton.buffer,
 1285.      9        baton.byteOffset + offset + 1 + 4,
 1286.      9        // remove null-terminator from string
 1287.      9        baton.getInt32(offset + 1, true) - 1
 1288.      9    ));
 1289.      9}
 1290.      1
 1291.   5154function jsbatonSetValue(baton, argi, val, bufi, referenceList) {
 1292.   5154
 1293.   5154// This function will set <val> to buffer <baton>.
 1294.   5154
 1295.   5154    let nn;
 1296.   5154    let nused;
 1297.   5154    let tmp;
 1298.   5154    let vsize;
 1299.   5154    let vtype;
 1300.   5154/*
 1301.   5154#define SQLITE_DATATYPE_BLOB            0x04
 1302.   5154#define SQLITE_DATATYPE_EXTERNALBUFFER          0x71
 1303.   5154#define SQLITE_DATATYPE_FLOAT           0x02
 1304.   5154#define SQLITE_DATATYPE_INTEGER         0x01
 1305.   5154#define SQLITE_DATATYPE_INTEGER_0       0x00
 1306.   5154#define SQLITE_DATATYPE_INTEGER_1       0x21
 1307.   5154#define SQLITE_DATATYPE_NULL            0x05
 1308.   5154#define SQLITE_DATATYPE_TEXT            0x03
 1309.   5154#define SQLITE_DATATYPE_TEXT_0          0x13
 1310.   5154    //  1. 0.bigint
 1311.   5154    //  2. 0.boolean
 1312.   5154    //  3. 0.function
 1313.   5154    //  4. 0.number
 1314.   5154    //  5. 0.object
 1315.   5154    //  6. 0.string
 1316.   5154    //  7. 0.symbol
 1317.   5154    //  8. 0.undefined
 1318.   5154    //  9. 1.bigint
 1319.   5154    // 10. 1.boolean
 1320.   5154    // 11. 1.function
 1321.   5154    // 12. 1.number
 1322.   5154    // 13. 1.object
 1323.   5154    // 14. 1.string
 1324.   5154    // 15. 1.symbol
 1325.   5154    // 16. 1.undefined
 1326.   5154    // 17. 1.buffer
 1327.   5154    // 18. 1.externalbuffer
 1328.   5154*/
 1329.   5154    // 10. 1.boolean
 1330.   5130    if (val === 1 || val === 1n) {
 1331.     30        val = true;
 1332.     30    }
 1333.   5154    switch (
 1334.   5154        val
 1335.   4773        ? "1." + typeof(val)
 1336.    381        : "0." + typeof(val)
 1337.   5154    ) {
 1338.   5154    //  1. 0.bigint
 1339.     24    case "0.bigint":
 1340.   5154    //  2. 0.boolean
 1341.     30    case "0.boolean":
 1342.   5154    //  4. 0.number
 1343.    250    case "0.number":
 1344.    250        if (Number.isNaN(val)) {
 1345.    250            vtype = SQLITE_DATATYPE_NULL;
 1346.    250            vsize = 0;
 1347.    250            break;
 1348.    250        }
 1349.    250        vtype = SQLITE_DATATYPE_INTEGER_0;
 1350.    250        vsize = 0;
 1351.    250        break;
 1352.   5154    //  3. 0.function
 1353.   5154    // case "0.function":
 1354.   5154    //  5. 0.object
 1355.     98    case "0.object":
 1356.   5154    //  7. 0.symbol
 1357.     98    case "0.symbol":
 1358.   5154    //  8. 0.undefined
 1359.    105    case "0.undefined":
 1360.   5154    // 11. 1.function
 1361.    119    case "1.function":
 1362.   5154    // 15. 1.symbol
 1363.    125    case "1.symbol":
 1364.    125    // 16. 1.undefined
 1365.    125    // case "1.undefined":
 1366.    125        vtype = SQLITE_DATATYPE_NULL;
 1367.    125        vsize = 0;
 1368.    125        break;
 1369.   5154    //  6. 0.string
 1370.     26    case "0.string":
 1371.     26        vtype = SQLITE_DATATYPE_TEXT_0;
 1372.     26        vsize = 0;
 1373.     26        break;
 1374.   5154    //  9. 1.bigint
 1375.     42    case "1.bigint":
 1376.     42        vtype = SQLITE_DATATYPE_INTEGER;
 1377.     42        vsize = 8;
 1378.     42        break;
 1379.   5154    // 10. 1.boolean
 1380.     36    case "1.boolean":
 1381.     36        vtype = SQLITE_DATATYPE_INTEGER_1;
 1382.     36        vsize = 0;
 1383.     36        break;
 1384.   5154    // 12. 1.number
 1385.    561    case "1.number":
 1386.    561        vtype = SQLITE_DATATYPE_FLOAT;
 1387.    561        vsize = 8;
 1388.    561        break;
 1389.   5154    // 14. 1.string
 1390.   4032    case "1.string":
 1391.   4032        val = new TextEncoder().encode(val);
 1392.   4032        vtype = SQLITE_DATATYPE_TEXT;
 1393.   4032        vsize = 4 + val.byteLength;
 1394.   4032        break;
 1395.   5154    // 13. 1.object
 1396.     82    default:
 1397.     82        // 18. 1.externalbuffer
 1398.     82        if (val.constructor === ArrayBuffer) {
 1399.     82            assertOrThrow(
 1400.     82                !IS_BROWSER,
 1401.     82                "external ArrayBuffer cannot be passed directly to wasm"
 1402.     82            );
 1403.     82            vtype = SQLITE_DATATYPE_EXTERNALBUFFER;
 1404.     82            vsize = 4;
 1405.     82            break;
 1406.     82        }
 1407.     82        // 17. 1.buffer
 1408.     82        if (ArrayBuffer.isView(val)) {
 1409.     82            if (val.byteLength === 0) {
 1410.     82                vtype = SQLITE_DATATYPE_NULL;
 1411.     82                vsize = 0;
 1412.     82                break;
 1413.     82            }
 1414.     82            vtype = SQLITE_DATATYPE_BLOB;
 1415.     82            vsize = 4 + val.byteLength;
 1416.     82            break;
 1417.     82        }
 1418.     82        // 13. 1.object
 1419.     82        val = new TextEncoder().encode(
 1420.     82            typeof val.toJSON === "function"
 1421.     82            ? val.toJSON()
 1422.     82            : JSON.stringify(val)
 1423.     82        );
 1424.     82        vtype = SQLITE_DATATYPE_TEXT;
 1425.     82        vsize = 4 + val.byteLength;
 1426.   5154    }
 1427.   5154    nused = baton.getInt32(4, true);
 1428.   5154    nn = nused + 1 + vsize;
 1429.   5154    assertOrThrow(
 1430.   5154        nn <= 0xffff_ffff,
 1431.   5154        "jsbaton cannot exceed 0x7fff_ffff / 2,147,483,647 bytes"
 1432.   5154    );
 1433.   5154    // exponentially grow baton as needed
 1434.   2136    if (baton.byteLength < nn) {
 1435.   2136        tmp = baton;
 1436.   2136        baton = new DataView(new ArrayBuffer(
 1437.   2136            Math.min(2 ** Math.ceil(Math.log2(nn)), 0x7fff_ffff)
 1438.   2136        ));
 1439.   2136        // update nallc
 1440.   2136        baton.setInt32(0, baton.byteLength, true);
 1441.   2136        // copy old-baton into new-baton
 1442.   2136        new Uint8Array(baton.buffer, baton.byteOffset, nused).set(
 1443.   2136            new Uint8Array(tmp.buffer, tmp.byteOffset, nused)
 1444.   2136        );
 1445.   2136    }
 1446.   5154    // push vtype - 1-byte
 1447.   5154    baton.setUint8(nused, vtype);
 1448.   5154    // update nused
 1449.   5154    baton.setInt32(4, nused + 1 + vsize, true);
 1450.   5154    // handle blob-value
 1451.   5154    switch (vtype) {
 1452.     30    case SQLITE_DATATYPE_BLOB:
 1453.   4090    case SQLITE_DATATYPE_TEXT:
 1454.   4090        // set argv[ii] to blob/text location
 1455.   4090        if (argi !== undefined) {
 1456.   4090            baton.setInt32(JSBATON_OFFSET_ARGV + argi * 8, nused, true);
 1457.   4090        }
 1458.   4090        vsize -= 4;
 1459.   4090        assertOrThrow(
 1460.   4090            0 <= vsize && vsize <= SIZEOF_BLOB_MAX,
 1461.   4090            (
 1462.   4090                "sqlite-blob byte-length must be within inclusive-range"
 1463.   4090                + ` 0 to ${SIZEOF_BLOB_MAX}`
 1464.   4090            )
 1465.   4090        );
 1466.   4090        // push vsize - 4-byte
 1467.   4090        baton.setInt32(nused + 1, vsize, true);
 1468.   4090        // push SQLITE-BLOB/TEXT - vsize-byte
 1469.   4090        new Uint8Array(
 1470.   4090            baton.buffer,
 1471.   4090            baton.byteOffset + nused + 1 + 4,
 1472.   4090            vsize
 1473.   4090        ).set(new Uint8Array(val.buffer, val.byteOffset, vsize));
 1474.   4090        break;
 1475.     12    case SQLITE_DATATYPE_EXTERNALBUFFER:
 1476.     12        vsize = val.byteLength;
 1477.     12        assertOrThrow(
 1478.     12            0 <= vsize && vsize <= SIZEOF_BLOB_MAX,
 1479.     12            (
 1480.     12                "sqlite-blob byte-length must be within inclusive-range"
 1481.     12                + ` 0 to ${SIZEOF_BLOB_MAX}`
 1482.     12            )
 1483.     12        );
 1484.     12        assertOrThrow(
 1485.     12            bufi[0] < JSBATON_ARGC,
 1486.     12            `cannot pass more than ${JSBATON_ARGC} arraybuffers`
 1487.     12        );
 1488.     12        // push externalbuffer - 4-byte
 1489.     12        baton.setInt32(nused + 1, bufi[0], true);
 1490.     12        // set buffer
 1491.     12        cModule._jsbatonSetArraybuffer(baton.buffer, bufi[0], val);
 1492.     12        // increment bufi
 1493.     12        bufi[0] += 1;
 1494.     12        // add buffer to reference_list to prevent gc during db_call.
 1495.     12        referenceList.push(val);
 1496.     12        break;
 1497.    561    case SQLITE_DATATYPE_FLOAT:
 1498.    561        // push SQLITE-REAL - 8-byte
 1499.    561        baton.setFloat64(nused + 1, val, true);
 1500.    561        break;
 1501.     42    case SQLITE_DATATYPE_INTEGER:
 1502.     42        assertInt64(val);
 1503.     42        // push SQLITE-INTEGER - 8-byte
 1504.     42        baton.setBigInt64(nused + 1, val, true);
 1505.     42        break;
 1506.   5142    }
 1507.   5142    return baton;
 1508.   5142}
 1509.      1
 1510.   1723function jsonParseArraybuffer(buf) {
 1511.   1723
 1512.   1723// This function will JSON.parse arraybuffer <buf>.
 1513.   1723
 1514.   1723    return JSON.parse(
 1515.   1723        (
 1516.   1723            IS_BROWSER
 1517.      1            ? new TextDecoder().decode(buf)
 1518.   1722            : buf
 1519.   1723        )
 1520.      1        || "null"
 1521.   1723    );
 1522.   1723}
 1523.      1
 1524.      2function jsonRowListFromCsv({
 1525.      2    csv
 1526.      2}) {
 1527.      2// This function will convert <csv>-text to json list-of-list.
 1528.      2//
 1529.      2// https://tools.ietf.org/html/rfc4180#section-2
 1530.      2// Definition of the CSV Format
 1531.      2// While there are various specifications and implementations for the
 1532.      2// CSV format (for ex. [4], [5], [6] and [7]), there is no formal
 1533.      2// specification in existence, which allows for a wide variety of
 1534.      2// interpretations of CSV files.  This section documents the format that
 1535.      2// seems to be followed by most implementations:
 1536.      2//
 1537.      2// 1.  Each record is located on a separate line, delimited by a line
 1538.      2//     break (CRLF).  For example:
 1539.      2//     aaa,bbb,ccc CRLF
 1540.      2//     zzz,yyy,xxx CRLF
 1541.      2//
 1542.      2// 2.  The last record in the file may or may not have an ending line
 1543.      2//     break.  For example:
 1544.      2//     aaa,bbb,ccc CRLF
 1545.      2//     zzz,yyy,xxx
 1546.      2//
 1547.      2// 3.  There maybe an optional header line appearing as the first line
 1548.      2//     of the file with the same format as normal record lines.  This
 1549.      2//     header will contain names corresponding to the fields in the file
 1550.      2//     and should contain the same number of fields as the records in
 1551.      2//     the rest of the file (the presence or absence of the header line
 1552.      2//     should be indicated via the optional "header" parameter of this
 1553.      2//     MIME type).  For example:
 1554.      2//     field_name,field_name,field_name CRLF
 1555.      2//     aaa,bbb,ccc CRLF
 1556.      2//     zzz,yyy,xxx CRLF
 1557.      2//
 1558.      2// 4.  Within the header and each record, there may be one or more
 1559.      2//     fields, separated by commas.  Each line should contain the same
 1560.      2//     number of fields throughout the file.  Spaces are considered part
 1561.      2//     of a field and should not be ignored.  The last field in the
 1562.      2//     record must not be followed by a comma.  For example:
 1563.      2//     aaa,bbb,ccc
 1564.      2//
 1565.      2// 5.  Each field may or may not be enclosed in double quotes (however
 1566.      2//     some programs, such as Microsoft Excel, do not use double quotes
 1567.      2//     at all).  If fields are not enclosed with double quotes, then
 1568.      2//     double quotes may not appear inside the fields.  For example:
 1569.      2//     "aaa","bbb","ccc" CRLF
 1570.      2//     zzz,yyy,xxx
 1571.      2//
 1572.      2// 6.  Fields containing line breaks (CRLF), double quotes, and commas
 1573.      2//     should be enclosed in double-quotes.  For example:
 1574.      2//     "aaa","b CRLF
 1575.      2//     bb","ccc" CRLF
 1576.      2//     zzz,yyy,xxx
 1577.      2//
 1578.      2// 7.  If double-quotes are used to enclose fields, then a double-quote
 1579.      2//     appearing inside a field must be escaped by preceding it with
 1580.      2//     another double quote.  For example:
 1581.      2//     "aaa","b""bb","ccc"
 1582.      2    let match;
 1583.      2    let quote;
 1584.      2    let rgx;
 1585.      2    let row;
 1586.      2    let rowList;
 1587.      2    let val;
 1588.      2    // normalize "\r\n" to "\n"
 1589.      2    csv = csv.trimEnd().replace((
 1590.      2        /\r\n?/gu
 1591.      2    ), "\n") + "\n";
 1592.      2    rgx = (
 1593.      2        /(.*?)(""|"|,|\n)/gu
 1594.      2    );
 1595.      2    rowList = [];
 1596.      2    // reset row
 1597.      2    row = [];
 1598.      2    val = "";
 1599.     28    while (true) {
 1600.     28        match = rgx.exec(csv);
 1601.     28        if (!match) {
 1602.     28// 2.  The last record in the file may or may not have an ending line
 1603.     28//     break.  For example:
 1604.     28//     aaa,bbb,ccc CRLF
 1605.     28//     zzz,yyy,xxx
 1606.     28            if (!row.length) {
 1607.     28                break;
 1608.     28            }
 1609.     28            // // if eof missing crlf, then mock it
 1610.     28            // rgx.lastIndex = csv.length;
 1611.     28            // match = [
 1612.     28            //     "\n", "", "\n"
 1613.     28            // ];
 1614.     28        }
 1615.     28        // build val
 1616.     28        val += match[1];
 1617.     28        if (match[2] === "\"") {
 1618.     28// 5.  Each field may or may not be enclosed in double quotes (however
 1619.     28//     some programs, such as Microsoft Excel, do not use double quotes
 1620.     28//     at all).  If fields are not enclosed with double quotes, then
 1621.     28//     double quotes may not appear inside the fields.  For example:
 1622.     28//     "aaa","bbb","ccc" CRLF
 1623.     28//     zzz,yyy,xxx
 1624.     28            quote = !quote;
 1625.     28        } else if (quote) {
 1626.     28// 7.  If double-quotes are used to enclose fields, then a double-quote
 1627.     28//     appearing inside a field must be escaped by preceding it with
 1628.     28//     another double quote.  For example:
 1629.     28//     "aaa","b""bb","ccc"
 1630.     28            if (match[2] === "\"\"") {
 1631.     28                val += "\"";
 1632.     28// 6.  Fields containing line breaks (CRLF), double quotes, and commas
 1633.     28//     should be enclosed in double-quotes.  For example:
 1634.     28//     "aaa","b CRLF
 1635.     28//     bb","ccc" CRLF
 1636.     28//     zzz,yyy,xxx
 1637.     28            } else {
 1638.     28                val += match[2];
 1639.     28            }
 1640.     28        } else if (match[2] === ",") {
 1641.     28// 4.  Within the header and each record, there may be one or more
 1642.     28//     fields, separated by commas.  Each line should contain the same
 1643.     28//     number of fields throughout the file.  Spaces are considered part
 1644.     28//     of a field and should not be ignored.  The last field in the
 1645.     28//     record must not be followed by a comma.  For example:
 1646.     28//     aaa,bbb,ccc
 1647.     28            // delimit val
 1648.     28            row.push(val);
 1649.     28            val = "";
 1650.     28        } else if (match[2] === "\n") {
 1651.     28// 1.  Each record is located on a separate line, delimited by a line
 1652.     28//     break (CRLF).  For example:
 1653.     28//     aaa,bbb,ccc CRLF
 1654.     28//     zzz,yyy,xxx CRLF
 1655.     28            // delimit val
 1656.     28            row.push(val);
 1657.     28            val = "";
 1658.     28            // append row
 1659.     28            rowList.push(row);
 1660.     28            // reset row
 1661.     28            row = [];
 1662.     28        }
 1663.     28    }
 1664.      2    // // append val
 1665.      2    // if (val) {
 1666.      2    //     row.push(val);
 1667.      2    // }
 1668.      2    // // append row
 1669.      2    // if (row.length) {
 1670.      2    //     rowList.push(row);
 1671.      2    // }
 1672.      2    return rowList;
 1673.      2}
 1674.      1
 1675.      1function libPlatformArchExt() {
 1676.      1    let libArch = process.arch;
 1677.      1    let libExt = process.platform;
 1678.      1    let libPlatform = process.platform;
 1679.      1    libExt = libExt.replace("darwin", "dylib");
 1680.      1    libExt = libExt.replace("win32", "dll");
 1681.      1    libExt = libExt.replace(libPlatform, "so");
 1682.      1    return `${libPlatform}_${libArch}.${libExt}`;
 1683.      1}
 1684.      1
 1685.      1function listOrEmptyList(list) {
 1686.      1
 1687.      1// This function will return <list> or empty-list if falsy.
 1688.      1
 1689.      1    return list || [];
 1690.      1}
 1691.      1
 1692.      8async function moduleFsInit() {
 1693.      8
 1694.      8// This function will import nodejs builtin-modules if they have not yet been
 1695.      8// imported.
 1696.      8
 1697.      8// State 3 - Modules already imported.
 1698.      8
 1699.      6    if (moduleFs !== undefined) {
 1700.      6        return;
 1701.      6    }
 1702.      2
 1703.      2// State 2 - Wait while modules are importing.
 1704.      2
 1705.      2    if (moduleFsInitResolveList !== undefined) {
 1706.      1        return new Promise(function (resolve) {
 1707.      1            moduleFsInitResolveList.push(resolve);
 1708.      1        });
 1709.      1    }
 1710.      1
 1711.      1// State 1 - Start importing modules.
 1712.      1
 1713.      1    moduleFsInitResolveList = [];
 1714.      1    [
 1715.      1        moduleChildProcess,
 1716.      1        moduleCrypto,
 1717.      1        moduleFs,
 1718.      1        modulePath,
 1719.      1        moduleUrl
 1720.      1    ] = await Promise.all([
 1721.      1        import("child_process"),
 1722.      1        import("crypto"),
 1723.      1        import("fs"),
 1724.      1        import("path"),
 1725.      1        import("url")
 1726.      1    ]);
 1727.      1    while (moduleFsInitResolveList.length > 0) {
 1728.      1        moduleFsInitResolveList.shift()();
 1729.      1    }
 1730.      1    SQLMATH_NODE = `_sqlmath.napi6_${process.platform}_${process.arch}.node`;
 1731.      1    SQLMATH_EXE = (
 1732.      1        `_sqlmath.shell_${process.platform}_${process.arch}`
 1733.      1        + process.platform.replace(
 1734.      1            "win32",
 1735.      1            ".exe"
 1736.      1        ).replace(
 1737.      1            process.platform,
 1738.      1            ""
 1739.      1        )
 1740.      1    );
 1741.      1}
 1742.      1
 1743.    263function noop(val) {
 1744.    263
 1745.    263// This function will do nothing except return <val>.
 1746.    263
 1747.    263    return val;
 1748.    263}
 1749.      1
 1750.  42774function objectDeepCopyWithKeysSorted(obj) {
 1751.  42774
 1752.  42774// This function will recursively deep-copy <obj> with keys sorted.
 1753.  42774
 1754.  42774    let sorted;
 1755.  28326    if (typeof obj !== "object" || !obj) {
 1756.  28326        return obj;
 1757.  28326    }
 1758.  14448
 1759.  14448// Recursively deep-copy list with child-keys sorted.
 1760.  14448
 1761.  14448    if (Array.isArray(obj)) {
 1762.   2202        return obj.map(objectDeepCopyWithKeysSorted);
 1763.  12246    }
 1764.  12246
 1765.  12246// Recursively deep-copy obj with keys sorted.
 1766.  12246
 1767.  12246    sorted = Object.create(null);
 1768.  13714    Object.keys(obj).sort().forEach(function (key) {
 1769.  13714        sorted[key] = objectDeepCopyWithKeysSorted(obj[key]);
 1770.  13714    });
 1771.  12246    return sorted;
 1772.  12246}
 1773.      1
 1774.      3async function sqlmathInit() {
 1775.      3
 1776.      3// This function will init sqlmath.
 1777.      3
 1778.      3    let moduleModule;
 1779.      3    dbFinalizationRegistry = (
 1780.      3        dbFinalizationRegistry
 1781.     19    ) || new FinalizationRegistry(function ({afterFinalization, ptr}) {
 1782.     19
 1783.     19// This function will auto-close any open sqlite3-db-pointer,
 1784.     19// after its js-wrapper has been garbage-collected.
 1785.     19
 1786.     19        dbCallAsync(
 1787.     19            jsbatonCreate("_dbClose"),
 1788.     19            [
 1789.     19                ptr[0]
 1790.     19            ]
 1791.     19        );
 1792.      1        if (afterFinalization) {
 1793.      1            afterFinalization();
 1794.      1        }
 1795.     19    });
 1796.      3
 1797.      3// Feature-detect nodejs.
 1798.      3
 1799.      3    if (
 1800.      3        typeof process !== "object"
 1801.      3        || typeof process?.versions?.node !== "string"
 1802.      3        || cModule
 1803.      1    ) {
 1804.      1        return;
 1805.      2    }
 1806.      2
 1807.      2// Init moduleFs.
 1808.      2
 1809.      2    await moduleFsInit();
 1810.      2    moduleFsInit(); // coverage-hack
 1811.      2    moduleChildProcessSpawn = moduleChildProcess.spawn;
 1812.      2
 1813.      2// Init moduleFs.
 1814.      2
 1815.      2    await moduleFsInit();
 1816.      2    moduleFsInit(); // coverage-hack
 1817.      2    moduleChildProcessSpawn = moduleChildProcess.spawn;
 1818.      2    cModulePath = moduleUrl.fileURLToPath(import.meta.url).replace(
 1819.      2        (/\bsqlmath\.mjs$/),
 1820.      2        SQLMATH_NODE
 1821.      2    );
 1822.      2
 1823.      2// Import napi c-addon.
 1824.      2
 1825.      2    if (!npm_config_mode_setup) {
 1826.      2        moduleModule = await import("module");
 1827.      2        if (!cModule) {
 1828.      2            cModule = moduleModule.createRequire(cModulePath);
 1829.      2            cModule = cModule(cModulePath);
 1830.      2        }
 1831.      2    }
 1832.      2    if (npm_config_mode_test) {
 1833.      2
 1834.      2// Mock consoleError.
 1835.      2
 1836.      2        consoleError = noop;
 1837.      2
 1838.      2// Mock moduleChildProcessSpawn.
 1839.      2
 1840.     15        moduleChildProcessSpawn = function () {
 1841.     15            let child = {
 1842.     15                end: noop,
 1843.     17                on: function (onType, resolve) {
 1844.     17                    switch (onType) {
 1845.      2                    case "data":
 1846.      2                        resolve(Buffer.alloc(0));
 1847.      2                        return;
 1848.     15                    default:
 1849.     15                        resolve(0);
 1850.     17                    }
 1851.     17                },
 1852.     15                setEncoding: noop,
 1853.     15                write: noop
 1854.     15            };
 1855.     15            child.stderr = child;
 1856.     15            child.stdin = child;
 1857.     15            child.stdout = child;
 1858.     15            return child;
 1859.     15        };
 1860.      2    }
 1861.      3}
 1862.      1
 1863.      1function sqlmathWebworkerInit({
 1864.      1    db,
 1865.      1    modeTest
 1866.      1}) {
 1867.      1
 1868.      1// This function will init sqlmath web-worker.
 1869.      1
 1870.      1// Feature-detect browser.
 1871.      1
 1872.      1    let Worker = globalThis.Worker;
 1873.      1    IS_BROWSER = true;
 1874.      1    if (modeTest) {
 1875.      1        Worker = function () {
 1876.      1            return;
 1877.      1        };
 1878.      1    }
 1879.      1    sqlWorker = new Worker("sqlmath_wasm.js");
 1880.      2    sqlWorker.onmessage = function ({
 1881.      2        data
 1882.      2    }) {
 1883.      2        sqlMessageDict[data.id](data);
 1884.      2    };
 1885.      1    if (modeTest) {
 1886.      2        sqlWorker.postMessage = function (data) {
 1887.      2            setTimeout(function () {
 1888.      2                sqlWorker.onmessage({data});
 1889.      2            });
 1890.      2        };
 1891.      1        // test dbCallAsync handling-behavior
 1892.      1        dbCallAsync(
 1893.      1            jsbatonCreate("testTimeElapsed"),
 1894.      1            [
 1895.      1                true
 1896.      1            ]
 1897.      1        );
 1898.      1        // test dbFileLoadAsync handling-behavior
 1899.      1        dbFileLoadAsync({db, filename: "aa", modeTest});
 1900.      1        // test jsonParseArraybuffer handling-behavior
 1901.      1        jsonParseArraybuffer(new TextEncoder().encode("0"));
 1902.      1        // revert IS_BROWSER
 1903.      1        IS_BROWSER = undefined;
 1904.      1    }
 1905.      1}
 1906.      1
 1907.      1function waitAsync(timeout) {
 1908.      1
 1909.      1// This function will wait <timeout> ms.
 1910.      1
 1911.      1    return new Promise(function (resolve) {
 1912.      1        let ms = Number(timeout);
 1913.      1        if (!Number.isFinite(ms)) {
 1914.      1            ms = 0;
 1915.      1        }
 1916.      1        setTimeout(resolve, ms * !npm_config_mode_test);
 1917.      1    });
 1918.      1}
 1919.      1
 1920.      1sqlmathInit(); // coverage-hack
 1921.      1await sqlmathInit();
 1922.      1sqlmathInit(); // coverage-hack
 1923.      1
 1924.      1export {
 1925.      1    DB_EXEC_PROFILE_DICT,
 1926.      1    DB_STATE,
 1927.      1    LGBM_DTYPE_FLOAT32,
 1928.      1    LGBM_DTYPE_FLOAT64,
 1929.      1    LGBM_DTYPE_INT32,
 1930.      1    LGBM_DTYPE_INT64,
 1931.      1    LGBM_FEATURE_IMPORTANCE_GAIN,
 1932.      1    LGBM_FEATURE_IMPORTANCE_SPLIT,
 1933.      1    LGBM_MATRIX_TYPE_CSC,
 1934.      1    LGBM_MATRIX_TYPE_CSR,
 1935.      1    LGBM_PREDICT_CONTRIB,
 1936.      1    LGBM_PREDICT_LEAF_INDEX,
 1937.      1    LGBM_PREDICT_NORMAL,
 1938.      1    LGBM_PREDICT_RAW_SCORE,
 1939.      1    SQLITE_OPEN_AUTOPROXY,
 1940.      1    SQLITE_OPEN_CREATE,
 1941.      1    SQLITE_OPEN_DELETEONCLOSE,
 1942.      1    SQLITE_OPEN_EXCLUSIVE,
 1943.      1    SQLITE_OPEN_FULLMUTEX,
 1944.      1    SQLITE_OPEN_MAIN_DB,
 1945.      1    SQLITE_OPEN_MAIN_JOURNAL,
 1946.      1    SQLITE_OPEN_MEMORY,
 1947.      1    SQLITE_OPEN_NOFOLLOW,
 1948.      1    SQLITE_OPEN_NOMUTEX,
 1949.      1    SQLITE_OPEN_PRIVATECACHE,
 1950.      1    SQLITE_OPEN_READONLY,
 1951.      1    SQLITE_OPEN_READWRITE,
 1952.      1    SQLITE_OPEN_SHAREDCACHE,
 1953.      1    SQLITE_OPEN_SUBJOURNAL,
 1954.      1    SQLITE_OPEN_SUPER_JOURNAL,
 1955.      1    SQLITE_OPEN_TEMP_DB,
 1956.      1    SQLITE_OPEN_TEMP_JOURNAL,
 1957.      1    SQLITE_OPEN_TRANSIENT_DB,
 1958.      1    SQLITE_OPEN_URI,
 1959.      1    SQLITE_OPEN_WAL,
 1960.      1    SQLMATH_EXE,
 1961.      1    SQLMATH_NODE,
 1962.      1    assertErrorThrownAsync,
 1963.      1    assertInt64,
 1964.      1    assertJsonEqual,
 1965.      1    assertNumericalEqual,
 1966.      1    assertOrThrow,
 1967.      1    childProcessSpawn2,
 1968.      1    ciBuildExt,
 1969.      1    dbCloseAsync,
 1970.      1    dbExecAndReturnLastBlob,
 1971.      1    dbExecAndReturnLastRow,
 1972.      1    dbExecAndReturnLastTable,
 1973.      1    dbExecAndReturnLastValue,
 1974.      1    dbExecAsync,
 1975.      1    dbExecProfile,
 1976.      1    dbFileLoadAsync,
 1977.      1    dbFileSaveAsync,
 1978.      1    dbNoopAsync,
 1979.      1    dbOpenAsync,
 1980.      1    dbTableImportAsync,
 1981.      1    debugInline,
 1982.      1    fsCopyFileUnlessTest,
 1983.      1    fsExistsUnlessTest,
 1984.      1    fsReadFileUnlessTest,
 1985.      1    fsWriteFileUnlessTest,
 1986.      1    jsbatonGetInt64,
 1987.      1    jsbatonGetString,
 1988.      1    libPlatformArchExt,
 1989.      1    listOrEmptyList,
 1990.      1    noop,
 1991.      1    objectDeepCopyWithKeysSorted,
 1992.      1    sqlmathWebworkerInit,
 1993.      1    version,
 1994.      1    waitAsync
 1995.      1};
 1996.      1