構文リファレンス
ActQLのプログラムに書けるすべての形。GoogleSQLのPipe演算子、ActQLが足した演算子、名前付き呼び出し、INFER、NEAREST、SERIALIZE、Effect。
プログラムは、Pipe構文を使ったGoogleSQLです。このページは、そのテキストに書けるすべての形を1か所に集めたものです。プログラムの構成、Pipe演算子(GoogleSQLのものと、ActQLが足したもの)、ベクトル・グラフ・イベントの名前付き呼び出し、INFER、NEAREST、SERIALIZE、そしてEffectを載せます。普通のSQL(SELECT、JOIN、スカラー関数)はSQL互換性と型と関数にあります。各環境で現時点にどの形が動くかは実装状況にあります。
各項目には、形([ ] は省略可、… は繰り返し、キーワードは大文字)、各部、意味、既定値、check を通る最小の例、check が報告するエラー、それを定義する仕様の節を載せます。例はクイックスタートのプロジェクトの接続を前提にし、パラメーターは明示します。それぞれの例はビルド時にフィクスチャに対して検査されます。
1. プログラムの構成
プログラムのテキスト
形
[WITH name AS (…), …] SELECT … [|> step …] [|> EFFECT …]
[WITH name AS (…), …] FROM source [JOIN …] |> step … [|> EFFECT …]
CREATE [OR REPLACE] TABLE conn.table AS (query)各部
| 部分 | 受け付けるもの |
|---|---|
WITH | 途中の値への名前付け(後述)。 |
SELECT … | 普通のGoogleSQLのクエリ。後ろにPipeのステップを続けられる。 |
FROM source [JOIN …] | Pipeクエリ。最初の FROM にJOINを含め、それ以降はすべて |> のステップ。 |
EFFECT … | データを変えるEffectは多くても1つで、常に最後のステップ。; の後ろにCommandの後置を続けられる(Effect)。 |
意味
1つのテキストは1つのクエリで、任意でデータを変えるEffect1つで終わり、その後ろに名前付きResultに対するCommandの後置を任意の数だけ続けられます(Effectを参照)。末尾の ; は許されます。; はクエリと後置を区切るもので、文をつないだりテキストをスクリプトにしたりはしません。順序のあるステップが必要なワークフローは、テキストが変換されるProgramモデルにJSONやYAMLで複数のStageとして書きます。FROM で始まるクエリには、裸の WHERE、ORDER BY、LIMIT はありません。最初の |> より後ろでは、すべての演算がステップです。Pipeは論理的な合成にすぎず、Stage、Checkpoint、実行の境界を作りません。
例
FROM support.cases AS c
|> WHERE c.status = 'open'
|> AGGREGATE COUNT(*) AS open_cases GROUP BY c.account_id
|> ORDER BY open_cases DESC
|> LIMIT 10;エラー query_syntax_invalid(2つ目の文、最後でないEffect、FROM の後ろの裸の句)。
仕様 SQL and explicit Pipe boundaries
WITH
形
WITH name AS ( query | GRAPH (…) | time_series(…) | calendar_series(…) | mean_graphs(…) ), …各部
| 部分 | 受け付けるもの |
|---|---|
name | 識別子。後ろのステップから、読み取り元として、または with: 引数として参照する。 |
| 本体 | SQLまたはPipeのクエリ、GRAPH 構築子、生成子の呼び出し。本体の中にさらに WITH を書ける。 |
意味
束縛は、値(テーブル、Graph、Vectors、Events)に名前を付け、後ろのステップから参照できるようにします。名前を付けても、読み取りも公開もしません。宣言そのものは読み取りを行わず、その名前がResultに現れることはありません。実行時には、意味を保ったまま、Hostが参照の間で1つの観測を共有したり計算を最適化したりできます。本体は副作用を持ちません。INFER、RESULT、EFFECT は本体の中では受け付けません。
例
WITH open_cases AS (FROM support.cases |> WHERE status = 'open')
SELECT account_id, COUNT(*) AS n FROM open_cases GROUP BY account_id;エラー query_syntax_invalid(本体の中の INFER、RESULT、EFFECT)、query_invalid(名前の二重定義、解決できない名前)。
仕様 WITH producers and pure Graph construction
WITH と AS と RESULT
| 形 | すること | 読む | 公開する |
|---|---|---|---|
WITH name AS (…) | 後ろから参照するために値に名前を付ける。 | しない | しない |
|> AS name | 現在のレコードに別名を付け直し、以降のステップで列を name.col と修飾できるようにする。 | しない | しない |
|> RESULT name | 現在のレコードを名前付きのResult name として公開し、続ける。 | しない | する |
読み取りだけのプログラムは、RESULT を宣言しなければ最終的なレコードをResult main として公開します。Effectで終わるプログラムは、RESULT を宣言しない限りResultを公開しません。RESULT は文の直下でだけ受け付けられ、WITH、派生テーブル、集合演算のオペランドの中には書けません。Resultは宣言した時点で確定し、後ろの SELECT や LIMIT で変わることはありません。
パラメーター
形 @name
意味
パラメーターは、プログラムが型付きで宣言し、実行時に渡します(--params、parameters)。パラメーターは値です。テキストに補間されることはなく、演算を選ぶことも、リソースを指定することもありません。式が書ける場所ならどこでも、また LIMIT/OFFSET と作者のガードに使えます。
例
SELECT id, name FROM crm.accounts WHERE owner = @owner;エラー parameter_undeclared、parameter_unused、supplied_value_type_mismatch。
仕様 Parameters
UNNEST
形
FROM UNNEST(array_expr) [AS] element [WITH OFFSET [AS] position]
… JOIN UNNEST(array_expr) [AS] element [ON cond]
… CROSS JOIN UNNEST(array_expr) [AS] element意味
配列を、要素ごとに1レコードへ展開します。element は要素の値全体の名前です。要素がオブジェクトなら、そのフィールドも element.field として見えます。配列には、パラメーター(UNNEST(@items))、ARRAY[…] 構築子、現在のレコードの列(相関展開)を使えます。NULL と空の配列はレコードを作りません。
例
SELECT element.id, position
FROM UNNEST(@items) AS element WITH OFFSET AS position;エラー query_expression_invalid(配列でない)、query_invalid(別名の重複)。
仕様 Declared UNNEST value tables
FROM のない SELECT
形 SELECT expr [AS name], …(FROM なし)
意味
式とパラメーターだけから作る、論理的な1レコードです。WHERE が偽ならレコードはありません。ほかのクエリと同じように、集合演算、WITH の本体、JOIN に使えます。
例
SELECT @account_id AS id, 'high' AS level;ARRAY 構築子
形
[expr, …] -- 裸の形。型は要素から推定
ARRAY[expr, …] -- 同じものを明示した形
ARRAY<T>[] -- 空の配列には要素の型が要るT は BOOL、BOOLEAN、STRING、FLOAT64、DOUBLE、TIMESTAMP、JSON のいずれかです。
意味
有限の配列です。要素は1つの型を共有する必要があり、空の配列には明示的な ARRAY<T> の注釈が要ります(ARRAY<STRING>[])。配列は、IN UNNEST、UNNEST の読み取り元、そして値として使えます。
例
SELECT id FROM crm.accounts WHERE tier IN UNNEST(['gold', 'platinum']);エラー expression_type_mismatch(要素の型が混在、[] に注釈がない)。
LIST_FILES
形 FROM LIST_FILES(connection.listing | connection [, paths => [string, …] | glob => string]) [AS alias]
各部
| 部分 | 受け付けるもの |
|---|---|
connection.listing | 接続のファイル一覧の読み取り元(gcs.objects、s3.objects、drive.files、local.files)。 |
connection | その短縮形。接続がファイル一覧の読み取り元をちょうど1つだけ公開しているときに限って受け付ける。複数あれば名前を書く。 |
paths => […] | パスの明示的な一覧。 |
glob => '…' | 1つのglobパターン。 |
意味
一覧が公開するファイルを、resource、version、path、media_type、size と、Connectorが持つそのほかのメタデータの列を持つレコードとして読み取る読み取り元です。paths と glob は排他です。選択子を書かないことが一覧全体を意味するわけではありません。Connectorが無条件の一覧を許可し、プログラムの件数の上限の中に収められる必要があります。上限で途中までになった一覧は不完全として報告され、全体として扱われることはありません。一覧に対する LIMIT は少ないファイルを求める指定であって、それを全部とみなす許可ではありません。一覧は内容を読みません。ファイルの内容は別の読み取り元 connection.contents(resource、version、取り込んだバイト列のメディアタイプを持つ content_ref の content)にあり、resource と version でJOINします。プログラムは読むバージョンを正確に指定することになります。
例
FROM LIST_FILES(gcs.objects, glob => r'reports/*.csv') AS f
|> JOIN gcs.contents AS c ON f.resource = c.resource AND f.version = c.version
|> SELECT f.path, f.media_type, c.content;エラー query_syntax_invalid(両方の選択子)、source_selector_unregistered(その一覧がない。一覧の読み取り元が複数ある接続を裸で指定した)。
2. Pipe演算子
Pipe構文はGoogleSQLのものです。最初の FROM の後ろ(または完全な SELECT の後ろ)のステップは、すべて |> で始め、直前のステップのレコードを入力にします。最初の表は、GoogleSQLのPipe演算子のうちActQLが受け付けるものを、GoogleSQLと同じ意味で載せます。2つ目の表は、ActQLが足した演算子です。
GoogleSQLの演算子
| 演算子 | すること |
|---|---|
|> WHERE cond | cond が TRUE のレコードを残す。 |
|> SELECT [DISTINCT] expr [AS name], … | 列を置き換える。入力の範囲スコープはここで終わる。*、* EXCEPT (…)、* REPLACE (…)、alias.*。 |
|> EXTEND expr AS name, … | 既存の列を残したまま列を足す。 |
|> SET name = expr, … | 既存の列の値を置き換える。 |
|> DROP name, … | 列を取り除く。 |
|> RENAME name AS new, … | 列名を変える。 |
|> AS alias | 現在のレコードに alias という別名を付け直す。 |
|> AGGREGATE agg [AS name], … [GROUP [AND ORDER] BY key [AS name] [ASC|DESC], …] | グループ化して集計する。GROUP BY がなければ1レコード。 |
|> DISTINCT | 重複するレコードを取り除く。 |
|> [INNER|LEFT|RIGHT|FULL] JOIN source ON cond | USING (col, …) [MAX_OUTPUT_ROWS n] | 等価キーで別のRelationと結合する。MAX_OUTPUT_ROWS はActQLのガード(§4)。 |
|> CROSS JOIN source [MAX_OUTPUT_ROWS n]、|> CROSS JOIN UNNEST(…) AS e | 交差結合。配列の展開。 |
|> ORDER BY expr [ASC|DESC] [NULLS FIRST|LAST], … | レコードを並べ替える。 |
|> LIMIT n [OFFSET m] | 先頭のレコードを残す。n、m は整数リテラルかパラメーター。 |
|> PIVOT(agg(expr) FOR col IN ('a', 'b', …)) | 文字列のバケットを列に回転する。集計は1つ、バケットはリテラル。 |
|> UNPIVOT [INCLUDE|EXCLUDE NULLS] ((col, …) FOR name IN (…)) | 列をレコードに回転する。 |
|> UNION ALL | UNION DISTINCT | INTERSECT DISTINCT | EXCEPT DISTINCT [BY NAME [ON (…)] | [STRICT] CORRESPONDING] (query) | 集合演算。BY NAME/CORRESPONDING がなければ位置による対応。 |
この表にないGoogleSQLの演算子(CALL、独立したステップとしての WINDOW、TABLESAMPLE)は0.1では受け付けず、check が名前付きの理由で拒否します。SELECT や EXTEND の中の WINDOW 句は受け付けます。
ActQLが足した演算子
| 演算子 | すること |
|---|---|
|> ASSERT UNIQUE BY (col, …) | キーが一意でなければRunを失敗させる(§4)。 |
|> RESULT name | レコードを名前付きのResultとして公開し、続ける(§1)。 |
|> INFER … | レコードごとにLLMに問い合わせる(§5)。 |
|> NEAREST … | レコードごとに近傍のベクトルを探す(§5)。 |
|> SERIALIZE FORMAT … | レコードをコンテンツにする(§8)。 |
|> name(key: value, …) | ベクトル、グラフ、イベントに対する名前付き呼び出し(§3)。 |
|> MATCH pattern | Graph入力に対するグラフのパターン(§6)。 |
|> EFFECT … | 書き込み。常に最後(§9)。 |
|> CREATE [OR REPLACE] TABLE conn.table | テーブル全体の書き込み。常に最後(§9)。 |
句の引数は、その演算子の中に収まります。AGGREGATE の GROUP BY、JOIN の ON、INFER の INPUT、LIMIT の OFFSET、SERIALIZE の OPTIONS が、独立した |> を取ることはありません。
仕様 SQL and explicit Pipe boundaries、 Scope and lowering
SET、EXTEND、AS
| ステップ | 列 | スコープ |
|---|---|---|
|> SET total = amount * 1.1 | すでにある total を上書きする。型は変わってもよい。ほかの列には触れない。 | 範囲の別名はそのまま有効。 |
|> EXTEND amount * 1.1 AS total | total を足す。すでにある名前はエラー。 | 範囲の別名はそのまま有効。 |
|> AS t | 列は変えない。 | ここから先、列は t.col と修飾する。以前の別名は使えなくなる。 |
SET は、置き換えた値を新しい値のスロットに束縛します。古い値から確定した INFER のキーが付け替えられることはありません。SELECT は、列を選ぶことと範囲スコープを終えることの両方を行うステップです。
3. 名前付き呼び出しの引数
名前付き呼び出しは |> name(key: value, …) と書きます。キーは演算ごとに閉じていて、大文字小文字を区別しません。予約語のキーはバッククォートで囲みます。各値の役割は、値の書き方ではなく、演算のシグネチャで決まります。
| 役割 | 例 | 意味 |
|---|---|---|
| ProducerRef | with: spans、start: {from: seeds, …} | WITH の名前。裸かバッククォート付き。文字列でproducerを指定することはできない。 |
| FieldRef | id: seeds.element、field: delta、by: [cohort, region] | 宣言されたオペランド(現在のレコード、または with: のproducer)の列。 |
| OutputName | into: month、output: previous、bindings: {source: src} | 新しい列の名前。既存の列は参照しない。 |
| 式 | where: e.kind = 1、expr: COALESCE(r.amount, 0) | 普通のクエリの式。シグネチャが許す位置でだけ。 |
| 列挙値・リテラル | direction: 'out'、kind: 'weak'、start: 'A'、k: 3 | データ。正確な文字列、数値、TRUE、FALSE、NULL。 |
| レコード・リスト | pattern: [{as: first, where: …}]、support: {nodes: 0.5} | 閉じた構造。各要素は、その位置が与える役割を保つ。 |
| パラメーター | max_output_rows: @cap | パラメーターを受け付ける位置での、パラメーター全体。 |
つまり interval_join(with: spans, …) は WITH のproducer spans と結合しますが、with: 'spans' は文字列なので拒否されます。数値リテラルには先頭に + か - を1つ付けられます。パラメーターや計算式に符号は付けられません。未知のキー、重複するキー、役割の違う値は、何かが動く前に拒否されます。
4. ガードとアサーション
どちらもActQL独自の形です。GoogleSQLにはJOINに対するガードがありません。ASSERT UNIQUE BY はActQLの assert_rows 演算のための書き方で、GoogleSQLの一部の実装にある |> ASSERT condition 演算子とは別のものです。その演算子は受け付ける形には含まれません。
MAX_OUTPUT_ROWS
形 … JOIN source ON cond MAX_OUTPUT_ROWS n
意味
1つのJOINに対する作者のガードです。JOINの出力が n レコードを超えるなら、上限の名前とともにRunが失敗します。切り詰めることはありません。n は正の整数リテラルかパラメーターです。WITH の中のJOINを含め、各 JOIN が自分のガードを持ちます。
例
FROM salesforce.accounts AS a
JOIN snowflake.usage_30d AS u ON a.id = u.account_id MAX_OUTPUT_ROWS 100000
|> SELECT a.id, u.active_users;エラー operation_parameter_invalid(ゼロ、負、許容される上限を超える)。
ASSERT UNIQUE BY
形 |> ASSERT UNIQUE BY (col, …)
意味
列挙した列が、現在のレコード全体で存在し、NULLでなく、一意であることを証明し、すべてのレコードをそのままの順序で通します。重複があればRunが失敗します。重複を取り除くことはありません。読み取り元でキーが証明されていないとき、後ろの INFER や EFFECT … ID が頼れるのがこの証明です。
例
FROM sheets.leads
|> ASSERT UNIQUE BY (email)
|> SELECT email, company;エラー query_invalid(空のキーの一覧、解決できない列)。実行時には、最初の重複キーを示すアサーションの失敗。
仕様 Composition assertions、
assert_rows
5. LLMとベクトル
INFER は各レコードをmodel taskに送ります。ベクトルの形は、すでにあるベクトルに対して働きます。score_vectors はVectorsの集合に1つのクエリベクトルに対するスコアを付け、NEAREST はレコードごとのクエリに対して候補の上位K件を返します。テキストから埋め込みを作るのは別のmodel taskで、どちらの形も暗黙には行いません。
INFER
形
|> INFER `model-task:<name>.v<n>`
[ITEM KEY (col, …)]
INPUT (col | expr AS field | field = expr, …)
[KEEP (col [AS name] | * | alias.*, …)]
AS name
[MAX ITEMS n]
[ON FAILURE FAIL]各部
| 部分 | 受け付けるもの |
|---|---|
`model-task:…` | 登録されたmodel taskの名前(LLMとINFER)。 |
ITEM KEY (…) | レコードを識別する列。 |
INPUT (…) | taskの入力フィールドと過不足なく対応するもの。col はその名前の列を送り、expr AS field と field = expr は同じ対応付けの2つの書き方で、同じフィールドを2回書けば拒否される。taskがメディアタイプの合うコンテンツのフィールドを宣言していれば、content_ref の列も渡せる。それ以外は送らない。 |
KEEP (…) | 入力の列のうち、レコードに残すもの。 |
AS name | 答えの名前。 |
MAX ITEMS n | 送る異なるキーの数に対する作者のガード。 |
ON FAILURE FAIL | 公開の規則。有限回の再試行のあとに1件でも非成功のレコードが残れば、ステップの結果を成功として公開しない。 |
意味
各レコードの INPUT をtaskのLLMに送り、オブジェクトの列 name を1つ足します。name.outcome(ok または failed:<reason>)、name.value(ok のときはtaskの型付きの出力、それ以外は NULL)、name.input_key を持ちます。LLMが答えられなかったレコードもほかと一緒に返ってくるので、name.value を読む前に name.outcome で絞り込んでください。入力の列はレコードに残り、そのままJOINや絞り込みに使えます。
既定値
| 省略したもの | 意味 |
|---|---|
ITEM KEY | ここまでのレコードで証明できる、唯一のNULLでない候補キーをレコードのキーにする。キーのある読み取り元を FROM で読んだ場合と、そのキーが一意のまま残ると証明できるJOINの後がこれにあたる。それ以外のJOINや集計の後には、たいてい候補がない。その場合はキーを指定し、check が証明できなければ ASSERT UNIQUE BY で証明する。 |
KEEP | KEEP (*)。見えている入力の列がすべて順序どおりに残り、その後ろに name が付く。 |
MAX ITEMS | taskとHostの上限が適用される。 |
ON FAILURE | すべてのレコードを返す。失敗はレコードごと。FAIL を付けると、部分的な結果が後ろのステップやEffectに渡ることはない。すでに行った呼び出しは、その費用とともに証跡として残る。 |
例
FROM salesforce.accounts AS a
JOIN snowflake.usage_30d AS u ON a.id = u.account_id
|> INFER `model-task:churn-risk.v1`
INPUT (notes = a.description, active_users = u.active_users, trend = u.trend) AS risk
|> WHERE risk.outcome = 'ok' AND risk.value.level = 'high';エラー query_invalid(未知のtask、入力フィールドの不足や余分、証明できるキーがない、KEEP の名前の重複、AS の名前との衝突)、expression_type_mismatch(入力の型)、operation_parameter_invalid(MAX ITEMS)。
仕様 INFER KEEP source projection、
infer
NEAREST
形
|> NEAREST candidates [AS c]
[USING expr | QUERY KEY (col, …) VECTOR expr]
[CANDIDATE KEY (col, …) VECTOR expr]
[METRIC cosine | dot | l2]
K n
[KEEP (col [AS name] | * | alias.*, …)]
AS hit各部
| 部分 | 受け付けるもの |
|---|---|
candidates | 候補のレコードまたはVectorsを持つ、読み取り元か WITH の名前。 |
AS c | 候補側の別名。既定は名前の最後の要素。 |
USING expr | 問い合わせのベクトル。現在のレコードに対する式。 |
QUERY KEY (…) VECTOR expr | 問い合わせ側のキーとベクトルの明示(USING の代わり)。 |
CANDIDATE KEY (…) VECTOR expr | 候補側のキーとベクトルの明示。 |
METRIC | cosine、dot、l2。 |
K n | 問い合わせのレコードごとの一致数。正の整数リテラル。 |
KEEP (…) | 残す列。両側に対して解決する。 |
AS hit | 一致オブジェクトの名前。 |
意味
現在の各レコードについて、指標のもとでスコアが最も良い K 件の候補を見つけ、一致ごとに1レコードを出します。検索は指標のもとで厳密です。ActQLが近似インデックスに置き換えることはありません。hit には hit.score、hit.rank、hit.query_key、hit.candidate_key と、候補に body 列があれば hit.body が入ります。候補のほかの列は KEEP (c.col) で取り出します。一致のないレコードはレコードを出しません。l2 のスコアは距離の符号を反転したものなので、「最も良い」は常にスコアが最大のものです。
既定値
| 省略したもの | 意味 |
|---|---|
| キーとベクトルの組 | 各側の唯一のベクトル列と、唯一の証明できる文字列キーを使う。あいまいならエラー。 |
METRIC | cosine。 |
KEEP | 問い合わせ側の列が順序どおりに残り、その後ろに hit が付く。これは KEEP (*) とは違う。KEEP (*) は問い合わせ側の列に続けて候補側の列も展開し、名前の重複を拒否する。 |
例
SELECT c.id, c.description AS question, c.embedding AS query_vec
FROM salesforce.cases AS c
WHERE c.priority = 'urgent'
|> NEAREST kb.articles USING query_vec K 3 AS hit
|> AGGREGATE ARRAY_AGG(hit.body ORDER BY hit.rank) AS refs GROUP BY id, question;エラー query_syntax_invalid(VECTOR のない KEY、USING と QUERY の併用)、query_invalid(ベクトル列やキーがない、またはあいまい、KEEP の名前の重複)、operation_parameter_invalid(K)。
仕様 NEAREST KEEP source projection、
nearest
ベクトルの呼び出し
| 呼び出し | 入力 → 出力 | 引数 |
|---|---|---|
to_vectors(id: col, vector: col) | レコード → Vectors | id はFieldRef(メンバーのキー)、vector はFieldRef。 |
vectors() | Vectors → レコード | なし。レコード(id、vector)に戻す橋渡し。 |
normalize_vectors() | Vectors → Vectors | なし。長さ1のベクトルにする。 |
score_vectors(query: value, metric: 'cosine' | 'dot' | 'l2') | Vectors → Vectors | query は、集合と同じ次元のNULLを含まない数値配列(値かパラメーター)。各メンバーに score を足す。スコアをレコードにするには vectors() を続ける。 |
pool_vectors(by: [col, …], method: 'sum' | 'mean' | 'max' [, vector: col] [, output_id: name]) | Vectors → Vectors | by はFieldRef。output_id はOutputNameで、グループ化のフィールドが1つのときだけ。 |
例
WITH v AS (FROM kb.articles |> to_vectors(id: id, vector: embedding) |> normalize_vectors())
FROM v
|> score_vectors(query: @query_vec, metric: 'cosine')
|> vectors()
|> ORDER BY score DESC |> LIMIT 5;エラー query_invalid(Carrierの不一致。vectors() なしでVectorsに ORDER BY などRelationのステップを適用)、operation_parameter_invalid(query の次元が違う、またはNULLを含む)。
仕様 Vector-set-preserving operations and bridges、
pool_vectors
ベクトル関数
| 関数 | 結果 |
|---|---|
vector_score(a, b, 'cosine' | 'dot' | 'l2') | レコード内のスコア。'l2' は距離の符号を反転した値を返すので、どの指標でも大きいほど近い。第3引数は文字列リテラルでなければならない。 |
vector_concat(a, b, …) | 2つ以上のベクトルの連結。次元は違っていてよく、結果の次元はその和。 |
VECTOR_COSINE_SIMILARITY(a, b) | vector_score(a, b, 'cosine') と同じ。 |
VECTOR_INNER_PRODUCT(a, b) | vector_score(a, b, 'dot') と同じ。 |
VECTOR_L2_DISTANCE(a, b) | 正の距離。-vector_score(a, b, 'l2')。 |
VECTOR_CONCAT(a, b, …) | vector_concat と同じ。 |
vector_score とその別名は、同じ次元の2つのベクトルを要求します。NULL はどの関数でも伝播します。
仕様 Row-local vector expressions、 Decoding and expression rules
6. グラフ
GRAPH 構築子
形
WITH g AS (GRAPH (
NODE TABLES (rows [AS N] KEY (col, …) [LABEL Name | DEFAULT LABEL] [PROPERTIES (col [AS name], …) | PROPERTIES ARE ALL COLUMNS [EXCEPT (…)] | NO PROPERTIES], …)
[EDGE TABLES (rows [AS E] KEY (col, …)
SOURCE KEY (col, …) REFERENCES N [(col, …)]
DESTINATION KEY (col, …) REFERENCES N [(col, …)]
[LABEL Name] [PROPERTIES (…)], …)]
))意味
RelationからGraphの値を作ります。各ノードテーブルは KEY をキーとするノードを、各エッジテーブルは両端が REFERENCES でノード定義を参照するエッジを提供します。ラベルとプロパティは定義に属します。Graphはプログラムの中にだけ存在し、カタログのオブジェクトは作られません。これはGoogleSQL/SQL-PGQのテーブル対応であって、ISO GQLの CREATE GRAPH ではありません。
例
WITH accounts AS (FROM crm.accounts |> SELECT id, name),
refs AS (FROM crm.referrals |> SELECT id, from_id, to_id),
g AS (GRAPH (
NODE TABLES (accounts AS Account KEY (id) LABEL Account PROPERTIES (name))
EDGE TABLES (refs AS Referred KEY (id)
SOURCE KEY (from_id) REFERENCES Account
DESTINATION KEY (to_id) REFERENCES Account
LABEL Referred NO PROPERTIES)
))
FROM g |> MATCH (a:Account)-[:Referred]->(b:Account) |> SELECT a.name, b.name AS referred;エラー graph_operation_invalid(REFERENCES の定義が未知、ラベルの重複、キーの型の不一致)。
仕様 WITH producers and pure Graph construction、
graph
MATCH
形
FROM [GRAPH] g
|> MATCH [p =] [WALK | TRAIL | ACYCLIC] node (edge node)…
node ::= ( [var] [:Label] [{prop: expr, …} | WHERE cond] )
edge ::= -[ [var] [:Label] [{…} | WHERE cond] ]-> | <-[ … ]- | -[ … ]- | -> | <- | -
[ {n} | {m,n} ]各部
| 部分 | 受け付けるもの |
|---|---|
GRAPH g | Graphの値。GRAPH の印は省略でき、付ければ型の期待を加える。 |
p = | パスの変数。 |
WALK、TRAIL、ACYCLIC | パスのモード。再訪を許す、エッジを再利用しない、ノードを再訪しない。 |
var | ノードまたはエッジの変数。後ろのステップで使える。 |
:Label | 定義のそのラベルへの所属(プロパティの比較ではない)。 |
{prop: expr} / WHERE cond | その要素に対する制約。 |
->、<-、- | 出る向き、入る向き、どちらでも。角括弧付きの形には変数、ラベル、制約を書ける。 |
{n}、{m,n} | 有限のホップ数。 |
意味
一致ごとに1レコードを出し、パターンの変数を束縛します。Graphの読み取り元1つにつき MATCH は1つです。2つ目のパターンには、別の読み取り元と普通のJOINが要ります。MATCH の後ろの SELECT はパターンのスコープを終え、その列だけを出します。これはGoogleSQLの要素パターンのプロファイルであって、GQL全体ではありません。
既定値 パスのモードは WALK。
例
FROM g
|> MATCH ACYCLIC (a:Account WHERE a.tier = 'gold')-[:Referred]->{1,3}(b:Account)
|> SELECT a.name AS source, b.name AS reached;エラー query_syntax_invalid(上限のない量指定子、2つ目の MATCH)、graph_operation_invalid(未知のラベル、すべての候補にないプロパティ)、query_invalid(Graphに対するレコードの別名)。
仕様 Graph pattern source、 Graph operations
グラフの呼び出し
断りがなければ、どれも現在の入力としてGraphを取ります。列挙値の引数は文字列で、direction は 'out'、'in'、'both' のいずれかです。
| 呼び出し | 引数 | 出力 |
|---|---|---|
reach(start: 'id' | {from: p, id: col}, direction, max_depth [, edge_types: [...]] [, max_output_rows]) | start は、開始点が1つならIDリテラル('acc_1')、WITH のRelationの各レコードから始めるなら選択子 {from: p, id: col}。あるクエリの結果を次のステップの開始集合にするのはこの形。 | レコード start_id、node_id、depth |
traverse(start, direction, min_hops, max_hops, emit: 'nodes' | 'paths' [, path_mode: 'walk' | 'trail' | 'acyclic'] [, edge_types] [, max_output_rows]) | reach と同じ。 | nodes:start_id、node_id、depth。paths:start_id、end_id、hop_count、node_ids、edge_ids |
shortest_path(source: 'id' | {from, id}, target: 'id' | {from, id}, direction, max_hops [, weight: col] [, max_output_rows]) | レコード source_id、target_id、total_cost、hop_count、node_ids、edge_ids | |
components(kind: 'weak' | 'strong' [, max_output_rows]) | レコード node_id、component_id、component_size | |
degree(direction) | レコード node_id、degree | |
graph_bounds(max_nodes, max_edges, max_degree) | 任意の組み合わせ。数値かパラメーター。 | レコード kind、node_id、actual、max。違反ごとに1つ |
match_nodes(ids: ['…', …] | where: cond [, label: '…' | definition: '…'], fields: [col, …]) | レコード:列挙したフィールド | |
match_edges([where: cond] [, label | definition], fields: [col, …]) | レコード:列挙したフィールド | |
normalize_graph() | Graph | |
subgraph(nodes: ['…', …] | {from: p, id: col} | where: cond [, edges: cond]) | nodes は reach の start と同じ選択子。edges は条件が真の辺だけを残す。 | Graph |
graft_graph(with: p) | p はGraphのproducer。 | Graph |
union_graphs(with: [p, …]) | Graph | |
subtract_graphs(with: p) | Graph | |
graphs_equal(with: p) | 1レコード equal | |
graph_diff(with: p) | 差分のレコード | |
apply_graph_delta(with: changes, field: delta) | changes は差分のproducer、field はその差分の列。 | Graph |
mean_graphs(with: [p, …], weights: [n, …], support: {nodes: x, edges: x}, properties: {nodes: {…}, edges: {…}}) | 生成子。現在の入力に対してではなく、WITH の本体として使う。 | Graph |
node_rows([definition: 'N' | label: 'L'])、edge_rows(…) | 選択子は多くても1つ。 | レコード:要素のキー、ラベル、プロパティ |
例
WITH seeds AS (FROM crm.accounts |> WHERE tier = 'gold' |> SELECT id)
FROM g
|> reach(start: {from: seeds, id: id}, direction: 'out', max_depth: 2)
|> SELECT start_id, node_id, depth;FROM g
|> shortest_path(source: 'acc_1', target: 'acc_9', direction: 'out', max_hops: 5)
|> SELECT total_cost, hop_count, node_ids;WITH stats AS (FROM g |> degree(direction: 'out'))
FROM stats |> WHERE degree > 10 |> SELECT node_id, degree |> RESULT hubs;エラー graph_operation_invalid(必須のキーがない、Carrierの不一致、producerや列を期待する位置に文字列)、operation_parameter_invalid。
仕様 Named logical SGA calls、 Graph operations
7. イベントと時間
イベントの呼び出し
to_events はレコードをEvents Carrierにし、events() はそれを戻します。その間の呼び出しは、与えられたCarrierを保ちます。時刻の引数(time、left_time、right_time、start、end)は timestamp の列か、エポックからのミリ秒の整数列です。列そのものはそのまま保たれます。occurred_ms を自分で作らず、occurred_at をそのまま渡してください。
| 呼び出し | 入力 → 出力 | 引数 |
|---|---|---|
to_events(id: col, time: col) | レコード → Events | 識別子と時刻(timestamp かミリ秒)のFieldRef。 |
events() | Events → レコード | なし。 |
session(by: [col, …], gap: '…') | Events → Events | gap は期間の文字列('30m')。 |
window_events(kind: 'fixed' | 'sliding', size [, step] [, offset]) | Events → Events | 大きさはミリ秒か期間の文字列。sliding には step が要る。 |
dedupe_events(by: [col, …], order_by: [{field: col, dir: 'asc' | 'desc' [, nulls: 'first' | 'last']}, …]) | Events → Events | その順序でキーごとに最初のイベントを残す。by が空なら全体。order_by は必ず書く。{col: 'asc'} は同じ並び順の短縮形で、NULLの順序は共通の規則に従う。 |
watermark_events(watermark_ms: n | @param, policy: 'mark' | 'drop') | Events → Events | 数値リテラルか、パラメーター全体。値はRunごとに固定され、再開や再試行をしても遅延扱いになるイベントは変わらない。 |
sequence([by: [col, …],] id: col, time: col, pattern: [{as: name, where: cond}, …], within: n [, overlap: 'allow' | 'disallow'] [, contiguity: 'adjacent' | 'subsequence'] [, max_matches_per_key] [, max_output_rows]) | レコードまたはEvents → レコード | 一致ごとに1レコード。パターンのステップごとに列 <name>_id。既定値は by: [](全体を1つのパーティションとする)、overlap: 'disallow'、contiguity: 'adjacent'(並べたパーティションの隣り合う要素を照合する。'subsequence' なら間の要素を飛ばして一致できる)。within は必ず書く。 |
row_window(time: col, kind: 'fixed' | 'sliding', size [, step] [, offset]) | レコード → レコード | window_start、window_end を足す。 |
window_group(by: [col, …], aggregates: {name: {fn: '…' [, expr] [, filter] [, distinct]}, …}) | レコード → レコード | row_window の後ろで。expr と filter は式。 |
lag(partition_by: [col, …], order_by: [{col: 'asc'}], field: col, output: name [, offset: n]) | レコード → レコード | リレーショナルなナビゲーション。 |
watermark_rows(time: col, late_policy: 'mark' | 'drop', watermark_ms: n | max_skew: n) | レコード → レコード | 2つのしきい値のどちらか1つだけ。 |
asof_join(with: p, kind, by: [col, …], left_time: col, right_time: col, direction, tolerance, select: {name: left.col | right.col, …} [, left_id] [, right_tie_break]) | レコードまたはEvents ⨝ レコード → レコード | with は WITH のproducer。 |
interval_join(with: p, kind: 'inner' | 'left', mode: 'point_in_interval' | …, on: [col, …], left: {time: col}, right: {start: col, end: col} [, select: {…}] [, max_output_rows]) | レコード ⨝ レコード → レコード | |
merge_rankings(with: p | [p, …], by: [col, …], candidate: col, k: n, score_policy: {rrf: {rank_constant, weights, rank_window}} | {max: …} | {weighted_sum: …} [, score] [, rank] [, score_contract] [, tie_break]) | レコード → レコード | 現在のレコードと相手側の順位の融合。score、rank を足す。 |
生成子
| 呼び出し | 引数 | 出力 |
|---|---|---|
time_series(start: ts, end: ts, step: n) | リテラルのtimestampかパラメーター全体。正のstep。 | レコード time |
calendar_series(start: ts, end: ts, unit: 'day' | 'week' | 'month' | …, timezone: '…' [, week_start: '…']) | week_start は week のとき必須で、それ以外では不可。 | レコード start、end |
生成子は入力を読まないので、WITH の本体(またはPipeの先頭)であって、|> のステップにはなりません。
calendar_bucket
形 |> calendar_bucket(time: col, into: name, unit: '…', timezone: '…' [, week_start: '…'])
意味 指定したタイムゾーンで time を含む暦のバケットを、列 name として足します。
例
WITH records AS (FROM app.events |> SELECT id, account_id, occurred_at, kind)
FROM records AS e
|> sequence(by: [e.account_id], id: e.id, time: e.occurred_at,
pattern: [{as: first, where: e.kind = 1}, {as: second, where: e.kind = 2}],
within: 20, max_output_rows: 100)
|> SELECT first_id, second_id;WITH ticks AS (FROM market.ticks |> SELECT id, at),
spans AS (FROM market.spans |> SELECT id, begin, finish)
FROM ticks AS t
|> interval_join(with: spans, kind: 'left', mode: 'point_in_interval',
on: [], left: {time: t.at}, right: {start: spans.begin, end: spans.finish},
select: {id: left.id, value: right.id}, max_output_rows: 1000)
|> SELECT id, value;WITH days AS (calendar_series(start: '2026-01-01T00:00:00.000Z',
end: '2026-03-01T00:00:00.000Z',
unit: 'day', timezone: 'Asia/Tokyo'))
FROM days AS d
|> calendar_bucket(time: d.start, into: month, unit: 'month', timezone: 'Asia/Tokyo')
|> AGGREGATE COUNT(*) AS days GROUP BY month;エラー query_invalid(Carrierの不一致、必須のキーがない)、operation_parameter_invalid(負の大きさ、week 以外の単位での week_start、リテラルが必要な位置のパラメーター)。
仕様 Event operations、
Relational temporal operations、
sequence、as-of join、
interval join、merge_rankings、
Calendar profile、
Named finite event sequences
8. シリアライズとその他のActQL関数
SERIALIZE
形
|> SERIALIZE FORMAT CSV | JSONL
ORDER BY col [ASC | DESC], … | PRESERVE ORDER
OPTIONS (name = '…', header = TRUE | FALSE, null_marker = '' | r'\N',
field_delimiter = '…', encoding = '…', line_ending = 'LF' | 'CRLF',
max_rows = n, max_bytes = n)各部
| 部分 | 受け付けるもの |
|---|---|
FORMAT | CSV または JSONL。 |
| 順序 | 明示的な ORDER BY、または入力の順序がすでに証明されているときの PRESERVE ORDER。 |
OPTIONS | 静的なリテラル。max_rows と max_bytes はパラメーターも受け付ける。CSV には header と null_marker が必須。 |
意味
現在のレコードを1つのコンテンツにエンコードします。出力はちょうど name、content(content_ref)、media_type、size_bytes、row_count を持つ1レコードで、入力の列は残りません。これはコンテンツを作る明示的な境界です。何もアップロードはしません。コンテンツをどこかへ書くのは、後ろの EFFECT STORE です。
例
FROM support.cases
|> WHERE status = 'open'
|> SELECT id, subject, opened_at
|> SERIALIZE FORMAT CSV ORDER BY opened_at
OPTIONS (name = 'open-cases.csv', header = TRUE, null_marker = '')
|> EFFECT STORE s3.objects SET (key = 'exports/' || name, content = content);エラー query_syntax_invalid(順序の句や OPTIONS がない)、operation_parameter_invalid(未知または重複するオプション、リテラルでない値、CSVでの header/null_marker の欠落)。
仕様 Content serialization、
serialize
GoogleSQLと意味が違う関数、ActQL独自の関数
| 関数 | 結果 |
|---|---|
CONCAT(a, b, …)、a || b | 文字列の連結。NULL は伝播する(GoogleSQLの規則)。 |
ACTQL.CONCAT(a, b, …) | NULL の引数を飛ばす連結。 |
SAFE_DIVIDE、SAFE_ADD、SAFE_SUBTRACT、SAFE_MULTIPLY、SAFE_NEGATE | ゼロ除算やオーバーフローのとき、失敗する代わりに NULL。 |
to_number、to_boolean、to_timestamp、to_string、to_decimal | 不正な入力で失敗する変換。CAST と同じ。 |
try_number、try_timestamp、try_decimal | 同じ変換で、不正な入力では NULL を返す。 |
quantize(d, scale) | decimalの唯一の丸め。 |
decimal_divide(a, b, scale) | スケールを指定した正確なdecimalの除算。 |
utf8_truncate(s, bytes) | 文字の途中で切らずに、バイト数の予算で文字列を切り詰める。 |
nfkc(s)、case_fold(s) | Unicodeの正規化と大文字小文字の畳み込み。それ以外では値は書いたまま保持される。 |
regex_match、regex_extract、regex_replace | ActQLの正規表現プロファイル(Text, time and regular expressions)。 |
vector_score、vector_concat | ベクトル関数を参照。 |
型と NULL の規則を含む関数の完全な一覧は、型と関数にあります。
仕様 Decoding and expression rules、 Common expression contract
9. Effect
プログラムが外部システムを変える手段は、Effectだけです。テキストの中でEffectを置ける場所は2つあります。Pipeの終端にはデータを変えるEffect(UPDATE、INSERT、UPSERT、DELETE、STORE、CREATE TABLE)を多くても1つ。そして、終端の ; の後ろには、クエリの名前付きResultをそれぞれ読むCommandの後置をいくつでも(この節の最後にある長い形式)。Pipeの中の2つ目のデータを変えるEffectや、WITH の中のEffectは拒否されます。1つのテキストで宣言したEffectは1つのStageに属し、1つのEffect Setになります。まとめて検査され、1つのCheckpointで承認されます。順序を守る必要のある処理(書き込んでから、その内容を通知する)は、文をつなぐのではなく、ProgramモデルのStageとして表現します。Effectの値は、現在のレコードに対する純粋な式です。列、リテラル、それらに対する関数が書けます。値は何かを送る前に評価され、評価された値がPreviewに固定され、承認の対象になります。すべてのEffectは、何かを送る前にポリシーを通り、ポリシーが求めるときはCheckpointを通ります。承認はEffect Set全体に対して行われ、Effectが1つならそのEffectが対象です(Effectと承認)。
対象とMapping。 conn.resource は、接続と、そのConnectorが公開するリソースの1つを指定します(actql catalog show conn)。書き込みのMapping、つまり設定できるフィールド、その型、キーは、Connectorがそのリソースについて公開している書き込みスキーマからHostが解決します。作者がMappingを指定することはありません。複数のMappingやCommand契約を公開しているリソースは、この節の最後にある長い形式で指定します。
EFFECT UPDATE
形 |> EFFECT UPDATE conn.resource ID key SET (field = value, …)
各部
| 部分 | 受け付けるもの |
|---|---|
conn.resource | 対象のリソース。 |
ID key | レコードの識別子を持つ、現在のレコードの列。 |
SET (…) | 1つ以上の対象フィールド。値はそれぞれレコードに対する式。 |
意味
レコードごとに1件を、キーで更新します。Previewにはすべての対象とフィールドの変更が並びます。書き込みのあと、各項目は applied、failed、unknown のいずれか(あとで書き込みを確認するConnectorでは accepted)になり、キーで突き合わせられます。
例
FROM salesforce.accounts AS a
|> WHERE a.id = @account_id
|> EFFECT UPDATE salesforce.Account ID id SET (Churn_Risk__c = 'high');エラー query_invalid(未知のリソース、書き込みスキーマにないフィールド、フィールドの重複、キーの列がない)、expression_type_mismatch。
EFFECT INSERT
形 |> EFFECT INSERT conn.resource (col, …) [VALUES (value, …)]
意味
レコードごとに1件を作成します。VALUES がなければ、各レコードの列挙した列が同じ名前のフィールドに書かれます。VALUES があれば、列挙した各列が対応する式の値を受け取ります。
例
FROM webshop.signups
|> WHERE created_at > @since
|> EFFECT INSERT hubspot.contacts (email, company) VALUES (email, company_name);EFFECT UPSERT
形 |> EFFECT UPSERT conn.resource ID key SET (field = value, …)
意味
そのキーのレコードを更新し、なければ作成します。Previewと結果は UPDATE と同じです。applied の項目には、どちらだったかの内訳(action: created または action: updated)が付きます。
EFFECT DELETE
形 |> EFFECT DELETE conn.resource ID key
意味 レコードごとに1件を、キーで削除します。Previewには対象が並びます。
EFFECT STORE
形 |> EFFECT STORE conn.resource [SET (field = value, …)]
意味
コンテンツまたはレコードを保存します。オブジェクトやファイルのリソース(s3.objects、gcs.objects、drive.files)に向けると、各レコードの content(SERIALIZE が作った、または contents の読み取り元から読んだ content_ref)を1つのオブジェクトとして書きます。SET のフィールドは保存先が受け取る入力で、それぞれレコードに対する式です。オブジェクトの置き場所(key、name、folder など)、content そのもの、既存のオブジェクトを置き換えてよいか(overwrite)を渡します。これらはEffectの設定ではなく、Effectのデータです。content のないレコードは拒否されます。Relationがコンテンツになるのは SERIALIZE を通したときだけです。Connectorが宣言するテーブルのリソース(local.<table>、tableau.datasources)に向けると、レコードそのものを、そのリソースが宣言する形で保存します。Previewには、保存先、コンテンツそのもの(コンテンツの識別子)または件数、そして上書きの条件が固定されます。リソースごとに受け取るフィールドは各Connectorのページにあります。
例
FROM support.cases
|> WHERE status = 'open'
|> SELECT id, subject, opened_at
|> SERIALIZE FORMAT CSV ORDER BY opened_at
OPTIONS (name = 'open-cases.csv', header = TRUE, null_marker = '')
|> EFFECT STORE s3.objects SET (key = 'exports/' || name, content = content);エラー query_invalid(オブジェクトのリソースに対して content の列がない、不明なフィールド)、expression_type_mismatch(content が content_ref でない)。
EFFECT COMMAND
形 |> EFFECT COMMAND conn.operation [TARGET expr] ID key [INPUT (field = value, …)]
各部
| 部分 | 受け付けるもの |
|---|---|
conn.operation | Connectorが宣言する操作(gmail.send、tableau.refresh)。バージョン付きのCommand契約1つに解決される。 |
TARGET expr | 契約が必要とする場合の、操作の対象となるリソース(ワークブック、スレッド、フォルダなど)。レコードごとに指定する。接続のメールボックスのように契約側で決まっている場合は省く。 |
ID key | レコードのキー。Preview、status、復旧で各操作を識別する。宛先や対象ではない。 |
INPUT (…) | 契約の入力フィールド。レコードに対する式。 |
意味
名前付きの操作をレコードごとに1回実行します。メッセージの送信、抽出の更新、ジョブの開始などです。契約が、入力の型、対象の種類、必要な権限、Previewに出る内容、結果の確認方法を決めます。check はそのすべてを検査します。項目ごとの結果は accepted(システムが要求を受け付けた)、applied(結果を確認した)、failed、unknown のいずれかです。不明な結果はConnector自身の証拠で確認し、再送はしません。複数のCommand契約を公開しているリソースは、この節の最後にある長い形式で指定します。
例
FROM support.replies AS r
|> WHERE r.status = 'ready'
|> EFFECT COMMAND gmail.send
ID r.id
INPUT (to = r.recipient, subject = r.subject, body = r.body);エラー query_invalid(不明な操作、入力フィールドの不足や余り、TARGET が必須なのに無い、または受け付けないのに有る)、expression_type_mismatch(入力や対象の型)。
CREATE TABLE
形
CREATE [OR REPLACE] TABLE conn.table AS (query)
… |> [EFFECT [name]] CREATE [OR REPLACE] TABLE conn.table意味
レコードをテーブル全体として書き込みます。CREATE はテーブルが存在しないことを要求し、CREATE OR REPLACE は同じスキーマでテーブル全体を置き換えます。作成時の競合は、OR REPLACE でも競合のままです。これはstoreのEffectで、storeと同じようにPreviewと承認を通ります。
例
FROM snowflake.usage_30d
|> WHERE active_users > 0
|> CREATE OR REPLACE TABLE duckdb.active_usage;仕様 Table create and whole-table replace
SQL文の形
形
UPDATE conn.resource SET field = value, … WHERE cond;
INSERT INTO conn.resource (col, …) VALUES (value, …) | SELECT …;
DELETE FROM conn.resource WHERE cond;意味
EFFECT UPDATE、EFFECT INSERT、EFFECT DELETE と同じEffectです。WHERE がキーの列との等価なら、キーで書き込みます。それ以外の WHERE では、Previewの時点で対象を選びます。Hostが一致するレコードを読んで、その識別子とバージョンを固定し、Previewにはちょうどそれらが並び、承認はそれらだけに及びます。適用時に WHERE を評価し直すことはないので、そのときに一致するようになったレコードが加わることはありません。適用時には各対象の条件(バージョンか現在の値)を確認し、変わっていたレコードは failed(conflict)で終わります。対象の集合とその条件をこの形で固定できないConnectorは、この形式を check で拒否します。キーによる書き込みが突き合わせはいちばん簡単ですが、WHERE で選んだ書き込みも、Connectorに操作ID、冪等性キー、監査記録があれば突き合わせられます。
例
UPDATE salesforce.Account
SET Churn_Risk__c = 'high'
WHERE Id = @account_id;長い形式
リソースが複数のMappingやCommand契約を公開しているときは、どれを使うかを指定します。
|> EFFECT mark UPDATE
TARGET 'connector://salesforce/Account'
MAPPING `mapping:salesforce.account-risk.v1`
ID id SET (Churn_Risk__c = risk.value.level);FROM support.escalations |> SELECT channel, message |> RESULT escalations;
EFFECT notify COMMAND
FROM RESULT escalations AS e
TARGET e.channel
CONTRACT `command:slack.post.v1`
INPUT (text = e.message);TARGET はリソースのURI、MAPPING または CONTRACT は公開された契約、省略可能なEffectの名前(mark、notify)はRunの状態や台帳がそのEffectを指すときの名前です。COMMAND の長い形式は ; で終わるクエリの後ろに置き、そのクエリの RESULT の1つを参照します。短い形式は、Effectの名前、Mapping、ResultをHostに任せた長い形式です。
エラー query_invalid(未知のMappingや契約、保持されていないResult、Pipeの中の2つ目のデータを変えるEffect)。
仕様 Terminal updates、 COMMAND postludes、 Effect declarations
10. 予定している構文
RESULT(name) — 同じプログラムの中で先に公開したResultへの参照で、読み取り元として使えます(FROM RESULT(updates))。1つのプログラムがレコードを公開し、公開したちょうどその内容から続けられるようにするものです。0.1より後の予定です。
BRANCH — それぞれが自分のResultを公開するステップのまとまりを、1つのプログラムの下で動かす本体です。共通の前段を繰り返さずに、1つのテキストから複数のResultへ分岐できるようにするものです。0.1より後の予定です。
11. クエリ構文のないプログラム演算
JSON/YAMLのプログラム文書には、SQLやPipeでは直接書けない演算があります。存在しないキーワードを探すことのないよう、ここに挙げます。|> name(…) とは書きません。
| 演算 | すること | SQL / Pipeで意味が一致する書き方と、その条件 |
|---|---|---|
top_k、top_k_by | スコアで上位 k 件のレコード。グループごとで、同点の規則が決まっている。 | 1グループで順序が全順序なら ORDER BY … LIMIT n。グループごとなら ROW_NUMBER() OVER (PARTITION BY … ORDER BY …) と QUALIFY。同点はこの演算の規則で決まるので、SQLで書くならそれを明示する。 |
json_pick | json から、宣言したパスで型付きの値を取り出す。 | オブジェクトに対する型付きのアクセス obj.field。json のパス構文はまだない。 |
nest | 子レコードを、オブジェクトの配列として親の下にまとめる。 | AGGREGATE ARRAY_AGG(…) GROUP BY …。 |
dedupe_rows | キーごとに1レコードを、決まった順序で選んで残す。 | 順序を明示した ROW_NUMBER() OVER (PARTITION BY key ORDER BY …) = 1 と QUALIFY。DISTINCT ではない。DISTINCT はレコード全体を比べ、異なるものをすべて残す。キーがすでに一意のはずなら ASSERT UNIQUE BY。 |
search_candidates | 外部の検索サービスに順位付きの候補を求める(NEAREST と違い、取得にあたる)。 | なし。 |
text_rank | 問い合わせ文字列に対するレコードの字句による順位付け。 | なし。 |
Effectの種類 create、update、upsert、delete、command、store | Effectの各形式が変換される先の、閉じた集合。 | EFFECT INSERT、UPDATE、UPSERT、DELETE、COMMAND、STORE / CREATE TABLE。 |
仕様 top_k、nest、
Reshaping and nested data、
search_candidates、
text_rank、
Effect declarations
Source: actql/actql/docs/reference/syntax.md at d904416674e4 · Edit on GitHub