alopex-sql 0.8.8

SQL parser components for the Alopex DB dialect
Documentation

alopex-sql

alopex-sql は Alopex の SQL 解析・計画・実行レイヤーを提供します。

Quick Start

use std::sync::{Arc, RwLock};

use alopex_core::kv::memory::MemoryKV;
use alopex_sql::catalog::MemoryCatalog;
use alopex_sql::dialect::AlopexDialect;
use alopex_sql::executor::{ExecutionResult, Executor};
use alopex_sql::parser::Parser;
use alopex_sql::planner::Planner;

let sql = r#"
    CREATE TABLE sales (region TEXT, amount INT);
    INSERT INTO sales (region, amount) VALUES ('us', 10), ('us', 20), ('eu', 7);
    SELECT region, SUM(amount) FROM sales GROUP BY region;
"#;

let dialect = AlopexDialect;
let statements = Parser::parse_sql(&dialect, sql).unwrap();

let catalog = Arc::new(RwLock::new(MemoryCatalog::new()));
let store = Arc::new(MemoryKV::new());
let mut executor = Executor::new(store, catalog.clone());

for stmt in statements {
    let plan = {
        let guard = catalog.read().unwrap();
        Planner::new(&*guard).plan(&stmt).unwrap()
    };
    let _ = executor.execute(plan).unwrap();
}

GROUP BY / HAVING

SELECT category, COUNT(*) FROM products GROUP BY category;
SELECT category, COUNT(*) FROM products GROUP BY category HAVING COUNT(*) > 10;
SELECT category, COUNT(*) FROM products GROUP BY category ORDER BY COUNT(*) DESC;

Pagination (LIMIT / OFFSET / FETCH)

SELECT id FROM t ORDER BY id LIMIT 10 OFFSET 20;
SELECT id FROM t ORDER BY id OFFSET 2 ROWS FETCH NEXT 2 ROWS ONLY;
SELECT id, score FROM t ORDER BY score FETCH FIRST 2 ROWS WITH TIES;

WITH TIES は境界行と ORDER BY キーが等しい peer 行を追加で返す(ORDER BY 必須、 PostgreSQL 準拠)。count は定数式を plan 時に畳み込み、LIMIT NULL / LIMIT ALL は無制限、負値はエラー。詳細は docs/sql-fetch-pagination.md

DISTINCT ON

SELECT DISTINCT ON (region) region, amount FROM sales ORDER BY region, amount;

キー群ごとに先頭 1 行を返す(PostgreSQL 準拠の ORDER BY prefix 制約、42P10 相当 は ALOPEX-T014)。ORDER BY で決まらない同順位は全入力列の schema 順比較で 決定的に解決するため、結果は物理挿入順に依存しない。詳細は docs/sql-distinct-on.md

GROUPING SETS / ROLLUP / CUBE

SELECT region, product, SUM(amount), GROUPING(region, product)
FROM sales GROUP BY CUBE(region, product);
SELECT region, COUNT(*) FROM sales GROUP BY GROUPING SETS ((region), ());

単一パスのハッシュ集約で複数 grouping set を同時評価する(PostgreSQL 準拠)。 subtotal 行の placeholder NULL と実データ NULL はどちらも SQL NULL で出力され、 区別は GROUPING/GROUPING_ID(BIGINT ビットマスク、左端引数が最上位ビット) のみで行う。通常キーとの混在はクロス積、重複 set は重複行を出力。展開後 set 数 は 4096、union キー数は 63 が上限。詳細は docs/sql-grouping-sets.md

LATERAL / table functions / relation alias column lists

SELECT p.id, top.val
FROM parent AS p
CROSS JOIN LATERAL (SELECT c.val FROM child AS c
                    WHERE c.parent_id = p.id ORDER BY c.val DESC LIMIT 1) AS top;
SELECT p.id, u.unnest FROM parent AS p, UNNEST(p.emb) AS u;
SELECT r.a, r.b FROM child AS r(a, b, c);

LATERAL 派生表は左側の FROM item を参照でき、左行ごとに再評価される (CROSS JOIN LATERAL / [INNER] JOIN LATERAL ... ON / LEFT [OUTER] JOIN LATERAL ... ONRIGHT/FULLALOPEX-T015)。 LATERAL を書かない派生表は従来どおり外側 FROM を参照できない。FROM 句の table function は UNNEST(VECTOR) のみで、LATERAL なしでも左側を参照する (implicit lateral)。GENERATE_SERIES は issue #157 用の予約枠。 AS t(c1, ..., cn) は base table / CTE 参照 / 派生表 / table function すべてで 使え、列数完全一致(ALOPEX-T012)を要求する。LATERAL は文脈キーワードなの で lateral という名前の関係は引き続き使える。詳細は docs/sql-lateral-table-functions.md

Supported Aggregate Functions

  • COUNT(*)
  • COUNT(column)
  • COUNT(DISTINCT column)
  • SUM(column) (numeric)
  • TOTAL(column) (numeric, returns 0.0 for all-NULL)
  • AVG(column) (numeric)
  • MIN(column) / MAX(column) (comparable types)
  • GROUP_CONCAT(column) / GROUP_CONCAT(column, separator)
  • STRING_AGG(column, separator)
  • PERCENTILE_DISC(fraction) WITHIN GROUP (ORDER BY expr) (ordered-set)

Aggregate FILTER / ordered aggregates / WITHIN GROUP

SELECT g, COUNT(*) FILTER (WHERE v > 10) FROM t GROUP BY g;
SELECT STRING_AGG(name, ',' ORDER BY v DESC, name ASC) FROM t;
SELECT PERCENTILE_DISC(0.5) WITHIN GROUP (ORDER BY v) FROM t;

FILTER は述語が TRUE の行だけを(DISTINCT より前に)集約へ渡す。集約内 ORDER BY は順序鋭敏な GROUP_CONCAT/STRING_AGG の連結順を決め、順序不感な 集約では検証後に破棄される。PERCENTILE_DISC は PostgreSQL 準拠の離散選択 (空グループは NULL、NULL ソート値は除外)。OVER との併用は明示エラー。詳細は docs/sql-aggregate-filter-within-group.md

Recursive CTE

直接自己再帰する単一 CTE を UNION または UNION ALL で実行できます。列名リストを省略した場合は、anchor term の出力名が公開スキーマになります。

WITH RECURSIVE counter(n) AS (
    SELECT 1
    UNION ALL
    SELECT n + 1 FROM counter WHERE n < 5
)
SELECT n FROM counter ORDER BY n;

実行は delta working table による固定点反復です。既定上限は 1,000 iterations、100,000 accumulated rows で、保持する working/result/accumulated/dedup key は query memory policy の対象です。

Recursive CTE Limitations

  • 相互再帰、複数の直接自己参照、recursive term 内の subquery・nested WITH・set operation は fail-closed で拒否します。
  • 再帰 CTE のリモート分散 read は未対応です。
  • 各 inner operator の独自 buffer は同じ memory policy を検査しますが、現在の policy API は retained recursive sets と transient buffer の合算 high-water tracker を共有しません。

Error Scenarios

Code Contract
ALOPEX-E001 Transaction conflict during execution.
ALOPEX-E002 A write was attempted through a read-only transaction.
ALOPEX-E003 実行時の resource exhaustion。再帰 CTE の iteration/row/memory limit と既存の aggregate/memory limit が対象。
ALOPEX-E004 CAST conversion failure。source/target type と bounded reason を公開し、内部 AST/MessagePack 名は公開しない。
  • ColumnNotFound: 存在しないカラムを GROUP BY で参照した場合。
  • TypeMismatch: SUM/AVG に非数値型、GROUP_CONCAT に非 TEXT を指定した場合。
  • InvalidExpression: HAVINGSELECT で GROUP BY に含まれない非集約列を参照した場合。
  • ResourceExhausted: resource limit を超えた場合。公開 SQL error code は ALOPEX-E003
  • CastFailed: CAST の変換不能。TRY_CAST はこの失敗だけを NULL に変換し、source expression の失敗は保持する。公開 SQL error code は ALOPEX-E004