Skip to content

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

License

Notifications You must be signed in to change notification settings

igapyon/sql-formatter

Repository files navigation

SQL Formatter (WIP)

このリポジトリは、SQL Formatter を作るためのプロジェクトです。 現在は SQL パーサー に加えて、フォーマッターの実装も進行中です。

Playground screenshot

目的

  • 最終目標: 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 の UI
  • sql-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(実装)を生成

生成AI向けの開発ガイド

アーキテクチャ概要

このプロジェクトは 2 段階のパーサーフォールバック戦略を採用しています:

  1. 第1段階: Apache Calcite パーサー(DML/DQL 最適化)

    • sql-formatter.jsformatSql() 関数で使用
    • SELECT, INSERT, UPDATE, DELETE 文を処理
  2. 第2段階: DDL 専用パーサー(DDL 文対応)

    • Calcite が失敗した場合のフォールバック
    • CREATE/ALTER/DROP TABLE, CREATE INDEX, CREATE VIEW など
    • spec/wellknown-sql-ddl.js から WellknownDdlLexer/Parser を使用
  3. 第3段階: パススルー

    • 両方のパーサーが失敗した場合は元の SQL を返す

フォーマッティングスタイル

- インデント: 4 スペース
- キーワード: 大文字(UPPERCASE)
- カンマ位置: リスト先頭(comma-first style)
- 主要句改行: FROM, JOIN, WHERE, GROUP BY, HAVING, ORDER BY は必ず改行

DDL 統合(2026年1月実装)

コミット: 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/LIKE
    • renderCreateIndex(): CREATE [UNIQUE] INDEX with column lists
    • renderAlterTable(): ALTER TABLE with flexible action capture
    • renderTruncateTable(): TRUNCATE TABLE
    • renderCreateView(): CREATE [OR REPLACE] VIEW with columns/AS
  • CompoundIdentifier ハンドラーを拡張(文字列と Identifier オブジェクト両対応)
  • 12 個の DDL テストケース追加

テスト結果: 117/117 テスト合格(リグレッションなし)

次のステップ(生成AI向け)

次の機能拡張を検討する際は以下を参考にしてください:

  1. UNION/INTERSECT/EXCEPT サポート

    • 現在: パススルー(フォーマット未実装)
    • 実装方針: 既存パーサーを拡張するか、DDL パーサーを活用
  2. WINDOW FUNCTIONS サポート

    • 現在: パススルー
    • 実装方針: renderNode() に OVER/PARTITION BY ハンドラー追加
  3. CTE (WITH) サポート

    • 現在: パススルー
    • 実装方針: Calcite パーサー拡張 or カスタムハンドラー追加
  4. 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): 未実装ノード型のマーク

Pull Request 作成時の注意事項

gh コマンドで自動的に PR を作成しないでください。

PR 作成する場合は、以下のいずれかの方法を使用してください:

  1. GitHub Web UI での手動作成(推奨)

    • 提供される PR テンプレートテキストをコピー
    • GitHub Web にブラウザでアクセス
    • "New Pull Request" ボタンで新規 PR を作成
    • テンプレートテキストを PR Description に貼付
  2. ローカルでの branch / commit 作成のみ実施

    • 機能実装と commit までを完了
    • PR テンプレートを生成
    • 実際の PR 作成はユーザーが GitHub Web UI で実施

理由: ユーザーの CI/CD パイプライン、approval flow、branch protection など、リポジトリ固有の PR プロセスに合わせる必要があるため、自動 PR 作成ではなく手動作成が前提です。

デモ機能

  • AST の JSON 出力
  • トークン一覧の表示
  • エラートークンのハイライト表示

ライセンス

LICENSE を参照してください。

About

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

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published