该解析器阶段包含两个部分
在gram.y
和scan.l
中定义的解析器是使用 Unix 工具bison和flex构建的。
该转换过程对解析器返回的数据结构进行修改和增强。
解析器必须检查查询字符串(以纯文本形式传入)的语法是否有效。如果语法正确,则会构建一个解析树并返回;否则,将返回错误。解析器和词法分析器是使用广为人知的 Unix 工具bison和flex实现的。
词法分析器定义在文件scan.l
中,负责识别标识符、SQL 关键字等。对于找到的每个关键字或标识符,都会生成一个标记并将其传递给解析器。
解析器定义在文件gram.y
中,包含一组语法规则和在规则触发时执行的操作。操作的代码(实际上是 C 代码)用于构建解析树。
文件scan.l
使用flex程序转换为 C 源文件scan.c
,而gram.y
使用bison程序转换为gram.c
。在这些转换完成后,可以使用普通的 C 编译器来创建解析器。切勿对生成的 C 文件进行任何修改,因为它们将在下次调用flex或bison时被覆盖。
提到的转换和编译通常使用PostgreSQL源分发包中附带的Makefile自动完成。
对bison或gram.y
中给出的语法规则进行详细描述将超出了本手册的范围。有许多书籍和文档涉及flex和bison。在开始研究gram.y
中的语法之前,您应该熟悉bison,否则您将无法理解那里发生了什么。
解析器阶段仅使用关于 SQL 语法结构的固定规则来创建解析树。它不进行任何系统目录查找,因此无法理解所请求操作的详细语义。解析器完成后,转换过程将解析器返回的树作为输入,并进行必要的语义解释,以理解查询引用的表、函数和运算符。用于表示此信息的构建的数据结构称为查询树。
将原始解析与语义分析分开的原因是,系统目录查找只能在事务内进行,而我们不希望在接收到查询字符串后立即启动事务。原始解析阶段足以识别事务控制命令(如BEGIN
、ROLLBACK
等),这些命令可以正确执行而无需进一步分析。一旦我们知道正在处理实际查询(如SELECT
或UPDATE
),就可以在尚未处于事务中的情况下启动事务。只有这样,才能调用转换过程。
转换过程创建的查询树在大多数地方在结构上与原始解析树相似,但在细节上有很多差异。例如,解析树中的FuncCall
节点代表看起来像函数调用的内容。这可能会根据引用的名称被转换为FuncExpr
或Aggref
节点,具体取决于引用名称是普通函数还是聚合函数。此外,有关列和表达式结果的实际数据类型的信息也会添加到查询树中。
如果您在文档中发现任何不正确、与您对特定功能的使用经验不符或需要进一步阐明的内容,请使用此表格报告文档问题。