intlib.c
上传用户:dgyhgb
上传日期:2007-01-07
资源大小:676k
文件大小:24k
- /*
- * intlib.c - interpretator library of GNU SQL server
- *
- * This file is a part of GNU SQL Server
- *
- * Copyright (c) 1996, 1997, Free Software Foundation, Inc
- * Developed at the Institute of System Programming
- * This file is written by Konstantin Dyshlevoi.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- * Contacts: gss@ispras.ru
- *
- */
- /* $Id: intlib.c,v 1.247 1997/04/06 17:28:58 kml Exp $ */
- #include "global.h"
- #include "inprtyp.h"
- #include "assert.h"
- #include "sql.h"
- /* In all leafs field Ptr points to element of type DataUnit *
- * where the type of the value is filled by codegen. */
- /* Type of result of subtree must be put into all according nodes *
- * ( if it's the logic value => T_BOOL). *
- * in nodes for subquery :.Rh- reference to programm for *
- * handling this subquery. */
- extern DataUnit *data_st;
- StackUnit *stack = NULL;
- extern i4_t dt_ind, dt_max;
- i4_t st_ind, st_max;
- DataUnit *ins_col_values = NULL;
- i4_t numb_ins_col = 0;
- static DataUnit *del_col_values = NULL;
- static i4_t numb_del_col = 0;
- tab_stat_info *fir_tab_stat = NULL, *cur_tab_stat = NULL;
- #define OLDSTAT(op,func) ((col_info[i]).op##_##func)
- #define NEWVAL(op) (op##_col_values[i])
- #define DO_CHANGE(op)
- {
- DO_CHANGE_(min, LT, op);
- DO_CHANGE_(max, GT, op);
- }
- /* func = 'min' or 'max'; comp = 'LT' or 'GT'; op = 'ins' or 'del' */
- #define DO_CHANGE_(func, comp, op)
- {
- if (use_values)
- {
- if (NEWVAL(op).dat.nl_fl == REGULAR_VALUE &&
- OLDSTAT(op,func).dat.nl_fl != NULL_VALUE)
- {
- if (OLDSTAT(op,func).dat.nl_fl == REGULAR_VALUE)
- MK_BIN_OPER (comp, NEWVAL(op), OLDSTAT(op,func));
- if (OLDSTAT(op,func).dat.nl_fl == UNKNOWN_VALUE || COMP_RESULT)
- OLDSTAT(op,func) = NEWVAL(op);
- }
- }
- else
- OLDSTAT(op,func).dat.nl_fl = NULL_VALUE;
- }
- int
- handle_statistic (i4_t untabid, i4_t tab_col_num,
- i4_t mod_col_num, i4_t *mod_col_list, i4_t use_values)
- /* if use_values == FALSE => there isn't info about old or new values */
- {
- i4_t i, error, col_num;
- col_change_info *col_info;
-
- if (!untabid)
- return 0;
-
- /* pointer to info for current table setting to cur_tab_stat : */
-
- if (!cur_tab_stat || cur_tab_stat->untabid != untabid)
- {
- for (cur_tab_stat = fir_tab_stat; cur_tab_stat;
- cur_tab_stat = cur_tab_stat->next)
- if (cur_tab_stat->untabid == untabid)
- break;
- if (!cur_tab_stat)
- {
- cur_tab_stat = TYP_ALLOC (1, tab_stat_info);
- cur_tab_stat->untabid = untabid;
- cur_tab_stat->ncols = tab_col_num;
- col_info = cur_tab_stat->col_info =
- TYP_ALLOC (tab_col_num, col_change_info);
- for (i = 0; i < tab_col_num; i++)
- {
- col_info[i].ins_min.dat.nl_fl = UNKNOWN_VALUE;
- col_info[i].ins_max.dat.nl_fl = UNKNOWN_VALUE;
- col_info[i].del_min.dat.nl_fl = UNKNOWN_VALUE;
- col_info[i].del_max.dat.nl_fl = UNKNOWN_VALUE;
- }
- cur_tab_stat->next = fir_tab_stat;
- fir_tab_stat = cur_tab_stat;
- }
- }
-
- col_info = cur_tab_stat->col_info;
- if (mod_col_list) /* UPDATE */
- for (i = 0; i < mod_col_num; i++)
- {
- col_num = mod_col_list[i];
-
- DO_CHANGE (ins);
- DO_CHANGE (del);
- }
- else
- {
- if (mod_col_num) /* INSERT */
- {
- (cur_tab_stat->nrows_change)++;
-
- for (i = 0; i < tab_col_num; i++)
- DO_CHANGE (ins);
- }
- else /* DELETE */
- {
- (cur_tab_stat->nrows_change)--;
-
- for (i = 0; i < tab_col_num; i++)
- DO_CHANGE (del);
- }
- }
- return 0;
- } /* handle_statistic */
- static int
- process_statistic (i4_t change_in_db)
- {
- col_change_info *col_info;
- i4_t i, error, nrows;
-
- while(fir_tab_stat)
- {
- cur_tab_stat = fir_tab_stat;
- if (change_in_db)
- {
- if (cur_tab_stat->nrows_change)
- {
- if ((nrows = get_nrows (cur_tab_stat->untabid)) < 0)
- return nrows;
-
- if ((error = put_nrows (cur_tab_stat->untabid,
- nrows + cur_tab_stat->nrows_change)))
- return error;
- }
-
- for (i = 0, col_info = cur_tab_stat->col_info;
- i < cur_tab_stat->ncols; i++, col_info++)
- if ((error = put_col_stat (cur_tab_stat->untabid, i, col_info)))
- return error;
- }
- fir_tab_stat = cur_tab_stat->next;
- xfree (cur_tab_stat->col_info);
- xfree (cur_tab_stat);
- }
- return 0;
- } /* process_statistic */
- int
- change_statistic (void)
- {
- return process_statistic(1);
- }
- int
- drop_statistic (void)
- {
- return process_statistic(0);
- }
- int
- check_and_put (i4_t mod_col_num, i4_t *mod_col_list, TRNode **tree_ptr_arr,
- DataUnit **res_data_arr, S_ConstrHeader *header)
- {
- i4_t i, j, error, read_num, *read_num_arr, reslt, max_clm_num, cur_colnum;
- S_Constraint *constr;
- VADR *V_constr_arr;
- i4_t *arg_num_list, *ref_num_list, tab_col_num;
- char null_fl;
- sql_type_t *read_type_arr;
- static DataUnit **read_adrs = NULL;
- static i4_t read_adrs_lng = 0;
-
- if (!header)
- return 0;
-
- read_num = header->old_vl_cnt;
- tab_col_num = header->tab_col_num;
- CHECK_ARR_SIZE (ins_col_values, numb_ins_col, tab_col_num, DataUnit);
- bzero (ins_col_values, tab_col_num * sizeof (DataUnit));
- if (res_data_arr)
- *res_data_arr = ins_col_values;
-
- /* new values forming : */
-
- for (i = 0; i < mod_col_num; i++)
- {
- if ((error = calculate (tree_ptr_arr[i], NULL, 0, 0, NULL)) < 0)
- return error;
- ins_col_values[(mod_col_list) ? mod_col_list[i] : i] = DtNextEl;
- }
-
- /* old values reading from scan : */
-
- if (read_num)
- {
- read_num_arr = V_PTR (header->old_vl_nums, i4_t);
- read_type_arr = V_PTR (header->old_vl_types, sql_type_t);
- CHECK_ARR_SIZE (read_adrs, read_adrs_lng, read_num, DataUnit *);
- CHECK_ARR_SIZE (del_col_values, numb_del_col, tab_col_num, DataUnit);
- for (i = 0; i < tab_col_num; i++)
- del_col_values[i].type.code = 0;
-
- for (i = 0; i < read_num; i++)
- {
- read_adrs[i] = del_col_values + read_num_arr[i];
- read_adrs[i]->type = read_type_arr[i];
- }
-
- if ((error = read_row (*V_PTR (header->scan, Scanid), read_num,
- read_num_arr, read_adrs)) < 0)
- return error;
-
- /* if there don't exist some new values then they are equal to old ones */
- for (i = 0; i < tab_col_num; i++)
- if (!(ins_col_values[i].type.code) && (del_col_values[i].type.code))
- ins_col_values[i] = del_col_values[i];
- }
-
- /* changing statistic info about table & columns */
- if ((error = handle_statistic (header->untabid, tab_col_num,
- mod_col_num, mod_col_list, TRUE)) < 0)
- return error;
-
- if (!(header->constr_num))
- return 0;
-
- /* constraints checking : */
-
- V_constr_arr = V_PTR (header->constr_arr, VADR);
- for (i = 0; i < header->constr_num; i++)
- {
- constr = V_PTR (V_constr_arr[i], S_Constraint);
- arg_num_list = V_PTR (constr->col_arg_list, i4_t);
- ref_num_list = V_PTR (constr->col_ref_list, i4_t);
- cur_colnum = constr->colnum;
-
- switch (constr->constr_type)
- {
- case FOREIGN :
- /* checking of NULL-values in referencing columns list */
- for (j = 0; j < cur_colnum; j++)
- {
- MK_UN_OPER (ISNULL, ins_col_values[arg_num_list[j]]);
- if (COMP_RESULT)
- /* there is NULL value */
- break;
- }
- if (j < cur_colnum)
- /* not all values of referencing columns are NOT NULL */
- break;
-
- CHECK_ARR_SIZE (read_adrs, read_adrs_lng, cur_colnum, DataUnit *);
- for (j = 0; j < cur_colnum; j++)
- read_adrs[j] = ins_col_values + arg_num_list[j];
-
- if (ind_read (V_PTR (constr->object, Indid), cur_colnum,
- read_adrs, 0, NULL, NULL, NULL, RSC))
- return -REF_VIOL;
- break;
-
- case REFERENCE :
- /* changing of values concerned by constraint checking */
- if (mod_col_list)
- {
- for (j = 0; j < cur_colnum; j++)
- {
- MK_BIN_OPER (EQU, ins_col_values[arg_num_list[j]],
- del_col_values[arg_num_list[j]]);
- if (!COMP_RESULT)
- /* old & new values are not equal */
- break;
- }
- if (j >= cur_colnum)
- /* old & new values of columns from constraint are all equal */
- break;
- }
-
- CHECK_ARR_SIZE (read_adrs, read_adrs_lng, cur_colnum, DataUnit *);
- for (j = 0, max_clm_num = 0; j < cur_colnum; j++)
- {
- if (max_clm_num < ref_num_list[j])
- max_clm_num = ref_num_list[j];
- read_adrs[j] = del_col_values + arg_num_list[j];
- }
-
- if (!tab_read (V_PTR (constr->object, Tabid), cur_colnum,
- max_clm_num, ref_num_list, read_adrs, 0, NULL, NULL))
- return -REF_VIOL;
- break;
-
- case VIEW :
- case CHECK :
- if ((error = calculate (V_PTR (constr->object, TRNode),
- &reslt, 0, 0, &null_fl)) < 0)
- return error;
- if ((null_fl != REGULAR_VALUE) || (reslt == 0))
- return (constr->constr_type == CHECK) ? -CHECK_VIOL : -VIEW_VIOL;
- break;
-
- default : break;
- }
- }
-
- return 0;
- } /* check_and_put */
- int
- chck_err (i4_t cd)
- /* error printing to stderr & roll back of transaction *
- * if it's needed & return in this case TRUE else FALSE *
- * remark : if cd==EOSCAN (end of scan) this is not error */
- {
- if (!cd)
- return 0;
-
- if (cd == -EOSCAN)
- {
- SQLCODE = 100;
- return 0;
- }
-
- if (cd < 0)
- SQLCODE = cd;
- else
- {
- SQLCODE = -SYER;
- rollback (cd);
- }
- return 1;
- } /* "chck_err" */
- void
- off_adr (PSECT_PTR * arr_ptr, i4_t nr)
- /* change virtual addresses in array arr_ptr *
- * of length nr to ordinary addresses */
- {
- PSECT_PTR *pptr;
- i4_t i;
-
- if (nr)
- {
- assert (arr_ptr->off);
- arr_ptr->adr = V_PTR (arr_ptr->off, char);
- pptr = (PSECT_PTR *) (arr_ptr->adr);
- for (i = 0; i < nr; i++, pptr++)
- pptr->adr = V_PTR (pptr->off, char);
- }
- else
- arr_ptr->adr = NULL;
- } /* "off_adr" */
- int
- like (char *x, char *y, char z)
- /* if there isn't ESCAPE in LIKE => z=0 */
- /* values of strings-arguments can't be unknown here */
- {
- char *px = x, *py = y;
- while ((*px && *py) || (*py == '%'))
- {
- if (*py == '%')
- {
- py++;
- do
- if (like (px, py, z))
- return 1;
- while (*px++);
- return 0;
- }
- if (*py != '_')
- {
- if (*py == z) /* if z=0, this condition is false always */
- py++;
- if (*px != *py)
- break;
- }
- px++;
- py++;
- } /* while */
- return !(*px || *py);
- } /* "like" */
- void
- SetHnd (TRNode * cur, MASK Handle)
- /* Bits from Handle are added to all node right from cur */
- {
- TRNode *dop;
- dop = cur;
- while (RhExist (dop))
- {
- dop = NextRh (dop);
- dop->Handle = BitOR (dop->Handle, Handle);
- }
- } /* SetHnd */
- i4_t
- calculate (TRNode * tr, void *res_ptr, i4_t res_size,
- byte res_type, char *null_fl)
- /* tree tr calculation & putting the result into res_ptr *
- * accordingly needed length res_size & type res_type *
- * res_size is used only if res_type == T_STR, *
- * if res_type==0 => result type isn't changed *
- * & it's length for strings isn't more than res_size. *
- * if null_fl != NULL => here will be result description *
- * (REGULAR_VALUE or NULL_VALUE) (if UNKNOWN_VALUE => error)*
- * *
- * Propositions : *
- * 1. In all leafs: Dn.off=NULL *
- * 2. .Ptr is used in all nodes : *
- * in leafs - for data referencing (DataUnit); *
- * in other nodes - for referencing to saved result *
- * of previous calculating of subtree *
- * This function returns value: *
- * 0 - if it's all right, *
- * < 0 - if error, *
- * > 0 - if result is string and this value = lenght of *
- * this string. It is greater than res_size *
- * (so string was shortened). */
- {
- char SIT;
- TRNode *pred, *cur;
- MASK Handle;
- i4_t res = 0;
- cur = tr;
- Handle = 0;
- assert(cur!=NULL);
- SIT = (Leaf(tr)) ? LEAF : OPERN;
- while (1)
- {
- switch (SIT)
- {
- case OPERN: /* cur - pointer to operation node */
- /* Handle value is stored in all operation nodes */
- Handle = BitAND (Handle, cur->Depend);
- Handle = cur->Handle = BitOR (Handle, cur->Handle);
- if (Handle || (cur->Ptr.off == VNULL))
- {
- /* it's needed to recalculating of subtree */
- if (cur->code == CALLPR) /* procedure call */
- {
- PrepSQ *InitDt = V_PTR (cur->Dn.off, PrepSQ);
-
- DtPush;
- DtCurEl = InitDt->ToDtStack;
-
- res = proc_work (V_PTR (InitDt->ProcAdr, char), NULL, Handle);
- if (res < 0)
- return res;
- else
- SQLCODE = 0;
-
- if (NlFlCur == UNKNOWN_VALUE)
- /* in SubQuery for comparison predicate there isn't any row */
- NlFlCur = NULL_VALUE;
-
- if (InitDt->GoUpNeed)
- {
- DtPredEl = DtCurEl;
- DtPop;
- CurPred;
- }
- SIT = DONE;
- break;
- }
-
- StPush;
- StcCur.TP = cur;
- StcCur.flg = 0;
-
- cur = NextDn (cur);
- if (Leaf (cur)) /* not operation */
- SIT = LEAF;
- }
- else
- SIT = LEAF;
- break;
-
- case LEAF:
- if ((res = PutDataNext (cur)))
- return res;
- SIT = DONE;
- break;
-
- case DONE: /* cur is pointer to node, subquery for which *
- * is already calculated. Result is in head of stack */
- cur->Handle = 0;
- if ((cur->Ptr.off != VNULL) && !(Leaf (cur)))
- *TP_ADR (cur, Ptr, DataUnit) = DtCurEl;
- if (cur == tr)
- { /* the work with tree is finished *
- * next two operations are putting the *
- * result into res_ptr, if res_ptr != NULL */
- if (res_ptr)
- res = put_dat (DU_PTR_VL (DtCurEl), LenCur, CodCur, NlFlCur,
- (char *) res_ptr, res_size, res_type, null_fl);
- else
- if (null_fl)
- *null_fl = NlFlCur;
- DtPop;
- return res;
- } /* if */
-
- pred = StcCur.TP;
-
- /* ------------ Optimisation of calculation --------------- */
- if (StcCur.flg == 0) /* The most left element of operation *
- * "pred" is in stack Data now */
- /* the logic expression's calculation may be finished here*/
- {
- if (pred->Arity == 1) /* unary operation */
- {
- res = oper (pred->code, 1);
- if (res < 0)
- return res;
- CurPred;
- break;
- }
-
- if (pred->code == IN) /* IN predicate with values list */
- {
- i4_t NlFl = FALSE;
- TRNode *where = NextRh (cur);
-
- if (!where)
- return -ER_1;
- if (NlFlCur == REGULAR_VALUE)
- /* if value expression in IN is NULL value => *
- * the result of IN is NULL too */
- {
- DtPush;
- do {
- DtCurEl = DtPredEl;
- PutDataNext (where);
- oper (EQU, 2);
- if (!NlFl && (NlFlCur == NULL_VALUE))
- NlFl = TRUE;
- } while (!LngCur && (where = NextRh (where)));
- if (NlFl && !LngCur)
- NlFlCur = NULL_VALUE;
- DtPredEl = DtCurEl;
- DtPop;
- }
- CurPred;
- break;
- }
-
- if (NlFlCur == REGULAR_VALUE)
- if ((pred->code == OR) || (pred->code == AND))
- if (((pred->code == OR) && (LngCur == 1)) ||
- ((pred->code == AND) && (LngCur == 0)))
- {
- SetHnd (cur, Handle);
- CurPred;
- break;
- }
- else
- if (RhExist (cur))
- DtPop
- else {}
- else
- (StcCur.flg)++;
- else /* NlFlCur == NULL_VALUE */
- if (Is_Comp_Code (pred->code) || Is_Arithm_Code (pred->code))
- {
- SetHnd (cur, Handle);
- CurPred;
- break;
- }
- else
- (StcCur.flg)++;
- }
- /* -------------- End of optimisation part ---------------- */
-
- else
- { /* the operand isn't most left => operation "pred" must *
- * be executed here for two arguments from stack Data */
- if (pred->code == LIKE)
- {
- if ((NlFlPred != REGULAR_VALUE) || (NlFlCur != REGULAR_VALUE))
- NlFlPred = NULL_VALUE;
- else
- {
- LngPred = like (StrPred, StrCur, (pred->Arity == 2) ? 0 :
- ADR (NextRh (cur), Ptr)[0]);
- /* if pred->Arity==2 : there isn't ESCAPE */
- CodPred = T_BOOL;
- }
- DtPop;
- CurPred;
- break;
- }
- else
- if (( res = oper (pred->code, 2) ) < 0)
- return res;
- } /* if else */
- if (RhExist (cur))
- {
- cur = NextRh (cur);
- if (Leaf (cur))
- SIT = LEAF;
- else
- SIT = OPERN;
- break;
- }
- else
- CurPred;
- break;
- } /* switch */
- } /* while */
- } /* "calculate" */
- void
- put_as (char ch, char *ch_ptr, i4_t how)
- {
- /* simbol ch is put into ch_ptr either as right half (how=0) *
- * or as left half (how=1)of char. */
- assert (ch);
- *ch_ptr |= (how) ? ch << 4 : ch;
- } /* put_as */
- #define LCodi (SPC[i].LeftCode)
- #define RCodi (SPC[i].RightCode)
- #define NullCodi (SPC[i].NullCode)
- #define Lefti (SPC[i].Left)
- #define Righti (SPC[i].Right)
- #define Typi (SPC[i].Type)
- #define COMP(oprn, elem, to) { MK_BIN_OPER (oprn, *DU, Cond->elem); to = COMP_RESULT; }
- int
- where_in_SP (DataUnit * DU, SP_Cond * Cond)
- /* returns position code for value from DU. This position is *
- * determined by simple predicate stored already in Cond *
- * There is EQU in Cond: | else - accordingly interval : *
- * -----*----- | ---------[-------------]---------- *
- * 0 1 2 | 3 4 5 6 7 */
- /* Values in Cond can't be unknown ( == NULL_VALUE) */
- {
- static char code[4][4] = {
- {5, 5, 6, 7},
- {3, -1, -1, -1},
- {4, -1, -1, -1},
- {5, 5, 6, 7}};
- i4_t error;
- i4_t wh_1, wh_2; /* position's codes for date from DU */
- wh_1 = 0; /* accordingly interval from *Cond */
- wh_2 = 0; /* 0 - there exist not a bound; *
- * *
- * 1 2 3 *
- * _____________*______________ */
-
- if (Cond->LeftCode)
- {
- /* putting to wh_1 : result of "DU > Cond.Left" */
- COMP(GT, Left, wh_1);
-
- if (wh_1)
- wh_1 = 3;
- else
- if (Cond->LeftCode == GT)
- wh_1 = 1;
- else
- {
- /* putting to wh_1 : result of "DU < Cond.Left" */
- COMP(LT, Left, wh_1);
-
- if (!wh_1)
- wh_1 = 2;
- }
- if (Cond->LeftCode == EQU)
- return wh_1 - 1;
- }
- if (((!wh_1) || (wh_1 > 2)) && (Cond->RightCode))
- {
- /* putting to wh_2 : result of "DU < Cond.Right" */
- COMP(LT, Right, wh_2);
- if (!wh_2)
- if (Cond->RightCode == LT)
- wh_2 = 3;
- else
- {
- /* putting to wh_2 : result of "DU > Cond.Right" */
- COMP(GT, Right, wh_2);
- wh_2 += 2;
- }
- }
- return code[wh_1][wh_2];
- } /* where_in_SP */
- #define RET(res) { xfree (SPC); return res; }
- int
- condbuf (char **bufptr, i4_t ClmCnt, VADR * Trees)
- /* returns : *
- * 1. as function : *
- * 0 if conditions are not compatible *
- * -error_code if error *
- * length of buffer if success *
- * 2. in bufptr : buffer address */
- {
- static int act_tab[6][8] =
- { /* 0 1 2 3 4 5 6 7 */
- /* EQU */ {3, 0, 3, 3, 1, 1, 1, 3},
- /* NE */ {0, 0, 0, 0, 0, 0, 0, 0},
- /* LE */ {3, 0, 0, 3, 4, 2, 0, 0},
- /* GE */ {0, 0, 3, 0, 0, 1, 4, 3},
- /* LT */ {3, 3, 0, 3, 3, 2, 2, 0},
- /* GT */ {0, 3, 3, 0, 1, 1, 3, 3}
- };
- static char code[7][7] =
- { /* 0 EQU NE LE GE LT GT */
- /* 0 */ {ANY, EQ, 0, SMLEQ, 0, SML, 0},
- /* EQU */ {EQ, 0, 0, EQ, 0, EQ, 0},
- /* NE */ {NEQ, 0, 0, 0, 0, 0, 0},
- /* LE */ {0, 0, 0, 0, 0, 0, 0},
- /* GE */ {GRTEQ, 0, 0, SESE, 0, SES, 0},
- /* LT */ {0, 0, 0, 0, 0, 0, 0},
- /* GT */ {GRT, 0, 0, SSE, 0, SS, 0}
- };
- #define NulCode (EQU - 1)
-
- TRNode *CurTree;
- SP_Cond *SPC;
- i4_t err, wh, i, j, act, size;
- char *curptr, null_fl, oper_code;
- enum token CurCode;
- DataUnit SaveVal;
- assert (ClmCnt);
- size = 0;
- SPC = GET_MEMC (SP_Cond, ClmCnt);
- for (i = 0; i < ClmCnt; i++)
- {
- CurTree = V_PTR (Trees[i], TRNode);
- if (CurTree)
- Typi = NextDn (CurTree)->Ty;
- for (; CurTree; CurTree = NextRh (CurTree))
- {
- CurCode = CurTree->code;
-
- switch (CurCode)
- {
- case ISNULL :
- if (LCodi || RCodi || NullCodi == NEQUN )
- /* conditions are not compatible */
- RET (0);
- NullCodi = EQUN;
- break;
-
- case ISNOTNULL :
- if (NullCodi == EQUN)
- /* conditions are not compatible */
- RET (0);
- NullCodi = NEQUN;
- break;
-
- default : /* comparison predicate */
- if (NullCodi == EQUN)
- /* conditions are not compatible */
- RET (0);
- if ((err = calculate (NextRh (NextDn (CurTree)),
- NULL, 0, 0, &null_fl)) < 0)
- RET (err);
- if (null_fl == UNKNOWN_VALUE)
- RET (-ER_1);
- if (null_fl == NULL_VALUE)
- RET (0);
- /* if success : data is in DtNextEl */
- if (CurCode == NE)
- act = 1;
- else
- {
- SaveVal = DtNextEl;
- if ((wh = where_in_SP (&SaveVal, SPC + i)) < 0)
- RET ((wh == -1) ? -ER_1 : wh);
- /* wh - relation code for current condition *
- * accordingly already stored simple predicate */
- act = act_tab[CurCode - EQU][wh];
- switch (act)
- {
- case 0: /* nothing to do */
- break;
- case 1: /* changing of left bound of Simple Predicate */
- LCodi = CurCode;
- Lefti = SaveVal;
- break;
- case 2: /* changing of right bound of Simple Predicate */
- RCodi = CurCode;
- Righti = SaveVal;
- break;
- case 3: /* conditions are not compatible */
- RET (0);
- break;
- case 4: /* making of predicate EQU */
- LCodi = EQU;
- RCodi = 0;
- Lefti = SaveVal;
- break;
- }
- } /* else */
- } /* swith */
- } /* for */
- if (LCodi)
- size += BUF_SIZE_VL (Lefti, Typi);
- if (RCodi)
- size += BUF_SIZE_VL (Righti, Typi);
- } /* for */
- j = ClmCnt / 2 + 1;
- size += j;
- *bufptr = GET_MEMC (char, size);
- curptr = *bufptr + j;
- put_as (ENDSC, *bufptr + j - 1, ClmCnt == 2 * j - 1);
- for (i = 0; i < ClmCnt; i++)
- {
- if (LCodi)
- if ((err = DU_to_buf (&Lefti, &curptr, &Typi)) < 0)
- RET (err);
-
- if ((LCodi != EQU) && (LCodi != NE) && RCodi)
- if ((err = DU_to_buf (&Righti, &curptr, &Typi)) < 0)
- RET (err);
-
- assert ((oper_code = code[(LCodi) ? LCodi - NulCode : 0]
- [(RCodi) ? RCodi - NulCode : 0]));
- put_as ((oper_code == ANY && NullCodi) ? NullCodi : oper_code,
- *bufptr + i / 2, i % 2);
- } /* for */
- RET (size);
- } /* condbuf */
- #undef RET
- #undef LCodi
- #undef RCodi
- #undef NullCodi
- #undef Lefti
- #undef Righti
- #undef Typi