OutSystems: 初心者の時に知りたかった機能2選

皆さま、始めまして。
突然ですが、私がOutSystemsと出会ってから、早いものでかれこれ2年半くらいになりました。

資格を取るために学習したり、あるいは担当するアプリの改修で課題を解決しようともがくうち、「そんないいモンあるなら言ってよ…」[^1]と愚痴りたくなるような便利機能を後から見つけることがちらほらありました。
この記事では、そんな機能のうち特に「先に知っていれば…!」と思った機能を2つご紹介します。
OutSystemsを学習される皆様のお役に少しでも立てば光栄です。

# 1. 文字列(Text)型のリストを、一つの文字列に結合する
特にDBのクエリ結果をログに残すときなど、リスト型で持っている値を、カンマ区切りで一つの文字列に結合したい場合があると思います。
そんな時分、かつて私はこんな実装をしていました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3632582/230f5766-8fbc-cb7b-7041-8135e8a70f0a.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3632582/d77eefdd-3fe0-6d09-c30a-1ba84f16f441.png)
ForEachでリストの各要素を取り出して、順繰りに結合していく**ゴリ押し戦法**です。
別にこれでも問題はないんですが、パッと見で何をしている処理か分かりづらく、またカンマを追加する処理にIf文が入るので、タイポによるバグの温床になります。
(実際何度もこの実装が原因のバグに苦しめられました。)

----------
そこで登場するのが、**String_Join**アクションです。**Text**モジュールに収録されています。
このアクションを使うと、同じ実装がこんな感じになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3632582/55e63a9b-547c-982c-7b3c-1d815cd5d6ca.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3632582/975f2e6e-ddbf-2c9d-fa10-a75b96078423.png)

かなりシンプルになりました。
アクションの引数(入力パラメータ)も単純明快ですね。
- くっつけたい文字列リスト
- 区切り文字

この2つだけです。
見た目もシンプルで可読性が上がり、手数も減るので実装にかかる作業時間も少なくなります。

::: note info
文字列リストの結合には
**String_Join(Textモジュール)**
を使用する！
:::

# 2.動的なSQL文(IN句)の作り方
データベースのテーブルから情報を持ってくるとき、OutSystemsには**Aggregate**というめちゃくちゃ便利な機能があります。これは、対象のテーブルやフィルタ、ソート順などのクエリの条件をGUIで指定すると、自動でSQL文を生成してくれる優れものです。
ただし、このAggregate、一つだけ大きな弱点があります。

それは、**IN句に対応していない**ということです。
なので、WHERE句などでIN句を使いたい場合は、自分でSQLを書いて、IN句を**引数として**渡してあげる必要があります。

私はここでも、ForEachでリストの各要素を取り出して、順繰りに結合していくゴリ押し戦法で実装していました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3632582/51b256d4-9f7c-caa1-bba7-53aa8b95bddb.png)

こんな実装をすると、先ほどの文字列連結と同じく、タイポによるバグの温床になることに加え、こんな警告が表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3632582/d393c7b6-701a-1316-55bf-16fd4e4193eb.png)

> SQLインジェクションに対し脆弱になるので、SQLクエリパラメータの"Expand Inline"プロパティをオンにすることは避けてください。

詳しい説明は割愛しますが、In句に使う値のリストがアクションの外部(=入力パラメータ)から来ているので、SQLインジェクションに弱くなってしまうよ、という警告です[^2]。

---
ここで登場するのが、Sanitizationモジュールの**BuildSafe_InClauseIntegerList**アクションです。
このアクションを使って同じ実装をすると、こうなります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3632582/aab59dbe-7ed9-0ac5-6e8f-1c0efc8edcea.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3632582/48c2d846-a848-6742-d464-a333a10bb3ff.png)

シンプルになりましたね。
このアクションは、入力パラメータにリストを渡せば、IN句の形('A','B','C',...の形)に変換して戻してくれるアクションです。
その際、SQL文として使用して問題ないように適切にエンコードもしてくれます。

:::note
SQL文のIN句は
**BuildSafe_InClauseTextList(Sanitizationモジュール)**
で作る！
:::

# 最後に
チュートリアルなどでは、なんでもかんでもリストとForEachでゴリ押しして実装するイメージがあったOutSystemsですが、こういった一部の用途では、便利なアクション(関数)が用意されています。

ただこういった関数はデフォルトの状態ではアクションリストに表示されず、対象のモジュールを依存関係に追加しないと表示されないので、存在を知らないとそもそも出会えない、というちょっとしたトラップが潜んでいます。

資格試験の要項の後ろの方に乗っている、試験範囲のドキュメント一覧に、こういった便利機能の記載がいろいろあるので、流し読みすると引き出しが増える(かもしれません)。

最後までお読みいただき、ありがとうございました！
明日の担当は記事担当は@ayukiyamaさんです。よろしくお願いします！

[^1]: もちろん、ちゃんと探せば書いてあるんですが、欲しい時に限って探しても見つからないことってありますよね…
[^2]: 警告文にある通り、パラメータの"Expand Inline"(クエリの値をそのままSQL文の一部として解釈する)をオフにすれば問題ありませんが、IN句として使用する場合はオンにする必要があります。