# エスケープと動的参照

パラメータのコンテキストに基づいてSQLインジェクション保護と値のエスケープを処理します。この仕組みはセキュリティを担保するだけでなく、テーブル名やカラム名などの動的な識別子の生成も可能にします。

## パラメータのエスケープ処理

### 1. 通常のコンテキストでの文字列パラメータ

* パラメータは文字列としてエスケープされて展開されます
* エスケープ処理は、選択されているコネクションのSQL文法に従って行われます

```sql
-- パラメータ値が user's "data" の場合
WHERE name = {{str_param}}         -> WHERE name = 'user\'s \"data\"'

-- パラメータ値が O'Reilly's "Book" の場合
SELECT name = {{company}}          -> SELECT name = 'O\'Reilly\'s \"Book\"'
```

### 2. 引用符付きコンテキストでの文字列パラメータ

* パラメータがダブルクォートやシングルクォートなどの引用符内にある場合、パラメータはその引用符を加味して、元の構文を壊さないようにエスケープされます
* エスケープ処理は、選択されているコネクションのSQL文法に従って行われます

```sql
-- 以下は BigQuery のコネクションを使用した場合の例

-- ダブルクオート内（"と'の両方をエスケープ）
-- パラメータ値が user"s 'data' の場合
SELECT "{{str_param}}" as alias    -> SELECT "user\"s \'data\'" as alias

-- シングルクオート内（"と'の両方をエスケープ）
-- パラメータ値が user"s 'data' の場合
SELECT '{{str_param}}' as alias    -> SELECT 'user\"s \'data\'' as alias

-- バッククォート内（`のみをエスケープ）
-- パラメータ値が user"s 'data` の場合
SELECT `{{str_param}}` as alias    -> SELECT `user"s 'data\`` as alias
```

### 3. 日付パラメータの特別処理

* 通常のコンテキスト: 日付は `YYYY-MM-DD` 形式で文字列として展開されます
* ただし、BigQueryのコネクションを利用している場合、バックティック(\`)で囲まれた中では `YYYYMMDD` 形式（ハイフンなし）に展開されます

```sql
-- 以下は BigQuery のコネクションを使用した場合の例

-- 通常の日付パラメータ
SELECT {{date_param}} as normal         -> SELECT '2024-10-02' as normal

-- 引用符内の日付は同じエスケープルールに従います
SELECT '{{date_param}}' as single_quote -> SELECT '2024-10-02' as single_quote
SELECT "{{date_param}}" as double_quote -> SELECT "2024-10-02" as double_quote

-- 特殊ケース: BigQueryでのテーブル名生成
SELECT * FROM `table_{{date_param}}`    -> SELECT * FROM `table_20241002`
```

### 4. その他のパラメータ

* 数値、真偽値パラメータはエスケープ処理は行われず、そのまま展開されます

## 動的な参照の生成

* パラメータを引用符内に配置することで、テーブル名やカラム名などの識別子を安全に生成することができます

```sql
-- ダイナミックなテーブル名
SELECT * FROM `table_{{table_suffix}}` -> SELECT * FROM `table_sales_2024`

-- ダイナミックなフィールド選択
SELECT "column_{{field_type}}"         -> SELECT "column_revenue"
```

{% hint style="warning" %}
外側の引用符に応じて、構文が壊れないようにエスケープ処理を行いますが、**文字列パラメータの値には任意の文字列が指定可能**なため、SQLの書き方によっては意図しないテーブルやカラムが参照されてしまう可能性があります。動的に識別子を生成する場合は、**プレフィックスやサフィックスを固定**する、**意図しない値が指定された時にSQLがエラーになるようにSQLを記述する**、等の対策を考えてください。
{% endhint %}
