optimize.k
上传用户:dgyhgb
上传日期:2007-01-07
资源大小:676k
文件大小:14k
源码类别:

SQL Server

开发平台:

Unix_Linux

  1. /*
  2.  *  optimize.k  - handler of optimizer pass of GNU SQL compiler
  3.  *
  4.  *  This file is a part of GNU SQL Server
  5.  *
  6.  *  Copyright (c) 1996, 1997, Free Software Foundation, Inc
  7.  *  Developed at the Institute of System Programming
  8.  *  This file is written by Andrew Yahin.
  9.  *
  10.  *  This program is free software; you can redistribute it and/or modify
  11.  *  it under the terms of the GNU General Public License as published by
  12.  *  the Free Software Foundation; either version 2 of the License, or
  13.  *  (at your option) any later version.
  14.  *
  15.  *  This program is distributed in the hope that it will be useful,
  16.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  17.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18.  *  GNU General Public License for more details.
  19.  *
  20.  *  You should have received a copy of the GNU General Public License
  21.  *  along with this program; if not, write to the Free Software
  22.  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  23.  *
  24.  *  Contacts: gss@ispras.ru
  25.  *
  26.  */
  27. /* $Id: optimize.k,v 1.245 1997/03/31 03:46:38 kml Exp $ */
  28. #include "setup_os.h"
  29. #include <stdio.h>
  30. #include "cycler.h"
  31. #include "kitty.h"
  32. #include "trl.h"
  33. #include "opt.h"
  34. #include "tree_gen.h"
  35. #include "cnf.h"
  36. #include <assert.h>
  37. #include "tassert.h"
  38. static void create_selection_vcb  __P((TXTREF curs_root));
  39. #define ALLOC_OPs(parent_node,number_of_OPs) 
  40. TXTREF Op[number_of_OPs];
  41. alloc_ops(DOWN_TRN(parent_node),Op,number_of_OPs);
  42. static void
  43. alloc_ops (TXTREF in_link_ptr, TXTREF * Ops, i4_t number_of_OPs)
  44. {
  45.   register TXTREF src;
  46.   register i4_t i;
  47.   for (i = 0, src = in_link_ptr; i < number_of_OPs && src;
  48.        i++, src = RIGHT_TRN (src))
  49.     Ops[i] = src;
  50.   while (i < number_of_OPs)
  51.     Ops[i++] = TNULL;
  52. }
  53. static TXTREF 
  54. process_q_predicate(TXTREF in)
  55. {
  56.   TXTREF s;
  57.   
  58.   if (CODE_TRN(in)==EXISTS  || !HAS_DOWN(in) || ARITY_TRN(in) <2) 
  59.     return in; /* there is nothing to do for exist */
  60.   s = RIGHT_TRN(DOWN_TRN(in));
  61.   if (CODE_TRN(s) != SUBQUERY)
  62.     s = TNULL;
  63.       
  64.   if(CODE_TRN(in)==IN)
  65.     if(s)
  66.       {
  67. TXTREF t= DOWN_TRN(in);
  68.         free_node(in);
  69.         return #(Some { (Equ { (C_code:list "t") })});
  70.       }
  71.     else
  72.       {
  73. TXTREF v=DOWN_TRN(in);
  74. TXTREF val=RIGHT_TRN(v);
  75.         if (!val || (CODE_TRN(val)!=VALUES)/* job has already done */ )
  76.           return in;
  77.         /*
  78.          * (In { (ColPtr) (Values { (val_0) ... (val_n) }) }) ===>
  79.          * ==> (In {(ColPtr) (val_0) ... (val_n) }) and (Values {}) --> xxxx
  80.          */
  81. RIGHT_TRN(v)=DOWN_TRN(val);
  82. arity_trn(in);
  83. free_node(val); 
  84. return in;
  85.       }
  86.   if(Is_Operation(in) && s)
  87.     {
  88.       if (TstF_TRN(in,SOME_F))
  89.         return #(Some { (C_code "in") });
  90.       if (TstF_TRN(in,QUANTIF_F))
  91.         return #(All  { (C_code "in") });
  92.     }
  93.   return in;
  94. }
  95. static void
  96. process_pos_del(TXTREF del_stmt)
  97. {
  98.   TXTREF d, decl_curs;
  99.   char *err = NULL;
  100.   TASSERT(CODE_TRN(del_stmt)==DELETE,del_stmt);
  101.   decl_curs = CUR_DECL(UPD_CURS(del_stmt));
  102.   if(decl_curs==TNULL)
  103.     {
  104.       errors--;
  105.       err="warning: positioned delete by unknown cursor; ";
  106.     }
  107.   else
  108.     {
  109.       decl_curs = DOWN_TRN(decl_curs);
  110.       d = DOWN_TRN(decl_curs);
  111.       if (RIGHT_TRN(d)!=TNULL)
  112.         SetF_TRN(d,RO_F);
  113.       if (TstF_TRN(d,RO_F)) /* if not updatable query */
  114.         err="positional delete by nonupdatable query";
  115.       else if (!trn_equal_p(DOWN_TRN(del_stmt) /* tblptr to modified table */,
  116.                             /* tblptr from      updateble query */
  117.                             DOWN_TRN (DOWN_TRN (d))))
  118.         err="positional delete table is not the same as cursor's one";
  119.       else /* if everything ok */
  120.         SetF_TRN(decl_curs,DEL_CUR_F);
  121.     }        
  122.   if (err)
  123.     {
  124.       file_pos = LOCATION_TRN(del_stmt);
  125.       yyerror(err);
  126.     }
  127.   free_tree(del_stmt);
  128. }
  129. static TXTREF 
  130. invert(TXTREF n)
  131. {
  132.   TXTREF res = n, p;
  133.   switch(CODE_TRN(n))
  134.     {
  135.     case AND: 
  136.       CODE_TRN(n) = OR;
  137.       for( p = DOWN_TRN(n); p ; p = RIGHT_TRN(p))
  138.         p = invert(p);
  139.       break;
  140.     case OR:
  141.       CODE_TRN(n) = AND;
  142.       for( p = DOWN_TRN(n); p ; p = RIGHT_TRN(p))
  143.         p = invert(p);
  144.       break;
  145.     case NOT:
  146.       res = DOWN_TRN(n);
  147.       RIGHT_TRN(res) = RIGHT_TRN(n); 
  148.       free_node(n);
  149.       break;
  150.     case EQU: CODE_TRN(n) = NE ; break;
  151.     case NE : CODE_TRN(n) = EQU; break;
  152.     case LE : CODE_TRN(n) = GT ; break;
  153.     case GE : CODE_TRN(n) = LT ; break;
  154.     case LT : CODE_TRN(n) = GE ; break;
  155.     case GT : CODE_TRN(n) = LE ; break;
  156.     case ISNULL    : CODE_TRN(n) = ISNOTNULL ; break;
  157.     case ISNOTNULL : CODE_TRN(n) = ISNULL    ; break;
  158.     default:
  159.       return TNULL;
  160.     }
  161.   return res;
  162. }
  163. TXTREF
  164. transformer(TXTREF in, i4_t f)
  165. {
  166.   i4_t ok;
  167.   TXTREF res;
  168.   /* set default result value */
  169.   res = in;
  170.   if(f) /* for external processors */
  171.     {
  172.       res = group_by_proc(res,f);  /* make group processing */
  173.       res = sorting_proc(res,f);   /* sorter preparation    */ 
  174.     }
  175.   
  176.   if (f == 0) /* initialization */
  177.     {
  178.       res = cycler (in, transformer, 
  179.                     CYCLER_LD + CYCLER_DR + CYCLER_RL +
  180.                     CYCLER_RLC + CYCLER_LN);
  181.     }
  182.   else if (f == CYCLER_LD)
  183.     {
  184.       if (Is_Statement(res)) 
  185.         { /* clear checked flag of parameters */
  186.           TXTREF p;
  187.           for (p = STMT_VCB(res); p ; p = RIGHT_TRN(p))
  188.             if (CODE_TRN(p) == PARAMETER)
  189.               ClrF_TRN(p,CHECKED_F);
  190.         }
  191.       switch (CODE_TRN (res))
  192. {
  193. case GRANT:
  194.           cycler_skip_subtree = 1;
  195.           break;
  196. case TBLPTR:
  197.           if (CODE_TRN(COR_TBL(TABL_DESC(res)))==VIEW)  /* get view in tree */
  198.             {
  199.               TXTREF t,c,tbl;
  200.               tbl = COR_TBL(TABL_DESC(res));
  201.               /* if some tmptable of view has the same atributes (names) as local tmptable
  202.                * change it's name until it become unique */
  203.               for (t=VIEW_VCB(tbl); t; t = RIGHT_TRN(t))
  204.                 while (find_entry(t)) /* check tmptable in statement local vcb */
  205.                   {
  206.                     static i4_t tmptbl_no = 100;
  207.                     char   tn[100];
  208.                     TXTREF lv = LOCAL_VCB_ROOT;
  209.                     LTRLREF l;
  210.                     LOCAL_VCB_ROOT = VIEW_VCB(tbl);
  211.                     TASSERT(CODE_TRN(t)==TMPTABLE,t);
  212.                     do  /* check for uniqueness in view vcb */
  213.                       {
  214.                         sprintf(tn,"%s_%d",STRING(TBL_NAME(t)),tmptbl_no++);
  215.                         l = ltr_rec(tn);
  216.                       }
  217.                     while (find_table(TMPTABLE,TBL_FNAME(t),l));
  218.                     TBL_NAME(t)= ltr_rec(tn);
  219.                     LOCAL_VCB_ROOT = lv;
  220.                   }
  221.               c = #(TblPtr (Scan ));
  222.               COR_TBL(TABL_DESC(c)) = tbl;
  223.               check_scan_cols(c);
  224.               t = gen_node(TMPTABLE);
  225.               TBL_COLS(t)  = COR_COLUMNS(TABL_DESC(c));
  226.               TBL_NCOLS(t) = TBL_NCOLS(tbl);
  227.               TBL_FNAME(t) = TBL_FNAME(tbl);
  228.               TBL_NAME(t)  = TBL_NAME(tbl);
  229.               free_node(TABL_DESC(c));
  230.               free_node(c);
  231.               for(c=TBL_COLS(t);c;c=COL_NEXT(c))
  232.                 CODE_TRN(c) = COLUMN;
  233.               add_info(t);
  234.               VIEW_QUERY(t) = copy_tree(VIEW_QUERY(tbl));
  235.               COR_VIEW(TABL_DESC(res)) = tbl;
  236.               tbl = COR_TBL(TABL_DESC(res)) = t;
  237.             }
  238.           if (CODE_TRN(COR_TBL(TABL_DESC(res)))==TMPTABLE)  
  239.             { /* go throuth nested query */
  240.               TXTREF t = COR_TBL(TABL_DESC(res));
  241.               VIEW_QUERY(t) = transformer(VIEW_QUERY(t),0);
  242.             } 
  243.           break;
  244.         default: break;
  245.         }
  246.     }
  247.   else if (f == CYCLER_DR)
  248.     {
  249.       /* let's try to make fast selection */
  250.       switch (CODE_TRN (res))
  251. {
  252. case DECL_CURS:
  253.           create_selection_vcb (res);
  254.           break;
  255. case DELETE:
  256.           if (!Is_Statement(res)) /* grant delete */
  257.             break;  /* do nothing */
  258.           res = get_up_nested_table(res,0);
  259.           if (UPD_CURS(res)) /* positioned delete by UPD_CURS cursor */
  260.             {
  261.               process_pos_del(res);
  262.               res = TNULL;
  263.             }
  264.           else /* searched only **** Ops     0     1     */
  265.             {                  /****      TblPtr Where   */
  266.               ALLOC_OPs (res, 2);
  267.               DOWN_TRN (res) =
  268. #               (Query {
  269.             (From {(Op:0)})
  270.                   (Selection)
  271.           (Op:1)
  272.                 } )
  273.                 ;
  274.               ARITY_TRN (res) = 1;
  275.             }
  276.           break;
  277. case UPDATE:
  278.           if (!Is_Statement(res)) /* grant update */
  279.             break;  /* do nothing */
  280.           res = process_update (get_up_nested_table(res,0));
  281.   break;
  282. case INSERT:
  283.   res = process_insert (get_up_nested_table(res,0));
  284.   break;
  285. case CREATE:
  286.           if (CODE_TRN(CREATE_OBJ(res))==VIEW)
  287.             { /* compute RO_F in view query */
  288.               TXTREF view,lvcb;
  289.               view = CREATE_OBJ(res);
  290.               lvcb = LOCAL_VCB_ROOT;
  291.               LOCAL_VCB_ROOT = VIEW_VCB(view);
  292.               VIEW_QUERY(view) = transformer(VIEW_QUERY(view),0);
  293.               VIEW_VCB(view) = LOCAL_VCB_ROOT;
  294.               LOCAL_VCB_ROOT = lvcb;
  295.               if (!TstF_TRN(VIEW_QUERY(view),RO_F))
  296.                 /*           colptrs  selection from     query              */
  297.                 for ( lvcb = DOWN_TRN(RIGHT_TRN(DOWN_TRN(VIEW_QUERY(view))));
  298.                       lvcb;
  299.                       lvcb = RIGHT_TRN(lvcb))
  300.                   if (CODE_TRN(lvcb)!=COLPTR)
  301.                     {
  302.                       SetF_TRN(VIEW_QUERY(view),RO_F);
  303.                       break;
  304.                     }
  305.             }
  306.   break;
  307. case UNION: /* processed in sorter */
  308.           SetF_TRN(res,RO_F);
  309.   break;
  310. case WHERE:
  311. case HAVING:
  312.   DOWN_TRN(res) = rule_CNF (&ok, DOWN_TRN (res));
  313.   break;
  314. case BETWEEN: /* OPs  0   1     2   */
  315.   { /*    what left right */
  316.     ALLOC_OPs (res, 3);
  317.             if (Is_Operation(Op[0]))
  318.               {
  319.                 Op[0] = #(Noop 2 { (Op:0) });
  320.                 res = 
  321. #                 (And
  322.             {
  323.       (Ge { (Noop  { (Op:0) }) (Op:1) })
  324.       (Le { (Noop  { (Op:0) }) (Op:2) })
  325.                   } );
  326.               }
  327.             else
  328.               {
  329.                 res =
  330. #                 (And
  331.             {
  332.      (Ge { (Op: 0)        (Op:1) })
  333.      (Le { (COPY (Op: 0)) (Op:2) })
  334.                     } );
  335.               }
  336.     break;
  337.   }
  338. case NOT:
  339.           {
  340.             TXTREF to_del = res;
  341.             res = invert(DOWN_TRN (to_del));
  342.             if (res)
  343.               free_node(to_del);
  344.             else
  345.               res = to_del;
  346.             break;
  347.           }
  348. default:
  349.   /* otherwise we have to do complex tree analysys */
  350.   res = process_q_predicate (res);
  351. }
  352.     }
  353.   else if (f == CYCLER_RL) {}
  354.   return res;
  355. }
  356. i4_t 
  357. transform (void)
  358. {
  359.   ROOT = get_up_nested_table(transformer(ROOT,0),-CYCLER_LN);
  360.   free_patterns();
  361.   return 0;
  362. }
  363. int
  364. assotiative_operation (TXTREF node)
  365. {
  366.   switch (CODE_TRN (node))
  367.     {
  368.     case ADD:case OR:case MULT:case AND:
  369.       return 1;
  370.     default: break;
  371.     }
  372.   return 0;
  373. }
  374. int
  375. the_same_code (TXTREF node)
  376. {
  377.   static i4_t odd = 0;
  378.   static enum token code = UNKNOWN;
  379.   register enum token ccode = CODE_TRN (node);
  380.   if (!assotiative_operation (node))
  381.     return 0;
  382.   odd = 1 - odd;
  383.   if (odd)
  384.     code = ccode;
  385.   return (code == ccode);
  386. }
  387. void
  388. adjust_parameter (TXTREF p, TXTREF c)
  389. {
  390.   TXTREF parm = p,col = c ;
  391.   
  392.   if (CODE_TRN(parm) == PARMPTR)
  393.     parm = OBJ_DESC(parm);
  394.   if ( CODE_TRN(parm) != PARAMETER )
  395.     return;
  396.   
  397.   if (CODE_TRN(col) == COLPTR)
  398.     col = OBJ_DESC(col);
  399.   switch (CODE_TRN(col))
  400.     {
  401.     case SCOLUMN:
  402.       {
  403.         TXTREF tbl = COR_TBL(COL_TBL(col));
  404.         if (CODE_TRN(tbl) != TABLE)
  405.           goto default_l;
  406.         col = find_column(tbl,COL_NAME(col));
  407.       }
  408.     case COLUMN:
  409.       if (!TstF_TRN(parm,CHECKED_F))
  410.         PAR_NAME(parm) = COL_NAME(col);
  411.       if (COL_DEFAULT(col) == TNULL)    /* if it's not null value        */
  412.         PAR_INDICATOR(parm) = TNULL;
  413.       else if (PAR_INDICATOR(parm) == TNULL && !TstF_TRN(parm,CHECKED_F)) 
  414.         {/* if parameter can be NULL and parameter-indicator doesn't exist */
  415.           TXTREF pi;
  416.           char   b[100];
  417.           sprintf(b,"ind_of_%s",STRING(PAR_NAME(parm)));
  418.           pi = #(Parameter:indicator_f <ltr_rec(b)> Int[0,0] Int[0,0] );
  419.           if (TstF_TRN(parm,OUT_F))
  420.             SetF_TRN(pi,OUT_F);
  421.           add_info(pi);
  422.         }
  423.       break;
  424.     default:
  425.     default_l:
  426.       {
  427.         char b[100];
  428.         sprintf(b,"SQL__%d",(i4_t)(parm&0x7fff));
  429.         PAR_NAME(parm) = ltr_rec(b);
  430.       }      
  431.       break;
  432.     }
  433.   SetF_TRN(parm,CHECKED_F);
  434. }
  435. static void
  436. create_selection_vcb (TXTREF curs_root)
  437. {
  438.   register TXTREF vp = TNULL;
  439.   register TXTREF cn, cp;
  440.   register i4_t i,under_union = 0;
  441.   TXTREF   query = curs_root;
  442.   
  443.   while ((CODE_TRN(query)==CUR_AREA) ||
  444.          (CODE_TRN(query)==DECL_CURS))
  445.     query = DOWN_TRN(query);
  446.   while (CODE_TRN(query)==UNION)
  447.     { query = DOWN_TRN(query); under_union = 1; }
  448.   
  449.   TASSERT(CODE_TRN(query) == QUERY,curs_root);
  450.   vp = LOCAL_VCB_ROOT; 
  451.   /*        1st sel_elm  selection  from      query */
  452.   for (cn = DOWN_TRN    (RIGHT_TRN (DOWN_TRN (query))), i = 0;
  453.        cn;
  454.        cn = RIGHT_TRN (cn), i++ )
  455.     {
  456.       sql_type_t type = *node_type(cn);
  457.       char pn[100];
  458.       /* skip everything till parameter:out_f  */
  459.       while (vp &&
  460.              (CODE_TRN(vp)!=PARAMETER || !TstF(vp,OUT_F)  ||
  461.               TstF(vp,INDICATOR_F) ))
  462.         vp = RIGHT_TRN(vp);
  463.       if (vp)
  464.         cp = vp;
  465.       else
  466.         cp = #(Parameter:out_f - <type> <type>);
  467.       if (CODE_TRN(cn)==COLPTR || under_union == 0)
  468.         adjust_parameter(cp,cn);
  469.       else
  470.         {
  471.           sprintf(pn,"SQL__%s_%d",NAME(CODE_TRN(cn)),i);
  472.           PAR_NAME(cp) = ltr_rec(pn);
  473.           SetF_TRN(cp,CHECKED_F);
  474.         }
  475.           
  476.       if(vp) /* if we updated existed node */
  477.         vp = RIGHT_TRN(vp); 
  478.       else  /* if it was new node */
  479.         add_info(cp);
  480.     }
  481.   return;
  482. }