Druidデータソース:AST処理フロー

Druid SQL ASTシステムの概要:

一、全体アーキテクチャ概要

Druid SQL解析は主に3つの層で構成されています: ソースコード文字列 → 字句解析(Lexer) → 構文解析(Parser) → AST抽象構文木 → Visitorによる走査/修正/SQL生成

完全な処理フロー:

SQLテキスト
   ↓
Lexer 字句解析(Tokenに分解)
   ↓
Parser 構文解析(TokenをASTノードに構築)
   ↓
SQLStatement / SQLExprで完全なAST木を形成
   ↓
VisitorパターンによるASTの走査、抽出、修正
   ↓
ASTからSQLテキストを再生成

Druidの核心的な位置づけ:データベースを跨ぎ、解析可能、走査可能、書き換え可能、フォーマット可能な SQL AST エンジン

二、主要コンポーネントの概要

1. 主要トップレベルクラス(必須)

コンポーネント 役割
DbType データベース方言:MySQL/Oracle/PG/SQLServer
SQLUtils ツールエントリーポイント:フォーマット、解析、SQL生成、式の作成
SQLLexer 字句解析器:SQLをTokenに分解
SQLParser 構文解析器:TokenをAST木に構築
SQLStatement ASTトップレベルのステートメントノード(各SQLに対応)
SQLExpr AST式ノード(where、case、関数、フィールド、定数)
SQLObject 全ASTノードの**ルート親クラス**
SchemaStatVisitor 組み込みVisitor:テーブル、フィールド、操作タイプ、条件の抽出
SQLASTVisitor カスタムAST走査/修正の親クラス
SQLCreateTableStatement/SQLSelectStatement 各種具体的なステートメントのAST実装クラス

三、第一層:字句解析 Lexer(SQLLexer)

1. 職務

  • SQL文字列全体Tokenトークンに分割
  • キーワード、テーブル名、フィールド名、定数、記号、文字列、数字を認識
  • 空白、改行、コメントをフィルタリング

2. Tokenタイプの例

  • キーワード:SELECTFROMWHEREAND
  • 識別子:useridusername
  • 記号:=><,()
  • リテラル:123'張三'3.14

3. 処理フロー

SQL文字ストリーム → Lexer → Tokenストリーム → Parserに渡す

4. 特徴

  • 方言認識:異なるデータベースではキーワードが異なり、LexerはDbTypeに適応
  • コメント、空白文字の自動無視

四、第二層:構文解析 Parser(SQLParser)

1. 職務

データベース構文規則に従い、Tokenを順次読み取り、再帰的にAST構文木を構築します。

2. 細分化されたParser実装

Druidはデータベースごとに専用Parserを分割しています:

  • MySqlParser
  • OracleParser
  • SQLServerParser
  • PostgreSqlParser
  • Db2Parser

3. 解析結果

  • 単一SQL → 1つのSQLStatement
  • 複数SQL → List<SQLStatement>

4. 解析例外

構文エラーは直接ParserExceptionをスローし、SQL構文検証に利用できます。

五、第三層:AST抽象構文木の核心システム(最重要)

1. ASTトップレベル親クラス構造

すべてのノードは以下を継承します:

SQLObject
├─ SQLStatement   // 完全なSQLステートメントノード
└─ SQLExpr        // 式ノード(条件、関数、値、フィールド)

2. SQLStatementステートメントシステム(完全なSQL)

完全なSQLステートメントを表し、一般的な実装:

ステートメントクラス 対応SQL
SQLSelectStatement SELECTクエリ
SQLInsertStatement INSERT挿入
SQLUpdateStatement UPDATE更新
SQLDeleteStatement DELETE削除
SQLCreateTableStatement CREATE TABLE
SQLAlterTableStatement ALTERテーブル構造
SQLDropTableStatement DROP TABLE

構造例(SELECT):

SQLSelectStatement
 ├─ SQLSelectQueryBlock   // クエリ本体
 │  ├─ selectList  クエリフィールドリスト
 │  ├─ from        テーブル/関連テーブル
 │  ├─ where       条件句
 │  ├─ groupBy     グループ化
 │  ├─ having      グループ条件
 │  └─ orderBy     ソート
 └─ ... その他の句

3. SQLExpr式システム(条件、フィールド、値)

すべての条件、フィールド、定数、関数、演算SQLExprに属します

一般的な実装クラス:

  • SQLIdentifierExpr:フィールド名、テーブル名(例:idusername
  • SQLNumberExpr:数字定数(例:18100
  • SQLCharExpr:文字列定数(例:'張三'
  • SQLBinaryOpExpr:二項演算(例:a = bage > 18
  • SQLInExpr:IN式
  • SQLBetweenExpr:BETWEEN範囲
  • SQLMethodInvokeExpr:関数(例:count()sum()
  • SQLCaseExpr:case when式

WHERE条件の実体はSQLExpr二分木であり、AND/ORを介して継続的にネストされます。

4. その他の一般的なASTノード

  • SQLTableSource:from後のテーブル、関連テーブル
  • SQLJoinTableSource:JOIN関連
  • SQLOrderByExpr:ソートフィールド
  • SQLGroupByExpr:グループ化フィールド
  • SQLColumnDefinition:テーブル作成フィールド定義

六、第四層:Visitorアクセスシステム(ASTの走査と修正)

1. 設計パターン

Visitorパターン:ASTノードは固定で、Visitorがすべてのノードを走査し、木構造を変更せずに以下の操作が可能:

  • テーブル名、フィールドの抽出
  • すべての条件の走査 WHERE条件の動的追加 テーブル名、フィールド名の置換 SQLマスキング、監査、権限書き換え

2. 主要Visitorクラス

  1. SQLASTVisitor カスタムVisitorはこれを継承し、visitXxxメソッドをオーバーライドして対応ASTノードをインターセプトします。
  2. SchemaStatVisitor(組み込み常用) Druidが標準で提供し、直接使用可能:
  • すべてのテーブル名を取得
  • すべてのフィールドを取得
  • SQL操作タイプSELECT/INSERT/UPDATEを取得
  • WHERE条件、関連関係を取得

3. 走査フロー

AST木ルートノード → accept(visitor) → 自動的にすべての子ノードを再帰的に走査 → Visitor対応メソッドのコールバック

七、第五層:ASTからのSQL逆生成とフォーマット

1. 処理フロー

修正されたAST木 → toString / SQLUtils.toSQLStringを呼び出す → SQLテキストを再結合

2. フォーマット機能

SQLUtils.formatの内部:

  • ASTを走査
  • インデント、大文字小文字、改行規則に従って再レイアウト
  • カスタムFormatOptionをサポート

八、完全な解析プロセスのデモンストレーション(上記アーキテクチャに対応)

String query = "select id,name from users where age > 18";
// 1. 方言を指定
DbType databaseType = DbType.mysql;

// 2. 字句+構文解析 → ASTを生成
List<SQLStatement> statementList = SQLUtils.parseStatements(query, databaseType);
SQLSelectStatement selectStatement = (SQLSelectStatement) statementList.get(0);

// 3. Visitorでテーブルとフィールドを抽出
SchemaStatVisitor extractor = SQLUtils.createSchemaStatVisitor(databaseType);
selectStatement.accept(extractor);

// 4. 解析結果を取得
System.out.println("テーブル:" + extractor.getTables());
System.out.println("フィールド:" + extractor.getColumns());

// 5. ASTからフォーマットされたSQLを再生成
String formattedSql = SQLUtils.toSQLString(selectStatement, databaseType);
System.out.println(formattedSql);

完全なプロセス:Lexer → Parser → AST → Visitor → SQL生成 全フロー。

九、Druid ASTの主要応用シナリオ(下位層の原理対応)

  1. マルチテナントへの自動テナントID追加 ASTを走査し、WHEREノードを見つけてtenant_id = ?条件を追加
  2. シャーディング時の動的テーブル名置換 SQLTableSourceノードを走査し、テーブル名をシャーディング接尾辞に置換
  3. SQL監査における高リスク検出 ASTを解析し、DROP/ALTER/DELETE全テーブル無whereを検出
  4. データ権限の行レベルフィルタリング SELECTステートメントをインターセプトし、部署、データ範囲条件を動的に結合
  5. SQLフォーマット、構文検証 ASTに基づき再レイアウト、解析例外で構文の正当性を判断
  6. 汎用マッパー、動的SQL生成 手動でSQLSelectStatement + SQLExprを組み合わせてSQLを構築

十、システムの核心的まとめ(一言で覚える)

  1. Lexer:SQLをTokenに分割
  2. Parser:TokenでAST構文木を構築
  3. ASTSQLStatement(ステートメント) + SQLExpr(式) の2大システム
  4. Visitor:VisitorパターンでASTを走査、抽出、修正
  5. 最後に:ASTからSQLを逆生成 + フォーマット

全体のシステムは字句 → 構文 → AST木 → 走査 → 逆生成という標準的なコンパイラ原理のプロセスです。

タグ: Druid AST SQL解析 データベース 字句解析

6月12日 00:28 投稿