home *** CD-ROM | disk | FTP | other *** search
/ Complete Linux / Complete Linux.iso / docs / apps / database / postgres / postgre4.z / postgre4 / src / planner / path / orindxpath.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-05-05  |  7.7 KB  |  258 lines

  1.  
  2. /*     
  3.  *      FILE
  4.  *         orindxpath
  5.  *     
  6.  *      DESCRIPTION
  7.  *         Routines to find index paths that match a set of 'or' clauses
  8.  *     
  9.  */
  10.  
  11. /*  RcsId("$Header: /private/postgres/src/planner/path/RCS/orindxpath.c,v 1.20 1992/07/15 04:32:39 mer Exp $"); */
  12.  
  13. /*     
  14.  *      EXPORTS
  15.  *             create-or-index-paths
  16.  */
  17. #include "nodes/pg_lisp.h"
  18. #include "nodes/relation.h"
  19. #include "nodes/relation.a.h"
  20. #include "nodes/primnodes.h"
  21. #include "nodes/primnodes.a.h"
  22.  
  23. #include "tmp/nodeFuncs.h"
  24.  
  25. #include "planner/internal.h"
  26. #include "planner/clauses.h"
  27. #include "planner/orindxpath.h"
  28. #include "planner/costsize.h"
  29. #include "planner/cfi.h"
  30.  
  31. /*extern List index_selectivity(); #include "cfi.h" */ 
  32.  
  33. #define INDEX_SCAN 1
  34.  
  35. /*    
  36.  *        create-or-index-paths
  37.  *    
  38.  *        Creates index paths for indices that match 'or' clauses.
  39.  *    
  40.  *        'rel' is the relation entry for which the paths are to be defined on
  41.  *        'clauses' is the list of available restriction clause nodes
  42.  *    
  43.  *        Returns a list of these index path nodes.
  44.  *    
  45.  */
  46.  
  47. /*  .. create-or-index-paths, find-rel-paths */
  48.  
  49. LispValue
  50. create_or_index_paths (rel,clauses)
  51.      Rel rel;
  52.      List clauses ;
  53. {
  54.      LispValue t_list = LispNil;
  55.  
  56.      if ( consp (clauses) ) {
  57.       /* XXX - let form, maybe incorrect */
  58.       CInfo clausenode = (CInfo) (CAR (clauses));
  59.  
  60.       /* Check to see if this clause is an 'or' clause, and, if so, */
  61.       /* whether or not each of the subclauses within the 'or' clause has */
  62.       /* been matched by an index (the 'Index field was set in */
  63.       /* (match_or)  if no index matches a given subclause, one of the */
  64.       /* lists of index nodes returned by (get_index) will be 'nil'). */
  65.  
  66.       if(valid_or_clause (clausenode) &&
  67.          get_indexids (clausenode)) {
  68.            LispValue temp = LispNil;
  69.            LispValue index_list = LispNil;
  70.            bool index_flag = true;
  71.  
  72.            index_list = get_indexids(clausenode);
  73.            foreach(temp,index_list) {
  74.             if (!temp) 
  75.               index_flag = false;
  76.            }
  77.            if (index_flag) {   /* used to be a lisp every function */
  78.             IndexPath pathnode = RMakeIndexPath();
  79.             LispValue indexinfo = 
  80.               best_or_subclause_indices (rel,
  81.                          get_orclauseargs
  82.                              ((LispValue)get_clause(clausenode)),
  83.                          get_indexids (clausenode),
  84.                          LispNil,(Cost)0,
  85.                          LispNil);
  86.  
  87.             set_pathtype((Path)pathnode,INDEX_SCAN);
  88.             set_parent ((Path)pathnode,rel);
  89.             set_indexqual (pathnode,
  90.                    lispCons((LispValue)clausenode,LispNil));
  91.             set_indexid (pathnode,nth (0,indexinfo));
  92.             set_path_cost ((Path)pathnode,(Cost)CDouble(nth (1,indexinfo)));
  93.  
  94.             /* copy clauseinfo list into path for expensive 
  95.                function processing    -- JMH, 7/7/92 */
  96.             set_locclauseinfo
  97.               (pathnode,
  98.                set_difference(clauses,
  99.                       CopyObject(get_clauseinfo(rel))/*,
  100.                       LispNil (arg too much - kai) */));
  101.  
  102.             /* add in cost for expensive functions!  -- JMH, 7/7/92 */
  103.             set_path_cost((Path)pathnode, 
  104.                   get_path_cost((Path)pathnode) + 
  105.                   xfunc_get_path_cost(pathnode));
  106.  
  107.             set_selectivity(clausenode,(Cost)CDouble(nth(2,indexinfo)));
  108.             t_list = 
  109.               lispCons ((LispValue)pathnode,
  110.                 create_or_index_paths (rel,CDR (clauses)));
  111.            } 
  112.            else {
  113.             t_list = create_or_index_paths (rel,CDR (clauses));
  114.             
  115.            } 
  116.       }
  117.      }
  118.      return(t_list);
  119. }  /* function end  */
  120.  
  121. /*    
  122.  *        best-or-subclause-indices
  123.  *    
  124.  *        Determines the best index to be used in conjunction with each subclause
  125.  *        of an 'or' clause and the cost of scanning a relation using these
  126.  *        indices.  The cost is the sum of the individual index costs.
  127.  *    
  128.  *        'rel' is the node of the relation on which the index is defined
  129.  *        'subclauses' are the subclauses of the 'or' clause
  130.  *        'indices' are those index nodes that matched subclauses of the 'or'
  131.  *            clause
  132.  *        'examined-indexids' is a list of those index ids to be used with 
  133.  *            subclauses that have already been examined
  134.  *        'subcost' is the cost of using the indices in 'examined-indexids'
  135.  *        'selectivities' is a list of the selectivities of subclauses that
  136.  *            have already been examined
  137.  *    
  138.  *        Returns a list of the indexids, cost, and selectivities of each
  139.  *        subclause, e.g., ((i1 i2 i3) cost (s1 s2 s3)), where 'i' is an OID,
  140.  *        'cost' is a flonum, and 's' is a flonum.
  141.  *    
  142.  */
  143.  
  144. /*  .. best_or_subclause_indices, create_or_index_paths    */
  145.  
  146. LispValue
  147. best_or_subclause_indices (rel,subclauses,indices,
  148.                examined_indexids,subcost,selectivities)
  149.      Rel rel;
  150.      List subclauses,indices,examined_indexids, selectivities ;
  151.      Cost subcost;
  152. {
  153.      LispValue t_list = LispNil;
  154.      if ( null (subclauses) ) {
  155.       t_list = 
  156.         lispCons (nreverse (examined_indexids),
  157.               lispCons(lispFloat(subcost),
  158.                    lispCons(nreverse (selectivities),LispNil)));
  159.      } 
  160.      else {
  161.       LispValue indexinfo = 
  162.         best_or_subclause_index (rel,CAR (subclauses),CAR (indices));
  163.  
  164.       t_list = best_or_subclause_indices (rel,
  165.                           CDR (subclauses),
  166.                           CDR (indices),
  167.                           lispCons (nth (0,indexinfo),
  168.                             examined_indexids),
  169.                           subcost + (int) nth (1,indexinfo),
  170.                           lispCons (nth (2,indexinfo),
  171.                             selectivities));
  172.      } 
  173.      return (t_list);
  174. }  /* function end   */
  175.  
  176. /*    
  177.  *        best-or-subclause-index
  178.  *    
  179.  *        Determines which is the best index to be used with a subclause of
  180.  *        an 'or' clause by estimating the cost of using each index and selecting
  181.  *        the least expensive.
  182.  *    
  183.  *        'rel' is the node of the relation on which the index is defined
  184.  *        'subclause' is the subclause
  185.  *        'indices' is a list of index nodes that match the subclause
  186.  *    
  187.  *        Returns a list (index-id index-subcost index-selectivity)
  188.  *        (a fixnum, a fixnum, and a flonum respectively).
  189.  *    
  190.  */
  191.  
  192. /*  .. best-or-subclause-index, best-or-subclause-indices   o */
  193.  
  194. LispValue
  195. best_or_subclause_index (rel,subclause,indices)
  196.      Rel     rel;
  197.      LispValue  subclause;
  198.      List    indices ;
  199. {
  200.      LispValue t_list = LispNil;
  201.  
  202.      if ( consp (indices) ) {
  203.       Datum     value;
  204.       int         flag = 0;
  205.       LispValue pagesel = LispNil;
  206.       Cost         subcost;
  207.       LispValue     bestrest = LispNil;
  208.       Rel         index = (Rel)CAR (indices);
  209.       AttributeNumber attno = get_varattno (get_leftop (subclause));
  210.       ObjectId     opno = get_opno((Oper)CAR(subclause));
  211.       bool         constant_on_right = non_null((Expr)get_rightop(subclause));
  212.  
  213.       if(constant_on_right) {
  214.            value = get_constvalue((Const)get_rightop (subclause));
  215.       } 
  216.       else {
  217.            value = NameGetDatum("");
  218.       } 
  219.       if(constant_on_right) {
  220.            flag = (_SELEC_IS_CONSTANT_ ||_SELEC_CONSTANT_RIGHT_);
  221.       } 
  222.       else {
  223.            flag = _SELEC_CONSTANT_RIGHT_;
  224.       } 
  225.       pagesel = index_selectivity (CInteger(CAR(get_relids (index))) ,
  226.                        get_classlist (index),
  227.                        lispInteger(opno),
  228.                        CInteger(getrelid (CInteger
  229.                             (CAR(get_relids(rel))),
  230.                         _query_range_table_)),
  231.                        lispCons (lispInteger(attno),LispNil),
  232.                        lispCons (lispInteger(value),LispNil),
  233.                        lispCons (lispInteger(flag),LispNil),
  234.                        1);
  235.  
  236.       subcost = cost_index((ObjectId)CInteger(nth (0,get_relids(index))),
  237.                 (Count)CDouble(CAR(pagesel)),
  238.                 (Cost)CDouble(CADR(pagesel)),
  239.                 get_pages (rel),
  240.                 get_tuples (rel),
  241.                 get_pages (index),
  242.                 get_tuples (index), false);
  243.       bestrest = best_or_subclause_index (rel,subclause,CDR (indices));
  244.         
  245.       if(null (bestrest) || (subcost < CInteger(CAR(bestrest)) )) {
  246.            /* XXX - this used to be "list "(CAR(get....index),.." */
  247.            t_list = lispCons (get_relids (index),
  248.                   lispCons(lispFloat(subcost),
  249.                        lispCons(CADR(pagesel),
  250.                             LispNil)));
  251.       } 
  252.       else {
  253.            t_list = bestrest;
  254.       } 
  255.      } 
  256.      return(t_list);
  257. }
  258.