Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# AGENTS.md

このリポジトリで作業するエージェント向けの最小ガイドです。

## 目的
- 最終目標: SQL Formatter の実装
- 現状: SQL パーサーの実装とテストの整備

## 主要ファイル
- `spec/apache-calcite-Parser.js`: lexer + parser 本体
- `spec/apache-calcite-Parser-test.js`: 回帰/異常系テスト
- `spec/apache-calcite-Parser.md`: 仕様(EBNFベース)
- `index-parser.html`: SQL → AST 出力の簡易デモ

## 作業の基本方針
- `.md` と `.js` の production 名は一致させる
- 変更後は `node spec/apache-calcite-Parser-test.js` を実行
- 破壊的変更は `TODO.md` に記録

## 進捗の記録
- 直近のタスクは `TODO.md` を参照

## 実行コマンド
```bash
node spec/apache-calcite-Parser-test.js
```
142 changes: 142 additions & 0 deletions AST.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
# AST 仕様(暫定)

このドキュメントは、`spec/apache-calcite-Parser.js` が出力する AST の最小仕様をまとめたものです。
現状は実装の読みやすさ優先の軽量ノード構成です。

## 共通ルール
- すべてのノードは `type` フィールドを持つ
- 省略可能要素は `null` または未設定
- リストは配列で表現

## ルート
- `SqlStmtList`
- `statements`: ステートメント配列
- `SqlStmtEof`
- `stmt`
- `SqlExpressionEof`
- `expr`

## クエリ
- `SqlSelect`
- `hints`: `TableHints | null`
- `stream`: `boolean`
- `setQuantifier`: `"ALL" | "DISTINCT" | null`
- `selectItems`: `AddSelectItem[]`
- `from`: `FromClause | null`
- `where`: `Where | null`
- `groupBy`: `GroupBy | null`
- `having`: `Having | null`
- `window`: `Window | null`
- `qualify`: `Qualify | null`
- `QueryOrExpr`
- `withList`, `leaf`, `setOps`
- `OrderedQueryOrExpr`
- `query`, `orderByLimitOpt`

## 句
- `FromClause`
- `first`: `TableRef`
- `joins`: (`JoinTable` | `CommaJoin` | `ApplyJoin`)[]
- `JoinTable`
- `natural`: `boolean`
- `joinType`: `string` (e.g. `"JOIN"`, `"LEFT JOIN"`)
- `table`: `TableRef`
- `condition`: `On | Using | null`
- `CommaJoin`
- `table`
- `Where`
- `expr`
- `GroupBy`
- `set`: `"DISTINCT" | "ALL" | null`
- `list`: `GroupingElementList`
- `Having`
- `expr`
- `Window`
- `items`: `AddWindowSpec[]`
- `Qualify`
- `expr`
- `OrderBy`
- `list`: `OrderItemList`
- `LimitClause`
- `value`, `offset`
- `OffsetClause`
- `value`, `rows`
- `FetchClause`
- `mode`, `value`, `rows`

## テーブル参照
- `TableRef`
- `base`, `pivot`, `unpivot`, `matchRecognize`, `alias`, `columns`, `tablesample`
- `TableName`
- `name`: `CompoundTableIdentifier`
- `Subquery`
- `query`: `OrderedQueryOrExpr`
- `Unnest`
- `items`: `Expression[]`
- `withOrdinality`: `boolean`
- `TableFunctionCall`
- `call`: `NamedRoutineCall`
- `Pivot`
- `aggs`: `AddPivotAgg[]`
- `axis`: `SimpleIdentifierOrList`
- `values`: `AddPivotValue[]`
- `Unpivot`
- `nulls`: `"INCLUDE" | "EXCLUDE" | null`
- `columns`: `SimpleIdentifierOrList`
- `axis`: `SimpleIdentifierOrList`
- `values`: `AddUnpivotValue[]`
- `MatchRecognize`
- `partitionBy`, `orderBy`, `measures`, `rowsPerMatch`, `afterMatchSkip`
- `pattern`, `anchorStart`, `anchorEnd`, `within`, `subsets`, `define`

## 式
- `Expression2b`(内部表現)
- `prefixes`, `base`, `extensions`
- `BinaryExpression`
- `operator`, `left`, `right`
- `Literal`
- `value`
- `StringLiteral`
- `value`
- `NumericLiteral`
- `value`
- `Identifier`
- `name`
- `CompoundIdentifier`
- `parts`

## 関数
- `NamedFunctionCall`
- `name`, `args`, `orderBy`, `withinGroup`, `nullTreatment`, `filter`, `over`
- `BuiltinFunctionCall`
- `kind` ごとにフィールドが異なる(各関数ノード参照)
- `MatchRecognizeFunctionCall`

## DML/DDL
- `SqlInsert` / `SqlDelete` / `SqlUpdate` / `SqlMerge`
- `SqlSetOption` / `SqlAlter` / `SqlExplain` / `SqlDescribe`

## 例
```json
{
"type": "SqlStmtList",
"statements": [
{
"type": "SqlSelect",
"selectItems": [
{ "type": "AddSelectItem", "expr": { "type": "SelectExpression", "star": true } }
],
"from": {
"type": "FromClause",
"first": { "type": "TableRef", "base": { "type": "TableName", "name": { "type": "CompoundTableIdentifier" } } },
"joins": []
}
}
]
}
```

## TODO
- `Expression*` 系の正規化
- `BuiltinFunctionCall` の各関数ノードの仕様を追加
- テストで AST 形を固定
57 changes: 57 additions & 0 deletions FORMATTER_RULES.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# SQL Formatter ルール(暫定)

本ドキュメントは SQL Formatter の出力スタイルを定義するルール表です。

## 基本スタイル
- インデント: **4 スペース**
- キーワード: **大文字 (UPPER)**
- 末尾セミコロン: **なし**
- カンマ位置: **先頭**

## SELECT 句
- カラムは **1 行 1 カラム**
- 例:
```sql
SELECT
col_a
, col_b
, SUM(col_c)
FROM table_name
```

## 主要句の改行方針
- 以下の句は **必ず改行**
- `FROM`
- `JOIN`
- `WHERE`
- `GROUP BY`
- `HAVING`
- `ORDER BY`

## JOIN の整形
- JOIN 句は 1 行 1 句
- `ON` / `USING` は次行にインデント

例:
```sql
FROM table_a a
JOIN table_b b
ON a.id = b.id
```

## WHERE / GROUP BY / HAVING / ORDER BY
- 各句は 1 行開始
- `AND` / `OR` は **次行** に出す

例:
```sql
WHERE a = 1
AND b = 2
```

## TODO
- サブクエリ・括弧のインデント方針
- 関数引数の改行ルール
- CASE 式の整形ルール
- SETOP(UNION/INTERSECT/EXCEPT)の改行規則
- WINDOW 句/OVER 句の改行規則
46 changes: 46 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# SQL Formatter (WIP)

このリポジトリは、最終的に **SQL Formatter** を作るためのプロジェクトです。
現在は前段として **SQL パーサー** を実装しています。

![Playground screenshot](screenshot.png)

## 目的
- 最終目標: SQL を整形するフォーマッタの実装
- 現状: SQL パーサーを自作し、AST を生成する段階

## 現在の構成
- `spec/apache-calcite-Parser.js`: パーサー本体(lexer + parser)
- `spec/apache-calcite-Parser-test.js`: 回帰/異常系テスト
- `spec/apache-calcite-Parser.md`: 仕様(EBNFベース)
- `spec/apache-calcite-Parser.jj`: 参照文法
- `AST.md`: AST 仕様(暫定)
- `FORMATTER_RULES.md`: SQL Formatter の出力ルール
- `index-parser.html`: SQL → AST 出力の簡易デモ
- `index.html`: SQL Formatter の UI(WIP)

## 使い方(開発時)
テストを実行してパーサーの動作確認ができます。

```bash
node spec/apache-calcite-Parser-test.js
```

## 直近の作業予定
- **index-parser.html**: SQL → AST を出力する簡易デモ(実装済み)
- **index.html**: 将来的に SQL Formatter の UI を実装予定
- AST 仕様の整理と固定化
- 構文の厳密化(句の順序/排他の追加チェック)
- 最終的に formatter へ接続

## 仕様情報の流れ(開発過程)
- `spec/apache-calcite-Parser.jj` の文法を元に `spec/apache-calcite-Parser.md`(EBNF仕様)を作成
- `spec/apache-calcite-Parser.md` を元に `spec/apache-calcite-Parser.js`(実装)を生成

## デモ機能
- AST の JSON 出力
- トークン一覧の表示
- エラートークンのハイライト表示

## ライセンス
`LICENSE` を参照してください。
35 changes: 20 additions & 15 deletions TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,27 @@
- Stage 1: lexer + 全 production skeleton 済み。
- 入口/Select/From/Join/式/関数/型/JSON/日付系の主要骨格は実装済み。
- md⇔js の production 名・順序は一致済み(ヘルパー除外で一致)。
- 回帰テスト/異常系テストを追加済み(全 187 件通過)。
- lexer 実用化(コメント/文字列エスケープ/指数/引用識別子/Unicode/BigQuery/ヒント/数値種別/Unicodeエスケープ検証)対応済み。
- 構文厳密化(FROM 必須/HAVING 制約/JOIN 条件/フレーム条件/ORDER+FETCH など)対応済み。

## 残り作業(優先順の目安・更新)
1. SetOp/Query 周り
- AddSetOpQuery / BinaryQueryOperator / AddSetOpQueryOrExpr / Query / SqlQueryEof
- PartitionedQueryOrQueryOrExpr / OrderByOfSetSemanticsTable
2. テーブル参照の拡張
- Snapshot / Tablesample / Pivot / Unpivot / MatchRecognize / TableOverOpt / Over / ExtendedTableRef
3. LIMIT/OFFSET/FETCH と ORDER BY 制約
- LimitClause / OffsetClause / FetchClause
4. Add* 系の実装(実用上の肝)
- AddSelectItem / AddOrderItem / AddGroupingElement / AddWindowSpec / AddWithItem など
5. DDL/DML の細部
- SqlSetOption/SqlAlter/SqlExplain などの分岐網羅(現状は最小実装)
6. 低優先ユーティリティ
- ReservedFunctionName / NonReserved* / CollectionsTypeName / CollateClause など
7. 厳格な突合(最終)
1. AST 仕様の整理
- ノード型の命名とフィールドを最終定義し、テストで固定化
2. 構文厳密化の追加候補
- 句の出現順序/必須/排他の追加チェック(ORDER/LIMIT/OFFSET/FETCH/QUALIFY など)
- 省略可能要素の優先順位を整理(誤って別名に吸われる余地の洗い出し)
3. テスト拡張(必要なら)
- SETOP/ORDER/LIMIT の境界・エラー例を追加
4. 仕様(.md)と実装(.js)の差分反映
- TableRef 修飾子(TableHints/ExtendTable/TableOverOpt/Snapshot)の対応を整理 ✅
- ASOF JOIN の MATCH_CONDITION を仕様に合わせて反映 ✅
- lexer の識別子/文字列/数値トークン差分を解消 ✅
- HYPHENATED/BRACKET/BIG_QUERY 系識別子 ✅
- PREFIXED/UNICODE/BINARY/UESCAPE/連結文字列 ✅
- DECIMAL/APPROX 数値リテラル ✅
- TableHints がコメントとして破棄されないよう lexer と整合 ✅
5. 厳格な突合(最終)
- apache-calcite-Parser.md を正とし、apache-calcite-Parser.js の整合を最終チェック。
- 手順(最小):
1) .md から production 名一覧を抽出(順序付き)
Expand All @@ -33,7 +38,7 @@
- 差分一覧(テキスト)と、反映後の .js

## 実装方針メモ
- lexer は最小: IDENT/NUMBER/STRING/SYMBOL/EOF のみ。予約語判定は isKeyword で大文字比較。
- lexer は実用化済み(コメント/エスケープ/指数/引用識別子対応)。予約語判定は isKeyword で大文字比較。
- AST 形式は自由だが、既存の軽量ノード(type + 必要最小限のフィールド)で統一。
- 失敗時は notImplemented を残して段階的に埋める。

Expand Down
Loading