刹那(せつな)の瞬き

Willkömmen! Ich heiße Setsuna. Haben Sie etwas Zeit für mich?

Knex.js ver 0.95.0以降でSQLServerのdatabase libraryがtediousに変わってた

Knex.js を利用して SQLServer に接続するコードを書いて実行したところ、

Error: No event 'socketConnect' in state 'SentPrelogin'

のようなエラーが発生して接続できませんでした。
他の DB には接続できるのに SQLServer だけ接続できないのは釈然としません。

非常に困ってたのですが、同じ問題に直面している記事を見つけました。

要するに、node-mssql だといろいろ問題があったので、Knex.js ver 0.95.0以降では直接 tedious を使うようになったそうです。

そのため、今後はnpm install mssqlではなく、npm install tediousにする必要があります。

当該ブロジェクトの package.json を確認したら、"knex": "^0.95.4",だったので、

$ npm uninstall mssql
$ npm install tedious

のように処理したところ、問題なく接続できました。
Linux (KDE neon 5.21.3)と Mac (Intel macOS Mojave10.14.6)で確認済み

おまけ

当初、SQL Builder として Squel.js を利用しようとしたら、Knex.js を奨められたので、そのまま成り行きで利用してます。

ついでに、以前に書いた node-mssql を利用したコードを同じ条件で Knex.js に書き換えてみました。

ソースコード: crud.js

const knex = require('knex')({ 
    client: 'mssql',    // ここは 'mssql' のまま
    connection: {
        server: 'localhost',
        user: 'sa',
        password: 'abcd1234$',
        database: 'my_test_db',
        options: {
            enableArithAbort: true,
        }
    }
});

(async () => {
    console.log("#### Start ####");
    try {
        console.log("-- DROP & CREATE TABLE");
        await knex.schema.dropTableIfExists("会員名簿");
        await knex.schema.createTable("会員名簿", table => {
            table.integer("番号");
            table.string("氏名", 40);
            table.date("誕生日");
        });

        console.log("-- INSERT");
        for (const [id, name, birthday] of [
            [ 110, "岸本 龍也", "1989-11-06" ],
            [ 210, "荒井 伸次郎", "1974-01-30" ],
            [ 105, "江口 美奈", "1979-06-23" ],
            [ 304, "長田 隆次", "1991-05-25" ],
            [ 307, "中居 雄樹", "1984-02-29" ],
        ]) {
            await knex("会員名簿").insert({ 
                "番号": id, "氏名": name, "誕生日": birthday,
            });
        }
        display(await knex.select().table("会員名簿"));

        console.log("-- UPDATE");
        const update_id = 307;
        const new_name = "中井 雄樹";
        await knex("会員名簿").where("番号", "=", update_id)
                .update({ "氏名": new_name });
        display(
            await knex.select("番号","氏名").from("会員名簿")
                .orderBy("番号")
        );

        console.log("-- DELETE");
        const delete_id = 210;
        await knex("会員名簿").where("番号", "=", delete_id).del();
        display(
            await knex.select("番号","氏名","誕生日").from("会員名簿")
                .orderBy("誕生日", "desc")
        );
    } catch (e) {
        console.log("#### Catch !! ####");
        console.log(e);
    } finally {
        knex.destroy();
    }
    console.log("#### Finish ####");
})()

function display(rs) {
    let row_count = 0;
    if (rs.length > 0) {
        // カラム名
        const columns = Object.keys(rs[0]);
        const header = [];
        for (const col_name of columns) {
            header.push(` | ${col_name}`);
        }
        header.push(" |");
        console.log(header.join(""));
        // ロー
        for (const row of rs) {
            const buff = [];
            for (const col_name of columns) {
                buff.push(` | ${row[col_name]}`);
            }
            buff.push(" |");
            console.log(buff.join(""));
            ++row_count;
        }
    } 
    console.log(`結果 ${row_count} 行 (${rs.length})`);
}

ソースコードの生SQL文字列を QueryBuilder / SchemaBuilder で書き換えてます。
個人的には、生SQL文字列と比較しても、あまり違和感はないかと。

検証用はともかく、新規なのに大量の埋め込みSQL文は見たくないですね。