目次
リファレンス

構文リファレンス

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 で変わることはありません。

仕様 Named intermediate Results

パラメーター

形 @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;

仕様 Source-free SELECT

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(要素の型が混在、[] に注釈がない)。

仕様 ARRAY constructors

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(その一覧がない。一覧の読み取り元が複数ある接続を裸で指定した)。

仕様 File listing Sources

2. Pipe演算子

Pipe構文はGoogleSQLのものです。最初の FROM の後ろ(または完全な SELECT の後ろ)のステップは、すべて |> で始め、直前のステップのレコードを入力にします。最初の表は、GoogleSQLのPipe演算子のうちActQLが受け付けるものを、GoogleSQLと同じ意味で載せます。2つ目の表は、ActQLが足した演算子です。

GoogleSQLの演算子

演算子すること
|> WHERE condcond が 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 patternGraph入力に対するグラフのパターン(§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 totaltotal を足す。すでにある名前はエラー。範囲の別名はそのまま有効。
|> AS t列は変えない。ここから先、列は t.col と修飾する。以前の別名は使えなくなる。

SET は、置き換えた値を新しい値のスロットに束縛します。古い値から確定した INFER のキーが付け替えられることはありません。SELECT は、列を選ぶことと範囲スコープを終えることの両方を行うステップです。

仕様 Scope and lowering

3. 名前付き呼び出しの引数

名前付き呼び出しは |> name(key: value, …) と書きます。キーは演算ごとに閉じていて、大文字小文字を区別しません。予約語のキーはバッククォートで囲みます。各値の役割は、値の書き方ではなく、演算のシグネチャで決まります。

役割例意味
ProducerRefwith: spans、start: {from: seeds, …}WITH の名前。裸かバッククォート付き。文字列でproducerを指定することはできない。
FieldRefid: seeds.element、field: delta、by: [cohort, region]宣言されたオペランド(現在のレコード、または with: のproducer)の列。
OutputNameinto: 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つ付けられます。パラメーターや計算式に符号は付けられません。未知のキー、重複するキー、役割の違う値は、何かが動く前に拒否されます。

仕様 Named logical SGA calls

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(ゼロ、負、許容される上限を超える)。

仕様 Composition assertions

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 で証明する。
KEEPKEEP (*)。見えている入力の列がすべて順序どおりに残り、その後ろに name が付く。
MAX ITEMStaskと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候補側のキーとベクトルの明示。
METRICcosine、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 のスコアは距離の符号を反転したものなので、「最も良い」は常にスコアが最大のものです。

既定値

省略したもの意味
キーとベクトルの組各側の唯一のベクトル列と、唯一の証明できる文字列キーを使う。あいまいならエラー。
METRICcosine。
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)レコード → Vectorsid はFieldRef(メンバーのキー)、vector はFieldRef。
vectors()Vectors → レコードなし。レコード(id、vector)に戻す橋渡し。
normalize_vectors()Vectors → Vectorsなし。長さ1のベクトルにする。
score_vectors(query: value, metric: 'cosine' | 'dot' | 'l2')Vectors → Vectorsquery は、集合と同じ次元のNULLを含まない数値配列(値かパラメーター)。各メンバーに score を足す。スコアをレコードにするには vectors() を続ける。
pool_vectors(by: [col, …], method: 'sum' | 'mean' | 'max' [, vector: col] [, output_id: name])Vectors → Vectorsby は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 gGraphの値。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 → Eventsgap は期間の文字列('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)

各部

部分受け付けるもの
FORMATCSV または 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_replaceActQLの正規表現プロファイル(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.operationConnectorが宣言する操作(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_pickjson から、宣言したパスで型付きの値を取り出す。オブジェクトに対する型付きのアクセス 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、storeEffectの各形式が変換される先の、閉じた集合。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