カスタムクリーンルームテンプレートのリファレンス¶
clean roomテンプレートについて¶
クリーンルームのテンプレートは JinjaSQL で書かれています。JinjaSQL は、Jinjaテンプレート言語の拡張であり、出力として SQL クエリを生成します。これにより、テンプレートは論理ステートメントと実行時の変数解決を使用して、テーブル名、テーブル列、および実行時にクエリで使用されるカスタム値をユーザーに指定させられるようになります。
Snowflakeは、一般的なユースケース向けに事前に設計された、いくつかのテンプレートを提供しています。しかし、ほとんどのユーザーは、クリーンルーム用のカスタムクエリテンプレートを作成することを好みます。カスタムテンプレートの作成には、クリーンルーム API を使用しますが、実行はコードで行うか、クリーンルーム UI を使用するかのいずれかです。
テンプレートには大きく分けて2つのタイプがあります:
分析テンプレート は、評価すると SELECT ステートメント(または SELECT 操作のセット)になり、テンプレート実行者に結果を表示します。
アクティベーションテンプレート は、結果をすぐに環境に表示するのではなく、Snowflakeアカウントまたはサードパーティに結果をアクティブ化するために使用されます。アクティベーションテンプレートは、 いくつかの追加要件 を備えた分析テンプレートと非常によく似ています。
クリーンルーム UI では、分析テンプレートをアクティベーションテンプレートに関連付けることで、呼び出し元が分析を実行し、結果を確認し、自分自身またはサードパーティにデータをアクティブ化できるようにします。アクティベーションテンプレートは、関連する分析テンプレートと同じクエリに解決する必要はありません。
カスタムテンプレートの作成と実行¶
デフォルト設定のクリーンルームでは、 カスタムテンプレートの使用ドキュメント で説明されているように、プロバイダーがクリーンルームにテンプレートを追加し、コンシューマーがテンプレートを実行します。
簡単な例¶
以下は、プロバイダーテーブルとコンシューマーテーブルをメールで結合し、重複回数を都市ごとに表示するシンプルな SQL の例です:
呼び出し元が使用するテーブルのほか、JOIN および GROUP BY 列を選択できるようにした JinjaSQL テンプレートとして表示されるクエリは次のようになります。
このテンプレートの注意事項:
{{ double bracket pairs }} 内の値はカスタム変数です。
group_by_col、my_table、source_table、consumer_join_col、provider_join_col、group_by_colはすべて、呼び出し元が設定したカスタム変数です。source_tableおよびmy_tableは、呼び出し元が設定するSnowflake定義の文字列配列変数です。配列のメンバーは、clean roomにリンクされたプロバイダーとコンシューマーテーブルの完全修飾名です。呼び出し元は、各配列にどのテーブルを含めるかを指定します。テンプレートでは、プロバイダーテーブルは 小文字の
pとして、コンシューマーテーブルは 小文字のcとしてエイリアス化する必要があります。複数のテーブルがある場合は、p1、p2、c1、c2のようにインデックスを付けることができます。IDENTIFIER がすべての列名とテーブル名に必要です。なぜなら、 {{ double brackets }} の変数は文字列リテラルに評価されますが、これは有効な識別子ではないからです。
JinjaSQL フィルター を変数に適用して、いずれかの側で設定された任意の 結合ポリシーまたは列ポリシー を強制できます。Snowflakeはカスタムフィルターの
join_policyおよびcolumn_policyを実装します。これは、列がクリーンルームの結合ポリシーまたは列ポリシーのそれぞれに準拠しているかどうかを確認し、そうでない場合はクエリを失敗します。フィルターは{{ column_name | filter_name }}のように列名に適用されます。
これらの点については、後で詳しく説明します。
コンシューマーがこのテンプレートを実行するコードを以下に示します。列名がテンプレートで宣言されたテーブルエイリアスによって修飾される点に注目してください。
クリーンルーム UI でこのテンプレートを使用できるようにするため、プロバイダーは :ref:`テンプレート <dcr_provider_add_ui_form_customizations> 用のカスタム UI フォームを作成する ` 必要があります。その UI フォームには、テンプレート変数名に対応する名前付きのフォーム要素が含まれ、フォームで提供された値はテンプレートに渡されます。
カスタムテンプレートの開発¶
クリーンルームのテンプレートは JinjaSQL テンプレートです。テンプレートを作成するには、次のトピックに精通している必要があります。
consumer.get_jinja_sql プロシージャを使用して、テンプレートの有効性をテストしてから、レンダリングされたテンプレートを実行して、期待される結果が得られることを確認します。このプロシージャは、 join_policy などのクリーンルームフィルター拡張機能をサポートしていないため、これらのフィルターなしでテンプレートをテストし、後で追加する必要があります。
例:
レンダリングされたテンプレートは次のようになります。
環境内で上記の SQL ステートメントの実行を試み、ステートメントが機能し、期待される結果が得られるかどうかを確認します。
次に、WHERE 句なしでテンプレートをテストします。
レンダリングされたテンプレート:
ポリシーフィルターをテンプレートに追加し、テンプレートをクリーンルームに追加します。
データ保護¶
テンプレートはプロバイダーとコンシューマーがclean roomにリンクしたデータセットにのみアクセスできます。
プロバイダーもコンシューマーも、データに結合ポリシー、列ポリシー、アクティベーションポリシーを設定して、結合、投影、またはアクティベーションできる列を保護できます。ただし テンプレートには、ポリシーを適用する列に対して 適切な JinjaSQL ポリシーフィルター が含まれている 必要があります 。
カスタムテンプレートの構文¶
Snowflake Data Clean Roomsは、いくつか機能が拡張されたV3の JinjaSQL をサポートしています。
このセクションには以下のトピックが含まれます:
テンプレートの命名規則¶
テンプレートを作成する際、名前はすべて小文字、数字、スペース、またはアンダースコアでなければなりません。アクティベーションテンプレート(コンシューマーが実行するプロバイダーのアクティベーションを除く)は、activation_ で始まる名前でなければなりません。テンプレート名は、 provider.add_custom_sql_template または consumer.create_template_request を呼び出すときに割り当てられます。
有効な名前の例:
my_templateactivation_template_1
無効な名前の例:
my template- スペースは使用できませんMy_Template- 小文字のみ使用可
テンプレート変数¶
テンプレートの呼び出し元は、テンプレート変数に値を渡すことができます。JinjaSQL 構文を使用すると、 {{ double_brackets }} 内の任意の変数名に対する変数バインディングが可能になりますが、Snowflakeは以下に説明するように、変数名をいくつか予約しており、それらをオーバーライドすることはできません。
注意
Snowflake定義の変数でも、カスタム変数でも、すべての変数をユーザーが入力するため、注意して適切に操作する必要があります。Snowflake Data Clean Roomsテンプレートは必ず、単一の SELECT ステートメントに解決されますが、すべての変数が呼び出し元から渡されることを覚えておく必要があります。
Snowflake定義の変数¶
すべてのclean roomテンプレートは、Snowflakeによって定義される以下のグローバル変数にアクセスできますが、それらは呼び出し元から渡されます。
source_table:clean roomでプロバイダーがリンクしたテーブルとビューの、ゼロベースの文字列配列。テンプレートで使用します。テーブル名は次のように完全修飾されます:
my_db.my_sch.provider_customers例:
SELECT col1 FROM IDENTIFIER({{ source_table[0] }}) AS p;my_table:clean roomのコンシューマーテーブルとビューの、ゼロベースの文字列配列。テンプレートで使用使用します。テーブル名は次のように完全修飾されます:
my_db.my_sch.consumer_customers例:
SELECT col1 FROM IDENTIFIER({{ my_table[0] }}) AS c;privacy:ユーザーとテンプレートに関連するプライバシー関連の値のセット。利用可能な子フィールドのリストをご参照ください 。これらの値はユーザーに対して 明示的に設定する ことができますが、テンプレートでデフォルト値を設定することをお勧めします。
privacy.thresholdなどの、テンプレートの子フィールドに直接アクセスします。例:
threshold_valueを使用して集約句に最小グループサイズを適用するテンプレートのコード例を以下に示します。measure_column:dimensions:where_clause:レガシーのクリーンルームのグローバル変数。これらの使用は推奨されなくなりましたが、引き続き定義されており、一部のレガシーテンプレートとドキュメントでは表示されるので、名前の衝突を避けるため、これらの名前でテーブルや列をエイリアス化しないでください。
テンプレートで
measure_columnまたはdimensionsを使用している場合、列ポリシーは、これらの変数に渡されたすべての列に対してチェックされます。テンプレートで結合条件(例:
table1.column1 = table2.column2)を持つwhere_clauseを使用している場合、結合ポリシーがそこに指定された列すべてに対してチェックされます。それ以外の場合は、列ポリシーが、そこに指定された列すべてに対してチェックされます。
カスタム変数¶
テンプレート作成者は、呼び出し元が入力できるテンプレートに任意の変数を含めることができます。これらの変数には、Snowflake定義の変数やテーブルエイリアス名以外の、Jinjaに準拠した任意の名前を付けることができます。クリーンルーム UI でテンプレートの使用を可能にしたい場合は、クリーンルーム UI ユーザー用の UI フォームも提供する必要があります。API ユーザーの場合は、必須変数とオプション変数の適切なドキュメントを提供する必要があります。
カスタム変数は、以下に示すカスタム変数 max_income のように、テンプレートからアクセスできます。
ユーザーは2種類の方法で、変数をテンプレートに渡すことができます。
クリーンルーム UI で、 テンプレート開発者によって作成された UI フォームを介して値を選択または提供します。この UI フォームには、ユーザーがテンプレートの値を指定できるフォーム要素が含まれています。フォーム要素の名前は、変数の名前です。テンプレートは、単純にフォーム要素の名前を使用して値にアクセスします。provider.add_ui_form_customizations を使用して、UI フォームを作成します。
コードの場合は、 コンシューマーが consumer.run_analysis を呼び出し、引数配列のテーブル名、および名前と値のペアであるカスタム変数を、
analysis_arguments引数に渡します。
注釈
クリーンルームにアップロードされたカスタムPythonコードで、ユーザーが提供した値にアクセスする必要がある場合は、Python関数の引数を介してコードに 変数の値を明示的に渡す 必要があります。テンプレート変数は、 {{jinja variable binding syntax}} を使用してPythonコード内で直接アクセスすることはできません。
変数を正しく解決する¶
文字列値はテンプレートに渡されると、最終的なテンプレートで文字列リテラルに解決されます。バインドされた変数の処理が適切出ない場合、 SQL 解析エラーまたは論理エラーの原因になります:
SELECT {{ my_col }} FROM P;- これはSELECT 'my_col' from P;に解決され、文字列 "my_col" を返します。これは希望するものではないかもしれません。SELECT age FROM {{ my_table[0] }} AS P;- これはSELECT age FROM 'somedb.somesch.my_table' AS P;に解決されますが、テーブルはリテラル文字列ではなく識別子である必要があるため、解析エラーが発生します。SELECT age FROM IDENTIFIER({{ my_table[0] }}) AS P {{ where_clause }};- "WHERE age < 50" を渡し、SELECT age FROM mytable AS P 'WHERE age < 50';に評価します。リテラル文字列である WHERE 句により、解析エラーが起こります。
したがって、必要に応じて変数を解決する必要があります。次では、テンプレートで変数を適切に解決する方法を説明します:
- テーブル名と列名の解決
テーブル名や列名を指定する変数は、以下の2つの方法のどちらかを使用し、テンプレート内で識別子に変換する必要があります:
IDENTIFIER: 例:
SELECT IDENTIFIER({{ my_column }}) FROM P;sqlsafe: この JinjaSQL フィルターは識別子の文字列を SQL テキストに解決します。前項と同等のステートメントは
SELECT {{ my_column | sqlsafe }} FROM P;です
IDENTIFIER と
sqlsafeのどちらを使うかは、状況によって異なります。たとえば、c.{{ my_column | sqlsafe }}は、 IDENTIFIER を使用して簡単に書き換えることはできません。- 動的 SQL の解決
WHERE 句のように、リテラル SQL として使用する文字列変数がある場合は、
sqlsafeフィルターをテンプレートで使用してください。例:ユーザーが "age< 50 "を
where_clauseに渡した場合、このクエリはSELECT age FROM sometable AS C WHERE 'age < 50';に解決されますが、リテラル文字列の WHERE 条件により、無効な SQL になります。この場合は、sqlsafeフィルターを使用する必要があります:
必須のテーブルエイリアス¶
クエリの最上位では、Snowflakeがクエリで結合と列のポリシーを正しく検証できるよう、すべてのテーブルまたはサブクエリは p (プロバイダーテーブルの場合)または c (コンシューマーテーブルの場合)のいずれかとしてエイリアス化されている必要があります。結合ポリシーまたは列のポリシーに対して検証する必要がある列は、小文字の p または c テーブルエイリアスで修飾されている必要があります。(p または c を指定することで、それぞれプロバイダーポリシーまたはコンシューマーポリシーに対して列を検証するかどうかをバックエンドに指示します。)
クエリで複数のプロバイダーテーブルまたはコンシューマーテーブルを使用する場合は、最初のテーブルエイリアスの後は、数値の連番で1から始まるサフィックスを追加します。したがって、最初、2番目、3番目のプロバイダーテーブルは p 、 p1 、 p2 のように、最初、2番目、3番目のコンシューマーテーブルは c 、 c1 、 c2 のようになります。p または c インデックスは、空きのない連続である必要があります(つまり、エイリアスは p 、 p1 、 p2 と作成し、p 、 p2 、 p4 とはしない)
例
カスタムのクリーンルームテンプレートフィルター¶
Snowflake は、すべての 標準 Jinja フィルター と、ほとんどの標準 JinjaSQL フィルター、およびいくつかの拡張機能をサポートしています:
join_policy: 列がデータ所有者の結合ポリシーにある場合は成功し、それ以外の場合は失敗します。column_policy:列がデータ所有者の列ポリシーにある場合は成功し、それ以外の場合は失敗します。activation_policy:列がデータ所有者のアクティベーションポリシーにある場合は成功し、それ以外の場合は失敗します。join_and_column_policy:列がデータ所有者の結合または列ポリシーにある場合は成功し、それ以外の場合は失敗します。identifierJinjaSQL フィルターは、Snowflakeテンプレートでは サポートされていません 。
Tip
JinjaSQL ステートメントは左から右に評価されます。
{{ my_col | column_policy }}正しい{{ my_col | sqlsafe | column_policy }}正しい{{ column_policy | my_col }}正しくない{{ my_col | column_policy | sqlsafe }}正しくない:column_policyは、文字列としてmy_col値をチェックされ、エラーが起こります。
clean roomへのポリシーの適用¶
クリーンルームは、テンプレートで使用された列に対してクリーンルームポリシーを自動的にチェックしません。列に対してポリシーを強制する場合は、次のとおりです。
テンプレートのその列に適切な ポリシーフィルター を適用する必要があります。例:
テーブルを 小文字の pまたはcとしてエイリアス化する必要があります。必須のテーブルエイリアス をご参照ください。
ポリシーは、他のコラボレーターが所有する列に対してのみチェックされます。ポリシーが、自分の所有するデータに対してチェックされることはありません。
ポリシーをテストするときに、列名をあいまいにしないよう注意してください。2つのテーブルに同じ名前の列がある場合、その列に対してポリシーをテストするには、列名を修飾する必要があります。
カスタムなPythonコードの実行¶
clean roomにアップロードされたPythonコードを、テンプレートから実行することができます。テンプレートからPython関数を呼び出し、データ行から値を受け取ったり、クエリで使用する値や投影する値を返したりできます。
プロバイダー がカスタムPythonコードをクリーンルームにアップロードすると、テンプレートは構文
cleanroom.function_nameでPython関数を呼び出します。詳細はこちらをご参照ください。コンシューマー がカスタムPythonコードをクリーンルームにアップロードすると、テンプレートはそのままの
function_name値をconsumer.generate_python_request_template(プロバイダーコードのように`クリーンルーム`にスコープされていない)に渡して関数を呼び出します。詳細はこちらをご参照ください。
プロバイダーコードの例:
セキュリティに関する考慮事項¶
クリーンルームテンプレートは、現在のユーザーのIDでは実行されません。
ユーザーはclean room内のデータに直接アクセスするのではなく、すべてのアクセスがテンプレート結果を介して、ネイティブアプリケーションで行われます。
テンプレートで列が使用されるたびにポリシーフィルターを適用し、ポリシーとすべてのコラボレーターのポリシーが確実に尊重されるようにします。
可能な場合はユーザー提供の変数を IDENTIFIER() でラップし、SQL インジェクション攻撃に対してテンプレートを強化します。
アクティベーションテンプレート¶
テンプレートを使用すると、クエリ結果をclean room外のテーブルに保存することもできます。これを アクティベーション と呼びます。現在、カスタムテンプレートでサポートされているアクティベーションは、プロバイダーのアクティベーションと、コンシューマーのアクティベーション (それぞれプロバイダーまたはコンシューマーのSnowflakeアカウントに結果を保存します) のみです。アクティベーションの実装方法についてはこちらをご参照ください。
アクティベーションテンプレートは、以下の要件が追加された分析テンプレートです:
アクティベーションテンプレートは、 SQL スクリプトブロックに評価される JinjaSQL ステートメントで、単純な SELECT ステートメントになる分析テンプレートとは異なります。
アクティベーションテンプレートは、クリーンルームにテーブルを作成して結果を保存し、テーブル名(または名前の断片)をテンプレート呼び出し元に返します。
スクリプトブロックの最後には RETURN ステートメントを記述します。これは、生成されたテーブルの名前をから
cleanroom.やcleanroom.activation_data_のプレフィックスを除いた名前を返します。テンプレートの名前、テンプレートが作成する内部テーブルの名前、テンプレートが返すテーブル名は、以下のパターンに従います。
アクティベーションタイプ |
テンプレート名のプレフィックス |
テーブル名のプレフィックス |
返されるテーブル名 |
|---|---|---|---|
コンシューマー実行コンシューマー |
|
|
プレフィックスなしのテーブル名 |
コンシューマー実行プロバイダー |
プレフィックスは不要 |
|
プレフィックスなしのテーブル名 |
プロバイダー実行プロバイダー |
|
|
|
アクティベートされる列は、データをリンクしたプロバイダーまたはコンシューマーの アクティベーションポリシー にリストされ、かつ
activation_policyフィルターが適用されている必要があります。列はアクティベーション列の場合もあれば、結合列の場合もあります。テンプレートをクリーンルーム UI から実行する場合、
activation_template_nameとenabled_activationsを含む ウェブフォームを提供 する必要があります。UI で使用するテンプレートには、分析テンプレートと関連するアクティベーションテンプレートの両方が必要です。テーブルが生成されるため、すべての計算列は推測される名前ではなく、明示的にエイリアスされなければなりません。つまり:
SELECT COUNT(*), p.status from T AS P;FAILS (COUNT 列名が推測されるため失敗)。SELECT COUNT(*) AS COUNT_OF_ITEMS, p.status from T AS P;SUCCEEDS (COUNT 列を明示的にエイリアス化するため成功)
以下に、基本的なアクティベーションテンプレートの例を2つ示します。1つはプロバイダーが実行するサーバーのアクティベーションで使用し、もう1つはその他のアクティベーションタイプで使用します。両者の違いは、結果テーブルの名前を含む強調表示された2行です。
テーブル名が cleanroom.temp_result_data である必要があります。
テーブル名にはプレフィックス cleanroom.activation_data が必要です。
次のステップ¶
テンプレートシステムの説明は以上です。以下では、clean roomの実装についてテンプレートタイプ別に説明します:
プロバイダーテンプレート は、プロバイダーが作成するテンプレートです。これがデフォルトのユースケースです。
コンシューマーテンプレート はコンシューマーが記述したテンプレートです。場合によっては、クリーンルーム作成者は、コンシューマーがクリーンルームに独自のテンプレートを作成、アップロード、実行できるようにしたいと考えています。
アクティベーションテンプレート 実行に成功すると結果テーブルが作成されます。アクティベーションテンプレートに応じて、結果テーブルはclean room外のプロバイダーまたはコンシューマーのアカウントに保存されることも、アクティベーションハブにリストされたサードパーティのアクティベーションプロバイダーに送信されることもあります。
連鎖テンプレート 複数のテンプレートを連鎖させて、各テンプレートの出力を次のテンプレートで使用することができます。