From 2b2f1994a919eafec41a47dcf8bf302ac907dc28 Mon Sep 17 00:00:00 2001 From: ma91n Date: Tue, 30 Sep 2025 13:51:31 +0900 Subject: [PATCH] =?UTF-8?q?PostgreSQL=20=E5=85=A8=E6=A7=8B=E6=96=87?= =?UTF-8?q?=E5=AF=BE=E5=BF=9C=E3=81=AE=20Pure=20Rust=20=E3=81=AA=20CST=20?= =?UTF-8?q?=E3=83=91=E3=83=BC=E3=82=B5=E3=83=BC=E3=82=92=E4=BD=9C=E3=81=A3?= =?UTF-8?q?=E3=81=A6=E3=81=BF=E3=81=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...43\203\274\343\202\271\360\237\216\211.md" | 7 +- ...43\343\201\246\343\201\277\343\201\237.md" | 436 ++++++++++++++++++ .../2025/20250930a/2025-02-28_14h09_26.png | Bin 0 -> 38281 bytes source/images/2025/20250930a/thumbnail.png | Bin 0 -> 26710 bytes 4 files changed, 441 insertions(+), 2 deletions(-) create mode 100644 "source/_posts/2025/20250930a_PostgreSQL_\345\205\250\346\247\213\346\226\207\345\257\276\345\277\234\343\201\256_Pure_Rust_\343\201\252_CST_\343\203\221\343\203\274\343\202\265\343\203\274\343\202\222\344\275\234\343\201\243\343\201\246\343\201\277\343\201\237.md" create mode 100644 source/images/2025/20250930a/2025-02-28_14h09_26.png create mode 100644 source/images/2025/20250930a/thumbnail.png diff --git "a/source/_posts/2025/20250929a_Pure_Rust\343\201\247\347\224\237\343\201\276\343\202\214\345\244\211\343\202\217\343\201\243\343\201\237PostgreSQL\345\205\254\345\274\217\346\247\213\346\226\207\346\272\226\346\213\240SQL\343\203\225\343\202\251\343\203\274\343\203\236\343\203\203\343\202\277\343\203\274\343\200\214uroborosql-fmt\343\200\215\343\202\222\343\203\252\343\203\252\343\203\274\343\202\271\360\237\216\211.md" "b/source/_posts/2025/20250929a_Pure_Rust\343\201\247\347\224\237\343\201\276\343\202\214\345\244\211\343\202\217\343\201\243\343\201\237PostgreSQL\345\205\254\345\274\217\346\247\213\346\226\207\346\272\226\346\213\240SQL\343\203\225\343\202\251\343\203\274\343\203\236\343\203\203\343\202\277\343\203\274\343\200\214uroborosql-fmt\343\200\215\343\202\222\343\203\252\343\203\252\343\203\274\343\202\271\360\237\216\211.md" index 65c1b21fda8..6c0610f34a6 100644 --- "a/source/_posts/2025/20250929a_Pure_Rust\343\201\247\347\224\237\343\201\276\343\202\214\345\244\211\343\202\217\343\201\243\343\201\237PostgreSQL\345\205\254\345\274\217\346\247\213\346\226\207\346\272\226\346\213\240SQL\343\203\225\343\202\251\343\203\274\343\203\236\343\203\203\343\202\277\343\203\274\343\200\214uroborosql-fmt\343\200\215\343\202\222\343\203\252\343\203\252\343\203\274\343\202\271\360\237\216\211.md" +++ "b/source/_posts/2025/20250929a_Pure_Rust\343\201\247\347\224\237\343\201\276\343\202\214\345\244\211\343\202\217\343\201\243\343\201\237PostgreSQL\345\205\254\345\274\217\346\247\213\346\226\207\346\272\226\346\213\240SQL\343\203\225\343\202\251\343\203\274\343\203\236\343\203\203\343\202\277\343\203\274\343\200\214uroborosql-fmt\343\200\215\343\202\222\343\203\252\343\203\252\343\203\274\343\202\271\360\237\216\211.md" @@ -35,7 +35,7 @@ lede: "roborosql-fmtの新バージョンv1.0.0をリリースしました。当 また、今回のアップデートについては、以下のシリーズ記事でも詳しく解説しています。 -- 新パーサーの技術詳細: (近日公開予定!) +- [PostgreSQL 全構文対応の Pure Rust な CST パーサーを作ってみた](/articles/20250930a/) - パーサーの置き換え戦略: (近日公開予定!) # 当社のSQLフォーマッター開発の歩みと課題の変遷 @@ -153,4 +153,7 @@ Linter機能は具体的に、以下のような警告・エラーをVSCode上 - [future-architect/uroborosql-fmt - GitHub](https://github.com/future-architect/uroborosql-fmt) -後日postgresql-cst-parser開発の話、パーサー移行に伴うフォーマッター移行作業の話の2本の記事を公開予定です。お楽しみに! +postgresql-cst-parser開発の話、パーサー移行に伴うフォーマッター移行作業の話の2本の記事を公開予定です。お楽しみに! + +- [PostgreSQL 全構文対応の Pure Rust な CST パーサーを作ってみた](/articles/20250930a/) +- パーサーの置き換え戦略: (近日公開予定!) diff --git "a/source/_posts/2025/20250930a_PostgreSQL_\345\205\250\346\247\213\346\226\207\345\257\276\345\277\234\343\201\256_Pure_Rust_\343\201\252_CST_\343\203\221\343\203\274\343\202\265\343\203\274\343\202\222\344\275\234\343\201\243\343\201\246\343\201\277\343\201\237.md" "b/source/_posts/2025/20250930a_PostgreSQL_\345\205\250\346\247\213\346\226\207\345\257\276\345\277\234\343\201\256_Pure_Rust_\343\201\252_CST_\343\203\221\343\203\274\343\202\265\343\203\274\343\202\222\344\275\234\343\201\243\343\201\246\343\201\277\343\201\237.md" new file mode 100644 index 00000000000..ac9b33a016d --- /dev/null +++ "b/source/_posts/2025/20250930a_PostgreSQL_\345\205\250\346\247\213\346\226\207\345\257\276\345\277\234\343\201\256_Pure_Rust_\343\201\252_CST_\343\203\221\343\203\274\343\202\265\343\203\274\343\202\222\344\275\234\343\201\243\343\201\246\343\201\277\343\201\237.md" @@ -0,0 +1,436 @@ +--- +title: "PostgreSQL 全構文対応の Pure Rust な CST パーサーを作ってみた" +date: 2025/09/30 00:00:00 +postid: a +tag: + - Rust + - PostgreSQL + - 構文解析 + - 2WaySQL +category: + - DB +thumbnail: /images/2025/20250930a/thumbnail.png +author: 山田修路 +lede: "先日リリースされたuroboroSQL-fmt ver1.0.0では、過去バージョンの課題を解決するために、新たに自作したパーサーを利用するように変更しました。" +--- +# はじめに + +こんにちは、Core Technology Groupの山田です。 +PostgreSQL のフォーマッターである uroborosql-fmt[^1] の開発に携わっています。 + +先日リリースされたuroboroSQL-fmt ver1.0.0では、過去バージョンの課題を解決するために、新たに自作したパーサーを利用するように変更しました。 + +自作したパーサーであるpostgresql\-cst\-parserはこちらのリポジトリに置いています。 + +1. [tanzaku/postgresql\-cst\-parser](https://github.com/tanzaku/postgresql-cst-parser) +1. [future\-architect/postgresql\-cst\-parser](https://github.com/future-architect/postgresql-cst-parser) + +個人リポジトリの方は実験的に作成していた際のリポジトリで汎用的なパーサーとしての機能のみ実装されており、当社の organization 配下の方はフォーマッターへ組み込むために機能拡張したものです。 + +今回は過去uroborosql-fmtで使用していたパーサーの課題の紹介と、その課題を解決するためにパーサーを自作した話を紹介します。 + +今回のアップデートについては、以下のシリーズ記事でも詳しく解説しています。 + +- リリース概要: [Pure Rustで生まれ変わったPostgreSQL公式構文準拠SQLフォーマッター「uroborosql-fmt」をリリース🎉 ](/articles/20250929a/) +- パーサーの置き換え戦略: (近日公開予定!) + +::: note +本記事のAppendixではflex・bisonの定義ファイルの構造、2WaySQLのエラー回復について説明していますが、発展的な内容であるため、興味のある方以外は読み飛ばしていただいて問題ありません。 +::: + +# 背景 + +uroborosql-fmt では tree-sitter-sql という CST パーサーを用いてパースしていました[^2]。 + +開発初期には当時存在したパーサーを調査し最も有望そうなものを選定しましたが、開発を進めるにつれて tree-sitter-sql の課題[^3]が浮き彫りになってきました。 + +## 1. サポートされている文法が少なく grammar の改善にも工数がかかる + +tree-sitter-sql でサポートされている文法が少なく、フォーマッター改修の際に tree-sitter-sql の変更が伴うことによる工数増や、そもそも tree-sitter-sql に手を入れられる人でないと uroborosql-fmt の改善ができないといった問題がありました。 + +## 2. wasm にコンパイルする際に wasm-bindgen を使用できない + +tree-sitter は C のコードを出力するため、 FFI で uroborosql-fmt からCの関数を呼び出すつくりになっています。 C への FFI を含むため wasm32-unknown-unknown ターゲットでビルドすることができず、 wasm-bindgen を利用できませんでした。そこで emscripten でビルドすることで wasm にコンパイルしていますが、以下の2点の理由でいまいちでした。 + +1. emscripten でビルドしているのでjavascriptから呼び出す際にシンプルにかけない +1. uroborosql-fmt 全体をemscriptenターゲットでビルドするとエラーになるため、tree-sitter-sqlパッケージのみ単体で先にビルドしておくという特殊な手順で何とか回避している + +これらの課題を満たすライブラリが存在しなかった[^4]ため自作してみました。 + +# 方針 + +PostgreSQL のパーサーを Rust に porting することで全ての文法をカバーするパーサーを作成することができるのではないかと考え、その方針で進めました。 + +## PostgreSQLのパーサーの流れ + +PostgreSQL のパーサー[^5]はこのような構成だと認識しています。 + +1. 入力の読み込み +1. 字句解析器による字句解析[^6] +1. 前段で作成したトークンの書換え[^7] +1. 構文解析器で構文解析[^8] + +パース過程のイメージ画像 +2025-02-28_14h09_26.png + +## porting の方針 + +以下の方針で porting を行いました。 + +1. 字句解析器の定義ファイル (scan.l) は規模が小さく更新頻度も高くないため、手で Rust に porting +1. トークンの書換え処理も同様に手で Rust に porting +1. 構文解析器は定義ファイル (gram.y) をパースし、文法定義から構文解析表を生成しパーサーを生成 +1. 構文解析表は比較的大きいサイズなので、wasmにした際のサイズを抑えるために圧縮 + +# 対応 + +具体的な対応内容を紹介します。 + +## 1. PostgreSQL のソースにパッチ適用 + +PostgreSQL の素の字句解析器ではコメントはスキップされてしまうため、コメントもトークン化できるよう PostgreSQL のソースに [libpg_query](https://github.com/pganalyze/libpg_query/tree/17-latest) のパッチを適用しました + +## 2. 字句解析器の C のソースを porting + +字句解析器の定義ファイル (scan.l) に含まれる C のコードを Rust に porting していきました。また、字句解析器の処理で [キーワードか否かを判定しているところ](https://github.com/postgres/postgres/blob/master/src/backend/parser/scan.l#L1079) があるため、[kwlist.h](https://github.com/postgres/postgres/blob/master/src/include/parser/kwlist.h)をパースしキーワードの一覧を作成なども行っています。 +その後、定義やルールを読み込んで、porting した Rust コードとあわせて字句解析器を生成しました。 + +flex の定義ファイルの構造についての簡単な説明は、Appendix.1 flex の定義ファイルの構造をご覧ください。 + +## 3. 構文解析器の porting + +構文解析器の定義ファイル (gram.y) については一切変更を入れず、ファイルの内容を読み込んで構文解析表[^9]を生成しました。 +また、構文解析表を基にLR構文解析を実施する処理は bison の porting ではなく独自にLALR法を実装しました。 + +bison の定義ファイルの構造についての簡単な説明は、Appendix. 2 bison の定義ファイルの構造をご覧ください。 + +## 4. 構文解析表の圧縮 + +構文解析表はサイズがやや大きく、wasm のサイズを小さくするために圧縮して埋め込み、実行時に展開しています。 + +# 完成 + +こちらで[デモ](https://tanzaku.github.io/postgresql-cst-parser/)を用意しているので、興味のある方はぜひ試してみてください。 +gram.y で定義された grammar 通りの CST が出来るため決して使い勝手のよい形のツリーではありませんが、PostgreSQLの全ての構文をカバーしており、フォーマッターに利用するものとしては十分なものが出来たと考えています。 + +また当初想定していなかったメリットとして、2WaySQL で出てくる通常のパーサーではパースエラーとなるような SQL も自然とパースする仕組みを作れるようになりました。 +興味があれば Appendix.3. 2WaySQL のエラー回復をご参照ください。 + +# さいごに + +最初は実験的なコードの予定でしたが、uroborosql-fmt をより発展させていくためにパーサーを置き替えることになり、約半年かけて置き換えを実施しました。自作のパーサーに置き替えることで PostgreSQL のバージョンアップに追従するコストや保守コストなどがかかってくるため負の側面が大きいことも理解していますが、よりよいツールを開発し、生産性や品質を高めるために頑張っていきたいと思っています。 + +crateもリリースしておいたので、興味があればぜひ使ってみてください。 + +- [postgresql-cst-parser - crates.io: Rust Package Registry](https://crates.io/crates/postgresql-cst-parser) + +# Appendix + +## 1. flex の定義ファイルの構造 + +flex の定義ファイルは以下のような構造になっています。 +※ PostgreSQL の定義ファイルの雰囲気を理解できる最低限の内容に絞っています。 + +```flex +定義セクション +%% +ルールセクション +%% +ユーザーコード +``` + +### 定義セクション + +定義セクションでは、字句解析器の状態の定義と、ルールセクションで使用するパターンの定義を行うことができます。 + +`%x` で始まる行は字句解析器の状態定義です。 +各状態の説明は以下に記載があります。 +[postgres/src/backend/parser/scan\.l at REL\_16\_STABLE · postgres/postgres](https://github.com/postgres/postgres/blob/REL_16_STABLE/src/backend/parser/scan.l#L176) + +```l +%x xb +%x xc +%x xd +%x xh +%x xq +%x xqs +%x xe +%x xdolq +%x xui +%x xus +%x xeu +``` + +ルールセクションで使用するパターンの定義は以下のように行うことができます。 +この例では、数字一桁と数字複数桁の定義である decdigit, decinteger の定義が行われています。 + +```l +decdigit [0-9] +decinteger {decdigit}(_?{decdigit})* +``` + +### ルールセクション + +ルールセクションは字句解析器のメインの部分で、状態ごとにルールにマッチした際のアクションを定義することができます。 +アクションはCのコードになっており、この中で字句解析器の状態を変更したり、トークンを受理することができます。 +特に状態が指定されていない場合は、INITIALというデフォルト状態のパターンとして認識されます。 + +```c +/* 単一パターンの書き方 */ +パターン アクション + +/* 同一状態の複数パターンをまとめて記述する書き方 */ +<状態名>{ +パターン アクション +パターン アクション +} + +/* 特定状態の単一パターンのみ記述する書き方 */ +<状態名1,状態名2,...>パターン アクション + +/* 複数のパターンのアクションをまとめる書き方 */ +<状態名>パターン1 | +<状態名>パターン2 アクション +``` + +#### 状態遷移の例 + +アクション部で `BEGIN(遷移先の状態)` と書くことで、別の状態に遷移することができます。 +以下の例では `{xcstart}` のパターンにマッチした際に、`BEGIN(xc)` を呼び出すことでC形式のコメント内部を表す xc に遷移しています。 + +```l +{xcstart} { + /* Set location in case of syntax error in comment */ + SET_YYLLOC(); + yyextra->xcdepth = 0; + BEGIN(xc); + /* Put back any characters past slash-star; see above */ + yyless(2); + } +``` + +#### 余談 + +定義ファイルを見ると、これまで知らなかった書き方を知ることがあります。 + +一例ですが `select n'1';` のように文字列の前に `n` というプレフィックスを付与することが定義できるというのは、この作業を通じて知りました。 + +この仕様はドキュメントでは見つけられませんでしたが、flex の定義ファイルの以下の部分を眺めることで知ることができ、こういったマイナーな書き方の発見もパーサー作成の面白さの一つだなと感じました。 + +```l +/* National character */ +xnstart [nN]{quote} + +{xnstart} { + /* National character. + * We will pass this along as a normal character string, + * but preceded with an internally-generated "NCHAR". + */ + int kwnum; + + SET_YYLLOC(); + yyless(1); /* eat only 'n' this time */ + + kwnum = ScanKeywordLookup("nchar", + yyextra->keywordlist); + if (kwnum >= 0) + { + yylval->keyword = GetScanKeyword(kwnum, + yyextra->keywordlist); + return yyextra->keyword_tokens[kwnum]; + } + else + { + /* If NCHAR isn't a keyword, just return "n" */ + yylval->str = pstrdup("n"); + return IDENT; + } + } +``` + +### 参考 + +1. Lexical Analysis With Flex, for Flex 2.6.2: Format https://westes.github.io/flex/manual/Format.html#Format +1. Flex: 3. Flex記述言語 https://web.sfc.wide.ad.jp/~sagawa/gnujdoc/flex-2.5.4/flex-ja_3.html +1. Flex - Flex記述言語 https://www.asahi-net.or.jp/~wg5k-ickw/html/online/flex-2.5.4/flex_5.html + +## 2. bison の定義ファイルの構造 + +bison の定義ファイルは以下のような構造になっています。 +※ PostgreSQL の定義ファイルの雰囲気を理解できる最低限の内容に絞っています + +```c +%{ +C宣言部(C declarations) +%} + +Bison宣言部(Bison declarations) + +%% +文法規則部(Grammar rules) +%% + +追加のCプログラム部(Additional C code) +``` + +上の構造は[こちら](https://guppy.eng.kagawa-u.ac.jp/2019/Compiler/bison-1.2.8/bison-ja_6.html#:~:text=%E7%B5%82%E3%82%8F%E3%82%8A%E3%81%BE%E3%81%99%E3%80%82-,Bison%E6%96%87%E6%B3%95%E3%81%AE%E6%A6%82%E8%A6%81,-Bison%E6%96%87%E6%B3%95%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB) に記載されています。 + +### Bison宣言部 + +#### 1. tokenの宣言 + +パーサーで使用するトークンの宣言を行うことができます。 + +```l +%token IDENT UIDENT FCONST SCONST USCONST BCONST XCONST Op +%token ICONST PARAM +%token TYPECAST DOT_DOT COLON_EQUALS EQUALS_GREATER +%token LESS_EQUALS GREATER_EQUALS NOT_EQUALS +``` + +#### 2. 結合性の宣言 + +結合性の宣言を行うことができます。 +%leftで左結合、%rightで右結合、%nonassocで無結合を宣言できます。 +また優先度が低い順に記載されており、この例では OR より AND の方が優先度が高いことがわかります。 + +```l +/* Precedence: lowest to highest */ +%left UNION EXCEPT +%left INTERSECT +%left OR +%left AND +%right NOT +%nonassoc IS ISNULL NOTNULL /* IS sets precedence for IS NULL, etc */ +%nonassoc '<' '>' '=' LESS_EQUALS GREATER_EQUALS NOT_EQUALS +%nonassoc BETWEEN IN_P LIKE ILIKE SIMILAR NOT_LA +%nonassoc ESCAPE /* ESCAPE must be just above LIKE/ILIKE/SIMILAR */ +``` + +### 文法規則部 + +以下のような形式で文法規則が与えられます。 + +```l +非終端記号: ルール1 { アクション1 } + | ルール2 { アクション2 } +``` + +具体例は以下のようになります。 + +```l +parse_toplevel: + stmtmulti + { + pg_yyget_extra(yyscanner)->parsetree = $1; + (void) yynerrs; /* suppress compiler warning */ + } + | MODE_TYPE_NAME Typename + { + pg_yyget_extra(yyscanner)->parsetree = list_make1($2); + } + ... + ; +``` + +各ルールは優先度を持ち、優先度はそのルールにでてくる最後の終端記号と同じになります。 +デフォルトとは異なる優先度を設定する場合、以下のように `%prec` で指定することができます。 + +```l +SelectStmt: select_no_parens %prec UMINUS + | select_with_parens %prec UMINUS + ; +``` + +### 参考 + +1. Bison 3.8.1 https://www.gnu.org/software/bison/manual/bison.html +1. Bison 1.28 - Bison文法ファイル https://guppy.eng.kagawa-u.ac.jp/2019/Compiler/bison-1.2.8/bison-ja_6.html +1. Bison入門: 1. Bisonの概念 https://web.sfc.wide.ad.jp/~sagawa/gnujdoc/bison-1.28/bison-ja_4.html + +## 3. 2WaySQL のエラー回復 + +### 2WaySQLとは + +コメントで制御フローやバインド変数などを記述し、動的に SQL を生成するような実行方法です。動的生成に関わる部分がコメントで記載されており、単体の SQL 文としても実行できるため 2Way と呼ばれています。 +上述の通り 2WaySQL は基本的には単体の SQL ファイルとして実行可能になっていますが、時に単体では SQL として実行できないようなケースも存在します。 + +当社で開発、公開しているOSSである [uroboroSQL](https://future-architect.github.io/uroborosql-doc/) も 2WaySQL が利用可能なライブラリで、uroborosql-fmt は 2WaySQL のフォーマットもサポートしています。以下の説明では [uroboroSQL](https://future-architect.github.io/uroborosql-doc/) の 2WaySQL 前提としています。 + +### 1. バインドパラメータのサンプル値漏れ + +uroboroSQLでは、以下のようにバインドパラメータをセットすることができます。この SQL を uroboroSQL を使わずに実行した場合は name カラムに foo という値がセットされ、uroboroSQL で実行した場合には 'foo' は無視され name にバインドした値で置き替えられます。 + +```sql +select + /*name*/'foo' as name +; +``` + +この 'foo' のように、バインドパラメータ等の直後の仮置きの値のことをサンプル値と呼んでいます。 +サンプル値が無くても uroboroSQL では実行できてしまうため、以下のようにサンプル値のないSQLが作成されてしまうことがあります。サンプル値漏れのSQLは一般的なパーサーではエラーになってしまいますが、新パーサーではサンプル値漏れでエラーになるケースでエラー回復することができます。 + +```sql +select + /*name*/ as name -- バインドパラメータのサンプル値が欠けている +; +``` + +### 2. 置換文字列のサンプル値漏れ + +以下のような置換文字列でも同様にサンプル値が漏れていることがありますが、こちらも同様にエラーを回復することができます。 + +```sql +select + * +from /*$table_name*/ -- 置換文字列のサンプル値が欠けている +; +``` + +### 3. 不要なカンマ + +uroboroSQL では、以下のようにselectやorder byの直後に余計なカンマがあっても実行できます[^10]。サンプル値漏れと同様に通常のパーサーではエラーになりますが、新パーサーではこちらもエラー回復し、さらに余計な `,` を保持した CST を構築することができます。 + +```sql +select +/*IF detail*/ +, first_name -- 不要なカンマがあり、多くのパーサーではパースできない +, last_name +, birth_date +, gender +/*END*/ +, emp_no +from + employee emp +order by +/*IF detail*/ +, birth_date -- 不要なカンマがあり、多くのパーサーではパースできない +/*END*/ +, emp_no +``` + +### 4. 不要なand/or + +uroboroSQL では、以下のように where の直後に余計な and/or があっても実行できます。新パーサーではこちらもエラー回復し、余計な and/or を保持した CST を構築することができます。 + +```sql +select + 1 +from + employee emp +where +and emp.id = 1 -- 余計なand/orが先頭にある +``` + + +[^1]:[新しいSQLフォーマッターであるuroboroSQL\-fmtをリリースしました \| フューチャー技術ブログ](https://future-architect.github.io/articles/20231120a/) +[^2]:[Engineer Camp2022 RustでSQLフォーマッタ作成(前編) \| フューチャー技術ブログ](https://future-architect.github.io/articles/20220916b/#%E4%BD%9C%E6%88%90%E3%81%97%E3%81%9F%E3%83%95%E3%82%A9%E3%83%BC%E3%83%9E%E3%83%83%E3%82%BF%E3%81%AE%E5%87%A6%E7%90%86%E3%81%AE%E6%B5%81%E3%82%8C) +[^3]:ANTLR や tree-sitter などを見ると様々な言語のパーサーやグラマーはインターネットには溢れており、パースすることは一軒容易に見えるかもしれません。しかし私の所属するチームでの経験から考えると、対象言語の文法を網羅し実用的なパフォーマンスで動作するパーサーは、公式で提供されているパーサー以外では非常に少ないのではないかと思います。(少なくとも私は出会ったことがありません) +[^4]:本パーサーの開発当時、PostgreSQL の CST パーサーでデファクトと言えるものは存在しないようで、 supabase でも[独自に CST パーサーを開発](https://supabase.com/blog/postgres-language-server-implementing-parser) しているようです。ただ、こちらは PostgreSQL の C ソースを含む[pg_query.rs](https://github.com/pganalyze/pg_query.rs)を利用していることから wasm にビルドするのは容易でないと考えています。 +[^5]:PL/pgSQL は別の grammar が存在するので、本パーサーでは現在サポートしていません。 +[^6]:字句解析器は flex を用いて [scan.l](https://github.com/postgres/postgres/blob/master/src/backend/parser/scan.l) から生成 +[^7]:書換え箇所はこちらです [postgres/src/backend/parser/parser\.c at REL\_16\_STABLE · postgres/postgres](https://github.com/postgres/postgres/blob/REL_16_STABLE/src/backend/parser/parser.c#L195) +[^8]:構文解析器は bison を用いて [gram.y](https://github.com/postgres/postgres/blob/master/src/backend/parser/gram.y) から生成 +[^9]:アクションは無視しているため本来はエラーになるべきSQLがエラーにならなかったりするのですが、それは許容しています +[^10]:詳しくは [uroboroSQL のドキュメント](https://future-architect.github.io/uroborosql-doc/background/#%E4%B8%8D%E8%A6%81%E3%81%AA%E3%82%AB%E3%83%B3%E3%83%9E%E3%81%AE%E9%99%A4%E5%8E%BB)を参照ください。 + diff --git a/source/images/2025/20250930a/2025-02-28_14h09_26.png b/source/images/2025/20250930a/2025-02-28_14h09_26.png new file mode 100644 index 0000000000000000000000000000000000000000..5db248e1b09cb5e891cdfe987b12909b23542900 GIT binary patch literal 38281 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≪)zOz_P zOg%ox+2Fs8tvDNM-|p(lOT0x%W82u;+zhs%SJrZ=JL+DuZFCYYC@z+X%c~ptM6RN$ zDiM!2YrI|k-*d?_?a&pKQfJPL#4*(>Oc1FR|3ob_;xm2PN?s?C%*?)&JEjGq;czZj zRgEuM%bTR59^L;I2Ho6ZZp)|V=dsN2Xq0Fzd&_&qMP?t*+(ik~{;qa-KF{RK31zW( zns5Po4K(i()%AvHJ}*<$Eqy%1U?W0-_wR;4AR3HNBLVFhoGev|(fGo>cS1WQkJ~wQ z=#X2l8zVFTY`DYmr4(v;=CxyIuo(xhTS^ERz6`;z#xY`waSYW=m!6hKJknCQDAE=`^CIs!a2bkA?cHM4l(7qxuQ~(InQ-y;7t& z35i~A|0v~woLoGoRyHjzcC3Zj$$8~E$MK;|qG{()>s)A#6>pMK@(b#{aQ|=ZOCuT{ z09kjOp=fn!W|4yv+$V;Eob3i|*W?-{@#Z&=)ESp~j}B)5o1H zQq(=pPobrV1*4>}?V|7=d$5CRUu#-xSp%#8mYWu%0?P+k{w}HG%AdWAaWyOStsP?1 zzR>bpw)8U`SL2zLby+l?AgUuJy4%HfYHa9mJXRQ7MCo|OMF9NVJNX(@pCQf8rd|oO$QWAYN{WD>X)=R6P3_l`FU*7YBLYVo64v( zAqeC|ELWkuKb-Q%(%miw`rst*0!N|kT>3Z$^RJ?!A|(a?t4;AGAP1Vcdg_{6qc21Re~n40f>utUN||Tblf^}2XsrR*3xM-Kkq4!;W;Ik-%M6P_ r{#Y>K8-cFBSL^9tzLUbhyuaUFQVZettdT>%7X%|Cp&(u%YT)-jkpg71 literal 0 HcmV?d00001