home *** CD-ROM | disk | FTP | other *** search
/ Complete Linux / Complete Linux.iso / docs / apps / database / postgres / postgre4.z / postgre4 / src / planner / plan / initsplan.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-08-27  |  10.1 KB  |  405 lines

  1. /*     
  2.  *      FILE
  3.  *         initsplan
  4.  *     
  5.  *      DESCRIPTION
  6.  *         Target list, qualification, joininfo initialization routines
  7.  *     
  8.  */
  9.  
  10. /* RcsId("$Header: /private/postgres/src/planner/plan/RCS/initsplan.c,v 1.23 1992/07/15 04:33:11 mer Exp $");  */
  11.  
  12. /*     
  13.  *      EXPORTS
  14.  *             initialize-targetlist
  15.  *             initialize-qualification
  16.  *             initialize-join-clause-info
  17.  *     
  18.  *      NOTES
  19.  *         These routines are called by(subplanner) and modify global state of
  20.  *         the planner(adding entries to *query-relation-list* or modifying an
  21.  *         existing entry).
  22.  */
  23.  
  24. #include "tmp/c.h"
  25.  
  26. #include "nodes/pg_lisp.h"
  27. #include "nodes/plannodes.h"
  28. #include "nodes/plannodes.a.h"
  29. #include "nodes/relation.h"
  30. #include "nodes/relation.a.h"
  31.  
  32. #include "utils/lsyscache.h"
  33.  
  34. #include "planner/internal.h"
  35. #include "planner/clause.h"
  36. #include "planner/clauses.h"
  37. #include "planner/clausesel.h"
  38. #include "planner/initsplan.h"
  39. #include "planner/joininfo.h"
  40. #include "planner/relnode.h"
  41. #include "planner/tlist.h"
  42. #include "planner/var.h"
  43.  
  44. extern bool _enable_mergesort_;
  45. extern bool _enable_hashjoin_;
  46. extern int Quiet;
  47.  
  48. /*         ============
  49.  *         TARGET LISTS
  50.  *         ============
  51.  */
  52.  
  53. /*    
  54.  *        initialize-targetlist
  55.  *    
  56.  *        Creates rel nodes for every relation mentioned in the target list
  57.  *        'tlist' (if a node hasn't already been created) and adds them to
  58.  *        *query-relation-list*.  Creates targetlist entries for each member of
  59.  *        'tlist' and adds them to the tlist field of the appropriate rel node.
  60.  *    
  61.  *        Returns nothing.
  62.  *    
  63.  */
  64.  
  65. /*  .. subplanner      */
  66.  
  67. void 
  68. initialize_targetlist(tlist)
  69.      List tlist ;
  70. {
  71.     List tlist_vars = LispNil;
  72.     List xtl = LispNil;
  73.     List tvar = LispNil;
  74.     
  75. #ifdef NO_PLEASE
  76.     if(!Quiet) {
  77.     lispDisplay(tlist,0);
  78.     printf("\n");
  79.     fflush(stdout);
  80.     }
  81. #endif NO_PLEASE
  82.  
  83.     foreach (xtl,tlist) {
  84.     TLE entry;
  85.     (LispValue)entry = CAR(xtl);
  86.  
  87. #ifdef NO_PLEASE
  88.         if(!Quiet) {
  89.     lispDisplay(entry,0);
  90.     fflush(stdout);
  91.     }
  92. #endif NO_PLEASE
  93.     tlist_vars = nconc(tlist_vars,pull_var_clause( (LispValue)
  94.                         get_expr(entry) ));
  95.     }
  96.  
  97.     foreach (tvar, tlist_vars) {
  98.     Var     var;
  99.     Index   varno;
  100.     Rel    result;
  101.     
  102.     var = (Var)CAR(tvar);
  103.     varno = get_varno(var);
  104.     result = get_rel(lispInteger(varno));
  105.  
  106.     add_tl_element(result,var,LispNil);
  107.     }
  108.     
  109. }  /* function end   */
  110.  
  111. /*         ==============
  112.  *         QUALIFICATIONS
  113.  *         ==============
  114.  */
  115.  
  116. /*    
  117.  *        initialize-qualification
  118.  *    
  119.  *        Initializes ClauseInfo and JoinInfo fields of relation entries for all
  120.  *        relations appearing within clauses.  Creates new relation entries if
  121.  *        necessary, adding them to *query-relation-list*.
  122.  *    
  123.  *        Returns nothing of interest.
  124.  *    
  125.  */
  126.  
  127. /*  .. initialize-qualification, subplanner      */
  128.  
  129. void
  130. initialize_qualification(clauses)
  131.      LispValue clauses ;
  132. {
  133.      LispValue clause = LispNil;
  134.  
  135.      foreach (clause, clauses) {
  136.      if(consp(CAR(clause)) && IsA(CAR(clause),Func))
  137.         initialize_qualification(get_funcargs(CAR(clause)));
  138.       else 
  139.         if(consp(CAR(clause)) && IsA(CAR(clause),Oper))
  140.           initialize_qualification(get_opargs(CAR(clause)));
  141.       add_clause_to_rels(CAR(clause));
  142.      }
  143. }  /* function end   */
  144.  
  145. /*    
  146.  *        add-clause-to-rels
  147.  *    
  148.  *        Add clause information to either the 'ClauseInfo' or 'JoinInfo' field
  149.  *        of a relation entry(depending on whether or not the clause is a join)
  150.  *        by creating a new ClauseInfo node and setting appropriate fields
  151.  *        within the nodes.
  152.  *    
  153.  *        Returns nothing of interest.
  154.  *    
  155.  */
  156.  
  157. /*  .. initialize-qualification         */
  158.  
  159. void
  160. add_clause_to_rels(clause)
  161.      LispValue clause ;
  162. {
  163.      
  164.     /* Retrieve all relids and vars contained within the clause in the form */
  165.     /* ((relid relid ...) (var var ...)) */
  166.     
  167.     LispValue relids_vars = clause_relids_vars(clause);
  168.     LispValue relids = nth(0,relids_vars);
  169.     LispValue vars = nth(1,relids_vars);
  170.     
  171.     if(relation_level_clause_p(clause)) 
  172.       /*
  173.        * Ignore quals containing relation level clauses, but place the vars
  174.        * in the target list so their values can be referenced later.
  175.        */
  176.       add_vars_to_rels(vars,LispNil);
  177.     else {
  178.     CInfo clauseinfo = RMakeCInfo();
  179.     set_clause(clauseinfo,clause);
  180.     set_notclause(clauseinfo,contains_not(clause));
  181.     set_selectivity(clauseinfo,0);
  182.     set_indexids(clauseinfo,LispNil);
  183.     set_mergesortorder(clauseinfo,(MergeOrder)NULL);
  184.     set_hashjoinoperator(clauseinfo,(ObjectId)0);
  185.     
  186.     if(1 == length(relids)) {
  187.         
  188.         /* There is only one relation participating in 'clause', */
  189.         /* so 'clause' must be a restriction clause. */
  190.         /* XXX - let form, maybe incorrect */
  191.         Rel rel = get_rel(CAR(relids));
  192.         set_clauseinfo(rel,cons((LispValue)clauseinfo,
  193.                     (LispValue)get_clauseinfo(rel)));
  194.     } 
  195.     else {
  196.         /* 'clause' is a join clause, since there is more than one */
  197.         /*  atom in the relid list. */
  198.         
  199.         /*
  200.          * XXX If we have a func clause set selectivity to 1/3, really
  201.          *     need a true selectivity function.
  202.          */
  203.         if (is_funcclause(clause))
  204.         {
  205.         set_selectivity(clauseinfo,(Cost)0.3333333);
  206.         }
  207.         else
  208.         {
  209.         set_selectivity(clauseinfo,compute_clause_selec(clause,
  210.                                 LispNil));
  211.         }
  212.         add_join_clause_info_to_rels(clauseinfo,relids);
  213.         add_vars_to_rels(vars,relids);
  214.     }
  215.     }
  216. }  /* function end   */
  217.  
  218. /*    
  219.  *        add-join-clause-info-to-rels
  220.  *    
  221.  *        For every relation participating in a join clause, add 'clauseinfo' to
  222.  *        the appropriate joininfo node(creating a new one and adding it to the
  223.  *        appropriate rel node if necessary).
  224.  *    
  225.  *        'clauseinfo' describes the join clause
  226.  *        'join-relids' is the list of relations participating in the join clause
  227.  *    
  228.  *        Returns nothing.
  229.  *    
  230.  */
  231.  
  232. /*  .. add-clause-to-rels         */
  233.  
  234. void
  235. add_join_clause_info_to_rels(clauseinfo,join_relids)
  236.      CInfo clauseinfo;
  237.      List join_relids ;
  238. {
  239.     LispValue join_relid = LispNil;
  240.     foreach (join_relid, join_relids) {
  241.     JInfo joininfo = 
  242.       find_joininfo_node(get_rel(CAR(join_relid)),
  243.                   LispRemove(CAR(join_relid),join_relids));
  244.     set_jinfoclauseinfo(joininfo,
  245.                  lispCons((LispValue)clauseinfo,
  246.                    get_jinfoclauseinfo(joininfo)));
  247.  
  248.      }
  249. } /* function end  */
  250.  
  251. /*    
  252.  *        add-vars-to-rels
  253.  *    
  254.  *        For each variable appearing in a clause,
  255.  *        (1) If a targetlist entry for the variable is not already present in
  256.  *            the appropriate relation's target list, add one.
  257.  *        (2) If a targetlist entry is already present, but the var is part of a
  258.  *            join clause, add the relids of the join relations to the JoinList
  259.  *            entry of the targetlist entry.
  260.  *    
  261.  *        'vars' is the list of var nodes
  262.  *        'join-relids' is the list of relids appearing in the join clause
  263.  *            (if this is a join clause)
  264.  *    
  265.  *        Returns nothing.
  266.  *    
  267.  */
  268.  
  269. /*  .. add-clause-to-rels     */
  270.  
  271. void
  272. add_vars_to_rels(vars,join_relids)
  273.      List vars,join_relids ;
  274. {
  275.     Var var;
  276.     LispValue temp = LispNil;
  277.     Rel rel = (Rel)NULL;
  278.     LispValue tlistentry = LispNil;
  279.     LispValue other_join_relids = LispNil;
  280.     
  281.     foreach (temp, vars) {
  282.     var = (Var)CAR(temp);
  283.     rel = get_rel(lispInteger(get_varno(var)));
  284.     tlistentry = tlistentry_member(var,get_targetlist(rel));
  285.     other_join_relids = LispRemove(lispInteger(get_varno(var)),
  286.                     join_relids);
  287.     if(null(tlistentry))
  288.       /*   add a new entry */
  289.       add_tl_element(rel,var,other_join_relids);
  290.     else 
  291.       if(get_joinlist(tlistentry)) {
  292.           set_joinlist(tlistentry,
  293.                 /*   modify an existing entry */
  294.                 LispUnion(get_joinlist(tlistentry),
  295.                        other_join_relids));
  296.       } 
  297.     }
  298. } /* function end   */
  299.  
  300. /*         ========
  301.  *         JOININFO
  302.  *         ========
  303.  */
  304.  
  305. /*    
  306.  *        initialize-join-clause-info
  307.  *    
  308.  *        Set the MergeSortable or HashJoinable field for every joininfo node
  309.  *        (within a rel node) and the MergeSortOrder or HashJoinOp field for
  310.  *        each clauseinfo node(within a joininfo node) for all relations in a
  311.  *        query.
  312.  *    
  313.  *        Returns nothing.
  314.  *    
  315.  */
  316.  
  317. /*  .. subplanner    */
  318.  
  319. void
  320. initialize_join_clause_info(rel_list)
  321.      LispValue rel_list ;
  322. {
  323.     LispValue x;
  324.     Rel rel;
  325.     LispValue y;
  326.     JInfo joininfo;
  327.     LispValue z;
  328.     CInfo clauseinfo;
  329.     LispValue clause;
  330.     foreach (x, rel_list) {
  331.     rel = (Rel)CAR(x);
  332.     foreach (y, get_joininfo(rel)) {
  333.         joininfo = (JInfo)CAR(y);
  334.         foreach (z, get_jinfoclauseinfo(joininfo)) {
  335.         clauseinfo = (CInfo)CAR(z);
  336.         clause = (LispValue)get_clause(clauseinfo);
  337.         if( join_clause_p(clause) ) {
  338.             MergeOrder sortop = (MergeOrder)NULL;
  339.             ObjectId hashop = (ObjectId)NULL;
  340.  
  341.             if( _enable_mergesort_ ) 
  342.               sortop = mergesortop(clause);
  343.             if( _enable_hashjoin_ ) 
  344.               hashop = hashjoinop(clause);
  345.  
  346.             if( sortop) {
  347.             set_mergesortorder(clauseinfo, sortop);
  348.             set_mergesortable(joininfo,true);
  349.             }
  350.             if( hashop) {
  351.             set_hashjoinoperator(clauseinfo,hashop);
  352.             set_hashjoinable(joininfo,true);
  353.             }
  354.         }
  355.         }
  356.     }
  357.     }
  358. }  /* function end   */
  359.  
  360. /*    
  361.  *        mergesortop            === MERGE
  362.  *    
  363.  *        Returns the mergesort operator of an operator iff 'clause' is
  364.  *        mergesortable, i.e., both operands are single vars and the operator is
  365.  *        a mergesortable operator.
  366.  *    
  367.  */
  368. MergeOrder
  369. mergesortop(clause)
  370.      LispValue clause;
  371. {
  372.      LispValue sortops = op_mergesortable(get_opno((Oper)get_op(clause)),
  373.                        get_vartype(get_leftop(clause)),
  374.                        get_vartype(get_rightop(clause)));
  375.      if( consp(sortops) ) {
  376.       return(MakeMergeOrder(get_opno((Oper)get_op(clause)),
  377.                 (ObjectId)nth(0,sortops),
  378.                 (ObjectId)nth(1,sortops),
  379.                 get_vartype(get_leftop(clause)),
  380.                 get_vartype(get_rightop(clause))));
  381.      }
  382.      else 
  383.        return(NULL);
  384. }  /* function end  */
  385.  
  386. /*    
  387.  *        hashjoinop            ===  HASH
  388.  *    
  389.  *        Returns the hashjoin operator of an operator iff 'clause' is
  390.  *        hashjoinable, i.e., both operands are single vars and the operator is
  391.  *        a hashjoinable operator.
  392.  *    
  393.  */
  394.  
  395. /*  .. initialize-join-clause-info   */
  396.  
  397. ObjectId
  398. hashjoinop(clause)
  399.      LispValue clause ;
  400. {
  401.      return(op_hashjoinable(get_opno((Oper)get_op(clause)),
  402.                   get_vartype(get_leftop(clause)),
  403.                   get_vartype(get_rightop(clause))));
  404. }
  405.