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

SQL Server

开发平台:

Unix_Linux

  1. /*
  2.  *  intlib.c  -  interpretator library of GNU SQL server
  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: intlib.c,v 1.247 1997/04/06 17:28:58 kml Exp $ */
  28. #include "global.h"
  29. #include "inprtyp.h"
  30. #include "assert.h"
  31. #include "sql.h"
  32. /* In all leafs field Ptr points to element of type DataUnit      *
  33.  * where the type of the value is filled by codegen.              */
  34. /* Type of result of subtree must be put into all according nodes *
  35.  * ( if it's the logic value =>  T_BOOL).                         *
  36.  * in nodes for subquery :.Rh- reference to programm for          *
  37.  * handling this subquery.                                        */
  38. extern     DataUnit *data_st;
  39. StackUnit *stack = NULL;
  40. extern i4_t dt_ind, dt_max;
  41. i4_t        st_ind, st_max;
  42. DataUnit  *ins_col_values = NULL;
  43. i4_t       numb_ins_col = 0;
  44. static DataUnit *del_col_values = NULL;
  45. static i4_t numb_del_col = 0;
  46. tab_stat_info *fir_tab_stat = NULL, *cur_tab_stat = NULL;
  47. #define OLDSTAT(op,func) ((col_info[i]).op##_##func)
  48. #define NEWVAL(op)  (op##_col_values[i])
  49. #define DO_CHANGE(op)
  50. {
  51.   DO_CHANGE_(min, LT, op);
  52.   DO_CHANGE_(max, GT, op);
  53. }
  54. /* func = 'min' or 'max'; comp = 'LT' or 'GT'; op = 'ins' or 'del' */
  55. #define DO_CHANGE_(func, comp, op)         
  56. {
  57.   if (use_values)
  58.     {
  59.       if (NEWVAL(op).dat.nl_fl == REGULAR_VALUE && 
  60.           OLDSTAT(op,func).dat.nl_fl != NULL_VALUE) 
  61.         {
  62.           if (OLDSTAT(op,func).dat.nl_fl == REGULAR_VALUE) 
  63.             MK_BIN_OPER (comp, NEWVAL(op), OLDSTAT(op,func)); 
  64.           if (OLDSTAT(op,func).dat.nl_fl == UNKNOWN_VALUE || COMP_RESULT) 
  65.             OLDSTAT(op,func) = NEWVAL(op);
  66.         }
  67.     }
  68.   else
  69.     OLDSTAT(op,func).dat.nl_fl = NULL_VALUE;
  70. }
  71. int
  72. handle_statistic (i4_t untabid, i4_t tab_col_num,
  73.   i4_t mod_col_num, i4_t *mod_col_list, i4_t use_values)
  74. /* if use_values == FALSE => there isn't info about old or new values */
  75. {
  76.   i4_t i, error, col_num;
  77.   col_change_info *col_info;
  78.   
  79.   if (!untabid)
  80.     return 0;
  81.   
  82.   /* pointer to info for current table setting to cur_tab_stat : */
  83.   
  84.   if (!cur_tab_stat || cur_tab_stat->untabid != untabid)
  85.     {
  86.       for (cur_tab_stat = fir_tab_stat; cur_tab_stat;
  87. cur_tab_stat = cur_tab_stat->next)
  88. if (cur_tab_stat->untabid == untabid)
  89.   break;
  90.       if (!cur_tab_stat)
  91. {
  92.   cur_tab_stat = TYP_ALLOC (1, tab_stat_info);
  93.   cur_tab_stat->untabid = untabid;
  94.   cur_tab_stat->ncols = tab_col_num;
  95.   col_info = cur_tab_stat->col_info =
  96.             TYP_ALLOC (tab_col_num, col_change_info);
  97.   for (i = 0; i < tab_col_num; i++)
  98.             {
  99.               col_info[i].ins_min.dat.nl_fl = UNKNOWN_VALUE;
  100.               col_info[i].ins_max.dat.nl_fl = UNKNOWN_VALUE;
  101.               col_info[i].del_min.dat.nl_fl = UNKNOWN_VALUE;
  102.               col_info[i].del_max.dat.nl_fl = UNKNOWN_VALUE;
  103.             }
  104.   cur_tab_stat->next = fir_tab_stat;
  105.   fir_tab_stat = cur_tab_stat;
  106. }
  107.     }
  108.   
  109.   col_info = cur_tab_stat->col_info;
  110.   if (mod_col_list) /* UPDATE */
  111.     for (i = 0; i < mod_col_num; i++)
  112.       {
  113. col_num = mod_col_list[i];
  114. DO_CHANGE (ins);
  115.         DO_CHANGE (del);
  116.       }
  117.   else
  118.     {
  119.       if (mod_col_num) /* INSERT */
  120. {
  121.           (cur_tab_stat->nrows_change)++;
  122.   
  123.   for (i = 0; i < tab_col_num; i++)
  124.             DO_CHANGE (ins);
  125. }
  126.       else /* DELETE */
  127. {
  128.           (cur_tab_stat->nrows_change)--;
  129.   
  130.   for (i = 0; i < tab_col_num; i++)
  131.             DO_CHANGE (del);
  132. }
  133.     }
  134.   return 0;
  135. } /* handle_statistic */
  136. static int
  137. process_statistic (i4_t change_in_db)
  138. {
  139.   col_change_info *col_info;
  140.   i4_t i, error, nrows;
  141.   
  142.   while(fir_tab_stat)
  143.     {
  144.       cur_tab_stat = fir_tab_stat;
  145.       if (change_in_db)
  146.         {
  147.           if (cur_tab_stat->nrows_change)
  148.             {
  149.               if ((nrows = get_nrows (cur_tab_stat->untabid)) < 0)
  150.                 return nrows;
  151.               
  152.               if ((error = put_nrows (cur_tab_stat->untabid,
  153.                                       nrows + cur_tab_stat->nrows_change)))
  154.                 return error;
  155.             }
  156.           
  157.           for (i = 0, col_info = cur_tab_stat->col_info;
  158.                i < cur_tab_stat->ncols; i++, col_info++)
  159.             if ((error = put_col_stat (cur_tab_stat->untabid, i, col_info)))
  160.               return error;
  161.         }
  162.       fir_tab_stat = cur_tab_stat->next;
  163.       xfree (cur_tab_stat->col_info);
  164.       xfree (cur_tab_stat);
  165.     }
  166.   return 0;
  167. } /* process_statistic */
  168. int
  169. change_statistic (void)
  170. {
  171.   return process_statistic(1);
  172. }
  173. int
  174. drop_statistic (void)
  175. {
  176.   return process_statistic(0);
  177. }
  178. int
  179. check_and_put (i4_t mod_col_num, i4_t *mod_col_list, TRNode **tree_ptr_arr,
  180.        DataUnit **res_data_arr, S_ConstrHeader *header)
  181. {
  182.   i4_t i, j, error, read_num, *read_num_arr, reslt, max_clm_num, cur_colnum;
  183.   S_Constraint *constr;
  184.   VADR *V_constr_arr;
  185.   i4_t  *arg_num_list, *ref_num_list, tab_col_num;
  186.   char  null_fl;
  187.   sql_type_t *read_type_arr;
  188.   static DataUnit **read_adrs     = NULL;
  189.   static i4_t        read_adrs_lng = 0;
  190.   
  191.   if (!header)
  192.     return 0;
  193.   
  194.   read_num = header->old_vl_cnt;
  195.   tab_col_num = header->tab_col_num;
  196.   CHECK_ARR_SIZE (ins_col_values, numb_ins_col, tab_col_num, DataUnit);
  197.   bzero (ins_col_values, tab_col_num * sizeof (DataUnit));
  198.   if (res_data_arr)
  199.     *res_data_arr = ins_col_values;
  200.   
  201.   /* new values forming : */
  202.   
  203.   for (i = 0; i < mod_col_num; i++)
  204.     {
  205.       if ((error = calculate (tree_ptr_arr[i], NULL, 0, 0, NULL)) < 0)
  206. return error;
  207.       ins_col_values[(mod_col_list) ? mod_col_list[i] : i] = DtNextEl;
  208.     }
  209.   
  210.   /* old values reading from scan : */
  211.   
  212.   if (read_num)
  213.     {
  214.       read_num_arr = V_PTR (header->old_vl_nums, i4_t);
  215.       read_type_arr = V_PTR (header->old_vl_types, sql_type_t);
  216.       CHECK_ARR_SIZE (read_adrs, read_adrs_lng, read_num, DataUnit *);
  217.       CHECK_ARR_SIZE (del_col_values, numb_del_col, tab_col_num, DataUnit);
  218.       for (i = 0; i < tab_col_num; i++)
  219. del_col_values[i].type.code = 0;
  220.       
  221.       for (i = 0; i < read_num; i++)
  222. {
  223.   read_adrs[i] = del_col_values + read_num_arr[i];
  224.   read_adrs[i]->type = read_type_arr[i];
  225. }
  226.   
  227.       if ((error = read_row (*V_PTR (header->scan, Scanid), read_num,
  228.      read_num_arr, read_adrs)) < 0)
  229. return error;
  230.       /* if there don't exist some new values then they are equal to old ones */
  231.       for (i = 0; i < tab_col_num; i++)
  232. if (!(ins_col_values[i].type.code) && (del_col_values[i].type.code))
  233.   ins_col_values[i] = del_col_values[i];
  234.     }
  235.   
  236.   /* changing statistic info about table & columns */
  237.   if ((error = handle_statistic (header->untabid, tab_col_num,
  238.  mod_col_num, mod_col_list, TRUE)) < 0)
  239.     return error;
  240.   
  241.   if (!(header->constr_num))
  242.     return 0;
  243.   
  244.   /* constraints checking : */
  245.   
  246.   V_constr_arr = V_PTR (header->constr_arr, VADR);
  247.   for (i = 0; i < header->constr_num; i++)
  248.     {
  249.       constr = V_PTR (V_constr_arr[i], S_Constraint);
  250.       arg_num_list = V_PTR (constr->col_arg_list, i4_t);
  251.       ref_num_list = V_PTR (constr->col_ref_list, i4_t);
  252.       cur_colnum = constr->colnum;
  253.       
  254.       switch (constr->constr_type)
  255. {
  256. case FOREIGN :
  257.   /* checking of NULL-values in referencing columns list */
  258.   for (j = 0; j < cur_colnum; j++)
  259.     {
  260.       MK_UN_OPER (ISNULL, ins_col_values[arg_num_list[j]]);
  261.       if (COMP_RESULT)
  262. /* there is NULL value */
  263. break;
  264.     }
  265.   if (j < cur_colnum)
  266.     /* not all values of referencing columns are NOT NULL */
  267.     break;
  268.   
  269.   CHECK_ARR_SIZE (read_adrs, read_adrs_lng, cur_colnum, DataUnit *);
  270.   for (j = 0; j < cur_colnum; j++)
  271.     read_adrs[j] = ins_col_values + arg_num_list[j];
  272.       
  273.   if (ind_read (V_PTR (constr->object, Indid), cur_colnum,
  274. read_adrs, 0, NULL, NULL, NULL, RSC))
  275.     return -REF_VIOL;
  276.   break;
  277.   
  278. case REFERENCE :
  279.   /* changing of values concerned by constraint checking */
  280.   if (mod_col_list)
  281.     {
  282.       for (j = 0; j < cur_colnum; j++)
  283. {
  284.   MK_BIN_OPER (EQU, ins_col_values[arg_num_list[j]],
  285.        del_col_values[arg_num_list[j]]);
  286.   if (!COMP_RESULT)
  287.     /* old & new values are not equal */
  288.     break;
  289. }
  290.       if (j >= cur_colnum)
  291. /* old & new values of columns from constraint are all equal */
  292. break;
  293.     }
  294.   
  295.   CHECK_ARR_SIZE (read_adrs, read_adrs_lng, cur_colnum, DataUnit *);
  296.   for (j = 0, max_clm_num = 0; j < cur_colnum; j++)
  297.     {
  298.       if (max_clm_num < ref_num_list[j])
  299. max_clm_num = ref_num_list[j];
  300.       read_adrs[j] = del_col_values + arg_num_list[j];
  301.     }
  302.       
  303.   if (!tab_read (V_PTR (constr->object, Tabid), cur_colnum,
  304.  max_clm_num, ref_num_list, read_adrs, 0, NULL, NULL))
  305.     return -REF_VIOL;
  306.   break;
  307. case VIEW :
  308. case CHECK :
  309.           if ((error = calculate (V_PTR (constr->object, TRNode),
  310.   &reslt, 0, 0, &null_fl)) < 0)
  311.             return error;
  312.           if ((null_fl != REGULAR_VALUE) || (reslt == 0))
  313.             return (constr->constr_type == CHECK) ? -CHECK_VIOL : -VIEW_VIOL;
  314.   break;
  315.   
  316. default : break;
  317. }
  318.     }
  319.   
  320.   return 0;
  321. } /* check_and_put */
  322. int
  323. chck_err (i4_t cd)
  324. /* error printing to stderr & roll back of transaction    *
  325.  * if it's needed & return in this case TRUE else FALSE   *
  326.  * remark : if cd==EOSCAN (end of scan) this is not error */
  327. {
  328.   if (!cd)
  329.     return 0;
  330.   
  331.   if (cd == -EOSCAN)
  332.     {
  333.       SQLCODE = 100;
  334.       return 0;
  335.     }
  336.   
  337.   if (cd < 0)
  338.     SQLCODE = cd;
  339.   else
  340.     {
  341.       SQLCODE = -SYER;
  342.       rollback (cd);
  343.     }
  344.   return 1;
  345. } /* "chck_err" */
  346. void 
  347. off_adr (PSECT_PTR * arr_ptr, i4_t nr)
  348. /* change virtual addresses in array arr_ptr *
  349.  * of length nr to ordinary addresses        */
  350. {
  351.   PSECT_PTR *pptr;
  352.   i4_t i;
  353.   
  354.   if (nr)
  355.     {
  356.       assert (arr_ptr->off);
  357.       arr_ptr->adr = V_PTR (arr_ptr->off, char);
  358.       pptr = (PSECT_PTR *) (arr_ptr->adr);
  359.       for (i = 0; i < nr; i++, pptr++)
  360. pptr->adr = V_PTR (pptr->off, char);
  361.     }
  362.   else
  363.     arr_ptr->adr = NULL;
  364. } /* "off_adr" */
  365. int
  366. like (char *x, char *y, char z)
  367. /* if there isn't ESCAPE in LIKE => z=0              */
  368. /* values of strings-arguments can't be unknown here */
  369. {
  370.   char *px = x, *py = y;
  371.   while ((*px && *py) || (*py == '%'))
  372.     {
  373.       if (*py == '%')
  374. {
  375.   py++;
  376.   do
  377.     if (like (px, py, z))
  378.       return 1;
  379.   while (*px++);
  380.   return 0;
  381. }
  382.       if (*py != '_')
  383. {
  384.   if (*py == z)  /* if z=0, this condition is false always */
  385.     py++;
  386.   if (*px != *py)
  387.     break;
  388. }
  389.       px++;
  390.       py++;
  391.     } /* while */
  392.   return !(*px || *py);
  393. } /* "like" */
  394. void
  395. SetHnd (TRNode * cur, MASK Handle)
  396.      /* Bits from Handle are added to all node right from cur */
  397. {
  398.   TRNode *dop;
  399.   dop = cur;
  400.   while (RhExist (dop))
  401.     {
  402.       dop = NextRh (dop);
  403.       dop->Handle = BitOR (dop->Handle, Handle);
  404.     }
  405. } /* SetHnd */
  406. i4_t 
  407. calculate (TRNode * tr, void *res_ptr, i4_t res_size,
  408.    byte res_type, char *null_fl)
  409. /* tree tr calculation & putting the result into res_ptr    *
  410.  * accordingly needed length res_size & type res_type       *
  411.  * res_size is used only if res_type == T_STR,              *
  412.  * if res_type==0 => result type isn't changed              *
  413.  * & it's length for strings isn't more than res_size.      *
  414.  * if null_fl != NULL => here will be result description    *
  415.  * (REGULAR_VALUE or NULL_VALUE) (if UNKNOWN_VALUE => error)*
  416.  *                                                          *
  417.  * Propositions :                                           *
  418.  * 1. In all leafs: Dn.off=NULL                             *
  419.  * 2. .Ptr is used in all nodes :                           *
  420.  *      in leafs - for data referencing (DataUnit);         *
  421.  *      in other nodes - for referencing to saved result    *
  422.  *                       of previous calculating of subtree *
  423.  * This function returns value:                             *
  424.  * 0 - if it's all right,                                   *
  425.  * < 0 - if error,                                          *
  426.  * > 0 - if result is string and this value = lenght of     *
  427.  *       this string. It is greater than res_size           *
  428.  *       (so string was shortened).                         */
  429. {
  430.   char SIT;
  431.   TRNode *pred, *cur;
  432.   MASK Handle;
  433.   i4_t res = 0;
  434.   cur = tr;
  435.   Handle = 0;
  436.   assert(cur!=NULL);
  437.   SIT = (Leaf(tr)) ? LEAF : OPERN;
  438.   while (1)
  439.     {
  440.       switch (SIT)
  441. {
  442. case OPERN: /* cur - pointer to operation node     */
  443.   /* Handle value is stored in all operation nodes */
  444.   Handle = BitAND (Handle, cur->Depend);
  445.   Handle = cur->Handle = BitOR (Handle, cur->Handle);
  446.   if (Handle || (cur->Ptr.off == VNULL))
  447.     {
  448.       /* it's needed to recalculating of subtree */
  449.       if (cur->code == CALLPR) /* procedure call */
  450. {
  451.   PrepSQ *InitDt = V_PTR (cur->Dn.off, PrepSQ);
  452.       
  453.   DtPush;
  454.   DtCurEl = InitDt->ToDtStack;
  455.       
  456.   res = proc_work (V_PTR (InitDt->ProcAdr, char), NULL, Handle);
  457.   if (res < 0)
  458.     return res;
  459.   else
  460.     SQLCODE = 0;
  461.   
  462.   if (NlFlCur == UNKNOWN_VALUE)
  463.     /* in SubQuery for comparison predicate there isn't any row */
  464.     NlFlCur = NULL_VALUE;
  465.       
  466.   if (InitDt->GoUpNeed)
  467.     {
  468.       DtPredEl = DtCurEl;
  469.       DtPop;
  470.       CurPred;
  471.     }
  472.   SIT = DONE;
  473.   break;
  474. }
  475.       
  476.       StPush;
  477.       StcCur.TP = cur;
  478.       StcCur.flg = 0;
  479.       
  480.       cur = NextDn (cur);
  481.       if (Leaf (cur)) /* not operation  */
  482. SIT = LEAF;
  483.     }
  484.   else
  485.     SIT = LEAF;
  486.   break;
  487.   
  488. case LEAF:
  489.   if ((res = PutDataNext (cur)))
  490.     return res;
  491.   SIT = DONE;
  492.   break;
  493.   
  494. case DONE:  /* cur is pointer to node, subquery for which        *
  495.      * is already calculated. Result is in head of stack */
  496.   cur->Handle = 0;
  497.   if ((cur->Ptr.off != VNULL) && !(Leaf (cur)))
  498.     *TP_ADR (cur, Ptr, DataUnit) = DtCurEl;
  499.   if (cur == tr)
  500.     { /* the work with tree is finished          *
  501.                          * next two operations are putting the     *
  502.  * result into res_ptr, if res_ptr != NULL */
  503.       if (res_ptr)
  504. res = put_dat (DU_PTR_VL (DtCurEl), LenCur, CodCur, NlFlCur,
  505.        (char *) res_ptr, res_size, res_type, null_fl);
  506.       else
  507. if (null_fl)
  508.   *null_fl = NlFlCur;
  509.       DtPop;
  510.       return res;
  511.     } /* if  */
  512.   
  513.   pred = StcCur.TP;
  514.   
  515.   /* ------------ Optimisation of calculation --------------- */
  516.   if (StcCur.flg == 0) /* The most left element of operation *
  517.  * "pred" is in stack Data now        */
  518.     /* the logic expression's calculation may be finished here*/
  519.     {
  520.       if (pred->Arity == 1) /* unary operation */
  521. {
  522.   res = oper (pred->code, 1);
  523.   if (res < 0)
  524.     return res;
  525.   CurPred;
  526.   break;
  527. }
  528.       
  529.       if (pred->code == IN) /* IN predicate with values list */
  530. {
  531.   i4_t NlFl = FALSE;
  532.   TRNode *where = NextRh (cur);
  533.   
  534.   if (!where)
  535.     return -ER_1;
  536.   if (NlFlCur == REGULAR_VALUE)
  537.     /* if value expression in IN is NULL value => *
  538.      * the result of IN is NULL too               */
  539.     {
  540.       DtPush;
  541.       do {
  542. DtCurEl = DtPredEl;
  543. PutDataNext (where);
  544. oper (EQU, 2);
  545. if (!NlFl && (NlFlCur == NULL_VALUE))
  546.   NlFl = TRUE;
  547.       } while (!LngCur && (where = NextRh (where)));
  548.       if (NlFl && !LngCur)
  549. NlFlCur = NULL_VALUE;
  550.       DtPredEl = DtCurEl;
  551.       DtPop;
  552.     }
  553.   CurPred;
  554.   break;
  555. }
  556.       
  557.       if (NlFlCur == REGULAR_VALUE)
  558. if ((pred->code == OR) || (pred->code == AND))
  559.   if (((pred->code == OR) && (LngCur == 1)) ||
  560.       ((pred->code == AND) && (LngCur == 0)))
  561.     {
  562.       SetHnd (cur, Handle);
  563.       CurPred;
  564.       break;
  565.     }
  566.   else 
  567.     if (RhExist (cur))
  568.       DtPop
  569.     else {}
  570. else
  571.   (StcCur.flg)++;
  572.       else /* NlFlCur == NULL_VALUE */
  573. if (Is_Comp_Code (pred->code) || Is_Arithm_Code (pred->code))
  574.   {
  575.     SetHnd (cur, Handle);
  576.     CurPred;
  577.     break;
  578.   }
  579. else
  580.   (StcCur.flg)++;
  581.     }
  582.   /* -------------- End of optimisation part ---------------- */
  583.   
  584.   else
  585.     { /* the operand isn't most left => operation "pred" must *
  586.  * be executed here  for two arguments from stack Data  */
  587.       if (pred->code == LIKE)
  588. {
  589.   if ((NlFlPred != REGULAR_VALUE) || (NlFlCur != REGULAR_VALUE))
  590.     NlFlPred = NULL_VALUE;
  591.   else
  592.     {
  593.       LngPred = like (StrPred, StrCur, (pred->Arity == 2) ? 0 :
  594.       ADR (NextRh (cur), Ptr)[0]);
  595.       /* if pred->Arity==2 : there isn't ESCAPE */
  596.       CodPred = T_BOOL;
  597.     }
  598.   DtPop;
  599.   CurPred;
  600.   break;
  601. }
  602.       else
  603. if (( res = oper (pred->code, 2) ) < 0)
  604.   return res;
  605.     } /* if else */
  606.   if (RhExist (cur))
  607.     {
  608.       cur = NextRh (cur);
  609.       if (Leaf (cur))
  610. SIT = LEAF;
  611.       else
  612. SIT = OPERN;
  613.       break;
  614.     }
  615.   else
  616.     CurPred;
  617.   break;
  618. } /* switch  */
  619.     } /* while     */
  620. } /* "calculate" */
  621. void 
  622. put_as (char ch, char *ch_ptr, i4_t how)
  623. {
  624. /* simbol ch is put into ch_ptr either as right half (how=0) *
  625.  * or as left half (how=1)of char.                           */
  626.   assert (ch);
  627.   *ch_ptr |= (how) ? ch << 4 : ch;
  628. } /* put_as */
  629. #define LCodi    (SPC[i].LeftCode)
  630. #define RCodi    (SPC[i].RightCode)
  631. #define NullCodi (SPC[i].NullCode)
  632. #define Lefti    (SPC[i].Left)
  633. #define Righti   (SPC[i].Right)
  634. #define Typi     (SPC[i].Type)
  635. #define COMP(oprn, elem, to) { MK_BIN_OPER (oprn, *DU, Cond->elem); to = COMP_RESULT; }
  636. int
  637. where_in_SP (DataUnit * DU, SP_Cond * Cond)
  638. /* returns position code for value from DU. This position is     *
  639.  * determined by simple predicate stored already in Cond         *
  640.  * There is EQU in Cond:  |   else - accordingly interval :      *
  641.  *   -----*-----          |  ---------[-------------]----------  *
  642.  *     0  1  2            |     3     4      5      6     7      */
  643. /* Values in Cond can't be unknown ( == NULL_VALUE)              */ 
  644. {
  645.   static char code[4][4] = {
  646.     {5, 5, 6, 7},
  647.     {3, -1, -1, -1},
  648.     {4, -1, -1, -1},
  649.     {5, 5, 6, 7}};
  650.   i4_t error;
  651.   i4_t wh_1, wh_2;         /* position's codes for date from DU */
  652.   wh_1 = 0;              /* accordingly interval from *Cond   */
  653.   wh_2 = 0;                     /* 0 - there exist not a bound;      *
  654.                                  *                                   *
  655.                                  *     1        2       3            *
  656.                                  * _____________*______________      */
  657.   
  658.   if (Cond->LeftCode)
  659.     {
  660.       /* putting to wh_1 : result of "DU > Cond.Left" */
  661.       COMP(GT, Left, wh_1);
  662.       
  663.       if (wh_1)
  664. wh_1 = 3;
  665.       else 
  666. if (Cond->LeftCode == GT)
  667.   wh_1 = 1;
  668. else
  669.   {
  670.     /* putting to wh_1 : result of "DU < Cond.Left" */
  671.     COMP(LT, Left, wh_1);
  672.       
  673.     if (!wh_1)
  674.       wh_1 = 2;
  675.   }
  676.       if (Cond->LeftCode == EQU)
  677. return wh_1 - 1;
  678.     }
  679.   if (((!wh_1) || (wh_1 > 2)) && (Cond->RightCode))
  680.     {
  681.       /* putting to wh_2 : result of "DU < Cond.Right" */
  682.       COMP(LT, Right, wh_2);
  683.       if (!wh_2)
  684. if (Cond->RightCode == LT)
  685.   wh_2 = 3;
  686. else
  687.   {
  688.     /* putting to wh_2 : result of "DU > Cond.Right" */
  689.     COMP(GT, Right, wh_2);
  690.     wh_2 += 2;
  691.   }
  692.     }
  693.   return code[wh_1][wh_2];
  694. } /* where_in_SP */
  695. #define RET(res) { xfree (SPC); return res; }
  696. int
  697. condbuf (char **bufptr, i4_t ClmCnt, VADR * Trees)
  698. /* returns :                                *
  699.  * 1. as function :                         *
  700.  *    0  if conditions are not compatible   *
  701.  *    -error_code if error                  *
  702.  *    length of buffer if success           *
  703.  * 2. in bufptr : buffer address            */
  704. {
  705.   static int act_tab[6][8] =
  706.   { /* 0  1  2  3  4  5  6  7 */
  707.                         /* EQU */ {3, 0, 3, 3, 1, 1, 1, 3},
  708.                         /* NE  */ {0, 0, 0, 0, 0, 0, 0, 0},
  709.                         /* LE  */ {3, 0, 0, 3, 4, 2, 0, 0},
  710.                         /* GE  */ {0, 0, 3, 0, 0, 1, 4, 3},
  711.                         /* LT  */ {3, 3, 0, 3, 3, 2, 2, 0},
  712.                         /* GT  */ {0, 3, 3, 0, 1, 1, 3, 3}
  713.   };
  714.   static char code[7][7] =
  715.   { /* 0     EQU  NE  LE   GE  LT   GT */
  716.                        /*  0  */ {ANY,   EQ,  0, SMLEQ, 0, SML, 0},
  717.                        /* EQU */ {EQ,    0,   0, EQ,    0, EQ,  0},
  718.                        /* NE  */ {NEQ,   0,   0, 0,     0, 0,   0},
  719.                        /* LE  */ {0,     0,   0, 0,     0, 0,   0},
  720.                        /* GE  */ {GRTEQ, 0,   0, SESE,  0, SES, 0},
  721.                        /* LT  */ {0,     0,   0, 0,     0, 0,   0},
  722.                        /* GT  */ {GRT,   0,   0, SSE,   0, SS,  0}
  723.   };
  724. #define NulCode  (EQU - 1)
  725.   
  726.   TRNode *CurTree;
  727.   SP_Cond *SPC; 
  728.   i4_t err, wh, i, j, act, size;
  729.   char *curptr, null_fl, oper_code;
  730.   enum token CurCode;
  731.   DataUnit SaveVal;
  732.   assert (ClmCnt);
  733.   size = 0;
  734.   SPC = GET_MEMC (SP_Cond, ClmCnt);
  735.   for (i = 0; i < ClmCnt; i++)
  736.     {
  737.       CurTree = V_PTR (Trees[i], TRNode);
  738.       if (CurTree)
  739. Typi = NextDn (CurTree)->Ty;
  740.       for (; CurTree; CurTree = NextRh (CurTree))
  741. {
  742.   CurCode = CurTree->code;
  743.   
  744.   switch (CurCode)
  745.     {
  746.     case ISNULL :
  747.       if (LCodi || RCodi || NullCodi == NEQUN )
  748. /* conditions are not compatible */
  749. RET (0);
  750.       NullCodi = EQUN;
  751.       break;
  752.       
  753.     case ISNOTNULL :
  754.       if (NullCodi == EQUN)
  755. /* conditions are not compatible */
  756. RET (0);
  757.       NullCodi = NEQUN;
  758.       break;
  759.       
  760.     default : /* comparison predicate */
  761.       if (NullCodi == EQUN)
  762. /* conditions are not compatible */
  763. RET (0);
  764.       if ((err = calculate (NextRh (NextDn (CurTree)),
  765.                                     NULL, 0, 0, &null_fl)) < 0)
  766.                 RET (err);
  767.       if (null_fl == UNKNOWN_VALUE)
  768. RET (-ER_1);
  769.       if (null_fl == NULL_VALUE)
  770. RET (0);
  771.       /* if success : data is in DtNextEl */
  772.       if (CurCode == NE)
  773. act = 1;
  774.       else
  775. {
  776.   SaveVal = DtNextEl;
  777.   if ((wh = where_in_SP (&SaveVal, SPC + i)) < 0)
  778.     RET ((wh == -1) ? -ER_1 : wh);
  779.   /* wh - relation code for current condition    *
  780.    * accordingly already stored simple predicate */
  781.   act = act_tab[CurCode - EQU][wh];
  782.   switch (act)
  783.     {
  784.     case 0: /* nothing to do */
  785.       break;
  786.     case 1: /* changing of left bound of Simple Predicate */
  787.       LCodi = CurCode;
  788.       Lefti = SaveVal;
  789.       break;
  790.     case 2: /* changing of right bound of Simple Predicate */
  791.       RCodi = CurCode;
  792.       Righti = SaveVal;
  793.       break;
  794.     case 3: /* conditions are not compatible */
  795.       RET (0);
  796.       break;
  797.     case 4: /* making of predicate EQU */
  798.       LCodi = EQU;
  799.       RCodi = 0;
  800.       Lefti = SaveVal;
  801.       break;
  802.     }
  803. } /* else */
  804.     } /* swith */
  805. } /* for */
  806.       if (LCodi)
  807. size += BUF_SIZE_VL (Lefti, Typi);
  808.       if (RCodi)
  809. size += BUF_SIZE_VL (Righti, Typi);
  810.     } /* for */
  811.   j = ClmCnt / 2 + 1;
  812.   size += j;
  813.   *bufptr = GET_MEMC (char, size);
  814.   curptr = *bufptr + j;
  815.   put_as (ENDSC, *bufptr + j - 1, ClmCnt == 2 * j - 1);
  816.   for (i = 0; i < ClmCnt; i++)
  817.     {
  818.       if (LCodi)
  819. if ((err = DU_to_buf (&Lefti, &curptr, &Typi)) < 0)
  820.   RET (err);
  821.       
  822.       if ((LCodi != EQU) && (LCodi != NE) && RCodi)
  823. if ((err = DU_to_buf (&Righti, &curptr, &Typi)) < 0)
  824.   RET (err);
  825.       
  826.       assert ((oper_code = code[(LCodi) ? LCodi - NulCode : 0]
  827.                        [(RCodi) ? RCodi - NulCode : 0]));
  828.       put_as ((oper_code == ANY && NullCodi) ? NullCodi : oper_code,
  829.       *bufptr + i / 2, i % 2);
  830.     } /* for */
  831.   RET (size);
  832. } /* condbuf */
  833. #undef RET
  834. #undef LCodi
  835. #undef RCodi
  836. #undef NullCodi
  837. #undef Lefti
  838. #undef Righti
  839. #undef Typi