From 7ef2d4da9adb744d3665fc25fe423f064986b090 Mon Sep 17 00:00:00 2001 From: mziyut Date: Fri, 13 Oct 2023 09:44:15 +0000 Subject: [PATCH] Pull articles --- qiita/public/ccf2c58ae44c49a34b04.md | 154 +++++++++++++++++++++++++++ 1 file changed, 154 insertions(+) create mode 100644 qiita/public/ccf2c58ae44c49a34b04.md diff --git a/qiita/public/ccf2c58ae44c49a34b04.md b/qiita/public/ccf2c58ae44c49a34b04.md new file mode 100644 index 0000000..e89a2f7 --- /dev/null +++ b/qiita/public/ccf2c58ae44c49a34b04.md @@ -0,0 +1,154 @@ +--- +title: Dataform の Unit test で UNION ALL を書くのが辛くて JavaScript の wrapper を書いた話 +tags: + - JavaScript + - SQL + - テスト + - sqlx + - Dataform +private: false +updated_at: '2023-10-13T18:41:54+09:00' +id: ccf2c58ae44c49a34b04 +organization_url_name: qiita-inc +slide: false +ignorePublish: false +--- + +## はじめに + +Dataform には unit test を記述出来ます。 +ただし、テストに用いるデータは SQL で書く必要があり冗長なものになりがちです。 +Dataform は JavaScript を記述、読込みできるので wrapper を書きました。 + +## Dataform の Unit test について + +Dataform の Unit test はこのように記述できます。 +`example_originals` table からデータを参照する `example.sqlx` があったとします。 + +```sqlx:foo/example.sqlx +config { + type: "view", + name: "example_tables" +} + +SELECT + id, + title +FROM + ${ref("example_originals")} +``` + +この `example.sqlx` に対する Unit test を用意すると以下のようになります。 + +```sqlx:foo/test_example.sqlx +config { + type: "test", + dataset: "example_tables" +} + +SELECT + 1 AS id, + "title1" AS title +UNION ALL +SELECT + 2 AS id, + "title2" AS title +UNION ALL +SELECT + 3 AS id, + "title3" AS title + +input "example_originals" { + SELECT + 1 AS id, + "title1" AS title + UNION ALL + SELECT + 2 AS id, + "title2" AS title + UNION ALL + SELECT + 3 AS id, + "title3" AS title +} +``` + +test データを用意したいだけですが、 `UNION ALL` を何度も記載する必要があります。 +面倒で寿司、可読性も悪い状態になってしまいます。 + +苦し紛れではありますが、JavaScript を用いて `UNION ALL` のラッパー関数を作成しました。 + +## JavaScript の wrapper を書いた + +Dataform は `includes` 以下の ディレクトリに JavaScript ファイルを置くことで、 +SQLX 内から JavaScript に記載した処理を呼び出すことができます。 + +作成した JavaScript はこちらです。 +渡されたデータを `UNION ALL` で `join` するだけの簡単な処理です。 + +:::note warn +エスケープ処理等いくつか省略しています。 +::: + +```js:includes/sql.js +function build(data) { + if (data.length === 0) { + return ""; + } + + const keys = Object.keys(data[0]); + return data.map((item) => { + const values = keys.map((key) => { + if (typeof item[key] !== "string") { + return `${item[key]} AS ${key}`; + } + return `'${item[key]}' AS ${key}`; + }); + + return `SELECT ${values.join(", ")}`; + }).join(" UNION ALL "); +} + +module.exports = { + build, +}; +``` + +SQLX ファイルから処理を呼び出す場合は以下のように記載します。 + +```sqlx:foo/bar.sqlx +${ + sql.build([ + { id: 1, title: "title1" }, + { id: 2, title: "title2" } + ]) +} +``` + +すると以下のような SQL に変換します。 + +```sql +SELECT + 1 as id, + "title1" as title +UNION ALL +SELECT + 2 as id, + "title2" as title +``` + +## 最後に + +今回記事を書くために記載したテストデータの件数は3件程でした。 +Dataform で処理するデータ次第ですが、テストデータの件数はもっと多くなるはず。 + +ちょっとした JavaScript を書くだけで、すこしメンテナンスしやすなります。 +いい塩梅が求められる部分なので、やり過ぎは禁物です。 + +## References + +https://docs.dataform.co/guides/tests + +https://cloud.google.com/blog/ja/topics/data-warehousing/learn-how-to-use-the-dataform-cli-tool-to-unit-test-udfs?hl=ja + +https://cloud.google.com/blog/topics/data-warehousing/learn-how-to-use-the-dataform-cli-tool-to-unit-test-udfs/