arch-dev.sgml
上传用户:blenddy
上传日期:2007-01-07
资源大小:6495k
文件大小:148k
源码类别:

数据库系统

开发平台:

Unix_Linux

  1.  <chapter id="overview">
  2.   <title>Overview of PostgreSQL Internals</title>
  3.   <note>
  4.    <title>Author</title>
  5.    <para>
  6.     This chapter originally appeared as a part of
  7.     <xref linkend="SIM98" endterm="SIM98">, Stefan Simkovics'
  8.     Master's Thesis prepared at Vienna University of Technology under the direction
  9.     of O.Univ.Prof.Dr. Georg Gottlob and Univ.Ass. Mag. Katrin Seyr.
  10.    </para>
  11.   </note>
  12.   <para>
  13.    This chapter gives an overview of the internal structure of the
  14.    backend of <productname>Postgres</productname>.
  15.    After having read the following sections you
  16.    should have an idea of how a query is processed. Don't expect a
  17.    detailed description here (I think such a description dealing with
  18.    all data structures and functions used within <productname>Postgres</productname>
  19.    would exceed 1000
  20.    pages!). This chapter is intended to help understanding the general
  21.    control and data flow within the backend from receiving a query to
  22.    sending the results.
  23.   </para>
  24.   <sect1>
  25.    <title>The Path of a Query</title>
  26.    <para>
  27.     Here we give a short overview of the stages a query has to pass in
  28.     order to obtain a result.
  29.    </para>
  30.    <procedure>
  31.     <step>
  32.      <para>
  33.       A connection from an application program to the <productname>Postgres</productname>
  34.       server has to be established. The application program transmits a
  35.       query to the server and receives the results sent back by the server.
  36.      </para>
  37.     </step>
  38.     <step>
  39.      <para>
  40.       The <firstterm>parser stage</firstterm> checks the query
  41.       transmitted by the application
  42.       program (client) for correct syntax and creates
  43.       a <firstterm>query tree</firstterm>.
  44.      </para>
  45.     </step>
  46.     <step>
  47.      <para>
  48.       The <firstterm>rewrite system</firstterm> takes
  49.       the query tree created by the parser stage and looks for
  50.       any <firstterm>rules</firstterm> (stored in the
  51.       <firstterm>system catalogs</firstterm>) to apply to 
  52.       the <firstterm>querytree</firstterm> and performs the
  53.       transformations given in the <firstterm>rule bodies</firstterm>.
  54.       One application of the rewrite system is given in the realization of
  55.       <firstterm>views</firstterm>.
  56.      </para>
  57.      <para>
  58.       Whenever a query against a view
  59.       (i.e. a <firstterm>virtual table</firstterm>) is made,
  60.       the rewrite system rewrites the user's query to
  61.       a query that accesses the <firstterm>base tables</firstterm> given in
  62.       the <firstterm>view definition</firstterm> instead.
  63.      </para>
  64.     </step>
  65.     <step>
  66.      <para>
  67.       The <firstterm>planner/optimizer</firstterm> takes
  68.       the (rewritten) querytree and creates a 
  69.       <firstterm>queryplan</firstterm> that will be the input to the
  70.       <firstterm>executor</firstterm>.
  71.      </para>
  72.      <para>
  73.       It does so by first creating all possible <firstterm>paths</firstterm>
  74.       leading to the same result. For example if there is an index on a
  75.       relation to be scanned, there are two paths for the
  76.       scan. One possibility is a simple sequential scan and the other
  77.       possibility is to use the index. Next the cost for the execution of
  78.       each plan is estimated and the
  79.       cheapest plan is chosen and handed back.
  80.      </para>
  81.     </step>
  82.     <step>
  83.      <para>
  84.       The executor recursively steps through
  85.       the <firstterm>plan tree</firstterm> and
  86.       retrieves tuples in the way represented by the plan.
  87.       The executor makes use of the
  88.       <firstterm>storage system</firstterm> while scanning
  89.       relations, performs <firstterm>sorts</firstterm> and <firstterm>joins</firstterm>,
  90.       evaluates <firstterm>qualifications</firstterm> and finally hands back the tuples derived.
  91.      </para>
  92.     </step>
  93.    </procedure>
  94.    <para>
  95.     In the following sections we will cover every of the above listed items
  96.     in more detail to give a better understanding on <productname>Postgres</productname>'s internal
  97.     control and data structures.
  98.    </para>
  99.   </sect1>
  100.   <sect1>
  101.    <title>How Connections are Established</title>
  102.    <para>
  103.     <productname>Postgres</productname> is implemented using a simple "process per-user"
  104.     client/server model.  In this model there is one <firstterm>client process</firstterm>
  105.     connected to exactly one <firstterm>server process</firstterm>.
  106.     As we don't know <foreignphrase>per se</foreignphrase> 
  107.     how many connections will be made, we have to use a <firstterm>master process</firstterm>
  108.     that spawns a new server process every time a connection is
  109.     requested. This master process is called <literal>postmaster</literal> and 
  110.     listens at a specified TCP/IP port for incoming connections. Whenever
  111.     a request for a connection is detected the <literal>postmaster</literal> process
  112.     spawns a new server process called <literal>postgres</literal>. The server
  113.     tasks (<literal>postgres</literal> processes) communicate with each other using
  114.     <firstterm>semaphores</firstterm> and <firstterm>shared memory</firstterm>
  115.     to ensure data integrity
  116.     throughout concurrent data access. Figure
  117.     ref{connection} illustrates the interaction of the master process 
  118.     <literal>postmaster</literal> the server process <literal>postgres</literal> and a client
  119.     application. 
  120.    </para>
  121.    <para>
  122.     The client process can either be the <application>psql</application> frontend (for
  123.     interactive SQL queries) or any user application implemented using
  124.     the <filename>libpg</filename> library. Note that applications implemented using
  125.     <application>ecpg</application>
  126.     (the <productname>Postgres</productname> embedded SQL preprocessor for C)
  127.     also use this library.
  128.    </para>
  129.    <para>
  130.     Once a connection is established the client process can send a query
  131.     to the <firstterm>backend</firstterm> (server). The query is transmitted using plain text,
  132.     i.e. there is no parsing done in the <firstterm>frontend</firstterm> (client). The
  133.     server parses the query, creates an <firstterm>execution plan</firstterm>,
  134.     executes the plan and returns the retrieved tuples to the client
  135.     by transmitting them over the established connection.
  136.    </para>
  137. <!--
  138. begin{figure}[ht]
  139. begin{center}
  140. epsfig{figure=figures/connection.ps}
  141. caption{How a connection is established}
  142. label{connection}
  143. end{center}
  144. end{figure}
  145. -->
  146.   </sect1>
  147.   <sect1>
  148.    <title>The Parser Stage</title>
  149.    <para>
  150.     The <firstterm>parser stage</firstterm> consists of two parts:
  151.     <itemizedlist>
  152.      <listitem>
  153.       <para>
  154.        The <firstterm>parser</firstterm> defined in
  155.        <filename>gram.y</filename> and <filename>scan.l</filename> is
  156.        built using the UNIX tools <application>yacc</application>
  157.        and <application>lex</application>.
  158.       </para>
  159.      </listitem>
  160.      <listitem>
  161.       <para>
  162.        The <firstterm>transformation process</firstterm> does
  163.        modifications and augmentations to the data structures returned by the parser.
  164.       </para>
  165.      </listitem>
  166.     </itemizedlist>
  167.    </para>
  168.    <sect2>
  169.     <title>Parser</title>
  170.     <para>
  171.      The parser has to check the query string (which arrives as
  172.      plain ASCII text) for valid syntax. If the syntax is correct a
  173.      <firstterm>parse tree</firstterm> is built up and handed back otherwise an error is
  174.      returned. For the implementation the well known UNIX
  175.      tools <application>lex</application> and <application>yacc</application>
  176.      are used.
  177.     </para>
  178.     <para>
  179.      The <firstterm>lexer</firstterm> is defined in the file
  180.      <filename>scan.l</filename> and is responsible
  181.      for recognizing <firstterm>identifiers</firstterm>,
  182.      the <firstterm>SQL keywords</firstterm> etc. For
  183.      every keyword or identifier that is found, a <firstterm>token</firstterm>
  184.      is generated and handed to the parser.
  185.     </para>
  186.     <para>
  187.      The parser is defined in the file <filename>gram.y</filename> and consists of a
  188.      set of <firstterm>grammar rules</firstterm> and <firstterm>actions</firstterm>
  189.      that are executed
  190.      whenever a rule is fired. The code of the actions (which
  191.      is actually C-code) is used to build up the parse tree.
  192.     </para>
  193.     <para>
  194.      The file <filename>scan.l</filename> is transformed to
  195.      the C-source file <filename>scan.c</filename>
  196.      using the program <application>lex</application>
  197.      and <filename>gram.y</filename> is transformed to
  198.      <filename>gram.c</filename> using <application>yacc</application>.
  199.      After these transformations have taken
  200.      place a normal C-compiler can be used to create the
  201.      parser. Never make any changes to the generated C-files as they will
  202.      be overwritten the next time <application>lex</application>
  203.      or <application>yacc</application> is called.
  204.      <note>
  205.       <para>
  206.        The mentioned transformations and compilations are normally done
  207.        automatically using the <firstterm>makefiles</firstterm>
  208.        shipped with the <productname>Postgres</productname>
  209.        source distribution.
  210.       </para>
  211.      </note>
  212.     </para>
  213.     <para>
  214.      A detailed description of <application>yacc</application> or
  215.      the grammar rules given in <filename>gram.y</filename> would be
  216.      beyond the scope of this paper. There are many books and
  217.      documents dealing with <application>lex</application> and
  218.      <application>yacc</application>. You should be familiar with
  219.      <application>yacc</application> before you start to study the
  220.      grammar given in <filename>gram.y</filename> otherwise you won't
  221.      understand what happens there.
  222.     </para>
  223.     <para>
  224.      For a better understanding of the data structures used in
  225.      <productname>Postgres</productname>
  226.      for the processing of a query we use an example to illustrate the
  227.      changes made to these data structures in every stage.
  228.     </para>
  229.     <example id="simple-select">
  230.      <title>A Simple Select</title>
  231.      <para>
  232.       This example contains the following simple query that will be used in
  233.       various descriptions and figures throughout the following
  234.       sections. The query assumes that the tables given in
  235.       <citetitle>The Supplier Database</citetitle>
  236.       <!--
  237.       XXX The above citetitle should really be an xref,
  238.       but that part has not yet been converted from Stefan's original document.
  239.       - thomas 1999-02-11
  240.       <xref linkend="supplier" endterm="supplier">
  241.       -->
  242.       have already been defined.
  243.       <programlisting>
  244. select s.sname, se.pno
  245.     from supplier s, sells se
  246.     where s.sno > 2 and s.sno = se.sno;
  247.       </programlisting>
  248.      </para>
  249.     </example>
  250.     <para>
  251.      Figure ref{parsetree} shows the <firstterm>parse tree</firstterm> built by the
  252.      grammar rules and actions given in <filename>gram.y</filename> for the query
  253.      given in  <xref linkend="simple-select" endterm="simple-select">
  254.      (without the <firstterm>operator tree</firstterm> for
  255.      the <firstterm>where clause</firstterm> which is shown in figure ref{where_clause}
  256.      because there was not enough space to show both data structures in one
  257.      figure).
  258.     </para>
  259.     <para>
  260.      The top node of the tree is a <literal>SelectStmt</literal> node. For every entry
  261.      appearing in the <firstterm>from clause</firstterm> of the SQL query a <literal>RangeVar</literal>
  262.      node is created holding the name of the <firstterm>alias</firstterm> and a pointer to a
  263.      <literal>RelExpr</literal> node holding the name of the <firstterm>relation</firstterm>. All
  264.      <literal>RangeVar</literal> nodes are collected in a list which is attached to the field
  265.      <literal>fromClause</literal> of the <literal>SelectStmt</literal> node.
  266.     </para>
  267.     <para>
  268.      For every entry appearing in the <firstterm>select list</firstterm> of the SQL query a
  269.      <literal>ResTarget</literal> node is created holding a pointer to an <literal>Attr</literal>
  270.      node. The <literal>Attr</literal> node holds the <firstterm>relation name</firstterm> of the entry and
  271.      a pointer to a <literal>Value</literal> node holding the name of the
  272.      <firstterm>attribute</firstterm>.
  273.      All <literal>ResTarget</literal> nodes are collected to a list which is
  274.      connected to the field <literal>targetList</literal> of the <literal>SelectStmt</literal> node.
  275.     </para>
  276.     <para>
  277.      Figure ref{where_clause} shows the operator tree built for the
  278.      where clause of the SQL query given in example
  279.      <xref linkend="simple-select" endterm="simple-select">
  280.      which is attached to the field
  281.      <literal>qual</literal> of the <literal>SelectStmt</literal> node. The top node of the
  282.      operator tree is an <literal>A_Expr</literal> node representing an <literal>AND</literal>
  283.      operation. This node has two successors called <literal>lexpr</literal> and
  284.      <literal>rexpr</literal> pointing to two <firstterm>subtrees</firstterm>. The subtree attached to
  285.      <literal>lexpr</literal> represents the qualification <literal>s.sno &gt; 2</literal> and the one
  286.      attached to <literal>rexpr</literal> represents <literal>s.sno = se.sno</literal>. For every
  287.      attribute an <literal>Attr</literal> node is created holding the name of the
  288.      relation and a pointer to a <literal>Value</literal> node holding the name of the
  289.      attribute. For the constant term appearing in the query a
  290.      <literal>Const</literal> node is created holding the value.
  291.     </para>
  292. <!--
  293. XXX merge in the figures later... - thomas 1999-01-29
  294. begin{figure}[ht]
  295. begin{center}
  296. epsfig{figure=figures/parsetree.ps}
  297. caption{{it TargetList} and {it FromList} for query of example ref{simple_select}}
  298. label{parsetree}
  299. end{center}
  300. end{figure}
  301. begin{figure}[ht]
  302. begin{center}
  303. epsfig{figure=figures/where_clause.ps}
  304. caption{{it WhereClause} for query of example ref{simple_select}}
  305. label{where_clause}
  306. end{center}
  307. end{figure}
  308. -->
  309.    </sect2>
  310.    <sect2>
  311.      <title>Transformation Process</title>
  312.     <para>
  313.      The <firstterm>transformation process</firstterm> takes the tree handed back by
  314.      the parser as input and steps recursively through it.  If
  315.      a <literal>SelectStmt</literal> node is found, it is transformed
  316.      to a <literal>Query</literal>
  317.      node which will be the top most node of the new data structure. Figure
  318.      ref{transformed} shows the transformed data structure (the part
  319.      for the transformed <firstterm>where clause</firstterm> is given in figure
  320.      ref{transformed_where} because there was not enough space to show all
  321.      parts in one figure).
  322.     </para>
  323.     <para>
  324.      Now a check is made, if the <firstterm>relation names</firstterm> in the
  325.      <firstterm>FROM clause</firstterm> are known to the system. For every relation name
  326.      that is present in the <firstterm>system catalogs</firstterm> a <abbrev>RTE</abbrev> node is
  327.      created containing the relation name, the <firstterm>alias name</firstterm> and
  328.      the <firstterm>relation id</firstterm>. From now on the relation ids are used to
  329.      refer to the <firstterm>relations</firstterm> given in the query. All <abbrev>RTE</abbrev> nodes
  330.      are collected in the <firstterm>range table entry list</firstterm> which is connected
  331.      to the field <literal>rtable</literal> of the <literal>Query</literal> node. If a name of a
  332.      relation that is not known to the system is detected in the query an
  333.      error will be returned and the query processing will be aborted.
  334.     </para>
  335.     <para>
  336.      Next it is checked if the <firstterm>attribute names</firstterm> used are 
  337.      contained in the relations given in the query. For every
  338.      attribute} that is found a <abbrev>TLE</abbrev> node is created holding a pointer
  339.      to a <literal>Resdom</literal> node (which holds the name of the column) and a
  340.      pointer to a <literal>VAR</literal> node. There are two important numbers in the
  341.      <literal>VAR</literal> node. The field <literal>varno</literal> gives the position of the
  342.      relation containing the current attribute} in the range
  343.      table entry list created above. The field <literal>varattno</literal> gives the
  344.      position of the attribute within the relation. If the name
  345.      of an attribute cannot be found an error will be returned and
  346.      the query processing will be aborted.
  347.     </para>
  348. <!--
  349. begin{figure}[ht]
  350. begin{center}
  351. epsfig{figure=figures/transform.ps}
  352. caption{Transformed {it TargetList} and {it FromList} for query of example ref{simple_select}}
  353. label{transformed}
  354. end{center}
  355. end{figure}
  356. noindent Figure ref{transformed_where} shows the transformed {it where
  357. clause}. Every {tt A_Expr} node is transformed to an {tt Expr}
  358. node. The {tt Attr} nodes representing the attributes are replaced by
  359. {tt VAR} nodes as it has been done for the {it targetlist}
  360. above. Checks if the appearing {it attributes} are valid and known to the
  361. system are made. If there is an {it attribute} used which
  362. is not known an error will be returned and the {it query
  363. processing} will be aborted. \
  364. \
  365. The whole {it transformation process} performs a transformation of
  366. the data structure handed back by the {it parser} to a more
  367. comfortable form. The character strings representing the {it
  368. relations} and {it attributes} in the original tree are replaced by
  369. {it relation ids} and {tt VAR} nodes whose fields are referring to
  370. the entries of the {it range table entry list}. In addition to the
  371. transformation, also various checks if the used {it relation}
  372. and {it attribute} names (appearing in the query) are valid in the
  373. current context are performed.
  374. begin{figure}[ht]
  375. begin{center}
  376. epsfig{figure=figures/transform_where.ps}
  377. caption{Transformed {it where clause} for query of example ref{simple_select}}
  378. label{transformed_where}
  379. end{center}
  380. end{figure}
  381. pagebreak
  382. clearpage
  383. begin{figure}[ht]
  384. begin{center}
  385. epsfig{figure=figures/plan.ps}
  386. caption{{it Plan} for query of example ref{simple_select}}
  387. label{plan}
  388. end{center}
  389. end{figure}
  390. -->
  391.    </sect2>
  392.   </sect1>
  393.   <sect1>
  394.    <title>The <productname>Postgres</productname> Rule System</title>
  395.    <para>
  396.     <productname>Postgres</productname> supports a powerful
  397.     <firstterm>rule system</firstterm> for the specification
  398.     of <firstterm>views</firstterm> and ambiguous <firstterm>view updates</firstterm>.
  399.     Originally the <productname>Postgres</productname>
  400.     rule system consisted of two implementations:
  401.     <itemizedlist>
  402.      <listitem>
  403.       <para>
  404.        The first one worked using <firstterm>tuple level</firstterm> processing and was
  405.        implemented deep in the <firstterm>executor</firstterm>. The rule system was
  406.        called whenever an individual tuple had been accessed. This
  407.        implementation was removed in 1995 when the last official release
  408.        of the <productname>Postgres</productname> project was transformed into 
  409.        <productname>Postgres95</productname>. 
  410.       </para>
  411.      </listitem>
  412.      <listitem>
  413.       <para>
  414.        The second implementation of the rule system is a technique
  415.        called <firstterm>query rewriting</firstterm>.
  416.        The <firstterm>rewrite system</firstterm>} is a module
  417.        that exists between the <firstterm>parser stage</firstterm> and the
  418.        <firstterm>planner/optimizer</firstterm>. This technique is still implemented.
  419.       </para>
  420.      </listitem>
  421.     </itemizedlist>
  422.    </para>
  423.    <para>
  424.     For information on the syntax and creation of rules in the
  425.     <productname>Postgres</productname> system refer to
  426.     <citetitle>The PostgreSQL User's Guide</citetitle>.
  427.    </para>
  428.    <sect2>
  429.     <title>The Rewrite System</title>
  430.     <para>
  431.      The <firstterm>query rewrite system</firstterm> is a module between
  432.      the parser stage and the planner/optimizer. It processes the tree handed
  433.      back by the parser stage (which represents a user query) and if
  434.      there is a rule present that has to be applied to the query it
  435.      rewrites the tree to an alternate form.
  436.     </para>
  437.     <sect3 id="view-impl">
  438.      <title>Techniques To Implement Views</title>
  439.      <para>
  440.       Now we will sketch the algorithm of the query rewrite system. For
  441.       better illustration we show how to implement views using rules
  442.       as an example.
  443.      </para>
  444.      <para>
  445.       Let the following rule be given:
  446.       <programlisting>
  447.   create rule view_rule
  448.   as on select 
  449.   to test_view
  450.   do instead
  451.      select s.sname, p.pname
  452.      from supplier s, sells se, part p
  453.      where s.sno = se.sno and
  454.            p.pno = se.pno;   
  455.       </programlisting>
  456.      </para>
  457.      <para>
  458.       The given rule will be <firstterm>fired</firstterm> whenever a select
  459.       against the relation <literal>test_view</literal> is detected. Instead of
  460.       selecting the tuples from <literal>test_view</literal> the select statement
  461.       given in the <firstterm>action part</firstterm> of the rule is executed.
  462.      </para>
  463.      <para>
  464.       Let the following user-query against <literal>test_view</literal> be given:
  465.       <programlisting>
  466.   select sname 
  467.   from test_view
  468.   where sname &lt;&gt; 'Smith';
  469.       </programlisting>
  470.      </para>
  471.      <para>
  472.       Here is a list of the steps performed by the query rewrite
  473.       system whenever a user-query against <literal>test_view</literal> appears. (The
  474.       following listing is a very informal description of the algorithm just
  475.       intended for basic understanding. For a detailed description refer
  476.       to <xref linkend="STON89-full" endterm="STON89">).
  477.      </para>
  478.      <procedure>
  479.       <title><literal>test_view</literal> Rewrite</title>
  480.       <step>
  481.        <para>
  482. Take the query given in the action part of the rule.
  483.        </para>
  484.       </step>
  485.       <step>
  486.        <para>
  487. Adapt the targetlist to meet the number and order of
  488. attributes given in the user-query.
  489.        </para>
  490.       </step>
  491.       <step>
  492.        <para>
  493. Add the qualification given in the where clause of the
  494. user-query to the qualification of the query given in the
  495. action part of the rule.
  496.        </para>
  497.       </step>
  498.      </procedure>
  499.      <para>
  500.       Given the rule definition above, the user-query will be
  501.       rewritten to the following form (Note that the rewriting is done on
  502.       the internal representation of the user-query handed back by the
  503.       parser stage but the derived new data structure will represent the following
  504.       query):
  505.       <programlisting>
  506.   select s.sname
  507.   from supplier s, sells se, part p
  508.   where s.sno = se.sno and
  509.         p.pno = se.pno and
  510.         s.sname &lt;&gt; 'Smith';
  511.       </programlisting>
  512.      </para>
  513. </sect3>
  514.    </sect2>
  515.   </sect1>
  516.   <sect1>
  517.    <title>Planner/Optimizer</title>
  518.    <para>
  519.     The task of the <firstterm>planner/optimizer</firstterm> is to create an optimal
  520.     execution plan. It first combines all possible ways of
  521.     <firstterm>scanning</firstterm> and <firstterm>joining</firstterm>
  522.     the relations that appear in a
  523.     query. All the created paths lead to the same result and it's the
  524.     task of the optimizer to estimate the cost of executing each path and
  525.     find out which one is the cheapest.
  526.    </para>
  527.    <sect2>
  528.     <title>Generating Possible Plans</title>
  529.     <para>
  530.      The planner/optimizer decides which plans should be generated
  531.      based upon the types of indices defined on the relations appearing in
  532.      a query. There is always the possibility of performing a
  533.      sequential scan on a relation, so a plan using only
  534.      sequential scans is always created. Assume an index is defined on a
  535.      relation (for example a B-tree index) and a query contains the
  536.      restriction
  537.      <literal>relation.attribute OPR constant</literal>. If
  538.      <literal>relation.attribute</literal> happens to match the key of the B-tree
  539.      index and <literal>OPR</literal> is anything but '&lt;&gt;' another plan is created using
  540.      the B-tree index to scan the relation. If there are further indices
  541.      present and the restrictions in the query happen to match a key of an
  542.      index further plans will be considered.
  543.     </para>
  544.     <para>
  545.      After all feasible plans have been found for scanning single
  546.      relations, plans for joining relations are created. The
  547.      planner/optimizer considers only joins between every two relations for
  548.      which there exists a corresponding join clause (i.e. for which a
  549.      restriction like <literal>where rel1.attr1=rel2.attr2</literal> exists) in the
  550.      where qualification. All possible plans are generated for every
  551.      join pair considered by the planner/optimizer. The three possible join
  552.      strategies are:
  553.      <itemizedlist>
  554.       <listitem>
  555.        <para>
  556. <firstterm>nested iteration join</firstterm>: The right relation is scanned
  557. once for every tuple found in the left relation. This strategy
  558. is easy to implement but can be very time consuming.
  559.        </para>
  560.       </listitem>
  561.       <listitem>
  562.        <para>
  563. <firstterm>merge sort join</firstterm>: Each relation is sorted on the join
  564. attributes before the join starts. Then the two relations are
  565. merged together taking into account that both relations are
  566. ordered on the join attributes. This kind of join is more
  567. attractive because every relation has to be scanned only once.
  568.        </para>
  569.       </listitem>
  570.       <listitem>
  571.        <para>
  572. <firstterm>hash join</firstterm>: the right relation is first hashed on its
  573. join attributes. Next the left relation is scanned and the
  574. appropriate values of every tuple found are used as hash keys to
  575. locate the tuples in the right relation.
  576.        </para>
  577.       </listitem>
  578.      </itemizedlist>
  579.     </para>
  580.    </sect2>
  581.    <sect2>
  582.     <title>Data Structure of the Plan</title>
  583.     <para>
  584.      Here we will give a little description of the nodes appearing in the
  585.      plan. Figure ref{plan} shows the plan produced for the query in
  586.      example ref{simple_select}.
  587.     </para>
  588.     <para>
  589.      The top node of the plan is a <literal>MergeJoin</literal> node which has two
  590.      successors, one attached to the field <literal>lefttree</literal> and the second
  591.      attached to the field <literal>righttree</literal>. Each of the subnodes represents
  592.      one relation of the join. As mentioned above a merge sort
  593.      join requires each relation to be sorted. That's why we find
  594.      a <literal>Sort</literal> node in each subplan. The additional qualification given
  595.      in the query (<literal>s.sno &gt; 2</literal>) is pushed down as far as possible and is
  596.      attached to the <literal>qpqual</literal> field of the leaf <literal>SeqScan</literal> node of
  597.      the corresponding subplan.
  598.     </para>
  599.     <para>
  600.      The list attached to the field <literal>mergeclauses</literal> of the
  601.      <literal>MergeJoin</literal> node contains information about the join attributes.
  602.      The values <literal>65000</literal> and <literal>65001</literal>
  603.      for the <literal>varno</literal> fields in the
  604.      <literal>VAR</literal> nodes appearing in the <literal>mergeclauses</literal> list (and also in the
  605.      <literal>targetlist</literal>) mean that not the tuples of the current node should be
  606.      considered but the tuples of the next "deeper" nodes (i.e. the top
  607.      nodes of the subplans) should be used instead.
  608.     </para>
  609.     <para>
  610.      Note that every <literal>Sort</literal> and <literal>SeqScan</literal> node appearing in figure
  611.      ref{plan} has got a <literal>targetlist</literal> but because there was not enough space
  612.      only the one for the <literal>MergeJoin</literal> node could be drawn.
  613.     </para>
  614.     <para>
  615.      Another task performed by the planner/optimizer is fixing the
  616.      <firstterm>operator ids</firstterm> in the <literal>Expr</literal>
  617.      and <literal>Oper</literal> nodes. As
  618.      mentioned earlier, <productname>Postgres</productname> supports a variety of different data
  619.      types and even user defined types can be used. To be able to maintain
  620.      the huge amount of functions and operators it is necessary to store
  621.      them in a system table. Each function and operator gets a unique
  622.      operator id. According to the types of the attributes used
  623.      within the qualifications etc., the appropriate operator ids
  624.      have to be used.
  625.     </para>
  626.    </sect2>
  627.   </sect1>
  628.   <sect1>
  629.    <title>Executor</title>
  630.    <para>
  631.     The <firstterm>executor</firstterm> takes the plan handed back by the
  632.     planner/optimizer and starts processing the top node. In the case of
  633.     our example (the query given in example ref{simple_select}) the top
  634.     node is a <literal>MergeJoin</literal> node. 
  635.    </para>
  636.    <para>
  637.     Before any merge can be done two tuples have to be fetched (one from
  638.     each subplan). So the executor recursively calls itself to
  639.     process the subplans (it starts with the subplan attached to
  640.     <literal>lefttree</literal>). The new top node (the top node of the left subplan) is a
  641.     <literal>SeqScan</literal> node and again a tuple has to be fetched before the node
  642.     itself can be processed. The executor calls itself recursively
  643.     another time for the subplan attached to <literal>lefttree</literal> of the
  644.     <literal>SeqScan</literal> node.
  645.    </para>
  646.    <para>
  647.     Now the new top node is a <literal>Sort</literal> node. As a sort has to be done on
  648.     the whole relation, the executor starts fetching tuples
  649.     from the <literal>Sort</literal> node's subplan and sorts them into a temporary
  650.     relation (in memory or a file) when the <literal>Sort</literal> node is visited for
  651.     the first time. (Further examinations of the <literal>Sort</literal> node will
  652.     always return just one tuple from the sorted temporary
  653.     relation.)
  654.    </para>
  655.    <para>
  656.     Every time the processing of the <literal>Sort</literal> node needs a new tuple the
  657.     executor is recursively called for the <literal>SeqScan</literal> node
  658.     attached as subplan. The relation (internally referenced by the
  659.     value given in the <literal>scanrelid</literal> field) is scanned for the next
  660.     tuple. If the tuple satisfies the qualification given by the tree
  661.     attached to <literal>qpqual</literal> it is handed back, otherwise the next tuple
  662.     is fetched until the qualification is satisfied. If the last tuple of
  663.     the relation has been processed a <literal>NULL</literal> pointer is
  664.     returned.
  665.    </para>
  666.    <para>
  667.     After a tuple has been handed back by the <literal>lefttree</literal> of the
  668.     <literal>MergeJoin</literal> the <literal>righttree</literal> is processed in the same way. If both
  669.     tuples are present the executor processes the <literal>MergeJoin</literal>
  670.     node. Whenever a new tuple from one of the subplans is needed a
  671.     recursive call to the executor is performed to obtain it. If a
  672.     joined tuple could be created it is handed back and one complete
  673.     processing of the plan tree has finished. 
  674.    </para>
  675.    <para>
  676.     Now the described steps are performed once for every tuple, until a
  677.     <literal>NULL</literal> pointer is returned for the processing of the
  678.     <literal>MergeJoin</literal> node, indicating that we are finished.
  679.    </para>
  680.   </sect1>
  681. <!--
  682. **********************************************************
  683. **********************************************************
  684. **********************************************************
  685. **********************************************************
  686. **********************************************************
  687. pagebreak
  688. clearpage
  689. section{The Realization of the Having Clause}
  690. label{having_impl}
  691. The {it having clause} has been designed in SQL to be able to use the
  692. results of {it aggregate functions} within a query qualification. The
  693. handling of the {it having clause} is very similar to the handling of
  694. the {it where clause}. Both are formulas in first order logic (FOL)
  695. that have to evaluate to true for a certain object to be handed back:
  696. %
  697. begin{itemize}
  698. <step> The formula given in the {it where clause} is evaluated for
  699. every tuple. If the evaluation returns {tt true} the tuple is
  700. returned, every tuple not satisfying the qualification is ignored.
  701. %
  702. <step> In the case of {it groups} the {it having clause} is evaluated
  703. for every group. If the evaluation returns {tt true} the group is
  704. taken into account otherwise it is ignored.
  705. end{itemize}
  706. %
  707. subsection{How Aggregate Functions are Implemented}
  708. label{aggregates}
  709. Before we can describe how the {it having clause} is implemented we
  710. will have a look at the implementation of {it aggregate functions} as
  711. long as they just appear in the {it targetlist}. Note that {it aggregate
  712. functions} are applied to groups so the query must contain a {it
  713. group clause}.
  714. %
  715. begin{example} 
  716. label{having}
  717. Here is an example of the usage of the {it aggregate
  718. function} {tt count} which counts the number of part numbers ({tt
  719. pno}) of every group. (The table {tt sells} is defined in example
  720. ref{supplier}.)
  721. %
  722. begin{verbatim}
  723.   select sno, count(pno)
  724.   from sells
  725.   group by sno;
  726. end{verbatim}
  727. %
  728. end{example}
  729. %
  730. A query like the one in example ref{having} is processed by the usual
  731. stages:
  732. %
  733. begin{itemize}
  734. <step> the parser stage
  735. <step> the rewrite system
  736. <step> the planner/optimizer 
  737. <step> the executor
  738. end{itemize}
  739. %
  740. and in the following sections we will describe what every stage does
  741. to the query in order to obtain the appropriate result.
  742. subsubsection{The Parser Stage}
  743. begin{figure}[ht]
  744. begin{center}
  745. epsfig{figure=figures/parse_having.ps}
  746. caption{{it Querytree} built up for the query of example ref{having}}
  747. label{parse_having}
  748. end{center}
  749. end{figure}
  750. The parser stage builds up a {it querytree} containing the {it
  751. where} qualification and information about the {it grouping} that has
  752. to be done (i.e. a list of all attributes to group for is attached to
  753. the field {tt groupClause}). The main difference to {it querytrees}
  754. built up for queries without {it aggregate functions} is given in the
  755. field {tt hasAggs} which is set to {tt true} and in the {it
  756. targetlist}. The {tt expr} field of the second {tt TLE} node of the
  757. {it targetlist} shown in figure ref{parse_having} does not point
  758. directly to a {tt VAR} node but to an {tt Aggreg} node representing
  759. the {it aggregate function} used in the query.
  760. A check is made that every attribute grouped for appears only without
  761. an {it aggregate function} in the {it targetlist} and that every
  762. attribute which appears without an {it aggregate function} in the
  763. {it targetlist} is grouped for.
  764. %
  765. pagebreak 
  766. subsubsection{The Rewrite System}
  767. The rewriting system does not make any changes to the {it querytree}
  768. as long as the query involves just {it base tables}. If any {it
  769. views} are present the query is rewritten to access the tables
  770. specified in the {it view definition}.
  771. %
  772. subsubsection{Planner/Optimizer}
  773. Whenever an {it aggregate function} is involved in a query (which is
  774. indicated by the {tt hasAggs} flag set to {tt true}) the planner
  775. creates a {it plantree} whose top node is an {tt AGG} node. The {it
  776. targetlist} is searched for {it aggregate functions} and for every
  777. function that is found, a pointer to the corresponding {tt Aggreg}
  778. node is added to a list which is finally attached to the field {tt aggs} of
  779. the {tt AGG} node. This list is needed by the {it executor} to know which
  780. {it aggregate functions} are present and have to be
  781. handled.
  782. The {tt AGG} node is followed by a {tt GRP} node. The implementation
  783. of the {it grouping} logic needs a sorted table for its operation so
  784. the {tt GRP} node is followed by a {tt SORT} node. The {tt SORT}
  785. operation gets its tuples from a kind of {tt Scan} node (if no
  786. indices are present this will be a simple {tt SeqScan} node). Any
  787. qualifications present are attached to the {tt Scan} node. Figure
  788. ref{plan_having} shows the {it plan} created for the query given in
  789. example ref{having}.
  790. begin{figure}[ht]
  791. begin{center}
  792. epsfig{figure=figures/plan_having.ps}
  793. caption{{it Plantree} for the query of example ref{having}}
  794. label{plan_having}
  795. end{center}
  796. end{figure}
  797. Note that every node has its own {it targetlist} which may differ from the
  798. one of the node above or below.  The field {tt varattno} of every
  799. {tt VAR} node included in a {it targetlist} contains a number representing
  800. the position of the attribute's value in the tuple of the current node.
  801. pagebreak
  802. clearpage
  803. subsubsection{Executor}
  804. The {it executor} uses the function {tt execAgg()} to execute {tt AGG}
  805. nodes. As described earlier it uses one main function {tt
  806. ExecProcNode} which is called recursively to execute subtrees. The
  807. following steps are performed by {tt execAgg()}:
  808. %
  809. begin{itemize}
  810. %
  811. <step> The list attached to the field {tt aggs} of the {tt AGG} node is
  812. examined and for every {it aggregate function} included the {it transition
  813. functions} are fetched from a {it function table}. Calculating the
  814. value of an {it aggregate function} is done using three functions:
  815. %
  816. begin{itemize}
  817. <step> The {it first transition function} {tt xfn1} is called with the
  818. current value of the attribute the {it aggregate function} is applied
  819. to and changes its internal state using the attribute's value given as
  820. an argument.
  821. %
  822. <step> The {it second transition function} {tt xfn2} is called without any
  823. arguments and changes its internal state only according to internal rules.
  824. %
  825. <step> The {it final function} {tt finalfn} takes the final states of {tt
  826. xfn1} and {tt xfn2} as arguments and finishes the {it aggregation}.
  827. end{itemize}
  828. %
  829. begin{example} Recall the functions necessary to implement the
  830. {it aggregate function} {tt avg} building the average over all
  831. values of an attribute in a group (see section ref{ext_agg} {it
  832. Extending Aggregates}):
  833. %
  834. begin{itemize}
  835. %
  836. <step> The first transition function {tt xfn1} has to be a function that
  837. takes the actual value of the attribute {tt avg} is applied to as an
  838. argument and adds it to the internally stored sum of previous
  839. calls.
  840. %
  841. <step> The second transition function {tt xfn2} only increases an internal
  842. counter every time it is called. 
  843. %
  844. <step> The final function {tt finalfn} divides the result of {tt xfn1} by
  845. the counter of {tt xfn2} to calculate the average.
  846. %
  847. end{itemize}
  848. %
  849. end{example}
  850. %
  851. Note that {tt xfn2} and {tt finalfn} may be absent (e.g. for the
  852. {it aggregate function} {tt sum} which simply sums up all values of
  853. the given attribute within a group. \
  854. \
  855. {tt execAgg()} creates an array containing one entry for every {it
  856. aggregate function} found in the list attached to the field {tt
  857. aggs}. The array will hold information needed for the execution of
  858. every {it aggregate function} (including the {it transition functions}
  859. described above).
  860. %
  861. <step> The following steps are executed in a loop as long as there are
  862. still tuples returned by the subplan (i.e. as long as there are still
  863. tuples left in the current group). When there are no tuples left
  864. in the group a {tt NULL} pointer is returned indicating the end of the
  865. group.
  866. %
  867. begin{itemize}
  868. <step> A new tuple from the subplan (i.e. the {it plan} attached to the
  869. field {tt lefttree}) is fetched by recursively calling {tt
  870. ExecProcNode()} with the subplan as argument.
  871. %
  872. <step> For every {it aggregate function} (contained in the array created
  873. before) apply the transition functions {tt xfn1} and {tt xfn2} to
  874. the values of the appropriate attributes of the current tuple.
  875. end{itemize}
  876. %
  877. <step> When we get here, all tuples of the current group have been
  878. processed and the {it transition functions} of all {it aggregate
  879. functions} have been applied to the values of the attributes. We are
  880. now ready to complete the {it aggregation} by applying the {it final
  881. function} ({tt finalfn}) for every {it aggregate function}.
  882. %
  883. <step> Store the tuple containing the new values (the results of the
  884. {it aggregate functions}) and hand it back.
  885. end{itemize}
  886. %
  887. Note that the procedure described above only returns one tuple
  888. (i.e. it processes just one group and when the end of the group is
  889. detected it processes the {it aggregate functions} and hands back one
  890. tuple). To retrieve all tuples (i.e. to process all groups) the
  891. function {tt execAgg()} has to be called (returning a new tuple every
  892. time) until it returns a {tt NULL} pointer indicating that there are
  893. no groups left to process.
  894. subsection{How the Having Clause is Implemented}
  895. The basic idea of the implementation is to attach the {it operator tree}
  896. built for the {it having clause} to the field {tt qpqual} of
  897. node {tt AGG} (which is the top node of the query tree). Now the executor
  898. has to evaluate the new {it operator tree} attached to {tt qpqual} for
  899. every group processed. If the evaluation returns {tt true} the group
  900. is taken into account otherwise it is ignored and the next group will
  901. be examined. \
  902. \
  903. In order to implement the {it having clause} a variety of changes
  904. have been made to the following stages:
  905. %
  906. begin{itemize}
  907. <step> The {it parser stage} has been modified slightly to build up and
  908. transform an {it operator tree} for the {it having clause}.
  909. %
  910. <step> The {it rewrite system} has been adapted to be able to use {it
  911. views} with the {it having logic}.
  912. %
  913. <step> The {it planner/optimizer}  now takes the {it operator tree} of
  914. the {it having clause} and attaches it to the {tt AGG} node (which
  915. is the top node of the {it queryplan}).
  916. %
  917. <step> The {it executor} has been modified to evaluate the {it operator tree}
  918. (i.e. the internal representation of the {it having
  919. qualification}) attached to the {tt AGG} node and the results of the
  920. {it aggregation} are only considered if the evaluation returns {tt true}.
  921. end{itemize}
  922. %
  923. In the following sections we will describe the changes made to every
  924. single stage in detail.
  925. subsubsection{The Parser Stage}
  926. The grammar rules of the {it parser} defined in {tt gram.y} did not
  927. require any changes (i.e. the rules had already been prepared for the
  928. {it having clause}). The {it operator tree} built up for the {it having
  929. clause} is attached to the field {tt havingClause} of the {tt
  930. SelectStmt} node handed back by the {it parser}. \
  931. \
  932. The {it transformation} procedures applied to the tree handed back by
  933. the {it parser} transform the {it operator tree} attached to the field
  934. {tt havingClause} using exactly the same functions used for the
  935. transformation of the {it operator tree} for the {it where clause}. This
  936. is possible because both trees are built up by the same grammar rules
  937. of the {it parser} and are therefore compatible. Additional checks
  938. which make sure that the {it having clause} involves at least one
  939. {it aggregate function} etc. are performed at a later point in time
  940. in the {it planner/optimizer} stage. \
  941. \
  942. The necessary changes have been applied to the following functions
  943. included in the file {tt
  944. $ldots$/src/backend/parser/analyze.c}. Note, that only the relevant
  945. parts of the affected code are presented instead of the whole
  946. functions. Every added source line will be marked by a {tt '+'} at the
  947. beginning of the line and every changed source line will be marked by
  948. a {tt '!'} throughout the following code listings. Whenever a part of
  949. the code which is not relevant at the moment is skipped, three
  950. vertical dots are inserted instead.
  951. %
  952. pagebreak
  953. %
  954. begin{itemize}
  955. <step> {tt transformInsertStmt()} \
  956. This function becomes is invoked every time a SQL {tt insert}
  957. statement involving a {tt select} is used like the following example
  958. illustrates:
  959. %
  960. begin{verbatim}
  961.   insert into t2
  962.   select x, y
  963.   from t1;
  964. end{verbatim}
  965. %
  966. Two statements have been added to this function. The first one
  967. performs the transformation of the {it operator tree} attached to the
  968. field {tt havingClause} using the function {tt
  969. transformWhereClause()} as done for the {it where clause}. It is
  970. possible to use the same function for both clauses, because they are
  971. both built up by the same {it grammar rules} given in {tt gram.y}
  972. and are therefore compatible.
  973. The second statement makes sure, that {it aggregate functions} are
  974. involved in the query whenever a {it having clause} is used,
  975. otherwise the query could have been formulated using only a {it where
  976. clause}.
  977. %
  978. begin{verbatim}
  979.   static Query *
  980.   transformInsertStmt(ParseState *pstate, 
  981.                       InsertStmt *stmt)
  982.   {
  983.     /* make a new query tree */
  984.     Query *qry = makeNode(Query);
  985.                             .
  986.                             .
  987.                             .
  988.     /* fix where clause */
  989.     qry->qual = transformWhereClause(pstate, 
  990.                                      stmt->whereClause);
  991. +   /* The havingQual has a similar meaning as "qual" in 
  992. +    * the where statement. So we can easily use the  
  993. +    * code from the "where clause" with some additional
  994. +    * traversals done in .../optimizer/plan/planner.c 
  995. +    */
  996. +   qry->havingQual = transformWhereClause(pstate, 
  997. +                                   stmt->havingClause);     
  998.                             .
  999.                             .
  1000.                             .
  1001. +   /* If there is a havingQual but there are no 
  1002. +    * aggregates, then there is something wrong with 
  1003. +    * the query because having must contain aggregates 
  1004. +    * in its expressions! Otherwise the query could 
  1005. +    * have been formulated using the where clause.
  1006. +    */
  1007. +   if((qry->hasAggs == false) && 
  1008. +      (qry->havingQual != NULL))
  1009. +   {
  1010. +     elog(ERROR,"This is not a valid having query!");
  1011. +     return (Query *)NIL;
  1012. +   }
  1013.     return (Query *) qry;
  1014.   }
  1015. end{verbatim}
  1016. %
  1017. <step> {tt transformSelectStmt()} \
  1018. Exactly the same statements added to the function {tt
  1019. transformInsertStmt()} above have been added here as well.
  1020. %
  1021. begin{verbatim}
  1022.   static Query *
  1023.   transformSelectStmt(ParseState *pstate, 
  1024.                       SelectStmt *stmt)
  1025.   {
  1026.     Query  *qry = makeNode(Query);
  1027.     qry->commandType = CMD_SELECT;
  1028.                             .
  1029.                             .
  1030.                             .
  1031.     qry->qual = transformWhereClause(pstate, 
  1032.                                      stmt->whereClause);
  1033. +   /* The havingQual has a similar meaning as "qual" in 
  1034. +    * the where statement. So we can easily use the  
  1035. +    * code from the "where clause" with some additional
  1036. +    * traversals done in .../optimizer/plan/planner.c 
  1037. +    */
  1038. +   qry->havingQual = transformWhereClause(pstate, 
  1039. +                                   stmt->havingClause);     
  1040.                             .
  1041.                             .
  1042.                             .
  1043. +   /* If there is a havingQual but there are no 
  1044. +    * aggregates, then there is something wrong with 
  1045. +    * the query because having must contain aggregates 
  1046. +    * in its expressions! Otherwise the query could 
  1047. +    * have been formulated using the where clause.
  1048. +    */
  1049. +   if((qry->hasAggs == false) && 
  1050. +      (qry->havingQual != NULL))
  1051. +   {
  1052. +     elog(ERROR,"This is not a valid having query!");
  1053. +     return (Query *)NIL;
  1054. +   }
  1055.     return (Query *) qry;
  1056.   }
  1057. end{verbatim}
  1058. %
  1059. end{itemize}
  1060. subsubsection{The Rewrite System}
  1061. This section describes the changes to the {it rewrite system} of
  1062. <productname>Postgres</productname> that have been necessary to support the use of {it views}
  1063. within queries using a {it having clause} and to support the
  1064. definition of {it views} by queries using a {it having clause}.
  1065. As described in section ref{view_impl} {it Techniques To Implement
  1066. Views} a query rewrite technique is used to implement {it
  1067. views}. There are two cases to be handled within the {it rewrite
  1068. system} as far as the {it having clause} is concerned:
  1069. %
  1070. pagebreak
  1071. %
  1072. begin{itemize}
  1073. <step> The {it view definition} does not contain a {it having clause}
  1074. but the queries evaluated against this view may contain {it having
  1075. clauses}.
  1076. <step> The {it view definition} contains a {it having clause}. In this
  1077. case queries evaluated against this view must meet some
  1078. restrictions as we will describe later.
  1079. end{itemize}
  1080. %
  1081. paragraph{No having clause in the view definition:} First we will
  1082. look at  the changes necessary to support queries using a
  1083. {it having clause} against a {it view} defined without
  1084. a {it having clause}. \
  1085. \
  1086. Let the following view definition be given:
  1087. %
  1088. begin{verbatim}
  1089.   create view test_view
  1090.   as select sno, pno
  1091.      from sells
  1092.      where sno > 2;
  1093. end{verbatim}
  1094. %
  1095. and the following query made against <literal>test_view</literal>:
  1096. %
  1097. begin{verbatim}
  1098.   select * 
  1099.   from testview
  1100.   where sno <> 5;
  1101. end{verbatim}
  1102. %
  1103. The query will be rewritten to:
  1104. %
  1105. begin{verbatim}
  1106.   select sno, pno
  1107.   from sells
  1108.   where sno > 2 and
  1109.         sno <> 5;
  1110. end{verbatim}
  1111. %
  1112. The query given in the definition of the {it view} <literal>test_view</literal>
  1113. is the {it backbone} of the rewritten query. The {it targetlist} is taken
  1114. from the user's query and also the {it where qualification } of the
  1115. user's query is added to the {it where qualification} of the new
  1116. query by using an {tt AND} operation. \
  1117. \
  1118. Now consider the following query:
  1119. %
  1120. begin{verbatim}
  1121.   select sno, count(pno)
  1122.   from testview
  1123.   where sno <> 5
  1124.   group by sno
  1125.   having count(pno) > 1;  
  1126. end{verbatim}
  1127. %
  1128. From now on it is no longer sufficient to add just the {it where
  1129. clause} and the {it targetlist} of the user's query to the new query. The
  1130. {it group clause} and the {it having qualification} also have to be
  1131. added to the rewritten query:
  1132. %
  1133. begin{verbatim}
  1134.   select sno, count(pno)
  1135.   from sells
  1136.   where sno > 2 and
  1137.         sno <> 5
  1138.   group by sno
  1139.   having count(pno) > 1;
  1140. end{verbatim}
  1141. %
  1142. pagebreak
  1143. noindent Several changes that have already been applied to the {it
  1144. targetlist} and the {it where clause} also have to be applied to the
  1145. {it having clause}. Here is a collection of all {it additional} steps that
  1146. have to be performed in order to rewrite a query using a {it having
  1147. clause} against a simple {it view} (i.e. a {it view} whose
  1148. definition does not use any {it group} and {it having clauses}):
  1149. %
  1150. begin{itemize}
  1151. %
  1152. <step> Rewrite the subselects contained in the {it having clause} if any are
  1153. present.
  1154. %
  1155. <step> Adapt the {tt varno} and {tt varattno} fields of all {tt
  1156. VAR} nodes contained in the {it operator tree} representing the {it
  1157. having clause} in the same way as it has been done for the tree
  1158. representing the {it where clause}. The {tt varno} fields are changed
  1159. to use the {it base tables} given in the {it view definition} (which
  1160. have been inserted into the {it range table entry list} in the
  1161. meantime) instead of the {it virtual tables}. The positions of
  1162. the attributes used in the {it view} may differ from the positions of
  1163. the corresponding attributes in the {it base tables}. That's why the
  1164. {tt varattno} fields also have to be adapted.
  1165. %
  1166. <step> Adapt the {tt varno} and {tt varattno} fields of all {tt
  1167. VAR} nodes contained in the {tt groupClause} of the user's query in
  1168. the way and for the reasons described above.
  1169. %
  1170. <step> Attach the tree representing the {it having qualification} (which is
  1171. currently attached to the field {tt havingClause} of the {tt Query}
  1172. node for the user's query) to the field {tt havingClause} of the {tt
  1173. Query} node for the new (rewritten) query.
  1174. %
  1175. <step> Attach the list representing the {it group clause} (currently
  1176. attached to the field {tt groupClause} of the {tt Query} node for
  1177. the user's query) to the field {it group clause} of the node for the
  1178. new (rewritten) query.
  1179. %
  1180. end{itemize} 
  1181. paragraph{The view definition contains a having clause:}  Now we will
  1182. look at the problems that can arise using {it views} that are
  1183. defined using a query involving a {it having clause}. \
  1184. \
  1185. Let the following {it view definition} be given:
  1186. %
  1187. begin{verbatim}
  1188.   create view test_view
  1189.   as select sno, count(pno) as number
  1190.      from sells
  1191.      where sno > 2
  1192.      group by sno
  1193.      having count(pno) > 1;
  1194. end{verbatim}
  1195. %
  1196. Simple queries against this {it view} will not cause any troubles:
  1197. %
  1198. begin{verbatim}
  1199.   select * 
  1200.   from test_view
  1201.   where sno <> 5;
  1202. end{verbatim}
  1203. %
  1204. This query can easily be rewritten by adding the {it where
  1205. qualification} of the user's query ({tt sno $<>$ 5}) to the {it
  1206. where qualification} of the {it view definition's } query. \
  1207. \
  1208. The next query is also simple but it will cause troubles when
  1209. it is evaluated against the above given {it view definition}:
  1210. %
  1211. begin{verbatim}
  1212.   select * 
  1213.   from test_view
  1214.   where number > 1; /* count(pno) in the view def.
  1215.                      * is called  number here */
  1216. end{verbatim}
  1217. %
  1218. pagebreak
  1219. The currently implemented techniques for query rewriting will rewrite
  1220. the query to:
  1221. %
  1222. begin{verbatim}
  1223.   select *
  1224.   from sells
  1225.   where sno > 2 and
  1226.         count(pno) > 1
  1227.   group by sno         
  1228.   having count(pno) > 1;
  1229. end{verbatim}
  1230. %
  1231. which is an invalid query because an {it aggregate function} appears
  1232. in the {it where clause}. \
  1233. \
  1234. Also the next query will cause troubles:
  1235. %
  1236. begin{verbatim}
  1237.   select pno, count(sno)
  1238.   from test_view
  1239.   group by pno;
  1240. end{verbatim}
  1241. %
  1242. As you can see this query does neither involve a {it where clause}
  1243. nor a {it having clause} but it contains a {it group clause} which
  1244. groups by the attribute {tt pno}. The query in the definition of the
  1245. {it view} also contains a {it group clause} that groups by the
  1246. attribute {tt sno}. The two {it group clauses} are in conflict with
  1247. each other and therefore the query cannot be rewritten to a form that
  1248. would make sense.\
  1249. \
  1250. {bf Note:} There is no solution to the above mentioned problems at the
  1251. moment and it does not make sense to put much effort into that because
  1252. the implementation of the support for queries like:
  1253. %
  1254. begin{verbatim}
  1255.   select pno_count, count(sno) 
  1256.   from ( select sno, count(pno) as pno_count
  1257.          from sells 
  1258.          where sno > 2
  1259.          group by sno
  1260.          having count(pno) > 1)
  1261.   group by pno_count;
  1262. end{verbatim}
  1263. %
  1264. (which is part of the SQL92 standard) will automatically also solve
  1265. these problems. \
  1266. \
  1267. In the next part of the current section we will present the changes
  1268. applied to the source code in order to realize the above described
  1269. items. Note that it is not necessary to understand the meaning of
  1270. every single source line here and therefore we will not discuss
  1271. detailed questions like "Why has the variable {tt varno} to be
  1272. increased by 3?". Questions like that belong to a chapter dealing
  1273. with the implementation of {it views} in <productname>Postgres</productname> and to be able to
  1274. answer them it would be necessary to know all the functions and not
  1275. only those described here. The fact important for us is to make sure,
  1276. that whatever is applied to the {it targetlist} and the data
  1277. structures representing the {it where clause} is also applied to the
  1278. data structures for the {it having clause}. There are three files
  1279. affected: \
  1280. \
  1281. indent {tt $ldots$/src/backend/rewrite/rewriteHandler.c} \
  1282. indent {tt $ldots$/src/backend/rewrite/rewriteManip.c} \
  1283. indent {tt $ldots$/src/backend/commands/view.c} \
  1284. \
  1285. Here is a description of the changes made to the functions contained
  1286. in the file {tt $ldots$/src/backend/rewrite/rewriteHandler.c}:
  1287. %
  1288. pagebreak
  1289. %
  1290. begin{itemize}
  1291. <step> {tt ApplyRetrieveRule()} \
  1292. This function becomes invoked whenever a {tt select} statement
  1293. against a {it view} is recognized and applies the {it rewrite rule}
  1294. stored in the {it system catalogs}. The additional source lines given
  1295. in the listing below make sure that the functions {tt
  1296. OffsetVarNodes()} and {tt ChangeVarNodes()} that are invoked for the
  1297. {it where clause} and the {it targetlist} of the query given in the
  1298. {it view definition} are also called for the {it having clause} and
  1299. the {it group clause} of the query in the {it view
  1300. definition}. These functions adapt the {tt varno} and {tt varattno}
  1301. fields of the {tt VAR} nodes involved.
  1302. The additional source lines at the end of {tt ApplyRetrieveRule()}
  1303. attach the data structures representing the {it having clause} and
  1304. the {it group clause} of the query in the {it view definition} to
  1305. the rewritten {it parsetree}. As mentioned earlier, a {it view
  1306. definition} involving a {it group clause} will cause troubles
  1307. whenever a query using a different {it group clause} against this
  1308. {it view} is executed. There is no mechanism preventing these
  1309. troubles included at the moment.
  1310. Note that the functions {tt OffsetVarNodes()} , {tt ChangeVarNodes()}
  1311. and {tt AddHavingQual()} appearing in {tt ApplyRetrieveRule()} are
  1312. described at a later point in time.
  1313. %
  1314. begin{verbatim}
  1315.   static void
  1316.   ApplyRetrieveRule(Query *parsetree, RewriteRule *rule,
  1317.                     int rt_index, int relation_level,
  1318.                     Relation relation, int *modified)
  1319.   {
  1320.     Query  *rule_action = NULL;
  1321.     Node   *rule_qual;
  1322.     List   *rtable,
  1323.                             .
  1324.                             .
  1325.                             .
  1326.     OffsetVarNodes((Node *) rule_action->targetList, 
  1327.                    rt_length);
  1328.     OffsetVarNodes(rule_qual, rt_length);
  1329.         
  1330. +   OffsetVarNodes((Node *) rule_action->groupClause, 
  1331. +                  rt_length);
  1332. +   OffsetVarNodes((Node *) rule_action->havingQual, 
  1333. +                  rt_length);
  1334.                             .
  1335.                             .
  1336.                             .
  1337.     ChangeVarNodes(rule_qual, 
  1338.                    PRS2_CURRENT_VARNO + rt_length, 
  1339.                    rt_index, 0);
  1340. +   ChangeVarNodes((Node *) rule_action->groupClause,
  1341. +                  PRS2_CURRENT_VARNO + rt_length, 
  1342. +                  rt_index, 0);
  1343. +   ChangeVarNodes((Node *) rule_action->havingQual,
  1344. +                  PRS2_CURRENT_VARNO + rt_length, 
  1345. +                  rt_index, 0);
  1346.                             .
  1347.                             .
  1348.                             .
  1349. end{verbatim}
  1350. pagebreak
  1351. begin{verbatim}
  1352.     if (*modified && !badsql) 
  1353.     {
  1354.       AddQual(parsetree, rule_action->qual);
  1355. +     /* This will only work if the query made to the 
  1356. +      * view defined by the following groupClause 
  1357. +      * groups by the same attributes or does not use 
  1358. +      * groups at all! 
  1359. +      */
  1360. +      if (parsetree->groupClause == NULL)
  1361. +         parsetree->groupClause = 
  1362. +                    rule_action->groupClause;
  1363. +      AddHavingQual(parsetree, 
  1364. +                    rule_action->havingQual);
  1365. +      parsetree->hasAggs = 
  1366. +         (rule_action->hasAggs || parsetree->hasAggs);
  1367. +      parsetree->hasSubLinks = 
  1368. +         (rule_action->hasSubLinks || 
  1369. +          parsetree->hasSubLinks);
  1370.     }
  1371.   }
  1372. end{verbatim}
  1373. %
  1374. <step> {tt QueryRewriteSubLink()} \
  1375. This function is called by {tt QueryRewrite()} to process possibly
  1376. contained subqueries first. It searches for nested queries by
  1377. recursively tracing through the {it parsetree} given as argument. The
  1378. additional statement makes sure that the {it having clause} is also
  1379. examined.
  1380. %
  1381. begin{verbatim}
  1382.   static void
  1383.   QueryRewriteSubLink(Node *node)
  1384.   {
  1385.     if (node == NULL)
  1386.        return;
  1387.     switch (nodeTag(node))
  1388.     {
  1389.       case T_SubLink:
  1390.       {
  1391.                             .
  1392.                             .
  1393.                             .
  1394.          QueryRewriteSubLink((Node *) query->qual);
  1395. +        QueryRewriteSubLink((Node *) 
  1396. +                            query->havingQual);
  1397.                             .
  1398.                             .
  1399.                             .
  1400.       }
  1401.                             .
  1402.                             .
  1403.                             .
  1404.     }
  1405.     return;
  1406.   }
  1407. end{verbatim}
  1408. %
  1409. pagebreak
  1410. %
  1411. <step> {tt QueryRewrite()} \
  1412. This function takes the {it parsetree} of a query and rewrites it
  1413. using <productname>Postgres</productname>'s {it rewrite system}. Before the query itself can be
  1414. rewritten, subqueries that are possibly part of the query have to be
  1415. processed. Therefore the function {tt  QueryRewriteSubLink()} is
  1416. called for the {it where clause} and for the {it having clause}.
  1417. %
  1418. begin{verbatim}
  1419.   List *
  1420.   QueryRewrite(Query *parsetree)
  1421.   {
  1422.     QueryRewriteSubLink(parsetree->qual);       
  1423. +   QueryRewriteSubLink(parsetree->havingQual);
  1424.     return QueryRewriteOne(parsetree);
  1425.   } 
  1426. end{verbatim}
  1427. %
  1428. end{itemize}
  1429. %
  1430. Here we present the changes applied to the functions that are contained
  1431. in the file {tt $ldots$/src/backend/rewrite/rewriteManip.c}:
  1432. %
  1433. begin{itemize}
  1434. %
  1435. <step> {tt OffsetVarNodes()} \
  1436. Recursively steps through the {it parsetree} given as the first
  1437. argument and increments the {tt varno} and {tt varnoold} fields of
  1438. every {tt VAR} node found by the {it offset} given as the second
  1439. argument. The additional statements are necessary to be able to handle
  1440. {tt GroupClause} nodes and {tt Sublink} nodes that may appear in the {it
  1441. parsetree} from now on.
  1442. %
  1443. begin{verbatim}
  1444.   void
  1445.   OffsetVarNodes(Node *node, int offset)
  1446.   {
  1447.      if (node == NULL)
  1448.         return;
  1449.      switch (nodeTag(node))
  1450.      {
  1451.                             .
  1452.                             .
  1453.                             .
  1454. +       /* This has to be done to make queries using 
  1455. +        * groupclauses work on views 
  1456. +        */
  1457. +        case T_GroupClause:
  1458. +        {
  1459. +          GroupClause *group = (GroupClause *) node;
  1460. +                         
  1461. +          OffsetVarNodes((Node *)(group->entry), 
  1462. +                         offset);
  1463. +        }
  1464. +        break;
  1465.                             .
  1466.                             .
  1467.                             .
  1468. +        case T_SubLink:
  1469. +        {
  1470. +          SubLink *sublink = (SubLink *) node;
  1471. +          List *tmp_oper, *tmp_lefthand;                               
  1472. +
  1473. end{verbatim}
  1474. pagebreak
  1475. begin{verbatim}
  1476. +          /* We also have to adapt the variables used 
  1477. +           * in sublink->lefthand and sublink->oper 
  1478. +           */
  1479. +          OffsetVarNodes((Node *)(sublink->lefthand), 
  1480. +                         offset);
  1481. +
  1482. +          /* Make sure the first argument of 
  1483. +           * sublink->oper points to the same var as 
  1484. +           * sublink->lefthand does otherwise we will 
  1485. +           * run into troubles using aggregates (aggno 
  1486. +           * will not be set correctly) 
  1487. +           */
  1488. +          tmp_lefthand = sublink->lefthand;                            
  1489. +          foreach(tmp_oper, sublink->oper)
  1490. +          {                                
  1491. +            lfirst(((Expr *)lfirst(tmp_oper))->args) = 
  1492. +                                  lfirst(tmp_lefthand);
  1493. +            tmp_lefthand = lnext(tmp_lefthand);
  1494. +          }                                                            
  1495. +        }
  1496. +        break;
  1497.                             .
  1498.                             .
  1499.                             .
  1500.      }
  1501.   }
  1502. end{verbatim}
  1503. %
  1504. <step> {tt ChangeVarNodes()} \
  1505. This function is similar to the above described function {tt
  1506. OffsetVarNodes()} but instead of incrementing the fields {tt varno}
  1507. and {tt varnoold} of {it all} {tt VAR} nodes found, it processes
  1508. only those {tt VAR} nodes whose {tt varno} value matches the
  1509. parameter {tt old_varno} given as argument and whose {tt
  1510. varlevelsup} value matches the parameter {tt sublevels_up}. Whenever
  1511. such a node is found, the {tt varno} and {tt varnoold} fields are
  1512. set to the value given in the parameter {tt new_varno}. The
  1513. additional statements are necessary to be able to handle {tt GroupClause}
  1514. and {tt Sublink} nodes.
  1515. %
  1516. begin{verbatim}
  1517.   void
  1518.   ChangeVarNodes(Node *node, int old_varno, 
  1519.                  int new_varno, int sublevels_up)
  1520.   {
  1521.     if (node == NULL)
  1522.        return;
  1523.     switch (nodeTag(node))
  1524.     {
  1525.                             .
  1526.                             .
  1527.                             .
  1528. +     /* This has to be done to make queries using 
  1529. +      * groupclauses work on views */
  1530. +     case T_GroupClause:
  1531. +     {
  1532. +       GroupClause  *group = (GroupClause *) node;
  1533. +                       
  1534. end{verbatim}
  1535. pagebreak
  1536. begin{verbatim}  
  1537. +       ChangeVarNodes((Node *)(group->entry),
  1538. +                      old_varno, new_varno, 
  1539. +                      sublevels_up);
  1540. +     }
  1541. +     break;
  1542.                             .
  1543.                             .
  1544.                             .
  1545.       case T_Var:
  1546.       {
  1547.                             .
  1548.                             .
  1549.                             .
  1550.         /* This is a hack: Whenever an attribute
  1551.          * from the "outside" query is used within
  1552.          * a nested subquery, the varlevelsup will 
  1553.          * be >0. Nodes having varlevelsup > 0 are  
  1554.          * forgotten to be processed. The call to 
  1555.          * OffsetVarNodes() should really be done at 
  1556.          * another place but this hack makes sure 
  1557.          * that also those VAR nodes are processed.
  1558.          */
  1559. +       if (var->varlevelsup > 0) 
  1560. +          OffsetVarNodes((Node *)var,3);
  1561.       }
  1562.       break;
  1563.                             .
  1564.                             .
  1565.                             .
  1566.       case T_SubLink:
  1567.       {
  1568.                             .
  1569.                             .
  1570.                             .
  1571. +       ChangeVarNodes((Node *) query->havingQual, 
  1572. +                      old_varno, new_varno,
  1573. +                      sublevels_up);
  1574. +       ChangeVarNodes((Node *) query->targetList, 
  1575. +                      old_varno, new_varno,
  1576. +                      sublevels_up);
  1577. +
  1578. +       /* We also have to adapt the variables used in 
  1579. +        * sublink->lefthand and sublink->oper 
  1580. +        */
  1581. +       ChangeVarNodes((Node *) (sublink->lefthand), 
  1582. +                      old_varno, new_varno,
  1583. +                      sublevels_up);
  1584.       }
  1585.       break;
  1586.                             .
  1587.                             .
  1588.                             .
  1589.     }
  1590.   }
  1591. end{verbatim}
  1592. %
  1593. <step> {tt AddHavingQual()} \
  1594. This function adds the {it operator tree} given by the parameter {tt
  1595. havingQual} to the one attached to the field {tt havingQual} of the
  1596. {it parsetree} given by the parameter {tt parsetree}. This is done
  1597. by adding a new {tt AND} node and attaching the old and the new {it
  1598. operator tree} as arguments to it. {tt AddHavingQual()} has not been
  1599. existing until v6.3.2. It has been created for the {it having logic}.
  1600. %
  1601. begin{verbatim}
  1602.   void
  1603.   AddHavingQual(Query *parsetree, Node *havingQual)
  1604.   {
  1605.     Node  *copy, *old;
  1606.     if (havingQual == NULL)
  1607.        return;
  1608.     copy = havingQual;
  1609.     old = parsetree->havingQual;
  1610.     if (old == NULL)
  1611.         parsetree->havingQual = copy;
  1612.     else
  1613.         parsetree->havingQual =
  1614.             (Node *) make_andclause(
  1615.                        makeList(parsetree->havingQual, 
  1616.                                 copy, -1));
  1617.   }
  1618. end{verbatim}
  1619. %
  1620. <step> {tt AddNotHavingQual()} \
  1621. This function is similar to the above described function  {tt
  1622. AddHavingQual()}. It also adds the {it operator tree} given by the
  1623. parameter {tt havingQual} but prefixes it by a {tt NOT} node. {tt
  1624. AddNotHavingQual()} has also not been existing until v6.3.2 and has been
  1625. created for the {it having logic}.
  1626. %
  1627. begin{verbatim}
  1628.   void
  1629.   AddNotHavingQual(Query *parsetree, 
  1630.                    Node *havingQual)
  1631.   {
  1632.     Node *copy;
  1633.     if (havingQual == NULL)
  1634.        return;
  1635.     copy = (Node *) make_notclause((Expr *)havingQual);
  1636.     AddHavingQual(parsetree, copy);
  1637. }
  1638. end{verbatim}
  1639. %
  1640. <step> {tt nodeHandleViewRule()} \
  1641. This function is called by {tt HandleViewRule()}. It replaces all
  1642. {tt VAR} nodes of the {it user query} evaluated against the {it
  1643. view} (the fields of these {tt VAR} nodes represent the positions of
  1644. the attributes in the {it virtual} table) by {tt VAR} nodes that
  1645. have already been prepared to represent the positions of the
  1646. corresponding attributes in the {it physical} tables (given in the
  1647. {it view definition}). The additional statements make sure that {tt
  1648. GroupClause} nodes and {tt Sublink} nodes are handled correctly.
  1649. begin{verbatim}
  1650.   static void
  1651.   nodeHandleViewRule(Node **nodePtr, List *rtable, 
  1652.                      List *targetlist, int rt_index,
  1653.                      int *modified, int sublevels_up)
  1654.   {
  1655.     Node *node = *nodePtr;
  1656.     if (node == NULL)
  1657.        return;
  1658.     switch (nodeTag(node))
  1659.     {
  1660.                             .
  1661.                             .
  1662.                             .
  1663. +     /* This has to be done to make queries using 
  1664. +      * groupclauses work on views 
  1665. +      */
  1666. +     case T_GroupClause:
  1667. +     {
  1668. +       GroupClause  *group = (GroupClause *) node;
  1669. +       nodeHandleViewRule((Node **) (&(group->entry)), 
  1670. +                          rtable, targetlist, rt_index, 
  1671. +                          modified, sublevels_up);
  1672. +     }
  1673. +     break;
  1674.                             .
  1675.                             .
  1676.                             .
  1677.       case T_Var:
  1678.       {
  1679.                             .
  1680.                             .
  1681.                             .
  1682.         if (n == NULL)
  1683.         {
  1684.           *nodePtr = make_null(((Var *)node)->vartype);
  1685.         }                           
  1686.         else
  1687. +       /* This is a hack: The varlevelsup of the 
  1688. +        * original variable and the new one should 
  1689. +        * be the same. Normally we adapt the node 
  1690. +        * by changing a pointer to point to a var 
  1691. +        * contained in 'targetlist'. In the 
  1692. +        * targetlist all varlevelsups are 0 so if 
  1693. +        * we want to change it to the original 
  1694. +        * value we have to copy the node before! 
  1695. +        * (Maybe this will cause troubles with some 
  1696. +        * sophisticated queries on views?) 
  1697. +        */
  1698. +       {
  1699. +         if(this_varlevelsup>0)
  1700. +         {
  1701. +            *nodePtr = copyObject(n);
  1702. +         }
  1703. +         else 
  1704. +         {
  1705. +           *nodePtr = n;
  1706. +         }
  1707. +         ((Var *)*nodePtr)->varlevelsup = 
  1708. +                            this_varlevelsup;
  1709. +       }
  1710.         *modified = TRUE;
  1711.       }
  1712.       break;
  1713.                             .
  1714.                             .
  1715.                             .
  1716.       case T_SubLink:
  1717.       {
  1718.                             .
  1719.                             .
  1720.                             .
  1721. +       nodeHandleViewRule(
  1722. +                 (Node **) &(query->havingQual), 
  1723. +                 rtable, targetlist, rt_index, 
  1724. +                 modified, sublevels_up);
  1725. +       nodeHandleViewRule(
  1726. +                 (Node **) &(query->targetList), 
  1727. +                 rtable, targetlist, rt_index, 
  1728. +                 modified, sublevels_up);
  1729. +       /* We also have to adapt the variables used 
  1730. +        * in sublink->lefthand and sublink->oper 
  1731. +        */
  1732. +       nodeHandleViewRule(
  1733. +                 (Node **) &(sublink->lefthand), 
  1734. +                 rtable, targetlist, rt_index, 
  1735. +                 modified, sublevels_up);                              
  1736. +       /* Make sure the first argument of 
  1737. +        * sublink->oper points to the same var as 
  1738. +        * sublink->lefthand does otherwise we will 
  1739. +        * run into troubles using aggregates 
  1740. +        * (aggno will not be set correctly!)
  1741. +        */                             
  1742. +       pfree(lfirst(((Expr *) 
  1743. +                    lfirst(sublink->oper))->args));
  1744. +       tmp_lefthand = sublink->lefthand;                               
  1745. +       foreach(tmp_oper, sublink->oper)
  1746. +       {                                   
  1747. +          lfirst(((Expr *) lfirst(tmp_oper))->args) = 
  1748. +                                  lfirst(tmp_lefthand);
  1749. +          tmp_lefthand = lnext(tmp_lefthand);
  1750. +       }                                                               
  1751.       }
  1752.       break;
  1753.                             .
  1754.                             .
  1755.                             .
  1756.     }
  1757.   }
  1758. end{verbatim}
  1759. %
  1760. <step> {tt HandleViewRule()} \
  1761. This function calls {tt nodeHandleViewRule()} for the {it where
  1762. clause}, the {it targetlist}, the {it group clause} and the {it
  1763. having clause} of the {it user query} evaluated against the given
  1764. {it view}.
  1765. %
  1766. begin{verbatim}
  1767.   void
  1768.   HandleViewRule(Query *parsetree, List *rtable,
  1769.                  List *targetlist, int rt_index,
  1770.                  int *modified)
  1771.   {
  1772.                             .
  1773.                             .
  1774.                             .
  1775. +   /* The variables in the havingQual and 
  1776. +    * groupClause also have to be adapted 
  1777. +    */
  1778. +   nodeHandleViewRule(&parsetree->havingQual, rtable, 
  1779. +                      targetlist, rt_index,
  1780. +                      modified, 0);
  1781. +   nodeHandleViewRule(
  1782. +           (Node **)(&(parsetree->groupClause)), 
  1783. +           rtable, targetlist, rt_index, modified, 0);
  1784.   }
  1785. end{verbatim}
  1786. %
  1787. end{itemize}
  1788. %
  1789. The following function is contained in {tt
  1790. $ldots$/src/backend/commands/view.c}:
  1791. begin{itemize}
  1792. %
  1793. <step> {tt UpdateRangeTableOfViewParse()} \
  1794. This function updates the {it range table} of the {it parsetree}
  1795. given by the parameter {tt viewParse}. The additional statement makes
  1796. sure that the {tt VAR} nodes of the {it having clause} are modified
  1797. in the same way as the {tt VAR} nodes of the {it where clause} are.
  1798. %
  1799. begin{verbatim}
  1800.   static void
  1801.   UpdateRangeTableOfViewParse(char *viewName, 
  1802.                               Query *viewParse)
  1803.   {
  1804.                             .
  1805.                             .
  1806.                             .
  1807.     OffsetVarNodes(viewParse->qual, 2);
  1808. +   OffsetVarNodes(viewParse->havingQual, 2);
  1809.                             .
  1810.                             .
  1811.                             .
  1812.   }
  1813. end{verbatim}
  1814. %
  1815. end{itemize}
  1816. subsubsection{Planner/Optimizer}
  1817. The {it planner} builds a {it queryplan} like the one shown in
  1818. figure ref{plan_having} and in addition to that it takes the {it operator
  1819. tree} attached to the field {tt havingClause} of the {tt Query} node
  1820. and attaches is to the {tt qpqual} field of the {tt AGG}
  1821. node. 
  1822. Unfortunately this is not the only thing to do. Remember from section
  1823. ref{aggregates} {it How Aggregate Functions are Implemented} that
  1824. the {it targetlist} is searched for {it aggregate functions} which
  1825. are appended to a list that will be attached to the field {tt aggs}
  1826. of the {tt AGG} node. This was sufficient as long as {it aggregate
  1827. functions} have only been allowed to appear within the {it
  1828. targetlist}. Now the {it having clause} is another source of {it
  1829. aggregate functions}. Consider the following example:
  1830. %
  1831. begin{verbatim}
  1832.   select sno, max(pno)
  1833.   from sells
  1834.   group by sno
  1835.   having count(pno) > 1;
  1836. end{verbatim}
  1837. %
  1838. Here the {it aggregate functions} {tt max} and {tt count} are in
  1839. use. If only the {it targetlist} is scanned (as it was the case before the
  1840. {it having clause} had been implemented) we will only find and process the
  1841. {it aggregate function} {tt max}. The second function {tt count} is
  1842. not processed and therefore any reference to the result of {tt count}
  1843. from within the {it having clause} will fail. The solution to this
  1844. problem is to scan the whole {it operator tree} representing the {it having
  1845. clause} for {it aggregate functions} not contained in the {it targetlist} yet
  1846. and add them to the list of {it aggregate functions} attached to the
  1847. field {tt aggs} of the {tt AGG} node. The scanning is done by the
  1848. function mbox{{tt check_having_qual_for_aggs()}} which steps
  1849. recursively through the tree.\
  1850. \
  1851. While scanning the {it having clause} for {it aggregate functions}
  1852. not contained in the {it targetlist} yet, an additional check is made to
  1853. make sure that {it aggregate functions} are used within
  1854. the {it having clause} (otherwise the query could have been
  1855. formulated using the {it where clause}). Consider the following query
  1856. which is not a valid SQL92 query:
  1857. %
  1858. begin{verbatim}
  1859.   testdb=> select sno, max(pno)
  1860.   testdb-> from sells
  1861.   testdb-> group by sno
  1862.   testdb-> having sno > 1;
  1863.   ERROR:  This could have been done in a where clause!!
  1864.   testdb=>
  1865. end{verbatim}
  1866. %
  1867. There is no need to express this query using a {it having clause},
  1868. this kind of qualification belongs to the {it where clause}:
  1869. %
  1870. begin{verbatim}
  1871.   select sno, max(pno)
  1872.   from sells
  1873.   where sno > 1
  1874.   group by sno;
  1875. end{verbatim}
  1876. %
  1877. There is still an unsolved problem left. Consider the following query
  1878. where we want to know just the supplier numbers ({tt sno}) of all
  1879. suppliers selling more than one part:
  1880. %
  1881. begin{verbatim}
  1882.   select sno
  1883.   from sells
  1884.   group by sno
  1885.   having count(pno) > 1;
  1886. end{verbatim}
  1887. %
  1888. The {it planner} creates a {it queryplan} (like the one shown in figure
  1889. ref{plan_having}) where the {it targetlists} of all nodes involved contain
  1890. only entries of those attributes listed after the {tt select} keyword of
  1891. the query. Looking at the example above this means that the
  1892. {it targetlists} of the {tt AGG} node, the {tt GRP} node the {tt SORT}
  1893. node and the {tt SeqScan} node contain only the entry for the
  1894. attribute {tt sno}. As described earlier the {it aggregation logic}
  1895. operates on attributes of the tuples returned by the subplan of
  1896. the {tt AGG} node (i.e. the result of the {tt GRP} node). Which
  1897. attributes are contained in the tuples handed back by a subplan is
  1898. determined by the {it targetlist}. In the case of our example the attribute
  1899. {tt pno} needed for the {it aggregate function} {tt count} is not
  1900. included and therefore the {it aggregation} will fail. 
  1901. pagebreak
  1902. noindent The solution to this problem is given in the following
  1903. steps:
  1904. begin{itemize}
  1905. <step> Make a copy of the actual {it targetlist} of the {tt AGG} node.
  1906. %
  1907. <step> Search the {it operator tree} representing the {it having clause}