軽い修正かと思ってDELETEやUPDATEで気づかないと結構あわわなので注意
背景
WHEREに対する3つのAND条件にOR条件を追加する必要があった。
具体的にはNULLを条件に含める必要があり、比較演算子では対象から抜け落ちてしまうため条件を追加した。
結論
間のANDにOR条件を追加したい場合、評価のされ方が変わるので()で囲む必要がある
# 現行
A AND B AND C
# 追加
## 誤
A AND B OR X AND C
-> (A AND B) OR (C AND D)
## 正
A AND (B OR X) AND C
例
定期格納実施後に不正データを削除するSQL
格納したばかりのデータと同じデータが過去のデータに合った場合に削除する
DELETE FROM ${data_warehouse.database.table}
WHERE
/* 定期格納したデータの対象期間 */
TD_TIME_RANGE(time, TD_TIME_PARSE('${date_since}', '${date_timezone}'), TD_TIME_ADD(TD_TIME_PARSE('${date_until}', '${date_timezone}'), '1s'))
AND
/* 過去に格納されているデータ */
(updated_at < ${import_time} OR updated_at IS NULL) /* <-- ここにNULLを()なしで入れた */
AND
/* データを一意とする条件(スキーマの構造的にPKがないので) */
ARRAY_JOIN(ARRAY[${primary_keys}], ',')
IN (
/* 格納したばかりのデータ */
SELECT
ARRAY_JOIN(ARRAY[${primary_keys}], ',')
FROM
${data_warehouse.database.table}
WHERE
TD_TIME_RANGE(time, TD_TIME_PARSE('${since_date}', '${timezone}'), TD_TIME_ADD(TD_TIME_PARSE('${until_date}', '${timezone}'), '1s'))
AND
updated_at = ${import_time}
)
直前に格納したデータの対象期間
かつ
過去に格納されているデータまたはNULL
かつ
格納したばかりのデータと同じ
という条件のデータだけを削除するはずが、
直前に格納したデータの対象期間
かつ
過去に格納されているデータ
を全部削除するという形になってしまった。
つまり格納したデータ全部削除していた。(何も格納していないことになっていた。)
雑感
シンプルな対応でも少し複雑な処理に対して行う場合は、周辺の再確認時間を適切に確保して安直に行わないようにする
一意じゃないデータが入り得るのに一意のデータを入れていけないとなると大変