バージョンごとのドキュメント一覧

52.3. 構文解析過程 #

<title>The Parser Stage</title>

The <firstterm>parser stage</firstterm> consists of two parts: 構文解析過程は2つの部分から構成されています。

52.3.1. パーサ #

<title>Parser</title>

The parser has to check the query string (which arrives as plain text) for valid syntax. If the syntax is correct a <firstterm>parse tree</firstterm> is built up and handed back; otherwise an error is returned. The parser and lexer are implemented using the well-known Unix tools <application>bison</application> and <application>flex</application>. パーサは、(平文のテキストとして渡される)問い合わせ文字列が正しい構文になっているかチェックしなければいけません。 もし構文が正しい場合は構文解析ツリーが作られて返されます。 正しくない場合はエラーが返されます。 パーサと字句解析はUnixでよく知られたツールのbisonflexを使用して実装されています。

The <firstterm>lexer</firstterm> is defined in the file <filename>scan.l</filename> and is responsible for recognizing <firstterm>identifiers</firstterm>, the <firstterm>SQL key words</firstterm> etc. For every key word or identifier that is found, a <firstterm>token</firstterm> is generated and handed to the parser. 字句解析はファイルscan.lで定義され、識別子SQLキーワードなどの確認を担当します。 検出された全てのキーワードや識別子に対しトークンが生成されパーサに渡されます。

The parser is defined in the file <filename>gram.y</filename> and consists of a set of <firstterm>grammar rules</firstterm> and <firstterm>actions</firstterm> that are executed whenever a rule is fired. The code of the actions (which is actually C code) is used to build up the parse tree. パーサはファイルgram.yの中で定義され、文法ルールとルールが実行された時に実行されるアクションの組から構成されています。 アクションのコード(実際はC言語コードです)は構文解析ツリーを作るのに使われます。

The file <filename>scan.l</filename> is transformed to the C source file <filename>scan.c</filename> using the program <application>flex</application> and <filename>gram.y</filename> is transformed to <filename>gram.c</filename> using <application>bison</application>. After these transformations have taken place a normal C compiler can be used to create the parser. Never make any changes to the generated C files as they will be overwritten the next time <application>flex</application> or <application>bison</application> is called. ファイルscan.lはプログラムflexを使ってCのソースファイルscan.cに変換されます。 そしてgram.ybisonを使ってgram.cに書き換えられます。 これらの書き換えが終わると、パーサを作るために通常のCコンパイラが使えるようになります。 生成されたCのファイルには絶対に変更を加えないでください。 と言うのは次にflexもしくはbison が呼ばれた時に上書きされるからです。

注記

The mentioned transformations and compilations are normally done automatically using the <firstterm>makefiles</firstterm> shipped with the <productname>PostgreSQL</productname> source distribution. ここで言及した書き換えやコンパイルは通常PostgreSQLのソースと一緒に配布されるmakefileを使って自動的に行われます。

A detailed description of <application>bison</application> or the grammar rules given in <filename>gram.y</filename> would be beyond the scope of this manual. There are many books and documents dealing with <application>flex</application> and <application>bison</application>. You should be familiar with <application>bison</application> before you start to study the grammar given in <filename>gram.y</filename> otherwise you won't understand what happens there. bisonまたはgram.yで定義される文法ルールの詳細は本稿では説明しきれません。 flexbisonについては本や資料がたくさん出ています。 gram.yの文法の勉強を始める前にbisonの知識が必須となります。 その知識なしではそこで何が起こっているのかを理解することは難しいでしょう。

52.3.2. 書き換えプロセス #

<title>Transformation Process</title>

The parser stage creates a parse tree using only fixed rules about the syntactic structure of SQL. It does not make any lookups in the system catalogs, so there is no possibility to understand the detailed semantics of the requested operations. After the parser completes, the <firstterm>transformation process</firstterm> takes the tree handed back by the parser as input and does the semantic interpretation needed to understand which tables, functions, and operators are referenced by the query. The data structure that is built to represent this information is called the <firstterm>query tree</firstterm>. 構文解析過程ではSQLの構文構造に関する固定ルールのみを使って構文解析ツリーを作成します。 システムカタログの参照を行わないので、要求されている操作の詳細な語義は理解しません。 構文解析が終わった後に入力としてパーサから戻されたツリーを書き換えプロセスが引き受け、どのテーブル、関数、そして演算子が問い合わせによって参照されているのかの判断に必要な語義翻訳を行います。 この情報を表すために作成されるデータ構造を問い合わせツリーと呼びます。

The reason for separating raw parsing from semantic analysis is that system catalog lookups can only be done within a transaction, and we do not wish to start a transaction immediately upon receiving a query string. The raw parsing stage is sufficient to identify the transaction control commands (<command>BEGIN</command>, <command>ROLLBACK</command>, etc.), and these can then be correctly executed without any further analysis. Once we know that we are dealing with an actual query (such as <command>SELECT</command> or <command>UPDATE</command>), it is okay to start a transaction if we're not already in one. Only then can the transformation process be invoked. 語義解釈と入力の構文解釈を切り分ける理由は、システムカタログの参照はトランザクション内でのみ行うことができますが、問い合わせ文字列を受け取ってすぐにトランザクションを開始することは好ましくないと考えられるからです。 入力に対する構文解析過程ではトランザクション管理コマンド(BEGINROLLBACKなど)を特定するだけで十分であるとともに、それ以上の分析を行わなくても正しい処理が実行されます。 実際の問い合わせ(例えばSELECTもしくはUPDATE)に関わっていると言うことがわかっていて既にあるトランザクション内にいなければ新規トランザクションを開始することは問題ありません。 これ以降に限り書き換えプロセスを起動することができます。

The query tree created by the transformation process is structurally similar to the raw parse tree in most places, but it has many differences in detail. For example, a <structname>FuncCall</structname> node in the parse tree represents something that looks syntactically like a function call. This might be transformed to either a <structname>FuncExpr</structname> or <structname>Aggref</structname> node depending on whether the referenced name turns out to be an ordinary function or an aggregate function. Also, information about the actual data types of columns and expression results is added to the query tree. 書き換えプロセスで作成された問い合わせツリーはほとんどの箇所で加工されていない構文解析ツリーに構造的には似ていますが、細部では数多くの相違が存在します。 例えば、構文解析ツリーのFuncCallノードは構文的には関数呼び出しのように見える何かを表わしています。 これは参照された名前が通常の関数になるか集約関数となるかによってFuncExprもしくはAggrefに書き換えられることがあります。 さらに、列の実際のデータ型と式の結果についての情報が問い合わせツリーに書き加えられます。