PostgreSQL学习笔记搭建了Postgres在Windows上的编译调试环境.doc_第1页
PostgreSQL学习笔记搭建了Postgres在Windows上的编译调试环境.doc_第2页
PostgreSQL学习笔记搭建了Postgres在Windows上的编译调试环境.doc_第3页
PostgreSQL学习笔记搭建了Postgres在Windows上的编译调试环境.doc_第4页
PostgreSQL学习笔记搭建了Postgres在Windows上的编译调试环境.doc_第5页
免费预览已结束,剩余19页可下载查看

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

PostgreSQL学习笔记YY 搭建了Postgres在Windows上的编译调试环境分析Postgresql源代码 2011-07-01 15:58:41| 分类: IT-POSTGRESQL | 标签: |字号大中小 订阅 分析Postgresql源代码(01) 向前走,你就会产生勇气。现在,让我们一起来踏上postgresql源代码分析的艰辛之路吧。欲善其事,必利其器,我将在这第一篇文章中向你介绍如何做准备工作。 1)准备用于分析的源代码 首先,到去下载源代码,最好是下载那个全部打包在一起,8MB多的文件,然后,在linux下编译安装,最后将成功编译后的源代码打包拷回windows环境,因为我推荐的源代码分析工具都是windows环境下的 2)准备用于分析源代码的工具 可以在两个方案中选择: SourceInsight, Microsoft visual c+(可以再加上visual assistant) 我推荐SourceInsight 3)准备参考书籍 关于数据库系统理论的书籍,下面二选一: 数据库系统概论(第三版),萨师煊、王珊,高等教育出版社 数据库系统概念(第四版影印版),Abraham Silberschatz等,高等教育出版社 关于数据库系统实现的书籍,下面二选一: 数据库系统实现(中文版),杨冬青等译,机械工业出版社 数据库系统实现(英文版),Hector Garcia-Molina等,机械工业出版社 关于Unix编程 Unix环境高级编程, 尤晋元等译,机械工业出版社 4)准备向别人求教 我个人以为,postgresql源代码分析是需要相当长一段时间的。在这漫长的时间和庞大的代码量面前,我觉得进行分析的人目前的水平如何倒不是很重要的了,重要的是耐心和毅力。我特别希望这里能够成为切磋讨论的地方,所以有问题,就可以优先考虑到这里来发问。 发表于 2009-9-24 23:55 | 只看该作者 分析Postgresql源代码(02) 这一篇短文中,将介绍postgresql源代码的组成。先感谢鼓励我做源代码分析的兄弟,呵呵,你们的鼓励也许将我推上了一条不归路。 从Linux下拷回通过编译的源代码后,在硬盘上展开,例如我展开后将所有的源代码放到D:Postgresqlsource目录下。然后建立一个目录D:Postgresqlinsight,打开sourceinsight后在这个目录下创建一个project,将D:Postgresqlsourcebackend目录下的所有文件加入该项目 然后找到D:Postgresqlsourcedocpostgres.tar.gz,将它解开到D:Posgresqldoc目录下,再用浏览器打开D:Postgresqldochtmlindex.html并按ctrl+d加入收藏夹,有时间的话,最好先读完这份文档(这份文档有laser的中文翻译版)。另外再用浏览器打开D:Postgresqlsourcesrctoolsbackendindex.html,将它也加入收藏夹,这份文档的名称是How PostgreSQL Processes a Query,随便点击文档中的图上任一框即转到postgresql源代码组成介绍,大致意思翻译如下: PostgreSQL的Backend目录 作者:Bruce Momjian - 点击小节的标题即可见到该节的源代码 bootstrap - 通过initdb创建最初的数据库模板 几乎PostgreSQL的每一个操作都需要存取系统表,那么如何创建这些系统表呢?不能以通常的方式创建这些系统表并向其中插入数据,因为表的创建和插入要求系统表已经存在。这一部分代码的目的就是使用一种仅仅在bootstrap过程中使用的特殊方法来直接建立系统表 main - 将控制转到postmaster或postgres 检查进程名(argv0)和各种标志, 然后将控制转到postmaster或postgres postmaster - 控制postgres服务器启动/终止 创建共享内存,然后进入一个循环等待连接请求。当一个连接请求到达时,启动一个postgres后台服务进程,将连接转给它 libpq - 后台服务器libpq库函数 处理与客户进程间的通讯 tcop - 将请求分派到合适的模块 这是postgres后台服务进程的主要处理部分, 它调用parser, optimizer, executor, 和commands中的函数 parser - 将SQL查询转化为查询树 将来自libpq的SQL查询转换为命令形式的结构供optimizer/executor或commands使用.首先对SQL语句进行词法分析,转换为关键字,标识符和常量,然后进行语法分析。语法分析生成命令形式的结构来表示查询的组成。然后这个命令形式的结构被分离、检查和传送给commands中的处理函数,或者转换为结点链表供optimizer和executor处理 optimizer - 创建查询路径和查询计划 使用parser的输出来为executor生成优化了的查询计划. optimizer/path - 使用parser的输出创建查询路径 它使用parser的输出生成所有可能的执行方法,它检查表的连接顺序,where子句限制和optimizer的表统计信息来评估每一个可能的执行方法,并赋予每个方法一个代价 optimizer/geqo - 遗传算法查询优化 optimizer/path对所有连接表的方法进行了评估。但是当表的数目变得很大时,检测测的数目也会变得很大。遗传算法查询优化对每一个表进行考虑,然后计算出最优的顺序来执行连接。如果只有几个表,这种方法花费较长的时间,但对于大量的表,这种方法就比较快了。系统有一个选项用于控制何时使用这个功能 optimizer/plan - 优化path输出 为optimizer/path的输出选择代价最小的路径并创建一个执行计划 optimizer/prep - 处理特殊的查询计划 对特殊的查询计划进行处理 optimizer/util - 优化器支持函数 供优化器其他部分使用的函数 executor - 执行来自optimizer的复杂的节点形式的查询计划 处理select, insert, update,和delete语句. 处理这些语句的操作包括堆扫描、索引扫描、排序、连接表、分组、计算集函数和唯一性处理 commands - 不需要executor执行的命令 执行不需要复杂处理的SQL命令.包括vacuum, copy, alter, create table, create type以及许多其他未能例举的命令。调用这一部分代码时使用由parser生成的结构.大多数的函数先做一些处理,然后就调用catalog目录下的一些低层函数来做实际的工作 catalog - 系统目录操作 包含用于操作系统表和系统目录的函数.表、索引、过程、运算符、类型、和集函数的创建和操纵函数在这里可以找到。它们都是低层的函数,通常由上层将用户请求格式化为预定义格式的函数调用 storage - 管理各种类型的存储系统 支持服务器以统一的方式存取资源 storage/buffer - 共享缓冲区管理 storage/file - 文件管理 storage/ipc - 信号灯和共享内存 storage/large_object - 大对象 storage/lmgr - 锁管理器 storage/page - 页管理器 storage/smgr - 存储/磁盘管理器 access - 各种存取方法 支持堆, 索引, 和事务对数据的存取 access/common - 公共存取函数 access/gist - 可自定义的存取方法 access/hash - hash access/heap - 堆用于存取表 access/index - 所有索引类型都使用 access/nbtree - Lehman and Yao的btree管理算法 access/rtree - 用于索引2维数据 access/transam - 事务管理器(BEGIN/ABORT/COMMIT) nodes - 创建/操纵节点和链表 PostgreSQL将SQL查询存储到称为节点的结构中。节点是通用的容器,它包含一个类型字段和一个与类型有关的数据字段.节点通常串成链表。 链表包含一个元素和一个next指针.节点和链表广泛的用于parser,optimizer,和executor中用于存储请求和数据 utils - 支持程序 utils/adt - 内建数据类型 包含所有PostgreSQL自带数据类型 utils/cache - system/relation/function高速缓存 PostgreSQL支持自定义数据类型,因此没有数据类型是固化在核心当中的。当服务器需要查找一个数据类型时它就到系统表中去找。由于系统表频繁使用,所以设立一个高速缓存来加速查找。系统中包括一个系统关系cache, 一个函数/运算符cache和一个关系信息cache. 关系信息cache中包含所有最近访问过的表的信息而不仅仅包含系统表的信息 utils/error - 错误报告 向前台报告后台错误 utils/fmgr - 函数管理器 处理动态加载函数的调用和在系统表中定义的函数的调用 utils/hash - 内部使用的hash程序 用于cache和内存管理器以便快速查找动态存储的数据结构 utils/init - 各种初始化 utils/misc - 未归类的东东 utils/mmgr - 内存管理器(进程私有内存) PostgreSQL在显式的内存上下文中分配内存. 上下文可以是语句级、事务级或永久/全局级的.这样,后台服务器可以很容易地在一个语句或者事务结束的时候释放内存 utils/sort - 排序 在内存中或者使用磁盘文件排序 utils/time - 事务时间限定 检查元组是否仍然有效,还是属于未提交事务或者已被新行替代 include - 包含文件 每个子系统有一个目录 lib - 支持库 几个通用的程序 regex - 正规表达式库 用于后台服务器的正规表达式处理如. rewrite - 规则系统 完成规则系统的处理 tioga - 未用 (数组处理?) - 维护者: Bruce Momjian (pgmancandle.pha.pa.us) 最后更新于: Tue Dec 9 17:56:08 EST 1997 组成postgresql后台进程的源代码都在D:Postgresqlsourcesrcbackend目录下,上面这份文档中的小节标题就是子目录名称。面对着这份文档,该从哪里下手呢?我觉得所有服务器源代码大致可以分为四个组成部分:工具部分,查询处理部分,事务存储管理部分,系统初始化部分。工具部分基本集中于utils目录下,对于新手,可以由此入手感觉一下,例如分析分析mmgr的对外接口和内部实现算法。查询部分主要是tcop/rewrite/parser/optimizer/executor/commands等等。我打算从事务存储管理部分入手分析,主要的代码集中在storage/access之下。系统初始化部分最好到最后在分析。上面讲的还只是后台服务器,其他还有一些东东如odbc/jdbc、各种语言接口、管理工具如pgAdmin/pgAccess等等 接下来我要利用空闲时间读代码,估计要过一段时间(1-3个月?)才能再来和大家分享心得体会,热情希望和我有相同兴趣的兄弟也能利用自己工作之余的时间来做做源代码分析。 分析Postgresql源代码(03) 在上一篇文章中,laser讲到了他在postgresql 7.3的上的工作计划,我看了以后觉得自己应该向laser好好学习。我研究了一下postgresql的本地化问题,没有搞清楚,最后还是觉得我现在还是没有实力,不如仍然按照我自己的想法前进吧。这一篇文章,我想和大家讨论postgresql的内存管理问题,先发言如下 我这里所说的postgresql的内存管理对应的源代码在utils/mmgr目录之下。我们知道,编写c程序往往需要用malloc为指针变量分配内存,再在适当的时候用free回收分配给该指针变量的内存,malloc/free是必须配对使用的,如果不配对,就会产生内存泄漏的问题,久而久之就会导致所有的内存被用光。另外一个方面,在postgresql中会进行频繁的小块内存(几个字节到几k字节)的分配与回收,这样可能会产生大量的内存碎片,导致内存得不到有效的利用。postgresql的内存管理子系统的主要目的就是解决这两个问题 内存泄漏的问题。有的语言如java,有自动回收机制,不会产生内存泄漏问题。但c语言则不然,这个问题交给了程序员自己来处理。我听说,c+的stl中内存泄漏问题处理得很好,可以使得使用stl的程序员不需要担心内存泄漏的问题了,不知道它是如何做的?我们很快就能想到的一种解决内存泄漏问题的方法是,做一组函数把c语言中的内存分配函数包起来 内存碎片的问题。最好当然是由c语言的库函数或者操作系统来解决,但是它们做到了这一点吗?我想不出来其他为什么postgresql要自己解决内存碎片问题的理由,但是它的确做了这个工作 欢迎大家和我一起思考探讨,否则就会只有我一个人自言自语了。我想问的问题是这个模块做什么,它为什么要做,同样的问题其他系统是如何解决的,postgresql自己又是如何解决的等等。由于自己还要谋生,所以在这里的讨论我可能不会及时参与,请谅解在先 发表于 2009-9-25 00:01 | 只看该作者 分析Postgresql源代码(04) 在dbms的实现中,查找是一个要频繁进行的动作,有根据用户的请求而需要进行的外部数据库中数据的查找,也有dbms对自己所使用的内部数据的查找。索引可以大大加快查找的速度,hash表在没有冲突或者冲突较少时绝对是一种最佳的索引。postgresql的实现中包含了两个类型的hash表,一个是用做存取方法的外存hash表,另一个是用于内布数据查找的内存hash表。本篇将对后者进行讨论,源代码在utils/hash之下,仍然是我先发言如下。 我学过数据结构的人,也看过数据库管理系统实现一书,我总是觉得hash表这个东西说来简单,但却似乎没有什么用途。不过在我粗粗了解了postgresql的实现之后,不能不惊呼,hash表真是太有用了!如果你没有写过hash表的实现算法,建议你一定要认真读读postgresql的内存hash表的实现代码。读这部分代码花了我两个多星期,中间还因为上班迟到被老板k了一顿,但是读懂以后我觉得非常的快乐,从理论到实现再到应用,全部都走一遍,哈哈,爽!这部分代码的关键之处在于它实现的是可动态增长hash表,很容易知道,有两种动态hash表,那么,postgresql实现的是哪一种呢?欢迎大家和我一起思考探讨_re: appgamez 我开个头吧:首先说查询优化主要所涉及的数据类型:.SRCINCLUDENODES中的几个文件均包括了- ParseNodes.H 语法分析之后所形成数据结构的类型- PlanNodes.H 这个是经过优化之后的查询计划数据结构的类型- ExecNodes.H 这个是执行器在执行查询计划时使用的数据结构的类型等等,可以说,数据库系统执行的主线,主要就是这几个数据结构的生成和转换。然后说几个主要的入口点:Pgl的Core的几个主要的入口点都在:.SRCBACKENDEXECUTORSPI.C 中,所谓的SPI就是“Server Programming Interface”(服务器编程接口)比如:_SPI_execute主要是由SQL语句转换为AccessPlan就主要的查询语句而言:_SPI_execute调用了pg_parse_and_rewrite :这个是SQL语句语法分析,语义检查和基于规则的重写。planner:这个是Pgl查询优化器的入口点。(当然pg_parse_and_rewrite进一步调用了pg_parse_query和pg_analyze_and_rewrite,而pg_analyze_and_rewrite调用了parse_analyze和QueryRewrite)而: _SPI_execute_plan 则主要是对AccessPlan的执行基本框架差不多就是这样了re: appgamez 那好吧,多说无益,关键是开始行动。RDBMS大概可以分为几条线索,查询优化是一块,这个可以暂时由我来负责。存储管理也算是一块appgamez既然读了不少,我想你负责这一块比较合适。(这一块应该包含了:1,底层和操作系统的接口,比如读写文件,文件加锁等等;2:页缓冲池;3:索引的组织等等(这里包含物理schema);最后就是数据库系统里面比较重要的一条,那就是日志);事务处理是一块:Pgl我没有细看,不知道有没有涉及分部式事务处理的内容,如果没有,就相对简单一点,这里的负责人,请自告奋勇。还有一块就是对外的接口,这一块也是有相当的技术含量而且对一个数据库的成功起着非常关键的作用,这里的负责人,也清自高奋勇。还有一点,就是工具的准备,大家也许都在用,但是还是要提醒一下:Source Insight,我用的是3.0,看代码可以省你很多时间。Pgl的结构基本上是结构化的,所以其实采用所谓的“逆向工程”去分析要简单得多(相对面向对象的系统,当然,如果是面向对象的系统可以直接采用ROSE的C+ 分析器)关于读代码的方式,我个人希望采用“宽度遍历”的方式,即所谓的“自顶向下”,而不是过早地陷入细节之中。还缺2位负责人,请大家自告奋勇,其实不懂不要紧,关键是要参与,这一点最重要。 发表于 2009-9-25 00:03 | 只看该作者 分析Postgresql源代码(05) 写完这篇短文,我到目前为止阅读源代码的收获就算介绍完了,然后又要等一段时间才会和大家继续聊聊我读源代码的所见所想。这篇文章讨论的是storage/file和storage/smgr下面的源代码,换句话说数据库中的表格数据,最后存储在哪里,以什么方式呈现在用户面前。不用多说,你立即会想到,数据最终应该存储到磁盘上,那么在磁盘上又该如何存储呢?一种方法是不要操作系统的支持,直接通过bios之类的东西读写磁盘,这种方法之下,需要将磁盘上的一块特定区域交给dbms管理,我想,我以前听说过的装数据库管理系统需要在磁盘上划一个分区给它,大概就是用的这种方法吧。另一种方法则是建立在操作系统的基础之上,把数据放在文件里,这个时候你通常会看到一个很大的文件(如sybase sql anywhere的.db文件)或者是很多的文件(如foxpro中的.dbf文件),postgresql采用的是后面这种方法。当数据存储在很多文件当中的时候,进行数据库操作如查询时就可能需要同时打开很多文件,但是操作系统对可以同时打开文件数目是有限制的,如果dbms要同时打开的文件数目超过了这个限制,该怎么办呢?postgresql中storage/file子系统对这个问题给出了一个解决方案,那么它是如何做的呢?如何解决同时打开很多文件进行操作的问题你也许很容易想到答案,但是也许你没有想到是,数据最终可能不仅仅只是存储在硬盘着一种介质之上!比如光盘,又比如非易失性内存(例如闪存)。不要说,哦,我还以为有什么没见过的新东西呢,因为做为dbms的存储管理,它需要注意到不同的存储介质所具有的不同的特性,以便能够获得最佳的存储性能。postgresql中storage/smgr子系统对这个问题作了一个相当好的回答,看看代码吧,你很快就能明白,它所采用的解决方案其实已经司空见惯,无非就是给加上一个抽象层而已。不过实际的源代码读起来有点麻烦,因为它涉及其他子系统,如storage/freespace,先不管那些了,以后反正还会回来再读一遍的最后,我想提的问题是,如果定义一个名为test的表,并在其中插入一些数据,现在要读表中的数据,那么这些数据存在哪里呢,请给出可能的文件名字,并说明一个读文件的操作过程在storage/file和storage/smgr子系统中是如何进行的即涉及到哪些函数和这些函数的出场次序 发表于 2009-9-25 00:04 | 只看该作者 分析Postgresql源代码(06) 有时候我也在想,分析postgresql的源代码干嘛?真的会赚大钱么?在分析storage/ipc的时候,感觉到是相当的困难,再加上认为那些年轻的有背景的专业人士做起来肯定会相当的容易,放弃的想法就油然而生了。虽然有这些想法,但是在一个多月的反复折腾后,总算跌跌撞撞过了storage/ipc这一关。与此同时,在一个多月以前对unix的信号量共享内存之类的东东还一无所知的我,现在也对这些东西说上个abc来了。我突然觉得,学习也是一种乐趣和动力,也许对我而言,分析postgresql源代码这件事情本身比这件事情的结果更为重要废话少讲,本篇主要讨论storage/ipc下的源代码,这一模块可以划分成大致四个部分:ipc, shmem, pmsignal, sinval(呵呵,将就点吧,用中文不好命名)ipc这个部分的主要工作是登记和调用退出处理函数,信号量和共享内存的操作,共享内存的初始化。在unix当中,信号量和共享内存用一个码(key)来标识,我想问的问题是,postgresql如何标识自己创建的信号量和共享内存呢?不要简单的认为给自己创建的信号量和共享内存指定一个码就可以了shmem这个部分负责初始化和管理共享内存。当然重点是理解共享内存的分配方法,不过很有意思的是,这一部分还建立一个hash表shmemindex来对共享内存中对象进行索引,另外还有一组函数用于支持构成一个共享内存内的双向链表。pmsignal用于父子进程通讯,即postmaster和postgres间的通讯,子进程postgres可以先设置消息类型,然后通知父进程postmaster来读取该消息。很简单,是吗,但是你能说出来具体是怎么做的么?sinval部分为每个postgres后台进程建立一个procstate数据结构,处理一些与所有postgres后台进程有关的事务,例如察看一个数据库是否有活动的后台进程在使用它,呵呵,不过这不是sinval的主要用途。sinval的主要用途是用于一个后台进程向其他后台进程发消息而不使用unix的消息通讯机制。你很容易想到,象pmsignal一样,消息是放在共享内存之中的,那么这些消息具体是如何管理的呢?忍不住想多说一句,看看数据结构中的环形队列也许会有好处哦这是我的第6篇分析系列的文章了,前几篇文章的内容是:01 - 准备工作02 - 源代码的组成03 - 分析utils/mmgr04 - 分析utils/hash05 - 分析storage/file, storage/smgr热心盼望你这样的高手参加postgresql源代码分析活动,和我一起交流。我的下一个动作是分析storage/lmgr。 200 下水道 发表于 2009-9-25 00:05 | 只看该作者 PostgreSQL源码分析 常用数据类型/SQL语句的解释和执行主要分析文件: / basic nodes definition src/include/nodes/nodes.h / SQL parsed struct src/include/nodes/parsenodes.h / List定义 src/include/nodes/pg_list.h / List实现 src/backend/nodes/list.c / postgres运行入口文件 src/backend/tcop/postgres.c / utility Stmt运行文件 src/backend/tcop/utility.c / SQL analyze and rewrite src/backend/parser/analyze.c PostgreSQL用一种非常简单的形式实现了类似C+的继承,请看nodes.h :typedef struct NodeNodeTag type; Node;然后请看:parsenodes.h(SQL语句经过parser解析后都先对应该该文件的一个struct中)假设有一个create table的sql:create table test (name varchar(100, pass varchar(100);将会被解析到如下structure:typedef struct CreateStmtNodeTag type;RangeVar *relation; /* relation to create */List *tableElts; /* column definitions (list of ColumnDef) */List *inhRelations; /* relations to inherit from (list of * inhRelation) */List *constraints; /* constraints (list of Constraint nodes) */List *options; /* options from WITH clause */OnCommitAction oncommit; /* what do we do at COMMIT? */char *tablespacename; /* table space to use, or NULL */ CreateStmt;首先,看看该struct的第一个元素:type是一个NodeTag类型。PG的很多struct的第一个元素都是NodeTag,这样在函数中传递指针变量时,他可以很简单的把参数设置成:Node*说简单点,其实有点像是所有的struct都继承了Node这个struct.就是因为这个原因,看PG的代码很累,很多函数的参数和返回值都是一个简单的Node.在nodes.h中有每个Node的值的定义,比如:上面说的CreateStmt的type的值就是:T_CreateStmt然后,PG中大量的使用了链表类型:List在pg_list.h中有定义:typedef struct ListNodeTag type; /* T_List, T_IntList, or T_OidList */int length;ListCell *head;ListCell *tail; List;可以看到,List的定义是基于基类Node来进行的。常用的List操作函数有:/取List第一个元素ListCell *y = list_head(List *l);/得到List的元素个数list_length(List *l);/ 遍历Listforeach(cell, l)其他的很多函数具体可以参考pg_list.h和list.c下面接着说SQL的解释和执行。所有的SQL都会先解析成一个与之相对应的struct.Select会解析到:typedef struct SelectStmtNodeTag type;/* * These fields are used only in “leaf” SelectStmts. * * into, intoColNames, intoOptions, intoOnCommit, and intoTableSpaceName * are a kluge; they belong somewhere else */List *distinctClause; /* NULL, list of DISTINCT ON exprs, or * lcons(NIL,NIL) for all (SELECT DISTINCT) */RangeVar *into; /* target table (for select into table) */List *intoColNames; /* column names for into table */List *intoOptions; /* options from WITH clause */OnCommitAction intoOnCommit; /* what do we do at COMMIT? */char *intoTableSpaceName; /* table space to use, or NULL */List *targetList; /* the target list (of ResTarget) */List *fromClause; /* the FROM clause */Node *whereClause; /* WHERE qualification */List *groupClause; /* GROUP BY clauses */Node *havingClause; /* HAVING conditional-expression */* * In a “leaf” node representing a VALUES list, the above fields are all * null, and instead this field is set. Note that the elements of the * sublists are just expressions, without ResTarget decoration. Also note * that a list element can be DEFAULT (represented as a SetToDefault * node), regardless of the context of the VALUES list. Its up to parse * analysis to reject that where not valid. */List *valuesLists; /* untransformed list of expression lists */* * These fields are used in both “leaf” SelectStmts and upper-level * SelectStmts. */List *sortClause; /* sort clause (a list of SortBys) */Node *limitOffset; /* # of result tuples to skip */Node *limitCount; /* # of result tuples to return */List *lockingClause; /* FOR UPDATE (list of LockingClauses) */* * These fields are used only in upper-level SelectStmts. */SetOperation op; /* type of set op */bool all; /* ALL specified? */struct SelectStmt *larg; /* left child */struct SelectStmt *rarg; /* right child */* Eventually add fields for CORRESPONDING spec here */ SelectStmt;Delete会解析到:typedef struct DeleteStmtNodeTag type;RangeVar *relation; /* relation to delete from */List *usingClause; /* optional using clause for more tables */Node *whereClause; /* qualifications */List *returningList; /* list of expressions to return */ DeleteStmt;Update会解析到:typedef struct UpdateStmtNodeTag type;RangeVar *relation; /* relation to update */List *targetList; /* the target list (of ResTarget) */Node *whereClause; /* qualifications */List *fromClause; /* optional from clause for more tables */List *returningList; /* list of expressions to return */ UpdateStmt;从定义上看,Select比较复杂。其实在PG内部,把Select/Delete/Update当成一样处理,只是最后找到相应的结果集时采取不同的操作。postgres.c的804行可以看到这一步操作:parsetree_list = pg_parse_query(query_string);第一步完成后,只是做了很简单、很粗糙的事情,然后,要进一步进行rewrite, 在交给优化器进行优化和路径选择之前,所有的执行语句都要转换成struct Query:typedef struct QueryNodeTag type;CmdType commandType; /* select|insert|update|delete|utility */ /* 注意: 如果commandType为: utility,优化器不会对该SQL进行进一步优化,因为这个SQL 就是一些建表或者其他命令操作,无法进行路径选择和优化,这时候,executor直接 执行utilityStmt这个Node对应的Struct. 对于select|insert|update|delete这些SQL,优化器都需要进行评估和优化。 */QuerySource querySource; /* where did I come from? */bool canSetTag; /* do I set the command result tag? */Node *utilityStmt; /* non-null if this is a non-optimizable * statement */int resultRelation; /* rtable index of target relation for * INSERT/UPDATE/DELETE; 0 for SELECT */RangeVar *into; /* target relation for SELECT INTO */List *intoOptions; /* options from WITH clause */OnCommitAction intoOnCommit; /* what do we do at COMMIT? */char *intoTableSpaceName; /* table space to use, or NULL */bool hasAggs; /* has aggregates in tlist or havingQual */bool hasSubLinks; /* has subquery SubLink */List *rtable; /* list of range table entries */FromExpr *jointree; /* table join tree (FROM and WHERE clauses) */List *targetList; /* target list (of TargetEntry) */List *returningList; /* return-values list (of TargetEntry) */List *groupClause; /* a list of GroupClauses */Node *havingQual; /* qualifications applied to groups */List *distinctClause; /* a list of SortClauses */List *sortClause; /* a list of SortClauses */Node *limitOffset; /* # of result tuples to skip (int8 expr) */Node *limitCount; /* # of result tuples to return (int8 expr) */List *rowMarks; /* a list of RowMarkClauses */Node *setOperations; /* set-operation tree if this is top level of * a UNION/INTERSECT/EXCEPT query */* * If the resultRelation turns out to be the parent of an inheritance * tree, the planner will add all the child tables to the rtable and store * a list of the rtindexes of all the result relations here. This is done * at plan time, not parse time, since we dont want to commit to the * exact set of child tables at parse time. XXX This field ought to go in * some sort of TopPlan plan node, not in the Query. */List *resultRelations; /* integer list of RT indexes, or NIL */* * If the query has a returningList then the planner will store a list of * processed targetlists (one per result relation) here. We must have a * separate RETURNING targetlist for each result rel because column * numbers may vary wi

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论