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

  1.  
  2. /*     
  3.  *      FILE
  4.  *         prepunion
  5.  *     
  6.  *      DESCRIPTION
  7.  *         Routines to plan archive, inheritance, union, and version queries
  8.  *     
  9.  */
  10.  
  11. /* RcsId ("$Header: /private/postgres/src/planner/prep/RCS/prepunion.c,v 1.23 1992/08/21 05:46:12 mer Exp $");  */
  12.  
  13. /*     
  14.  *      EXPORTS
  15.  *             first-matching-rt-entry
  16.  *             plan-union-queries
  17.  *             fix-targetlist
  18.  */
  19.  
  20. #include "tmp/c.h"
  21.  
  22. #include "nodes/nodes.h"
  23. #include "nodes/pg_lisp.h"
  24. #include "nodes/execnodes.h"
  25. #include "nodes/plannodes.h"
  26. #include "nodes/plannodes.a.h"
  27. #include "nodes/relation.h"
  28. #include "nodes/relation.a.h"
  29.  
  30. #include "parser/parse.h"
  31. #include "parser/parsetree.h"
  32. #include "tmp/utilities.h"
  33. #include "utils/log.h"
  34. #include "utils/lsyscache.h"
  35.  
  36. #include "planner/internal.h"
  37. #include "planner/cfi.h"
  38. #include "planner/plancat.h"
  39. #include "planner/planner.h"
  40. #include "planner/prepunion.h"
  41. #include "planner/handleunion.h"
  42.  
  43. /*    
  44.  *        find-all-inheritors
  45.  *    
  46.  *        Returns a list of relids corresponding to relations that inherit
  47.  *        attributes from any relations listed in either of the argument relid
  48.  *        lists.
  49.  *    
  50.  */
  51.  
  52. /*  .. find-all-inheritors, plan-union-queries    */
  53.  
  54. LispValue
  55. find_all_inheritors (unexamined_relids,examined_relids)
  56.      LispValue unexamined_relids,examined_relids ;
  57. {
  58.     LispValue new_inheritors = LispNil;
  59.     LispValue new_examined_relids = LispNil;
  60.     LispValue new_unexamined_relids = LispNil;
  61.     
  62.     /*    Find all relations which inherit from members of */
  63.     /*    'unexamined-relids' and store them in 'new-inheritors'. */
  64.     
  65.     LispValue rels = LispNil;
  66.     LispValue newrels = LispNil;
  67.     
  68.      /* was lispDO */
  69.     foreach(rels,unexamined_relids) {
  70.     newrels = LispUnion(find_inheritance_children (CAR (rels)),
  71.                 newrels);
  72.     }
  73.     new_inheritors = newrels;
  74.     
  75.     new_examined_relids = LispUnion (examined_relids,unexamined_relids);
  76.     new_unexamined_relids = set_difference (new_inheritors,
  77.                         new_examined_relids);
  78.     
  79.     if(null (new_unexamined_relids)) {
  80.     return(new_examined_relids);
  81.     } else {
  82.     return (find_all_inheritors (new_unexamined_relids,
  83.                      new_examined_relids));
  84.     }
  85. } /* function end   */
  86.  
  87. /*            =====
  88.  *            UNION
  89.  *            =====
  90.  */
  91.  
  92. /*            =======
  93.  *            VERSION
  94.  *            =======
  95.  */
  96.  
  97. /*            ===============
  98.  *            COMMON ROUTINES
  99.  *            ===============
  100.  */
  101.  
  102. /*    
  103.  *        first-matching-rt-entry
  104.  *    
  105.  *        Given a rangetable, find the first rangetable entry that represents
  106.  *        the appropriate special case.
  107.  *    
  108.  *        Returns a rangetable index.
  109.  *    
  110.  */
  111.  
  112. /*  .. planner    */
  113.  
  114. int
  115. first_matching_rt_entry (rangetable,flag)
  116.      LispValue rangetable,flag ;
  117. {
  118.     
  119.  
  120.     int count = 0;
  121.     int position = -1;
  122.     LispValue temp = LispNil;
  123.     bool first = true;
  124. /*     XXX the bogus way to handle things (old parser)
  125.  *         (position-if (case flag
  126.  *                    (archive
  127.  *                     #'(lambda (x)
  128.  *                     (rt_archive_time x)))
  129.  *                    (inheritance
  130.  *                     #'(lambda (x)
  131.  *                     (and (rt_relid x)
  132.  *                          (listp (rt_relid x)))))
  133.  *                    ((union version)
  134.  *                     #'(lambda (x)
  135.  *                     #+opus43 (declare (special flag))
  136.  *                     (member flag (rt_flags x)))))
  137.  *    )
  138.  *     XXX new spiffy way to handle things (new parser)
  139.  */
  140.  
  141.     foreach (temp,rangetable) {
  142.     if (member (flag,rt_flags (CAR(temp))) && first) {
  143.         position = count;
  144.         first = false;
  145.     }
  146.     count++;
  147.       }
  148.     
  149.     if(position != -1) 
  150.       position++;
  151.      
  152.     return(position);
  153. } /* function end   */
  154.  
  155.  
  156. /*    
  157.  *        plan-union-queries
  158.  *    
  159.  *        Plans the queries for a given parent relation.
  160.  *    
  161.  *        Returns a list containing a list of plans and a list of rangetable
  162.  *        entries to be inserted into an APPEND node.
  163.  *     XXX - what exactly does this mean, look for make_append
  164.  */
  165.  
  166. /*  .. planner     */
  167.  
  168. Append
  169. plan_union_queries (rt_index,flag,root,tlist,qual,rangetable)
  170.      Index  rt_index;
  171.      int flag;
  172.      LispValue root,tlist,qual,rangetable ;
  173. {
  174.     LispValue temp_flag = LispNil;
  175.     LispValue rt_entry = rt_fetch (rt_index,rangetable);
  176.     LispValue union_relids = LispNil;
  177.     LispValue union_info = LispNil;
  178.     LispValue union_plans = LispNil;
  179.     LispValue union_rt_entries = LispNil;
  180.     LispValue temp = LispNil;
  181.     
  182.     switch (flag) {
  183.     
  184.       case INHERITS :
  185.     union_relids = 
  186.       find_all_inheritors (lispCons(rt_relid (rt_entry),
  187.                     LispNil),
  188.                    LispNil);
  189.     break;
  190.  
  191.       case UNION : {
  192.     Index rt_index = 0;
  193.       union_plans = handleunion(root,rangetable,tlist,qual);
  194.       return (make_append (union_plans,
  195.                    rt_index, rangetable,
  196.                    get_qptargetlist ((Plan)CAR(union_plans))));
  197.       }
  198.     break;
  199.     
  200.       case VERSION :
  201.     union_relids = find_version_parents (rt_relid (rt_entry));
  202.     break;
  203.     
  204.       case ARCHIVE :
  205.     union_relids = find_archive_rels(rt_relid(rt_entry));
  206.     break;
  207.  
  208.       default: 
  209.     /* do nothing */
  210.     break;
  211.     }
  212.  
  213.     /*    Remove the flag for this relation, */
  214.     /*     since we're about to handle it */
  215.     /*    (do it before recursing!). */
  216.     /*    XXX destructive parse tree change */
  217.     /*   was setf -- is this right?  */
  218.  
  219.     temp_flag = lispInteger(flag);
  220.     NodeSetTag(temp_flag,classTag(LispSymbol));
  221.     rt_flags (rt_fetch (rt_index,rangetable)) = 
  222.       LispRemove (temp_flag,
  223.           rt_flags (rt_fetch (rt_index,rangetable)));
  224.  
  225.     /* XXX - can't find any reason to sort union-relids
  226.        as paul did, so we're leaving it out for now
  227.        (maybe forever) - jeff & lp */
  228.  
  229.     union_info = plan_union_query (union_relids,
  230.                    rt_index,rt_entry,
  231.                    root,tlist,qual,rangetable);
  232.  
  233.     foreach(temp,union_info) {
  234.       union_plans = nappend1(union_plans,CAR(CAR(temp)));
  235.       union_rt_entries = nappend1(union_rt_entries,
  236.                   CADR (CAR(temp)));
  237.     }
  238.  
  239.     return (make_append (union_plans,
  240.              rt_index,
  241.              union_rt_entries,
  242.              get_qptargetlist ((Plan)CAR (union_plans))));
  243. }
  244.  
  245.  
  246. /*    
  247.  *        plan-union-query
  248.  *    
  249.  *        Returns a list of plans for 'relids'.
  250.  *    
  251.  */
  252.  
  253. /*  .. plan-union-queries, plan-union-query    */
  254.  
  255. LispValue
  256. plan_union_query (relids,rt_index,rt_entry,root,tlist,qual,rangetable)
  257.      LispValue relids,rt_entry,root,tlist,qual,rangetable ;
  258.      Index rt_index;
  259. {
  260.     LispValue i = LispNil;
  261.     LispValue union_plans = LispNil;
  262.  
  263.     foreach (i,relids) {
  264.     LispValue relid = CAR (i);
  265.     LispValue new_rt_entry = new_rangetable_entry (CInteger(relid),
  266.                                rt_entry);
  267.     LispValue new_root = subst_rangetable (root,
  268.                            rt_index,
  269.                            new_rt_entry);
  270.     LispValue new_parsetree = LispNil;
  271.     LispValue new_tlist = copy_seq_tree(tlist);
  272.     LispValue new_qual = copy_seq_tree(qual);
  273.  
  274.     /* reset the uniqueflag and sortclause in parse tree root, so that
  275.      * sorting will only be done once after append
  276.      */
  277.     root_uniqueflag(new_root) = LispNil;
  278.     root_sortclause(new_root) = LispNil;
  279.     if ( listp(rt_relid(rt_entry))) 
  280.       new_parsetree = fix_parsetree_attnums (rt_index, 
  281.                          /* XX temporary for inheritance */
  282.                          CInteger(CAR 
  283.                              (rt_relid(rt_entry))),
  284.                          CInteger(relid),
  285.                          lispCons(new_root,
  286.                               lispCons
  287.                                    (new_tlist,
  288.                                 lispCons
  289.                                 (new_qual,
  290.                                  LispNil))));
  291.     else 
  292.       new_parsetree = fix_parsetree_attnums (rt_index, 
  293.                          CInteger(rt_relid(rt_entry)),
  294.                          CInteger(relid),
  295.                          lispCons(new_root,
  296.                               lispCons
  297.                               (new_tlist,
  298.                                lispCons
  299.                                (new_qual,
  300.                                 LispNil))));
  301.  
  302.  
  303.     union_plans =
  304.         nappend1(union_plans,
  305.              lispCons((LispValue)planner(CopyObject(new_parsetree)),
  306.                   lispCons(new_rt_entry,
  307.                        LispNil)));
  308.     }
  309.     return(union_plans);
  310.  
  311. }  /* function end   */
  312.  
  313. /*    
  314.  *        new-rangetable-entry
  315.  *    
  316.  *        Replaces the name and relid of 'old-entry' with the values for 
  317.  *        'new-relid'.
  318.  *    
  319.  *        Returns a copy of 'old-entry' with the parameters substituted.
  320.  *    
  321.  */
  322.  
  323. /*  .. plan-union-query     */
  324.  
  325. LispValue
  326. new_rangetable_entry (new_relid,old_entry)
  327.      ObjectId new_relid;
  328.      LispValue old_entry ;
  329. {
  330.  
  331.     LispValue new_entry = copy_seq_tree (old_entry);
  332. /*
  333.  *  following stmt had to be changed to ensuing if stmt.
  334.  *
  335.  *   rt_relname (new_entry) = lispString(get_rel_name (new_relid));
  336.  *   
  337.  *  i know it's not a good idea to manipulate range table entry
  338.  *  without using macros defined in lib/H/parsetree.h, but i couldn't
  339.  *  think of a better way to do it.  i'll come with a better fix when
  340.  *  i get more familiar with the parser.   8/1/90 ron choi
  341.  */
  342.     if (!strcmp(CString(CAR(new_entry)), "*CURRENT*") ||
  343.         !strcmp(CString(CAR(new_entry)), "*NEW*"))
  344.       CAR(new_entry) =  lispString((char *)get_rel_name (new_relid));
  345.     else
  346.       CADR(new_entry) =  lispString((char *)get_rel_name (new_relid));
  347.  
  348.  
  349.     rt_relid (new_entry) = lispInteger(new_relid);
  350.     return(new_entry);
  351. }
  352.  
  353. /*    
  354.  *        subst-rangetable
  355.  *    
  356.  *        Replaces the 'index'th rangetable entry in 'root' with 'new-entry'.
  357.  *    
  358.  *        Returns a new copy of 'root'.
  359.  *    
  360.  */
  361.  
  362. /*  .. plan-union-query    */
  363.  
  364. LispValue
  365. subst_rangetable (root,index,new_entry)
  366.      LispValue root,new_entry ;
  367.      Index index;
  368. {
  369.     LispValue new_root = copy_seq_tree (root);
  370.     LispValue temp = LispNil;
  371.     int i = 0;
  372.  
  373.     for(temp = root_rangetable(new_root),i =1; i < index; temp =CDR(temp),i++)
  374.       ;
  375.     CAR(temp) = new_entry;
  376.     /*  setf(rt_fetch (index,root_rangetable (new_root)),new_entry); */
  377.     return (new_root);
  378.  
  379. }
  380.  
  381. /*    
  382.  *        fix-parsetree-attnums
  383.  *     
  384.  *        Replaces attribute numbers from the relation represented by
  385.  *        'old-relid' in 'parsetree' with the attribute numbers from
  386.  *        'new-relid'.
  387.  *    
  388.  *        Returns the destructively-modified parsetree.
  389.  *    
  390.  */
  391.  
  392. /*  .. fix-parsetree-attnums, plan-union-query    */
  393.  
  394. LispValue
  395. fix_parsetree_attnums (rt_index,old_relid,new_relid,parsetree)
  396.      Index rt_index;
  397.      ObjectId old_relid,new_relid;
  398.      LispValue parsetree ;
  399. {
  400.     LispValue i = LispNil;
  401.     Node foo = (Node)NULL;
  402.     
  403.     
  404.     /* If old_relid == new_relid, we shouldn't have to 
  405.      * do anything ---- is this right??
  406.      */
  407.  
  408.     if (old_relid != new_relid)
  409.       foreach(i,parsetree) {
  410.       foo = (Node)CAR(i);
  411.       if (!null(foo) && IsA(foo,Var) && 
  412.            (get_varno ((Var)foo) == rt_index) &&
  413.            (get_varattno((Var)foo) != 0)) {
  414.           set_varattno ((Var)foo, get_attnum (new_relid, get_attname(old_relid, get_varattno((Var)foo))));
  415.       }
  416.       if (!null(foo) && IsA(foo,LispList)) {
  417.           foo = (Node)fix_parsetree_attnums(rt_index,old_relid,
  418.                         new_relid,(LispValue)foo);
  419.       }
  420.       /* vectors ? */
  421.       /* all other cases are not interesting, I believe - jeff */
  422.       }
  423.  
  424.     return (parsetree);
  425. }
  426.  
  427. /*    
  428.  *        fix-rangetable
  429.  *    
  430.  *        Replaces the 'index'th rangetable entry with 'new-entry'.
  431.  *    
  432.  *        Returns a new copy of 'rangetable'.
  433.  *    
  434.  */
  435.  
  436. /*  .. print_plan    */
  437.  
  438. List
  439. fix_rangetable (rangetable,index,new_entry)
  440.      List rangetable;
  441.      int index;
  442.      List new_entry ;
  443. {
  444.   LispValue new_rangetable = copy_seq_tree (rangetable);
  445.   /* XXX was setf  */
  446.   rt_store (index,new_rangetable,new_entry);
  447.  
  448.   return (new_rangetable);
  449.  
  450. }
  451.  
  452. /*  XXX dummy function -- HELP fix me !  */
  453. TL
  454. fix_targetlist (oringtlist, tlist)
  455.      TL oringtlist,tlist;
  456. {
  457.     elog(WARN,"unsupported function, fix_targetlist");
  458.     return((TL)tlist);
  459. }
  460.         
  461.  
  462. Append
  463. make_append (unionplans,rt_index,union_rt_entries, tlist)
  464.      List unionplans,union_rt_entries,tlist;
  465.      Index rt_index;
  466. {
  467.   Append node = RMakeAppend();
  468.  
  469.   set_unionplans(node,unionplans);
  470.   set_unionrelid(node,rt_index);
  471.   set_unionrtentries(node,union_rt_entries);
  472.   set_cost((Plan)node,0.0);
  473.   set_fragment((Plan)node,0);
  474.   set_state((Plan)node,(EStatePtr)NULL);
  475.   set_qptargetlist((Plan)node,tlist);
  476.   set_qpqual((Plan)node,LispNil);
  477.   set_lefttree((Plan)node,(PlanPtr)NULL);
  478.   set_righttree((Plan)node,(PlanPtr)NULL);
  479.  
  480.   return(node);
  481. }
  482.