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

SQL Server

开发平台:

Unix_Linux

  1. /*
  2.  *  optim.c - optimization of input tree for synthesator
  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 Konstantin Dyshlevoi
  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: optim.c,v 1.246 1997/03/31 11:02:34 kml Exp $ */
  28. #include "global.h"
  29. #include "syndef.h"
  30. #include "inprtyp.h"
  31. #include <assert.h>
  32. #include "tassert.h"
  33. #define USE_INDEXES   1
  34. #define USE_SIMP_PRED 1
  35. #define OPEN_SCAN_COST 10
  36. #define DEFAULT_SEL    0.5
  37. #define PRINT(x, y) /* PRINTF ((x, y)) */
  38. #define PRINT_(x)   /* PRINTF ((x))    */
  39. extern DataUnit *data_st;
  40. extern i4_t   dt_ind, dt_max;
  41. extern SH_Info *tr_arr;
  42. extern i4_t tr_cnt, tr_max;
  43. static i4_t  MAX_LNG = ((u4_t)(-1))/2;
  44. static float FLT_MAX_LNG = (float)(((u4_t)(-1))/2);
  45. MASK *TblBits, *TblAllBits, _AllTblMsk;
  46. TXTREF *tbl_ind;
  47. i4_t TblNum;
  48. i4_t *CurTblOrder, *tab_col_num;
  49. float *NumRowScans;
  50. float BestCost;
  51. i4_t *NumRows; /* number of rows for every table        */
  52. i4_t DisNum;    /* number of AND sons in WHERE           *
  53.         * ( or 1 if there isn't AND in root )   */
  54. i4_t SPNum;     /* number of Simple Predicates for Query */
  55. Simp_Pred_Info *SP_Arr;
  56. SP_Ind_Info **SP_Ind_Arr;
  57. Col_Stat_Info *col_stat;
  58. i4_t *fin_nums;
  59. /* optimizator works only with input trees of procedurizator */
  60. #define CHECK_SEL_ERR(er) { if (er < 0) yyfatal (" Can't get statistic info n"); }
  61. float
  62. Mk_Sel (i4_t tbl_num, i4_t col_num, TXTREF col_node, TXTREF SP_Tree, i4_t prdc_num)
  63.      /* estimation of selectivity for predicate */
  64. {
  65.   TXTREF col_ptr   = DOWN_TRN (SP_Tree);
  66.   TXTREF right_ptr = RIGHT_TRN (col_ptr);
  67.   TXTREF cur_ptr;
  68.   VCBREF Tab, CurClm;
  69.   float sel = DEFAULT_SEL, min_sel = 1.0 / ((float) NumRows[tbl_num]);
  70.   i4_t sign = 0, err, op = CODE_TRN (SP_Tree);
  71.   col_stat_info **col_info;
  72.   
  73.   if (op == EQU)
  74.     return min_sel;
  75.   
  76.   if (SP_Arr[prdc_num].SQ_cost || SP_Arr[prdc_num].Depend != TblBits[tbl_num]
  77.       || SP_Arr[prdc_num].SP_Num != 1 || !Is_Comp_Code (op))
  78.     return sel;
  79.   
  80.   for (cur_ptr = right_ptr; cur_ptr; cur_ptr = DOWN_TRN (cur_ptr))
  81.     if (CODE_TRN (cur_ptr) == UMINUS)
  82.       sign = BitNOT (sign);
  83.     else
  84.       if (CODE_TRN (cur_ptr) != NOOP)
  85. break;
  86.   
  87.   if (cur_ptr && CODE_TRN (cur_ptr) == CONST)
  88.     /* SP has type : col_name 'op' constant */
  89.     {
  90.       VADR nd;
  91.       DataUnit cnst;
  92.       
  93.       nd = VMALLOC (1, TRNode);
  94.       prepare_CONST (cur_ptr, nd);
  95.       cnst = *V_PTR (V_PTR (nd, TRNode)->Ptr.off, DataUnit);
  96.       vmfree (nd);
  97.       
  98.       if (sign)
  99. {
  100.   DtPush;
  101.   DtCurEl = cnst;
  102.   err = oper (UMINUS, 1);
  103.   CHECK_SEL_ERR (err);
  104.   cnst = DtCurEl;
  105.   DtPop;
  106. }
  107.       /* there is right value of SP in *const now */
  108.       
  109.       Tab = COR_TBL (COL_TBL (col_node));
  110.       if (CODE_TRN (Tab) == TMPTABLE)
  111.         return sel;
  112.       for (CurClm = TBL_COLS (Tab); CurClm; CurClm = RIGHT_TRN (CurClm))
  113. if (COL_NO (CurClm) == col_num)
  114.   break;
  115.       assert (CurClm);
  116.       
  117.       col_info = (col_stat_info **)(&(COL_STAT (CurClm)));
  118.       if (!(*col_info))
  119. /* making statistic info about column : min & max values */
  120. {
  121.   *col_info = TYP_ALLOC (1, col_stat_info);
  122.   err = get_col_stat ((TBL_TABID (Tab)).untabid, col_num, *col_info);
  123.   CHECK_SEL_ERR (err);
  124.   
  125.   if ((*col_info)->min.dat.nl_fl == NULL_VALUE ||
  126.       (*col_info)->max.dat.nl_fl == NULL_VALUE)
  127.     {
  128.       i4_t spn, flist[2], nf = 0;
  129.               i4_t min_change_fl = FALSE, max_change_fl = FALSE;
  130.       char fl[2];
  131.       DataUnit *du[2];
  132.       col_change_info ch_info;
  133.               
  134.       if ((*col_info)->min.dat.nl_fl == NULL_VALUE)
  135. {
  136.   du[nf] = &((*col_info)->min);
  137.   du[nf]->type = COL_TYPE (CurClm);
  138.   min_change_fl = TRUE;
  139.   flist[nf] = col_num;
  140.   fl[nf++] = FN_MIN;
  141. }
  142.       if ((*col_info)->max.dat.nl_fl == NULL_VALUE)
  143. {
  144.   du[nf] = &((*col_info)->max);
  145.   du[nf]->type = COL_TYPE (CurClm);
  146.   max_change_fl = TRUE;
  147.   flist[nf] = col_num;
  148.   fl[nf++] = FN_MAX;
  149. }
  150.       
  151.       err = func (&TBL_TABID (Tab), &spn, 0, NULL, du, nf, flist, fl);
  152.       CHECK_SEL_ERR (err);
  153.               ch_info.del_min.dat.nl_fl = UNKNOWN_VALUE;
  154.               ch_info.del_max.dat.nl_fl = UNKNOWN_VALUE;
  155.               
  156.               if (min_change_fl)
  157.                 ch_info.ins_min = (*col_info)->min;
  158.               else
  159.                 ch_info.ins_min.dat.nl_fl = UNKNOWN_VALUE;
  160.               
  161.               if (max_change_fl)
  162.                 ch_info.ins_max = (*col_info)->max;
  163.               else
  164.                 ch_info.ins_max.dat.nl_fl = UNKNOWN_VALUE;
  165.               
  166.               put_col_stat ((TBL_TABID (Tab)).untabid, col_num, &ch_info);
  167.     }
  168. }
  169.       
  170.       if ((*col_info)->min.dat.nl_fl == NULL_VALUE ||
  171.   (*col_info)->max.dat.nl_fl == NULL_VALUE)
  172. /* column is empty or consists only of NULL VALUES */
  173. sel = min_sel;
  174.       else
  175. {
  176.   sel = sel_const (op, &cnst, &((*col_info)->min), &((*col_info)->max));
  177.   CHECK_SEL_ERR (sel);
  178.   if (!sel)
  179.     sel = min_sel;
  180. }
  181.     }
  182.   
  183.   return sel;
  184. } /* Mk_Sel */
  185. void
  186. Mk_SP_Info (TXTREF SP_Tree, i4_t prdc_num)
  187. /* Making information about simple predicate               *
  188.  * SP_Tree and placing it to SP_Ind_Arr for correspondent  *
  189.  * table and predicate (its number = prdc_num).            */
  190. {
  191.   TXTREF col_ptr = DOWN_TRN (SP_Tree), col_node, CurInd;
  192.   MASK Depend;
  193.   i4_t tbl_num;
  194.   SP_Ind_Info *res;
  195.   if (CODE_TRN (col_ptr) == NOOP)
  196.     col_ptr = DOWN_TRN (col_ptr);
  197.   assert (col_ptr && CODE_TRN (col_ptr) == COLPTR);
  198.   col_node = OBJ_DESC (col_ptr);
  199.   assert (col_node && CODE_TRN (col_node) == SCOLUMN);
  200.   
  201.   Depend = COR_MASK (COL_TBL (col_node));
  202.   
  203.   /* finding of corresponding table : */
  204.   for (tbl_num = 0; tbl_num < TblNum; tbl_num++)
  205.     if (TblBits[tbl_num] == Depend)
  206.       break;
  207.   assert (tbl_num < TblNum);
  208.   
  209.   res = SP_Ind_Arr[tbl_num] + prdc_num;
  210.     
  211.   res->ColNum = COL_NO (col_node);
  212.   res->category = (CODE_TRN (SP_Tree) == EQU) ? 1 : 2;
  213.   res->Sel = Mk_Sel (tbl_num, res->ColNum, col_node, SP_Tree, prdc_num);
  214.   
  215.   for (CurInd = tbl_ind[tbl_num]; CurInd; CurInd = RIGHT_TRN (CurInd))
  216.     if (COL_NO (OBJ_DESC (DOWN_TRN (CurInd))) == res->ColNum)
  217.       break;
  218.   res->IndExists = (CurInd != TNULL);
  219.   res->tree = SP_Tree;
  220. } /* Mk_SP_Info */
  221. float
  222. EstCostOrder (i4_t *res_row_num)
  223. /* Making estimation of query cost accordingly      *
  224.  * current order of tables in query                 *
  225.  * Functin returns value < 0  if it decides not to  *
  226.  * make all steps of estimation because the cost of *
  227.  * this order >> BestCost (if BestCost > 0)         *
  228.  * In another case it returns estimated cost (>=0)  */
  229. {
  230.   MASK Depend = _AllTblMsk;
  231.   i4_t tbl_num, prdc_num, i, real_num, ColNum;
  232.   float cost_all = 0.0, row_num = 1.0;
  233.   float ind_best_sel, sel;
  234.   SP_Ind_Info *CurIndInfo;
  235.   
  236.   /* estimation of the cost of tables scanning */
  237.   for (tbl_num = 0; tbl_num < TblNum; tbl_num++)
  238.     {
  239.       ind_best_sel = 1.0;
  240.       real_num = CurTblOrder [tbl_num];
  241.       TblAllBits[tbl_num] = Depend = BitOR (Depend, TblBits [real_num]);
  242.       
  243.       /* init of array for information about culumns */
  244.       for (i = 0; i < tab_col_num[real_num]; i++)
  245. col_stat[i].Sel = 1.0;
  246.       
  247.       /* checking information about SPs for current table */
  248.       for (prdc_num = 0; prdc_num < SPNum; prdc_num++)
  249. if (!(SP_Arr[prdc_num].flag) /* this predicate wasn't used yet */ &&
  250.     CAN_BE_USED (SP_Arr[prdc_num].Depend, Depend)
  251.     /* predicate can be used now */)
  252.   {
  253.     SP_Arr[prdc_num].flag++;
  254.     CurIndInfo = (SP_Ind_Arr[real_num]) + prdc_num;
  255.     if (CurIndInfo->Sel)
  256.       /* this predicate is SP for current table */
  257.       {
  258. ColNum = CurIndInfo->ColNum;
  259. if (col_stat[ColNum].Sel > CurIndInfo->Sel)
  260.   {
  261.     col_stat[ColNum].Sel = CurIndInfo->Sel;
  262.     if (CurIndInfo->IndExists /* there is index for the column of this SP */
  263. && col_stat[ColNum].Sel < ind_best_sel)
  264.       ind_best_sel = col_stat[ColNum].Sel;
  265.   }
  266.       }
  267.   }
  268.       
  269.      /* finding of common selectivity of all simple predicates for current table */
  270.       for (i = 0, sel = 1.0; i < tab_col_num[real_num]; i++)
  271. sel *=col_stat[i].Sel;
  272.      
  273.       /* adding of default selectivity for the rest of predicates */
  274.       for (prdc_num = SPNum; prdc_num < DisNum; prdc_num++)
  275. if (!(SP_Arr[prdc_num].flag) /* this predicate wasn't used yet */ &&
  276.     CAN_BE_USED (SP_Arr[prdc_num].Depend, Depend)
  277.     /* predicate can be used now */)
  278.   {
  279.     SP_Arr[prdc_num].flag++;
  280.             sel *= DEFAULT_SEL;
  281.           }
  282.       
  283.       NumRowScans [tbl_num] = NumRows[real_num] * ind_best_sel * row_num;
  284.       /* in NumRowScans [i] - estimated number of row's readings from i-th table */
  285.       cost_all += NumRowScans [tbl_num] + OPEN_SCAN_COST * row_num;
  286.       row_num *= NumRows[real_num] * sel;
  287.       
  288.     } /* for tbl_num: tables handling */
  289.       
  290.   for (prdc_num = 0; prdc_num < DisNum; prdc_num++)
  291.     SP_Arr[prdc_num].flag = 0;
  292.       
  293.   /* adding of the cost of all subqueries */
  294.   for (prdc_num = 0; prdc_num < DisNum; prdc_num++)
  295.     {
  296.       for (tbl_num = 0; tbl_num < TblNum; tbl_num++)
  297.         if (CAN_BE_USED (SP_Arr[prdc_num].SQ_deps, TblAllBits[tbl_num]))
  298.           break;
  299.       assert (tbl_num < TblNum);
  300.       
  301.       /* tbl_num - number of the last (in order) table *
  302.        * that is referenced in the predicate           */
  303.       cost_all += SP_Arr[prdc_num].SQ_cost * NumRowScans [tbl_num];
  304.     }
  305.   
  306.   *res_row_num = (row_num < 1.0) ? 1 :
  307.     ((row_num < FLT_MAX_LNG) ? (i4_t)row_num : MAX_LNG);
  308.   
  309.   return cost_all;
  310. } /* EstCostOrder */
  311. i4_t *
  312. NextOrder (void)
  313. /* making in array CurTblOrder[] next order of tables' numbers *
  314.  * returns NULL if all orders was already generated            *
  315.  *    else - pointer to array with new order              */
  316. {
  317.   i4_t i, j, bound_vl, bound_num;
  318.   
  319.   for (fin_nums[0] = CurTblOrder[TblNum - 1], i = TblNum - 1; i; i--)
  320.     if (CurTblOrder[i - 1] < CurTblOrder[i])
  321.       break;
  322.     else
  323.       fin_nums[TblNum - i] = CurTblOrder[i - 1];
  324.   
  325.   if (!i)
  326.     return NULL; /* all orders was generated */
  327.   
  328.   bound_num = i - 1;
  329.   bound_vl = CurTblOrder[bound_num];
  330.   
  331.   for (j = 0; fin_nums[j] < bound_vl; j++)
  332.     CurTblOrder[i++] = fin_nums[j];
  333.   
  334.   CurTblOrder[bound_num] = fin_nums[j++];
  335.   CurTblOrder[i++] = bound_vl;
  336.     
  337.   for (; i < TblNum; i++, j++)
  338.     CurTblOrder[i] = fin_nums[j];
  339.   
  340.   return CurTblOrder;
  341. } /* NextOrder */
  342. float
  343. opt_query (TXTREF FromNode, i4_t *res_row_num)
  344.      /* returns the cost of query */
  345. {
  346.   TXTREF sp_tree, fir_el, last_el = TNULL, CurInd, Ind, CurIndCol;
  347.   TXTREF ScanNode, Tab, SelectNode, WhereNode = TNULL, WhereTree = TNULL;
  348.   i4_t i, j, k, ColNum, tbl_num, prdc_num;
  349.   i4_t sp_clm_tab_num; /* number of columns for which there are simple *
  350.                        * predicates only for table (not for index)    */
  351.   Simp_Pred_Info TmpEl;
  352.   VADR *Tab_SP, *Ind_SP;
  353.   VADR Tree;
  354.   MASK Depend, tmp_dep, *CurTblBits;
  355.   i4_t real_num, CurTblNum;
  356.   i4_t *BestTblOrder;
  357.   TXTREF *TblPtr, TblPtrCur;
  358.   SP_Ind_Info *CurIndInfo, *Heap = NULL;
  359.   Col_Stat_Info best_ind_info;
  360.   i4_t max_col_num = 0, unused_prdc, Cur_in_Heap;
  361.   MASK AllTblMsk;
  362.   float cost, sel, tmp_build_cost = 0.0;
  363.   TRNode *trnode_dn;
  364.   VADR trnode_dn_rh;
  365.   i4_t categ_1, categ_2;
  366.   i4_t row_num, best_row_num = 0;
  367.   
  368.   SelectNode = RIGHT_TRN (FromNode);
  369.   WhereNode = (SelectNode) ? RIGHT_TRN (SelectNode) : TNULL;
  370.   if (WhereNode)
  371.     {
  372.       if (CODE_TRN (WhereNode) != WHERE)
  373. WhereNode = RIGHT_TRN (WhereNode);
  374.     }
  375.   
  376.   CurTblNum = ARITY_TRN (FromNode);
  377.   assert (CurTblNum > 0);
  378.   CurTblBits   = TYP_ALLOC (CurTblNum, MASK);
  379.   for (tbl_num = 0, TblPtrCur = DOWN_TRN (FromNode);
  380.        tbl_num < CurTblNum; tbl_num++, TblPtrCur = RIGHT_TRN (TblPtrCur))
  381.     CurTblBits[tbl_num] = COR_MASK (TABL_DESC (TblPtrCur));
  382.   
  383.   if (WhereNode)
  384.     {
  385.       Simp_Pred_Info *SP_temp;
  386.       WhereTree = DOWN_TRN (WhereNode);
  387.       DisNum = SP_Extract (WhereTree, CurTblBits, CurTblNum, &SP_temp);
  388.       /* after function SP_Extract tree WhereTree can't be used */
  389.       SP_Arr = SP_temp;
  390.     }
  391.   else
  392.     {
  393.       DisNum = 0;
  394.       SP_Arr = NULL;
  395.     }
  396.   
  397.   SPNum        = 0;
  398.   TblNum       = CurTblNum;
  399.   TblBits      = CurTblBits;
  400.   fin_nums     = TYP_ALLOC (TblNum, i4_t);
  401.   BestTblOrder = TYP_ALLOC (TblNum, i4_t);
  402.   CurTblOrder  = TYP_ALLOC (TblNum, i4_t);
  403.   tab_col_num  = TYP_ALLOC (TblNum, i4_t);
  404.   TblPtr       = TYP_ALLOC (TblNum, TXTREF);
  405.   SP_Ind_Arr   = TYP_ALLOC (TblNum, SP_Ind_Info *);
  406.   NumRows      = TYP_ALLOC (TblNum, i4_t);
  407.   TblAllBits   = TYP_ALLOC (TblNum, MASK);
  408.   tbl_ind      = TYP_ALLOC (TblNum, TXTREF);
  409.   NumRowScans  = TYP_ALLOC (TblNum, float);
  410.   
  411.   /* filling of statistic information about tables */
  412.   for (tbl_num = 0, TblPtrCur = DOWN_TRN (FromNode), AllTblMsk = 0;
  413.        tbl_num < TblNum; tbl_num++, TblPtrCur = RIGHT_TRN (TblPtrCur))
  414.     {
  415.       ScanNode = TABL_DESC (TblPtrCur);
  416.       TblPtr[tbl_num] = TblPtrCur;
  417.       Tab = COR_TBL (ScanNode);
  418.       tab_col_num[tbl_num] = ColNum = TBL_NCOLS (Tab);
  419.       tbl_ind[tbl_num] = (CODE_TRN (Tab) == TABLE) ? IND_INFO (Tab) : TNULL;
  420.       if (max_col_num < ColNum)
  421. max_col_num = ColNum;
  422.       if (CODE_TRN (Tab) == TABLE)
  423. {
  424.           i4_t rc = get_nrows ((TBL_TABID (Tab)).untabid);
  425.           NumRows[tbl_num] = 2; /* for statistic using purpose */
  426.           if (rc > 0)
  427.             NumRows[tbl_num] = rc;
  428.           else if (rc < 0) /* if error was registered */
  429.             {
  430.               yyerror("Required 'nrows' data was not found"); /*!!!!!*/
  431.               errors --;
  432.             }
  433.   }
  434.       else
  435. {
  436.   assert (CODE_TRN (Tab) == TMPTABLE);
  437.   NumRows[tbl_num] = NROWS_EST (Tab);
  438.   tmp_build_cost += BUILD_COST (Tab);
  439. }
  440.       AllTblMsk = BitOR (AllTblMsk, TblBits[tbl_num]);
  441.     }
  442.   _AllTblMsk = BitNOT (AllTblMsk);
  443.   col_stat = (max_col_num) ? TYP_ALLOC (max_col_num, Col_Stat_Info): NULL;
  444.   if (WhereNode)
  445.     {
  446.       assert (DisNum);
  447.       /* all SP are moving to the beginning of SP_Arr */
  448.       for (i = 0, j = DisNum - 1; i < j;)
  449. {
  450.   while (SP_Arr[i].SP_Num && i < j)
  451.     i++;
  452.   while (!(SP_Arr[j].SP_Num) && i < j)
  453.     j--;
  454.   if (i < j)
  455.     /* i-th and j-th elements are changed by places */
  456.     {
  457.       TmpEl = SP_Arr[i];
  458.       SP_Arr[i] = SP_Arr[j];
  459.       SP_Arr[j] = TmpEl;
  460.     }
  461. }
  462.       assert (i == j);
  463.       SPNum = (SP_Arr[i].SP_Num) ? i + 1 : i;
  464.       /* there are (SPNum) Simple Predicates & (DisNum - SPNum) others */
  465.       if (SPNum)
  466. {
  467.   Heap  = TYP_ALLOC (TblNum * SPNum, SP_Ind_Info);
  468.   for (tbl_num = 0, Cur_in_Heap = 0; tbl_num < TblNum;
  469.                tbl_num++, Cur_in_Heap += SPNum)
  470.     {
  471.       SP_Ind_Arr[tbl_num] = Heap + Cur_in_Heap;
  472.             }
  473.   for (prdc_num = 0; prdc_num < SPNum; prdc_num++)
  474.     for (sp_tree = SP_Arr[prdc_num].SP_Trees;
  475.  sp_tree; sp_tree = RIGHT_TRN (sp_tree))
  476.       /* for all interpretations of prdc_num-th disjunct as SP : */
  477.       Mk_SP_Info (sp_tree, prdc_num);
  478. }
  479.     } /* if (WhereNode) */
  480.   /* End of working structures filling */
  481.   /* initial order of tables */
  482.   for (tbl_num = 0; tbl_num < TblNum; tbl_num++)
  483.     BestTblOrder[tbl_num] = CurTblOrder[tbl_num] = tbl_num;
  484.   BestCost = 0.0;
  485.   /* optimization of table order in query */
  486.   PRINT_ ("n");
  487.   do {
  488.     /* EstCostOrder returns value < 0  if this function decided
  489.        not to make all steps of estimation because the cost of
  490.        this order >> BestCost */
  491.     cost = EstCostOrder (&row_num);
  492.     
  493.     PRINT_ ("ntable order: (");
  494.     for (i = 0; i < TblNum; i++)
  495.       { PRINT ("%d ", CurTblOrder[i]); }
  496.     PRINT (") cost = %f", cost);
  497.     
  498.     if (cost > 0 && (cost < BestCost || !BestCost))
  499.       {
  500. for (tbl_num = 0; tbl_num < TblNum; tbl_num++)
  501.   BestTblOrder[tbl_num] = CurTblOrder[tbl_num];
  502. BestCost = cost;
  503. best_row_num = row_num;
  504.       }
  505.   } while (NextOrder ());
  506.   PRINT_ ("n");
  507.   /* NextOrder returns FALSE when all orders was generated, else - TRUE */
  508.   assert (best_row_num);
  509.   
  510.   BestCost += tmp_build_cost;
  511.   if (res_row_num)
  512.     *res_row_num = best_row_num;
  513.   
  514.   /* changing of tables' order in query */
  515.   for (tbl_num = 0, DOWN_TRN (FromNode) = TblPtr[BestTblOrder[0]];
  516.        tbl_num < TblNum - 1; tbl_num++)
  517.     RIGHT_TRN (TblPtr[BestTblOrder[tbl_num]]) =
  518.       TblPtr[BestTblOrder[tbl_num+1]];
  519.   RIGHT_TRN (TblPtr[BestTblOrder[tbl_num]]) = TNULL;
  520.   unused_prdc = DisNum;
  521.   if (USE_INDEXES)
  522.     /* indexes choosing and forming of          *
  523.      * Simple Predicates for tables and indexes */
  524.     for (Depend = _AllTblMsk, tbl_num = 0; tbl_num < TblNum; tbl_num++)
  525.       {
  526.         sp_clm_tab_num = 0;
  527.         real_num = BestTblOrder [tbl_num];
  528.         ScanNode = TABL_DESC (TblPtr [real_num]);
  529.         Tab = COR_TBL (ScanNode); /* ScanNode must be not NULL */
  530.         Depend = BitOR (Depend, TblBits [real_num]);
  531.         /* @ if (CODE_TRN (Tab) != TABLE) continue; : can we use SPs for TMPTABLEs ? @ */
  532.         COR_TAB_SP (ScanNode) = VMALLOC (TBL_NCOLS (Tab), VADR);
  533.       
  534.         /* init of array for information about culumns */
  535.         for (i = 0; i < tab_col_num[real_num]; i++)
  536.           col_stat[i].Sel = 1.0;
  537.         /* checking information about SPs and compiling SPs in Tab_SP */
  538.         for (prdc_num = 0; prdc_num < SPNum; prdc_num++)
  539.           if (!(SP_Arr[prdc_num].flag) /* this SP wasn't used yet */ &&
  540.               CAN_BE_USED (SP_Arr[prdc_num].Depend, Depend)
  541.               /* SP can be used now */                               &&
  542.               (SP_Ind_Arr[real_num][prdc_num]).Sel
  543.               /* this predicate is SP for current table */             )
  544.             {
  545.               SP_Arr[prdc_num].flag++;
  546.               unused_prdc--;
  547.               CurIndInfo = (SP_Ind_Arr[real_num]) + prdc_num;
  548.     
  549.               sp_tree = CurIndInfo->tree;
  550.               Tree = Tr_RecLoad (sp_tree, &tmp_dep, FALSE, NULL);
  551.     
  552.               /* saving dependency of right part of SP */
  553.               assert ((trnode_dn = NextDn (V_PTR (Tree, TRNode))));
  554.               trnode_dn_rh = (trnode_dn->Rh).off;
  555.               if (trnode_dn_rh)
  556.                 SET (tr, trnode_dn_rh, NextRh (trnode_dn)->Depend);
  557.     
  558.               ColNum = CurIndInfo->ColNum;
  559.               if (col_stat[ColNum].Sel > CurIndInfo->Sel)
  560.                 col_stat[ColNum].Sel = CurIndInfo->Sel;
  561.               if (CurIndInfo->category == 1)
  562.                 (col_stat[ColNum].num_categ_1)++;
  563.               else
  564.                 (col_stat[ColNum].num_categ_2)++;
  565.               Tab_SP = V_PTR (COR_TAB_SP (ScanNode), VADR);
  566.               if (Tab_SP[ColNum])
  567.                 (V_PTR (Tree, TRNode)->Rh).off = Tab_SP[ColNum];
  568.               else
  569.                 sp_clm_tab_num++;
  570.               Tab_SP[ColNum] = Tree;
  571.             } /* if */
  572.         /* index for current table choosing */
  573.         if (tbl_ind[real_num]) /* there are indexes for current table */
  574.           {
  575.             Ind = TNULL;
  576.             best_ind_info.Sel = 1.0;
  577.             
  578.             for (CurInd = tbl_ind[real_num]; CurInd; CurInd = RIGHT_TRN (CurInd))
  579.               {
  580.                 sel = 1.0; /* in sel we accumulate selectivity *
  581.                             * for current index (CurInd)       */
  582.                 for (CurIndCol = DOWN_TRN (CurInd);
  583.                      CurIndCol; CurIndCol = RIGHT_TRN (CurIndCol))
  584.                   {
  585.                     ColNum = COL_NO (OBJ_DESC (CurIndCol));
  586.                     if (col_stat[ColNum].Sel < 1.0)
  587.                       {
  588.                         sel *= col_stat[ColNum].Sel;
  589.                         if (!(col_stat[ColNum].num_categ_1))
  590.                           break;
  591.                       }
  592.                     else
  593.                       break;
  594.                   }
  595.                 
  596.                 ColNum = COL_NO (OBJ_DESC (DOWN_TRN (CurInd)));
  597.                 categ_1 = col_stat[ColNum].num_categ_1;
  598.                 categ_2 = col_stat[ColNum].num_categ_2;
  599.                 if ((best_ind_info.Sel > sel) ||
  600.                     ( (best_ind_info.Sel == sel) &&
  601.                       ( (best_ind_info.num_categ_1 < categ_1) ||
  602.                         ((best_ind_info.num_categ_1 == categ_1) &&
  603.                          (best_ind_info.num_categ_2 < categ_2)) ) ))
  604.                   {
  605.                     Ind = CurInd;
  606.                     best_ind_info.Sel = sel;
  607.                     best_ind_info.num_categ_1 = categ_1;
  608.                     best_ind_info.num_categ_2 = categ_2;
  609.                   }
  610.               }
  611.             /* Ind - pointer to found index descriptor */
  612.             if (!Ind && COR_IND_SP (ScanNode))
  613.               {
  614.                 Ind = COR_IND_SP (ScanNode);
  615.                 COR_IND_SP (ScanNode) = TNULL;
  616.               }
  617.             
  618.             if (Ind)
  619.               {
  620.                 if (!COR_TID (ScanNode))
  621.                   COR_TID (ScanNode) = VMALLOC (1, UnId);
  622.                 V_PTR (COR_TID (ScanNode), UnId)->i = IND_INDID (Ind);
  623.                 IND_CLM_CNT (ScanNode) = ARITY_TRN (Ind);
  624.                 COR_IND_SP (ScanNode) = VMALLOC (ARITY_TRN (Ind), VADR);
  625.                 Ind_SP = V_PTR (COR_IND_SP (ScanNode), VADR);
  626.                 
  627.                 for (CurIndCol = DOWN_TRN (Ind), k = 0;
  628.                      CurIndCol; CurIndCol = RIGHT_TRN (CurIndCol), k++)
  629.                   {
  630.                     ColNum = COL_NO (OBJ_DESC (CurIndCol));
  631.                     Tab_SP = V_PTR (COR_TAB_SP (ScanNode), VADR);
  632.                     if (Tab_SP[ColNum])
  633.                       /* there are simple predicates for k-th column of index */
  634.                       {
  635.                         sp_clm_tab_num--;
  636.                         Ind_SP[k] = Tab_SP[ColNum];
  637.                         Tab_SP[ColNum] = VNULL;
  638.                         if (!(col_stat[ColNum].num_categ_1))
  639.                           /* for index's column there isn't SP 'EQU' */
  640.                           break;
  641.                       }
  642.                     else
  643.                       break;
  644.                   }
  645.               } /* if (Ind) */
  646.       
  647.             if (!sp_clm_tab_num && COR_TAB_SP (ScanNode))
  648.               /* all simple predicates was moved for index */
  649.               {
  650.                 vmfree (COR_TAB_SP (ScanNode));
  651.                 COR_TAB_SP (ScanNode) = VNULL;
  652.               }
  653.           } /* if (tbl_ind[real_num]) :            *
  654.              * there are indexes for current table */
  655.       } /* for : tbl_num - tables handling finished */
  656.   if (DisNum)
  657.     if (!unused_prdc) /* WHERE must be deleted */
  658.       {
  659.         free_tree (RIGHT_TRN (SelectNode));
  660.         RIGHT_TRN (SelectNode) = TNULL;
  661.       }
  662.     else
  663.       /* all not used disjuncts must be saved in WHERE */
  664.       {
  665.         for (fir_el = TNULL, prdc_num = 0; prdc_num < DisNum; prdc_num++)
  666.           if (!SP_Arr[prdc_num].flag)
  667.             /* this predicate was not used as simple one */
  668.             if (fir_el)
  669.               last_el = RIGHT_TRN (last_el) = SP_Arr[prdc_num].SP_Trees;
  670.             else
  671.               fir_el = last_el = SP_Arr[prdc_num].SP_Trees;
  672.         
  673.         assert (fir_el && last_el);
  674.         RIGHT_TRN (last_el) = TNULL;
  675.         
  676.         if (unused_prdc > 1)
  677.           {
  678.             WhereNode = DOWN_TRN (WhereNode);
  679.             TASSERT (CODE_TRN (WhereNode) == AND, WhereNode);
  680.           }
  681.         else
  682.           if (CODE_TRN (WhereTree) == AND)
  683.             free_node (WhereTree);
  684.         
  685.         DOWN_TRN (WhereNode) = fir_el;
  686.       }
  687.   
  688.   if (col_stat)
  689.     xfree (col_stat);
  690.   if (SP_Arr)
  691.     xfree (SP_Arr);
  692.   if (Heap)
  693.     xfree (Heap);
  694.   
  695.   xfree (fin_nums);
  696.   xfree (BestTblOrder);
  697.   xfree (CurTblOrder);
  698.   xfree (tab_col_num);
  699.   xfree (TblPtr);
  700.   xfree (SP_Ind_Arr);
  701.   xfree (NumRows);
  702.   xfree (TblBits);
  703.   xfree (TblAllBits);
  704.   xfree (tbl_ind);
  705.   xfree (NumRowScans);
  706.   return BestCost;
  707. }     /* opt_query */