sql >> データベース >  >> RDS >> SQLite

JavaScriptプロキシを使用してSQLiteでブール値を処理する方法

    SQLiteのブール値の問題

    SQLiteを使用したことがある場合は、サポートされているデータ型とBooleanに注意する必要があります。 それらの1つではありません。より具体的には、ここで述べられているように:

    2.1。ブールデータ型

    SQLiteには個別のブール型ストレージクラスはありません。代わりに、ブール値は整数0(false)および1(true)として格納されます。

    SQLiteは、バージョン3.23.0(2018-04-02)の時点で、キーワード「TRUE」と「FALSE」を認識しますが、これらのキーワードは、実際にはそれぞれ整数リテラル1と0の代替スペルにすぎません。

    SQLite3のほとんどのJavaScriptライブラリはTRUEをサポートしていません およびFALSE キーワードであり、整数を使用してコード内のステートメントを準備する必要があります。たとえば、better-sqlite3では、次のようにする必要があります。

    const payload = {
      isActive: 1, // <======
      username: 'Brad',
      password: '1234',
      email: '[email protected]',
    };
    
    const result = database
      .prepare(
        `INSERT INTO accounts(isActive, username, password, email) VALUES(@isActive, @username, @password, @email) `
      )
      .run({ bucketID, taskSiteID, name, username, password, email }).changes;
    

    numberを使用する booleanの代わりに アプリ全体で、開発者のエクスペリエンスがひどいものになります(さらに、おそらくより多くのメモリを使用します)。

    ヘルパー関数を使用して、ペイロードオブジェクトのブール値を変換できます。 プロパティを数値に (私は過去にこれを実際に一度行ったことがあります)が、その後はすべてのクエリの前に手動で実行する必要があります。うわぁ。ステートメントを準備して実行するたびに、このロジックがバックグラウンドで実行されたら素晴らしいと思いませんか?

    ようこそES6プロキシ👋

    新しいJavaScript機能の1つは、Proxyです。 物体。 プロキシ 本質的には、ゲッター、セッター、関数呼び出しなどのオブジェクト操作をインターセプトする「トラップ」です。 プロキシの使用 SQLite JSラッパーライブラリを変更して、ミドルウェアのような独自のロジックを実行できます。

    ヘルパー関数の記述

    開発を容易にするために、mapValuesを使用します &isPlainObject ユーティリティはlodashから機能しますが、もちろん独自にコーディングすることもできます。以下の関数は、オブジェクト(1レベルの深さ)をマップし、タイプbooleanの値を変換します。 numberと入力します 。

    import { mapValues } from 'lodash';
    
    const booleanEntriesToNumbers = (object) =>
      mapValues(object, (value) =>
        typeof value === 'boolean' ? Number(value) : value
      );
    

    プロキシを使用してクエリ呼び出しを傍受する

    以下にbetter-sqlite3をインポートします ライブラリを作成し、新しいデータベースインスタンスを作成します。その後、デフォルトのprepareをオーバーライドします 独自のメソッドを使用します。これにより、メソッドrunがオーバーライドされます。 、get およびall 、それぞれに新しいプロキシを作成します。もちろん、他の任意の方法のプロキシを作成することもできます。

    import Database from 'better-sqlite3';
    
    // Create new database instance
    const db = new Database(dbFilePath);
    
    // We will use this function to override the default "prepare" method
    const proxiedPrepare = new Proxy(db.prepare, {
        apply: (prepare, prepareThisArg, [stringStatement]) => {
          const statement = prepare.call(prepareThisArg, stringStatement);
    
          // Override the default "run" method
          statement.run = new Proxy(statement.run, {
            apply: (run, runThisArg, args) => {
              const mappedArgs = args.map((arg) =>
                isPlainObject(arg) ? booleanEntriesToNumbers(arg) : arg
              );
    
              return run.call(runThisArg, ...mappedArgs);
            },
          });
    
          // Override the default "get" method
          statement.get = new Proxy(statement.get, {
            apply: (get, getThisArg, args) => {
              const mappedArgs = args.map((arg) =>
                isPlainObject(arg) ? booleanEntriesToNumbers(arg) : arg
              );
    
              return get.call(getThisArg, ...mappedArgs);
            },
          });
    
          // Override the default "all" method
          statement.all = new Proxy(statement.all, {
            apply: (all, allThisArg, args) => {
              const mappedArgs = args.map((arg) =>
                isPlainObject(arg) ? booleanEntriesToNumbers(arg) : arg
              );
    
              return all.call(allThisArg, ...mappedArgs);
            },
          });
    
          return statement;
        },
      });
    
    // Override the default "prepare" method
    db.prepare = proxiedPrepare;
    

    基本的に、prepareを呼び出すと メソッドがトリガーされたら、JavaScriptに次のように伝えます。待ってください!この関数呼び出しを変更します。元の開発者が意図したロジックを実行する代わりに、最初に独自のロジック(オブジェクトペイロードのマッピング)を実行する必要があります。 独自のロジックを実行した後、callを使用して元のメソッドを呼び出した結果を返します。 thisをバインドする 口論。プロキシの仕組みについて詳しく知りたい場合は、こちらをお読みください。実装には、applyを使用しました ここの方法。

    この投稿を読んでくれてありがとう、JavaScriptでSQLiteを使っている人の助けになれば幸いです👊


    1. DundasBIでのQuickBooksデータの分析

    2. SQLiteで毎月第1月曜日を返す

    3. 高度なMySqlクエリ:別のテーブルからの情報でテーブルを更新します

    4. MariaDB JDBCドライバーはLog4jの脆弱性の影響を受けますか?