このリポジトリは、SQL Formatter を作るためのプロジェクトです。 現在は SQL パーサー に加えて、フォーマッターの実装も進行中です。
- 最終目標: SQL を整形するフォーマッタの実装
- 現状: SQL パーサー + フォーマッターの両方を実装中
spec/apache-calcite-Parser.js: パーサー本体(lexer + parser)spec/apache-calcite-Parser-test.js: 回帰/異常系テストspec/apache-calcite-Parser.md: 仕様(EBNFベース)spec/wellknown-sql-ddl.md: DDL 仕様(EBNFベース、ANSI SQL 風。元仕様が異なるためapache-calcite-Parser.mdと統合しない)spec/apache-calcite-Parser.jj: 参照文法AST.md: AST 仕様(暫定)FORMATTER_RULES.md: SQL Formatter の出力ルールindex-parser.html: SQL → AST 出力の簡易デモindex.html: SQL Formatter の UIsql-formatter.js: SQL フォーマッター本体sql-formatter-test.js: フォーマッターテスト
テストを実行してパーサーの動作確認ができます。
node spec/apache-calcite-Parser-test.js
node sql-formatter-test.js.mdと.jsの production 名は一致させる- パーサー変更時は
node spec/apache-calcite-Parser-test.jsを実行 - フォーマッター変更時は
node sql-formatter-test.jsも実行 - 破壊的変更は
TODO.mdに記録
- index-parser.html: SQL → AST を出力する簡易デモ(実装済み)
- DDL フォーマッター統合: CREATE/ALTER/DROP TABLE, CREATE INDEX など(実装済み)
- 6 つの DDL レンダラー関数を実装
- 12 個の DDL テストケースを追加
- 全 117 テスト合格(105 既存 DML + 12 新規 DDL)
- index.html: SQL Formatter の UI(実装中)
- フォーマッターの対応範囲拡張(UNION, WINDOW FUNCTIONS など)
- AST 仕様の整理と固定化
- 構文の厳密化(句の順序/排他の追加チェック)
spec/apache-calcite-Parser.jjの文法を元にspec/apache-calcite-Parser.md(EBNF仕様)を作成spec/apache-calcite-Parser.mdを元にspec/apache-calcite-Parser.js(実装)を生成
このプロジェクトは 2 段階のパーサーフォールバック戦略を採用しています:
-
第1段階: Apache Calcite パーサー(DML/DQL 最適化)
sql-formatter.jsのformatSql()関数で使用- SELECT, INSERT, UPDATE, DELETE 文を処理
-
第2段階: DDL 専用パーサー(DDL 文対応)
- Calcite が失敗した場合のフォールバック
- CREATE/ALTER/DROP TABLE, CREATE INDEX, CREATE VIEW など
spec/wellknown-sql-ddl.jsから WellknownDdlLexer/Parser を使用
-
第3段階: パススルー
- 両方のパーサーが失敗した場合は元の SQL を返す
- インデント: 4 スペース
- キーワード: 大文字(UPPERCASE)
- カンマ位置: リスト先頭(comma-first style)
- 主要句改行: FROM, JOIN, WHERE, GROUP BY, HAVING, ORDER BY は必ず改行
コミット: f91ec95 "Integrate DDL parser for table and index formatting"
実装内容:
- DDL パーサーのインポート追加
formatSql()に DDL フォールバック機能追加- 6 つの DDL レンダラー関数実装
renderDropTable(): DROP TABLE [IF EXISTS] [CASCADE/RESTRICT]renderCreateTable(): CREATE [TEMPORARY] TABLE with column definitions/AS/LIKErenderCreateIndex(): CREATE [UNIQUE] INDEX with column listsrenderAlterTable(): ALTER TABLE with flexible action capturerenderTruncateTable(): TRUNCATE TABLErenderCreateView(): CREATE [OR REPLACE] VIEW with columns/AS
- CompoundIdentifier ハンドラーを拡張(文字列と Identifier オブジェクト両対応)
- 12 個の DDL テストケース追加
テスト結果: 117/117 テスト合格(リグレッションなし)
次の機能拡張を検討する際は以下を参考にしてください:
-
UNION/INTERSECT/EXCEPT サポート
- 現在: パススルー(フォーマット未実装)
- 実装方針: 既存パーサーを拡張するか、DDL パーサーを活用
-
WINDOW FUNCTIONS サポート
- 現在: パススルー
- 実装方針: renderNode() に OVER/PARTITION BY ハンドラー追加
-
CTE (WITH) サポート
- 現在: パススルー
- 実装方針: Calcite パーサー拡張 or カスタムハンドラー追加
-
CASE 式のフォーマット
- 現在: パススルー(未実装)
- 実装方針: renderNode() に CASE ハンドラー追加
sql-formatter-test.js に以下の形式で新しいテストグループを追加:
const newFeatureTests = [
{
name: 'test-id',
category: 'category-name',
description: 'Test description',
sql: 'SELECT ...',
expect: `formatted output`, // または expectIncludes: ['keyword1', 'keyword2']
},
];
// allTestGroups 配列に登録
const allTestGroups = [
// ... existing groups ...
{ name: 'Feature Name', tests: newFeatureTests },
];renderNode(node, ctx): 全ての AST ノード型の統一入口ctxオブジェクト: インデントレベルと状態管理indent(ctx, extra): インデント生成ヘルパーmarkUnknown(ctx): 未実装ノード型のマーク
gh コマンドで自動的に PR を作成しないでください。
PR 作成する場合は、以下のいずれかの方法を使用してください:
-
GitHub Web UI での手動作成(推奨)
- 提供される PR テンプレートテキストをコピー
- GitHub Web にブラウザでアクセス
- "New Pull Request" ボタンで新規 PR を作成
- テンプレートテキストを PR Description に貼付
-
ローカルでの branch / commit 作成のみ実施
- 機能実装と commit までを完了
- PR テンプレートを生成
- 実際の PR 作成はユーザーが GitHub Web UI で実施
理由: ユーザーの CI/CD パイプライン、approval flow、branch protection など、リポジトリ固有の PR プロセスに合わせる必要があるため、自動 PR 作成ではなく手動作成が前提です。
- AST の JSON 出力
- トークン一覧の表示
- エラートークンのハイライト表示
LICENSE を参照してください。
