Skip to content

Commit 5ca574d

Browse files
authored
Merge pull request #10 from igapyon/devel
develの成果をmainに反映
2 parents d714cfa + f1f077f commit 5ca574d

12 files changed

Lines changed: 2175 additions & 94 deletions

AGENTS.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# AGENTS.md
2+
3+
このリポジトリで作業するエージェント向けの最小ガイドです。
4+
5+
## 目的
6+
- 最終目標: SQL Formatter の実装
7+
- 現状: SQL パーサーの実装とテストの整備
8+
9+
## 主要ファイル
10+
- `spec/apache-calcite-Parser.js`: lexer + parser 本体
11+
- `spec/apache-calcite-Parser-test.js`: 回帰/異常系テスト
12+
- `spec/apache-calcite-Parser.md`: 仕様(EBNFベース)
13+
- `index-parser.html`: SQL → AST 出力の簡易デモ
14+
15+
## 作業の基本方針
16+
- `.md``.js` の production 名は一致させる
17+
- 変更後は `node spec/apache-calcite-Parser-test.js` を実行
18+
- 破壊的変更は `TODO.md` に記録
19+
20+
## 進捗の記録
21+
- 直近のタスクは `TODO.md` を参照
22+
23+
## 実行コマンド
24+
```bash
25+
node spec/apache-calcite-Parser-test.js
26+
```

AST.md

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
# AST 仕様(暫定)
2+
3+
このドキュメントは、`spec/apache-calcite-Parser.js` が出力する AST の最小仕様をまとめたものです。
4+
現状は実装の読みやすさ優先の軽量ノード構成です。
5+
6+
## 共通ルール
7+
- すべてのノードは `type` フィールドを持つ
8+
- 省略可能要素は `null` または未設定
9+
- リストは配列で表現
10+
11+
## ルート
12+
- `SqlStmtList`
13+
- `statements`: ステートメント配列
14+
- `SqlStmtEof`
15+
- `stmt`
16+
- `SqlExpressionEof`
17+
- `expr`
18+
19+
## クエリ
20+
- `SqlSelect`
21+
- `hints`: `TableHints | null`
22+
- `stream`: `boolean`
23+
- `setQuantifier`: `"ALL" | "DISTINCT" | null`
24+
- `selectItems`: `AddSelectItem[]`
25+
- `from`: `FromClause | null`
26+
- `where`: `Where | null`
27+
- `groupBy`: `GroupBy | null`
28+
- `having`: `Having | null`
29+
- `window`: `Window | null`
30+
- `qualify`: `Qualify | null`
31+
- `QueryOrExpr`
32+
- `withList`, `leaf`, `setOps`
33+
- `OrderedQueryOrExpr`
34+
- `query`, `orderByLimitOpt`
35+
36+
##
37+
- `FromClause`
38+
- `first`: `TableRef`
39+
- `joins`: (`JoinTable` | `CommaJoin` | `ApplyJoin`)[]
40+
- `JoinTable`
41+
- `natural`: `boolean`
42+
- `joinType`: `string` (e.g. `"JOIN"`, `"LEFT JOIN"`)
43+
- `table`: `TableRef`
44+
- `condition`: `On | Using | null`
45+
- `CommaJoin`
46+
- `table`
47+
- `Where`
48+
- `expr`
49+
- `GroupBy`
50+
- `set`: `"DISTINCT" | "ALL" | null`
51+
- `list`: `GroupingElementList`
52+
- `Having`
53+
- `expr`
54+
- `Window`
55+
- `items`: `AddWindowSpec[]`
56+
- `Qualify`
57+
- `expr`
58+
- `OrderBy`
59+
- `list`: `OrderItemList`
60+
- `LimitClause`
61+
- `value`, `offset`
62+
- `OffsetClause`
63+
- `value`, `rows`
64+
- `FetchClause`
65+
- `mode`, `value`, `rows`
66+
67+
## テーブル参照
68+
- `TableRef`
69+
- `base`, `pivot`, `unpivot`, `matchRecognize`, `alias`, `columns`, `tablesample`
70+
- `TableName`
71+
- `name`: `CompoundTableIdentifier`
72+
- `Subquery`
73+
- `query`: `OrderedQueryOrExpr`
74+
- `Unnest`
75+
- `items`: `Expression[]`
76+
- `withOrdinality`: `boolean`
77+
- `TableFunctionCall`
78+
- `call`: `NamedRoutineCall`
79+
- `Pivot`
80+
- `aggs`: `AddPivotAgg[]`
81+
- `axis`: `SimpleIdentifierOrList`
82+
- `values`: `AddPivotValue[]`
83+
- `Unpivot`
84+
- `nulls`: `"INCLUDE" | "EXCLUDE" | null`
85+
- `columns`: `SimpleIdentifierOrList`
86+
- `axis`: `SimpleIdentifierOrList`
87+
- `values`: `AddUnpivotValue[]`
88+
- `MatchRecognize`
89+
- `partitionBy`, `orderBy`, `measures`, `rowsPerMatch`, `afterMatchSkip`
90+
- `pattern`, `anchorStart`, `anchorEnd`, `within`, `subsets`, `define`
91+
92+
##
93+
- `Expression2b`(内部表現)
94+
- `prefixes`, `base`, `extensions`
95+
- `BinaryExpression`
96+
- `operator`, `left`, `right`
97+
- `Literal`
98+
- `value`
99+
- `StringLiteral`
100+
- `value`
101+
- `NumericLiteral`
102+
- `value`
103+
- `Identifier`
104+
- `name`
105+
- `CompoundIdentifier`
106+
- `parts`
107+
108+
## 関数
109+
- `NamedFunctionCall`
110+
- `name`, `args`, `orderBy`, `withinGroup`, `nullTreatment`, `filter`, `over`
111+
- `BuiltinFunctionCall`
112+
- `kind` ごとにフィールドが異なる(各関数ノード参照)
113+
- `MatchRecognizeFunctionCall`
114+
115+
## DML/DDL
116+
- `SqlInsert` / `SqlDelete` / `SqlUpdate` / `SqlMerge`
117+
- `SqlSetOption` / `SqlAlter` / `SqlExplain` / `SqlDescribe`
118+
119+
##
120+
```json
121+
{
122+
"type": "SqlStmtList",
123+
"statements": [
124+
{
125+
"type": "SqlSelect",
126+
"selectItems": [
127+
{ "type": "AddSelectItem", "expr": { "type": "SelectExpression", "star": true } }
128+
],
129+
"from": {
130+
"type": "FromClause",
131+
"first": { "type": "TableRef", "base": { "type": "TableName", "name": { "type": "CompoundTableIdentifier" } } },
132+
"joins": []
133+
}
134+
}
135+
]
136+
}
137+
```
138+
139+
## TODO
140+
- `Expression*` 系の正規化
141+
- `BuiltinFunctionCall` の各関数ノードの仕様を追加
142+
- テストで AST 形を固定

FORMATTER_RULES.md

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
# SQL Formatter ルール(暫定)
2+
3+
本ドキュメントは SQL Formatter の出力スタイルを定義するルール表です。
4+
5+
## 基本スタイル
6+
- インデント: **4 スペース**
7+
- キーワード: **大文字 (UPPER)**
8+
- 末尾セミコロン: **なし**
9+
- カンマ位置: **先頭**
10+
11+
## SELECT 句
12+
- カラムは **1 行 1 カラム**
13+
- 例:
14+
```sql
15+
SELECT
16+
col_a
17+
, col_b
18+
, SUM(col_c)
19+
FROM table_name
20+
```
21+
22+
## 主要句の改行方針
23+
- 以下の句は **必ず改行**
24+
- `FROM`
25+
- `JOIN`
26+
- `WHERE`
27+
- `GROUP BY`
28+
- `HAVING`
29+
- `ORDER BY`
30+
31+
## JOIN の整形
32+
- JOIN 句は 1 行 1 句
33+
- `ON` / `USING` は次行にインデント
34+
35+
例:
36+
```sql
37+
FROM table_a a
38+
JOIN table_b b
39+
ON a.id = b.id
40+
```
41+
42+
## WHERE / GROUP BY / HAVING / ORDER BY
43+
- 各句は 1 行開始
44+
- `AND` / `OR`**次行** に出す
45+
46+
例:
47+
```sql
48+
WHERE a = 1
49+
AND b = 2
50+
```
51+
52+
## TODO
53+
- サブクエリ・括弧のインデント方針
54+
- 関数引数の改行ルール
55+
- CASE 式の整形ルール
56+
- SETOP(UNION/INTERSECT/EXCEPT)の改行規則
57+
- WINDOW 句/OVER 句の改行規則

README.md

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# SQL Formatter (WIP)
2+
3+
このリポジトリは、最終的に **SQL Formatter** を作るためのプロジェクトです。
4+
現在は前段として **SQL パーサー** を実装しています。
5+
6+
![Playground screenshot](screenshot.png)
7+
8+
## 目的
9+
- 最終目標: SQL を整形するフォーマッタの実装
10+
- 現状: SQL パーサーを自作し、AST を生成する段階
11+
12+
## 現在の構成
13+
- `spec/apache-calcite-Parser.js`: パーサー本体(lexer + parser)
14+
- `spec/apache-calcite-Parser-test.js`: 回帰/異常系テスト
15+
- `spec/apache-calcite-Parser.md`: 仕様(EBNFベース)
16+
- `spec/apache-calcite-Parser.jj`: 参照文法
17+
- `AST.md`: AST 仕様(暫定)
18+
- `FORMATTER_RULES.md`: SQL Formatter の出力ルール
19+
- `index-parser.html`: SQL → AST 出力の簡易デモ
20+
- `index.html`: SQL Formatter の UI(WIP)
21+
22+
## 使い方(開発時)
23+
テストを実行してパーサーの動作確認ができます。
24+
25+
```bash
26+
node spec/apache-calcite-Parser-test.js
27+
```
28+
29+
## 直近の作業予定
30+
- **index-parser.html**: SQL → AST を出力する簡易デモ(実装済み)
31+
- **index.html**: 将来的に SQL Formatter の UI を実装予定
32+
- AST 仕様の整理と固定化
33+
- 構文の厳密化(句の順序/排他の追加チェック)
34+
- 最終的に formatter へ接続
35+
36+
## 仕様情報の流れ(開発過程)
37+
- `spec/apache-calcite-Parser.jj` の文法を元に `spec/apache-calcite-Parser.md`(EBNF仕様)を作成
38+
- `spec/apache-calcite-Parser.md` を元に `spec/apache-calcite-Parser.js`(実装)を生成
39+
40+
## デモ機能
41+
- AST の JSON 出力
42+
- トークン一覧の表示
43+
- エラートークンのハイライト表示
44+
45+
## ライセンス
46+
`LICENSE` を参照してください。

TODO.md

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,22 +4,27 @@
44
- Stage 1: lexer + 全 production skeleton 済み。
55
- 入口/Select/From/Join/式/関数/型/JSON/日付系の主要骨格は実装済み。
66
- md⇔js の production 名・順序は一致済み(ヘルパー除外で一致)。
7+
- 回帰テスト/異常系テストを追加済み(全 187 件通過)。
8+
- lexer 実用化(コメント/文字列エスケープ/指数/引用識別子/Unicode/BigQuery/ヒント/数値種別/Unicodeエスケープ検証)対応済み。
9+
- 構文厳密化(FROM 必須/HAVING 制約/JOIN 条件/フレーム条件/ORDER+FETCH など)対応済み。
710

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

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

0 commit comments

Comments
 (0)