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を使っている人の助けになれば幸いです👊