一个查询通过 TCP/IP 或 Unix 域套接字到达后端的的数据包。它被加载到一个字符串中,并传递给 解析器, 其中词法扫描器 scan.l, 将查询分解为标记(单词)。解析器使用 gram.y 和这些标记来识别查询类型,并加载特定的查询结构,例如 CreateStmt 或 SelectStmt。
然后,该语句被识别为复杂(SELECT / INSERT / UPDATE / DELETE)或简单,例如 CREATE ROLE、ANALYZE 等。不需要执行器的简单实用程序命令由commands模块中的特定于语句的函数处理。复杂语句需要更多处理。
解析器获取一个复杂的查询,并创建一个 Query 结构,其中包含复杂查询使用的所有元素。Query.jointree 包含 FROM 和 WHERE 子句,由 transformFromClause() 和 transformWhereClause() 填充。查询中引用的每个表都由一个 RangeTblEntry 表示,并将它们链接在一起以形成查询的范围表,该表由 transformFromClause() 生成。Query.rtable 保存查询的范围表。
某些查询(如 SELECT)会返回数据列。其他查询(如 INSERT 和 UPDATE)则指定查询修改的列。这些列引用将转换为 TargetEntry 条目,这些条目链接在一起以构成查询的目标列表。目标列表存储在 Query.targetList 中,该列表由 transformTargetList() 生成。
其他查询元素(如聚合函数 (SUM())、GROUP BY 和 ORDER BY)也存储在它们自己的 Query 字段中。
下一步是由任何可能应用于查询的 VIEWS 或 RULES 修改 Query。这由 重写 系统执行。
优化器 使用 Query 结构来确定 RangeTable 中每个表的最佳表连接顺序和连接类型,使用 Query.jointree(FROM 和 WHERE 子句)来考虑最佳索引使用。
path 模块然后生成一个最佳的 Plan, 其中包含要执行查询的操作。然后,Plan 被传递给 执行器 进行执行,并将结果返回给客户端。Plan 实际上是一组节点,排列成一个树形结构,其中包含一个顶级节点和各种子节点作为子节点。
还有许多其他模块支持此基本功能。可以通过单击流程图来访问它们。