
Node.jsを使用してSQLクエリを生成する際、適切な方法で実装しなければSQLインジェクションのリスクが高まります。
本記事では、プレースホルダーを活用し、安全かつ柔軟なWHERE句を作成する方法を詳しく解説します。
SQLクエリの動的生成における課題
動的なSQLクエリを作成する場合、以下のような課題が発生することがあります。
- SQLインジェクションのリスク
- プレースホルダーの管理
- 複数の条件を適切に組み合わせる
- NULL値や配列の処理
特に、IN句を使う場合に適切な実装を行わないと、意図しないデータ構造になり、エラーの原因となります。
WHERE句を安全に生成する関数
以下の関数は、Node.jsでSQLクエリのWHERE句を安全に生成するものです。
/**
* WHERE句を作成する汎用関数
* @param {string} tableName - テーブル名
* @param {string} field - フィールド名
* @param {string} operator - 比較演算子
* @param {Array|string} addField - 追加のフィールド
* @param {Object} queryParams - クエリパラメータ
* @param {number} currentIndex - プレースホルダーのインデックス
* @returns {Object|null} - クエリテキストとインデックスを含むオブジェクト
*/
const whereQuery = (tableName, field, operator, addField = [], queryParams, currentIndex) => {
if (operator === 'IS NULL' || operator === 'IS NOT NULL') {
return { text: `(${tableName}.${field} ${operator})` };
}
const value = queryParams[field];
if (value === undefined || value === null || value === '') {
return null;
}
if (operator === 'LIKE') {
return {
text: `(${tableName}.${field} ${operator} $${currentIndex})`,
values: [`%${value}%`],
index: currentIndex + 1
};
}
if (operator === 'BETWEEN' && Array.isArray(addField) && addField.length === 2) {
const startValue = queryParams[addField[0]];
const endValue = queryParams[addField[1]];
return (startValue && endValue) ? {
text: `(${tableName}.${field} ${operator} $${currentIndex} AND $${currentIndex + 1})`,
values: [startValue, endValue],
index: currentIndex + 2
} : null;
}
if (operator === 'IN' && Array.isArray(addField) && addField.length > 0) {
const values = queryParams[addField];
if (Array.isArray(values) && values.length > 0) {
const placeholders = values.map((_, index) => `$${currentIndex + index}`).join(', ');
return {
text: `(${tableName}.${field} ${operator} (${placeholders}))`,
values: values,
index: currentIndex + values.length
};
}
return null;
}
return {
text: `(${tableName}.${field} ${operator} $${currentIndex})`,
values: [value],
index: currentIndex + 1
};
};
IN句を扱う際のポイント
誤った実装例(多次元配列の問題)
let queryValues = [];
if (wheres.length > 0) {
wheres.forEach(condition => {
if (condition.text) {
queryText.push(condition.text);
if (condition.value !== undefined) {
queryValues.push(condition.value);
}
if (condition.values !== undefined) {
queryValues.push(condition.values); // ここで多次元配列の可能性がある
}
}
});
}
上記のコードでは、queryValuesに配列をそのまま追加してしまうため、多次元配列になる可能性があります。
修正後の正しい実装
let queryValues = [];
if (wheres.length > 0) {
wheres.forEach(condition => {
if (condition.text) {
queryText.push(condition.text);
if (condition.value !== undefined) {
queryValues.push(condition.value);
}
if (Array.isArray(condition.values) && condition.values.length > 0) {
queryValues.push(...condition.values); // スプレッド構文で展開し追加
}
}
});
}
この修正により、多次元配列になることを防ぎ、期待どおりのフラットな配列が得られます。
まとめ
- Node.jsでSQLクエリを動的に生成する際は、プレースホルダーを活用して安全に実装する。
IN句を扱う場合、多次元配列が発生しないよう、スプレッド構文を使用する。Array.isArray()とlength > 0を組み合わせて適切なデータチェックを行う。- オプショナルチェーン(
?.)を活用すると、簡潔なコードが書ける。
このような工夫をすることで、安全で柔軟なSQLクエリを生成でき、バグの少ないシステム開発が可能になります。ぜひ、実装の際に参考にしてください。
- Original:https://minory.org/node-sefety-sql-query.html
- Source:minory
- Author:管理者
Amazonベストセラー
Now loading...