ふたつのキャスト
BigQuery には値をキャストする関数として CAST() と SAFE_CAST() の二つがある。
このように動作する。
SELECT CAST('0xDEADBEEF' AS INT64) AS number; /*------------* | number | +------------+ | 3735928559 | *------------*/ SELECT SAFE_CAST('0xDEADBEEF' AS INT64) AS number; /*------------* | number | +------------+ | 3735928559 | *------------*/
この時点では挙動が同じなので違いは見えない。キャストに失敗する値を渡してやると違いが見える。
SELECT CAST('0xDEADCHICKEN' AS INT64) AS number; /* Error: Bad int64 value: 0xDEADCHICKEN */ SELECT SAFE_CAST('0xDEADCHICKEN' AS INT64) AS number; /*--------* | number | +--------+ | NULL | *--------*/
16進数としてパースできない '0xDEADCHICKEN' を渡した場合、CAST はエラーになる。一方で SAFE_CAST はエラーにはならず NULL が返る。
| キャスト可能な引数 | キャスト不可な引数 | |
|---|---|---|
| CAST | CAST('42' AS INT) = 42 |
CAST('a' AS INT) → エラー |
| SAFE_CAST | SAFE_CAST('42' AS INT) = 42 |
SAFE_CAST('a' AS INT) IS NULL |
ドキュメントにも書いてある。
If you want to protect your queries from these types of errors, you can use SAFE_CAST.
意訳: 実行時エラーからクエリを守りたいなら
SAFE_CASTを使ってくれ
なるほど。SAFE_CAST を使えば安全。
逆じゃない?
設計原則に "Let It Crash" というのがある。
私の理解では
- 正常じゃないのに動き続けている処理はたちが悪い
- 処理の事前条件が満たされていないならさっさとクラッシュするのが被害最小
というような意味だ。
その思想で言えば、キャストが必要な処理にキャスト不可な値が入ってきた場合には即座に処理を中止して全体をロールバックさせるのが安全 (Safe) だ。
キャスト不可な値が NULL に差し替えられて正常終了してしまうほうが危険に思える。
というのは言いがかりで
まぁそういうネーミングなので仕方ない。
BigQuery の関数には CAST() と SAFE_CAST() のように通常版・安全版がそれぞれ用意された関数がいくつかある。
| 通常版 | 安全版 | |
|---|---|---|
/ (除算) |
SAFE_DIVIDE(x, y) |
y=0 のとき NULL を返す |
+ (加算) |
SAFE_ADD(x, y) |
オーバーフロー時に NULL を返す |
PARSE_DATETIME() |
SAFE.PARSE_DATETIME() |
パース失敗時に NULL を返す |
PARSE_JSON() |
SAFE.PARSE_JSON() |
パース失敗時に NULL を返す |
arr[0] |
arr[SAFE_OFFSET(0)] |
インデックスが存在しない時に NULL を返す |
arr[SAFE_OFFSET(0)] めっちゃ癖あるなぁー。
まとめ
私は名前が逆だと思いました。みなさんはどう思いますか?
私からは以上です。