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

SQL Server

开发平台:

Unix_Linux

  1. /*
  2.  *  catfun.c  -  DB catalogs request library
  3.  *               GNU SQL server
  4.  *
  5.  *  This file is a part of GNU SQL Server
  6.  *
  7.  *  Copyright (c) 1996, 1997, Free Software Foundation, Inc
  8.  *  Developed at the Institute of System Programming
  9.  *  This file is written by Konstantin Dyshlevoi.
  10.  *
  11.  *  This program is free software; you can redistribute it and/or modify
  12.  *  it under the terms of the GNU General Public License as published by
  13.  *  the Free Software Foundation; either version 2 of the License, or
  14.  *  (at your option) any later version.
  15.  *
  16.  *  This program is distributed in the hope that it will be useful,
  17.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  18.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  19.  *  GNU General Public License for more details.
  20.  *
  21.  *  You should have received a copy of the GNU General Public License
  22.  *  along with this program; if not, write to the Free Software
  23.  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  24.  *
  25.  *  Contacts: gss@ispras.ru
  26.  *
  27.  */
  28. /* $Id: catfun.c,v 1.245 1997/03/31 03:46:38 kml Exp $ */
  29. #include "global.h"
  30. #include "type_lib.h"
  31. #include "inprtyp.h"
  32. #include "sql.h"
  33. #include "const.h"
  34. #include "engine/fieldtp.h"
  35. #include "engine/expop.h"
  36. #include "engine/pupsi.h"
  37. #include "index.h"
  38. #include "exti.h"
  39. #include "tree_gen.h"
  40. #include <assert.h>
  41. extern i4_t transaction;
  42. extern     DataUnit *data_st;
  43. extern i4_t dt_ind, dt_max;
  44. #define DU_ARR_LEN MAX_COLNO /* max of ..._COLNO */
  45. #define MAX_STAT_LEN 10      /* maximum string length for statistic */
  46. static DataUnit *du;
  47. static DataUnit *arg_du[DU_ARR_LEN];
  48. static DataUnit *res_du[DU_ARR_LEN];
  49. static i4_t num_rows[DU_ARR_LEN], ind_clm_nums[DU_ARR_LEN], tab_clm_nums[DU_ARR_LEN];
  50. /********************************************************************/
  51. #define CHECK_LEN(owner)  {if (strlen (owner) > MAX_USER_NAME_LNG) 
  52.                              owner[MAX_USER_NAME_LNG] = 0;}
  53. #define ARGDAT(num) (&((arg_du[num])->dat))
  54. #define RESDAT(num) (&((res_du[num])->dat))
  55. #define RESCOD(num) ((res_du[num])->type.code)
  56. #define IND_CLM_STR(num, adr)                          
  57. { (arg_du[num])->type.code = T_STR;                    
  58.   (arg_du[num])->type.len = strlen (adr);              
  59.   STR_PTR (ARGDAT(num)) = adr;                         
  60.   NL_FL   (ARGDAT(num)) = REGULAR_VALUE;               
  61. }
  62. #define TAB_CLM_STR(num, adr, colno)                   
  63. { IND_CLM_STR(num, adr);                               
  64.   tab_clm_nums[num] = colno;                           
  65. }
  66. #define IND_CLM_NUM(num, typ, adr)                     
  67. { (arg_du[num])->type.code = typ;                      
  68.   mem_to_DU (REGULAR_VALUE, typ, 0, adr, arg_du[num]); 
  69. }
  70. #define TAB_CLM_NUM(num, typ, adr, colno)              
  71. { IND_CLM_NUM(num, typ, adr);                          
  72.   tab_clm_nums[num] = colno;                           
  73. }
  74. #define RES_CLM(num, typ, colno)  
  75. {                                 
  76.   (res_du[num])->type.code = typ; 
  77.   num_rows[num] = colno;          
  78. }
  79. #define IND_READ(indid, an, rn)                           
  80.   ind_read (indid, an, arg_du, rn, num_rows, res_du, NULL, RSC)
  81. #define IND_NEXT_READ(indid, an, rn)                      
  82.   ind_read (indid, an, arg_du, rn, num_rows, res_du, &scanid, RSC)
  83. #define IND_DEL_READ(indid, an, rn)                      
  84.   ind_read (indid, an, arg_du, rn, num_rows, res_du, &scanid, DSC)
  85. #define IND_UPD_READ(indid, an, rn)                      
  86.   ind_read (indid, an, arg_du, rn, num_rows, res_du, &scanid, MSC)
  87. #define TAB_READ(tabid, an, nmax, rn) tab_read (tabid, an, nmax, tab_clm_nums,   
  88.                                                 arg_du, rn, num_rows, res_du)
  89. /* for strings "ptr" gets new address of the result string, *
  90.  * for number types the result is copied to "ptr"           */
  91. #define GET_RES_STR(num, ptr)               
  92. {                                           
  93.   if (NL_FL (RESDAT(num)) == REGULAR_VALUE) 
  94.     ptr = STR_PTR (RESDAT(num));            
  95.   else                                      
  96.     ptr = NULL;                             
  97. }
  98. #define GET_RES_NUM(num, ptr)                                
  99. { put_dat (&VL (RESDAT(num)), 0, RESCOD (num),               
  100.    REGULAR_VALUE, ptr, 0, RESCOD (num), NULL);       
  101. }
  102. void
  103. db_func_init (void)
  104. {
  105.   i4_t i;
  106.   
  107.   du = TYP_ALLOC (DU_ARR_LEN * 2, DataUnit);
  108.   for (i = 0; i < DU_ARR_LEN; i++)
  109.     {
  110.       arg_du[i] = du + i;
  111.       res_du[i] = du + i + DU_ARR_LEN;
  112.       ind_clm_nums[i] = i;
  113.     }
  114. } /* db_func_init */
  115. #define PUT_BUF(num, dat) {cond[num/2] |= (num/2 * 2 == num) ? dat : (char) dat << 4;}
  116. #define GET_BUF(num) (cond[num/2] & ((char) ((num/2 * 2 == num) ? 15 : 240)))
  117. int
  118. cond_form (i4_t clm_cnt, i4_t max_clm_num, i4_t *clm_nums,
  119.    DataUnit **cond_du, char **res_cond)
  120. /* forming of condition for open of scanning.                *
  121.    (max_clm_num = (max column number in array clm_nums) + 1) *
  122.  * Returns length of scale and pointer to it in res_cond     */
  123. {
  124.   i4_t i, err, sc_len, beg_len;
  125.   static i4_t cond_lng = 0;
  126.   static char *cond = NULL;
  127.   char *cur_in_cond;
  128.   
  129.   /* length of scale for condition */
  130.   beg_len = max_clm_num/2 + 1;
  131.   
  132.   /* length of condition */
  133.   for (sc_len = beg_len + clm_cnt * SZ_SHT, i = 0; i < clm_cnt; i++)
  134.     sc_len += sizeof_sqltype ((cond_du[i])->type);
  135.   
  136.   /* scale of condition making : */
  137.   CHECK_ARR_SIZE (cond, cond_lng, sc_len, char);
  138.   bzero (cond, sc_len);
  139.   for (i = 0; i < clm_cnt; i++)
  140.     PUT_BUF (clm_nums[i], EQ);
  141.   for (i = 0; i < max_clm_num; i++)
  142.     if (!GET_BUF (i))
  143.       PUT_BUF(i, ANY);
  144.   PUT_BUF (max_clm_num, ENDSC);
  145.   
  146.   /* the rest part of condition making : */
  147.   for (cur_in_cond = cond + beg_len, i = 0; i < clm_cnt; i++)
  148.     {
  149.       err = DU_to_buf (cond_du[i], &cur_in_cond, &((cond_du[i])->type));
  150.       if (err < 0)
  151. return err;
  152.     }
  153.   
  154.   *res_cond = cond;
  155.   return sc_len;
  156. } /* cond_form */
  157. int
  158. ind_read (Indid * indid, i4_t ind_clm_cnt, DataUnit **ind_cond_du, i4_t read_cnt,
  159.   i4_t *read_col_nums, DataUnit **read_du, Scanid *ext_scanid, char mode)
  160.      /* Reading read_cnt columns from table accordingly index indid and *
  161.       * given values (ind_cond_du) for finding in index;                *
  162.       * If ext_scanid == NULL => function tries to read only first row  *
  163.       *                        accordingly this index;                  *
  164.       * If ext_scanid != NULL  => function reads next row in ext_scanid *
  165.       * Function returns :  0 if the result was found,                  *
  166.       *                     <0 if the result of index scanning is empty */
  167. {
  168.   i4_t cod = 0, spn = 0, sc_len;
  169.   char *ind_cond;
  170.   Scanid local_scanid = -1, *scanid;
  171.   
  172.   scanid = (ext_scanid) ? ext_scanid : &local_scanid;
  173.   
  174.   if (*scanid < 0)
  175.     {
  176.       /* forming of condition for open of index scanning */
  177.       sc_len = cond_form (ind_clm_cnt, ind_clm_cnt, ind_clm_nums, ind_cond_du, &ind_cond);
  178.       if (sc_len < 0)
  179. return -ER_1;
  180.       
  181.       /* index scanning : */
  182.       cod = *scanid = openiscan (indid, &spn, mode, read_cnt, read_col_nums, 0,
  183.  NULL, sc_len, (cond_buf_t) ind_cond, 0, NULL);
  184.       if (spn > 0)
  185.         {
  186.           rollback (spn);
  187.           return -SYER;
  188.         }
  189.     }
  190.   
  191.   if (cod >= 0)
  192.     cod = findrow (*scanid, read_cnt, read_du);
  193.   if (!ext_scanid || cod < 0)
  194.     {
  195.       if (*scanid >= 0)
  196. closescan (*scanid);
  197.       *scanid = -1;
  198.     }
  199.   
  200.   return (cod);
  201. } /* ind_read */
  202. int
  203. tab_read (Tabid * tabid, i4_t tab_clm_cnt, i4_t max_clm_num,
  204.   i4_t *tab_col_nums, DataUnit **tab_cond_du,
  205.   i4_t read_cnt, i4_t *read_col_nums, DataUnit **read_du)
  206.      /* Reading read_cnt columns from table tabid accordingly   *
  207.       * given values (tab_cond_du) for finding in table;        *
  208.       * (max_clm_num = max column number in array tab_col_nums) *
  209.       * Function returns :  0 if the result was found,          *
  210.       *            <0 if the result of table scanning is empty  */
  211. {
  212.   i4_t cod = 0, spn = 0, sc_len,  def_num[1];
  213.   char *tab_cond;
  214.   Scanid scanid;
  215.   
  216.   def_num[0] = 0;
  217.   /* forming of condition for open of table scanning */
  218.   sc_len = cond_form (tab_clm_cnt, max_clm_num + 1, tab_col_nums, tab_cond_du, &tab_cond);
  219.   if (sc_len < 0)
  220.     return -ER_1;
  221.   
  222.   /* table scanning : */
  223.   if ((scanid = opentscan (tabid, &spn, 'R', (read_cnt) ? read_cnt : 1,
  224.    (read_cnt) ? read_col_nums : def_num,
  225.    sc_len, (cond_buf_t) tab_cond, 0, NULL)) < 0)
  226.     return (scanid);
  227.   if (spn > 0)
  228.     {
  229.       rollback (spn);
  230.       return -SYER;
  231.     }
  232.   cod = findrow (scanid, read_cnt, read_du);
  233.   closescan (scanid);
  234.   return (cod);
  235. } /* tab_read */
  236. int
  237. existsc (char *autnm)
  238.      /* checking the existing of scheme with name "autnm"
  239. the function result is no 0 if that scheme
  240. doesn't exist and 0 in another way
  241.      */
  242. {
  243.   CHECK_LEN (autnm);
  244.   
  245.   TAB_CLM_STR (0, autnm, SYSTABOWNER);
  246.   return TAB_READ (&systabtabid, 1, SYSTABOWNER, 0);
  247. } /* existsc */
  248. /*-------------------------------------------------*/
  249. int
  250. existtb (char *owner, char *tabnm, Tabid * tabid, char *type)
  251.      /* checking the existing in scheme the table with name
  252. tabnm; this name must be qualified (with authorization
  253. identifier); the result of function is 0
  254. if table doesn't exist and 1 in another case.
  255.         In the case of VIEW in tabid only field untabid is being filled.
  256.     
  257.       char  *tabnm;   * string containing table name        *
  258.                      
  259.       char  *owner;   * string containing user name         *
  260.       Tabid *tabid;   * answer parameter - table identifier *
  261.                       * if tabid == NULL,                   *
  262.                       * identifier isn't returned           *
  263.       char  *type;    * answer parameter - table type:      *
  264.                       * 'B' - base table , 'V' - view       */
  265. {
  266.   i4_t int_res;
  267.   char *tabtype;
  268.   CHECK_LEN (owner);
  269.   
  270.   IND_CLM_STR (0, tabnm);
  271.   IND_CLM_STR (1, owner);
  272.   RES_CLM (0, T_INT, SYSTABUNTABID);
  273.   RES_CLM (1, T_SRT, SYSTABSEGID);
  274.   RES_CLM (2, T_INT, SYSTABTABD);
  275.   RES_CLM (3, T_STR, SYSTABTABTYPE);
  276.   int_res = IND_READ (SYSTABLESIND1ID, 2, 4);
  277.   if (int_res < 0)
  278.     return 0;
  279.   
  280.   GET_RES_STR (3, tabtype);
  281.   if (type)
  282.     *type = tabtype[0];
  283.   if (tabid)
  284.     {
  285.       GET_RES_NUM (0, &(tabid->untabid));
  286.       if (tabtype[0] == 'B')    /* base table */
  287.         {
  288.           GET_RES_NUM (1, &(tabid->segid));
  289.           GET_RES_NUM (2, &(tabid->tabd));
  290.         }
  291.       else
  292.         {
  293.           assert (tabtype[0] == 'V'); /* view */
  294.           tabid->segid = tabid->tabd = 0;
  295.         }
  296.     }
  297.   return 1;
  298. } /* existtb */
  299. /*--------------------------------------------------------*/
  300. int
  301. existcl (Tabid * tabid, char *colnm, sql_type_t * type,
  302.          i4_t *colnumb, i4_t *def_func_id)
  303. /*
  304.   checking the existing of column  with given name in the pointed
  305.   table; column name has to be  simple; the result of function is
  306.   0 if this column exists, >0  if table exists but column doesn't
  307.   and result is <0 if given table doesn't exist
  308.   
  309.       Tabid      *tabid;    ;; table identifier                      
  310.       char       *colnm;    ;; column name                           
  311.       sql_type_t *type;     ;; answer parameter - column description 
  312.       i4_t        *colnumb;  ;; answer parameter - column number
  313. */
  314. {
  315.   i4_t int_res, collen, colprec;
  316.   i2_t numb;
  317.   char *coltype;
  318.   IND_CLM_STR (0, colnm);
  319.   IND_CLM_NUM (1, T_INT, &(tabid->untabid));
  320.   
  321.   RES_CLM (0, T_SRT, SYSCOLCOLNO);
  322.   RES_CLM (1, T_STR, SYSCOLCOLTYPE);
  323.   RES_CLM (2, T_INT, SYSCOLCOLTYPE1);
  324.   RES_CLM (3, T_INT, SYSCOLCOLTYPE2);
  325.   
  326.   int_res = IND_READ (SYSCOLUMNSIND1ID, 2, 4);
  327.   if (int_res < 0)
  328.     return int_res;
  329.   
  330.   GET_RES_NUM (0, &numb);
  331.   GET_RES_STR (1, coltype);
  332.   GET_RES_NUM (2, &collen);
  333.   GET_RES_NUM (3, &colprec);
  334.   
  335.   *colnumb  = numb;
  336.   *def_func_id = 0;
  337.   if (*coltype == SQLType_Char && colprec > 0)
  338.     {
  339.       *def_func_id = colprec;
  340.       colprec = 0;
  341.     }
  342.   *type = pack_type(*coltype,collen,colprec);
  343.   
  344.   return 0;
  345. }
  346. /*--------------------------------------------------------*/
  347. #define   STR_SAVE(to)                           
  348. {                                                
  349.   if (string)                                    
  350.     {                                            
  351.       to = GET_MEMC (char, strlen (string) + 1); 
  352.       strcpy (to, string);                       
  353.     }                                            
  354.   else                                           
  355.     to = NULL;                                   
  356. }
  357. int
  358. tab_cl (Tabid * tabid, i2_t clnm, sql_type_t * type, 
  359. char **cl_name, char **defval, char **defnull,
  360.         i4_t *def_func_id)
  361. /*
  362.   this  function gets information  about  column which number  is
  363.   clnm.  The function  result is 0  in the case of correct finish
  364.   of function and <0 if that table doesn't exist
  365.       Tabid *tabid;      ;; table identifier                   
  366.       i4_t    clnm;       ;; column number                      
  367.       sql_type_t  *type; ;; answer parameter - column description 
  368. */
  369. {
  370.   i4_t int_res, collen, colprec;
  371.   char *coltype, *string;
  372.   
  373.   IND_CLM_NUM (0, T_INT, &(tabid->untabid));
  374.   IND_CLM_NUM (1, T_SRT, &clnm);
  375.   
  376.   RES_CLM (0, T_STR, SYSCOLCOLNAME);
  377.   RES_CLM (1, T_STR, SYSCOLCOLTYPE);
  378.   RES_CLM (2, T_INT, SYSCOLCOLTYPE1);
  379.   RES_CLM (3, T_INT, SYSCOLCOLTYPE2);
  380.   RES_CLM (4, T_STR, SYSCOLDEFVAL);
  381.   RES_CLM (5, T_STR, SYSCOLDEFNULL);
  382.   
  383.   int_res = IND_READ (SYSCOLUMNSIND2ID, 2, 6);
  384.   if (int_res < 0)
  385.     return int_res;
  386.   
  387.   if (cl_name)
  388.     {
  389.       GET_RES_STR (0, string);
  390.       STR_SAVE (*cl_name);
  391.     }
  392.   GET_RES_STR (1, coltype);
  393.   GET_RES_NUM (2, &collen);
  394.   GET_RES_NUM (3, &colprec);
  395.   if (defval)
  396.     {
  397.       GET_RES_STR (4, string);
  398.       STR_SAVE (*defval);
  399.     }
  400.   if (defnull)
  401.     {
  402.       GET_RES_STR (5, string);
  403.       STR_SAVE (*defnull);
  404.       if (**defnull == '0')
  405. **defnull = 0;
  406.     }
  407.   if (def_func_id)
  408.     {
  409.       *def_func_id = 0;
  410.       if (*coltype == SQLType_Char && colprec > 0)
  411. {
  412.   *def_func_id = colprec;
  413.   colprec = 0;
  414. }
  415.     }
  416.   *type = pack_type(*coltype,collen,colprec);
  417.   
  418.   return 0;
  419. } /* tab_cl */
  420. /*--------------------------------------------------------*/
  421. int
  422. get_col_stat (i4_t untabid, i2_t clnm, col_stat_info *col_info)
  423.      /* function gets statistic information about column      *
  424.       * which number is clnm. The function result is 0 in the *
  425.       * case of correct finish of function and <0 if error    */
  426. {
  427.   i4_t int_res, collen, colprec;
  428.   char *coltype, *string;
  429.   
  430.   IND_CLM_NUM (0, T_INT, &untabid);
  431.   IND_CLM_NUM (1, T_SRT, &clnm);
  432.   
  433.   RES_CLM (0, T_STR, SYSCOLCOLTYPE);
  434.   RES_CLM (1, T_INT, SYSCOLCOLTYPE1);
  435.   RES_CLM (2, T_INT, SYSCOLCOLTYPE2);
  436.   RES_CLM (3, T_STR, SYSCOLMIN);
  437.   RES_CLM (4, T_STR, SYSCOLMAX);
  438.   
  439.   int_res = IND_READ (SYSCOLUMNSIND2ID, 2, 5);
  440.   if (int_res < 0)
  441.     return int_res;
  442.   
  443.   GET_RES_STR (0, coltype);
  444.   col_info->min.type.code = col_info->max.type.code = *coltype;
  445.   
  446.   GET_RES_NUM (1, &collen);
  447.   col_info->min.type.len = col_info->max.type.len = collen;
  448.   
  449.   GET_RES_NUM (2, &colprec);
  450.   col_info->min.type.prec = col_info->max.type.prec = colprec;
  451.   
  452.   GET_RES_STR (3, string);
  453.   mem_to_DU ((string) ? REGULAR_VALUE : NULL_VALUE, col_info->min.type.code,
  454.      (string) ? strlen (string) : 0, string, &(col_info->min));
  455.   
  456.   GET_RES_STR (4, string);
  457.   mem_to_DU ((string) ? REGULAR_VALUE : NULL_VALUE, col_info->max.type.code,
  458.      (string) ? strlen (string) : 0, string, &(col_info->max));
  459.   
  460.   return 0;
  461. } /* get_col_stat */
  462. /*--------------------------------------------------------*/
  463. static int
  464. DU_change_type (DataUnit *dt, i4_t tp_code)
  465. {
  466.   i4_t int_res = 0;
  467.   
  468.   if (dt->type.code != tp_code && dt->dat.nl_fl == REGULAR_VALUE)
  469.     {
  470.       int_res = put_dat (&VL(&(dt->dat)), 0, dt->type.code, 
  471.                          REGULAR_VALUE, &VL(&(dt->dat)), 0, tp_code, NULL);
  472.       dt->type.code = tp_code;
  473.     }
  474.   if (dt->type.len > MAX_STAT_LEN)
  475.     dt->type.len = MAX_STAT_LEN;
  476.     
  477.   return int_res;
  478. } /* DU_change_type */
  479. /*--------------------------------------------------------*/
  480. #define INS_min change_info->ins_min
  481. #define INS_max change_info->ins_max
  482. #define DEL_min change_info->del_min
  483. #define DEL_max change_info->del_max
  484. int
  485. put_col_stat (i4_t untabid, i2_t clnm, col_change_info *change_info)
  486.      /* modifies info in SYSCOLUMNS about MIN and/or MAX value in column. */
  487. {
  488.   static DataUnit null_val;
  489.   DataUnit du_arr[COLUMNS_COLNO];
  490.   DataUnit *new_min = NULL, *new_max = NULL;
  491.   i4_t mlist[2], nm = 0, int_res;
  492.   sql_type_t tp[2];
  493.   Scanid scanid = -1;
  494.   col_stat_info col_info;
  495.   i4_t error, col_nl_fl, ins_nl_fl, del_nl_fl;
  496.   bzero(&col_info,sizeof(col_info));
  497.   null_val.dat.nl_fl = NULL_VALUE;
  498.   
  499.   if (!change_info ||
  500.       (INS_min.dat.nl_fl == UNKNOWN_VALUE &&
  501.        INS_max.dat.nl_fl == UNKNOWN_VALUE &&
  502.        DEL_min.dat.nl_fl == UNKNOWN_VALUE &&
  503.        DEL_max.dat.nl_fl == UNKNOWN_VALUE))
  504.     return 0;
  505.   
  506.   if ((error = get_col_stat (untabid, clnm, &col_info)) < 0)
  507.     return error;
  508.   col_nl_fl = col_info.min.dat.nl_fl;
  509.   ins_nl_fl = INS_min.dat.nl_fl;
  510.   del_nl_fl = DEL_min.dat.nl_fl;
  511.   assert (col_nl_fl == col_info.max.dat.nl_fl &&
  512.           ins_nl_fl == INS_max.dat.nl_fl &&
  513.           del_nl_fl == DEL_max.dat.nl_fl);
  514.   /* making of new_min & new_max */
  515.   if (col_nl_fl == NULL_VALUE)
  516.     if (ins_nl_fl == REGULAR_VALUE)
  517.       /* insertion of not null value */
  518.       {
  519.         new_min = &(INS_min);
  520.         new_max = &(INS_max);
  521.       }
  522.     else {}
  523.   else
  524.     if (del_nl_fl == NULL_VALUE || ins_nl_fl == NULL_VALUE)
  525.       /* deletion or insertion of unknown value */
  526.       new_min = new_max = &null_val;
  527.     else
  528.       {
  529.         if (ins_nl_fl == REGULAR_VALUE)
  530.           {
  531.             MK_BIN_OPER (LT, INS_min, col_info.min);
  532.             if (COMP_RESULT)
  533.               {
  534.                 new_min = &(INS_min);
  535.                 col_info.min = INS_min;
  536.               }
  537.             MK_BIN_OPER (GT, INS_max, col_info.max);
  538.             if (COMP_RESULT)
  539.               {
  540.                 new_max = &(INS_max);
  541.                 col_info.max = INS_max;
  542.               }
  543.           }
  544.         if (del_nl_fl == REGULAR_VALUE)
  545.           {
  546.             i4_t lo=0,hi=0;
  547.             MK_BIN_OPER (LE, DEL_min, col_info.min);
  548.             if (COMP_RESULT) lo = 1 ;
  549.             MK_BIN_OPER (GE, DEL_max, col_info.max);
  550.             if (COMP_RESULT) hi = 1;
  551.             
  552. #if 0
  553.             if (lo) new_min = &null_val; /* conflict with assertation above */
  554.             if (hi) new_max = &null_val;
  555. #else
  556.             if ( lo && hi )
  557.               new_min = new_max = &null_val;
  558. #endif
  559.           }
  560.       }
  561.   if (new_min || new_max)
  562.     {
  563.       bzero (du_arr, sizeof (DataUnit) * COLUMNS_COLNO);
  564.       IND_CLM_NUM (0, T_INT, &untabid);
  565.       IND_CLM_NUM (1, T_SRT, &clnm);
  566.   
  567.       if ((int_res = IND_UPD_READ (SYSCOLUMNSIND2ID, 2, 0)))
  568.         return int_res;
  569.   
  570.       if (new_min)
  571.         {
  572.           DU_change_type (new_min, col_info.min.type.code);
  573.           mlist[nm] = SYSCOLMIN;
  574.           conv_DU_to_str (new_min, du_arr + SYSCOLMIN);
  575.           tp[nm++] = du_arr[SYSCOLMIN].type;
  576.         }
  577.       if (new_max)
  578.         {
  579.           DU_change_type (new_max, col_info.min.type.code);
  580.           mlist[nm] = SYSCOLMAX;
  581.           conv_DU_to_str (new_max, du_arr + SYSCOLMAX);
  582.           tp[nm++] = du_arr[SYSCOLMAX].type;
  583.         }
  584.   
  585.       if ((int_res = mod_data (scanid, nm, du_arr, tp, NULL, mlist)))
  586.         return int_res;
  587.       closescan (scanid);
  588.     }
  589.   return 0;
  590. } /* put_col_stat */
  591. #undef INS_min
  592. #undef INS_max
  593. #undef DEL_min
  594. #undef DEL_max
  595. /*--------------------------------------------------------*/
  596. int
  597. tabclnm (Tabid * tabid, i4_t *nnulcolnum)
  598.      /* this function gets the number of columns in pointed table;
  599. the result of function is this number (>0)
  600. or negative if table doesn't exist
  601.   
  602.       Tabid *tabid;        * table identifier          */
  603. {
  604.   i4_t int_res;
  605.   i2_t ncols; /* the number of columns   */
  606.   
  607.   assert (nnulcolnum);
  608.   IND_CLM_NUM (0, T_INT, &(tabid->untabid));
  609.   RES_CLM (0, T_SRT, SYSTABNCOLS);
  610.   RES_CLM (1, T_INT, SYSTABNNULCOLNUM);
  611.   int_res = IND_READ (SYSTABLESIND2ID, 1, 2);
  612.   if (int_res < 0)
  613.     return int_res;
  614.   
  615.   GET_RES_NUM (0, &ncols);
  616.   GET_RES_NUM (1, nnulcolnum);
  617.   
  618.   return ncols;
  619. } /* tabclnm */
  620. /*--------------------------------------------------------*/
  621. int
  622. get_nrows (i4_t untabid)
  623.      /* function gets the number of rows in table; *
  624.       * the result of function is this number (>0) *
  625.       * or negative if table doesn't exist         */
  626. {
  627.   i4_t int_res, nrows;
  628.   
  629.   IND_CLM_NUM (0, T_INT, &untabid);
  630.   RES_CLM (0, T_INT, SYSTABNROWS);
  631.   if ((int_res = IND_READ (SYSTABLESIND2ID, 1, 1)))
  632.     return int_res;
  633.   
  634.   GET_RES_NUM (0, &nrows);
  635.   
  636.   return nrows;
  637. } /* get_nrows */
  638. /*--------------------------------------------------------*/
  639. int
  640. put_nrows (i4_t untabid, i4_t nrows)
  641. /* modifies info in SYSTABLES about rows number in table */
  642. {
  643.   i4_t mlist = SYSTABNROWS, int_res;
  644.   sql_type_t tp;
  645.   DataUnit du_arr[TABLES_COLNO];
  646.   Scanid scanid = -1;
  647.   
  648.   tp = pack_type(T_INT,0,0);
  649.   
  650.   bzero (du_arr, sizeof (DataUnit) * TABLES_COLNO);
  651.   IND_CLM_NUM (0, T_INT, &untabid);
  652.   
  653.   if ((int_res = IND_UPD_READ (SYSTABLESIND2ID, 1, 0)))
  654.     return int_res;
  655.   
  656.   du_arr[SYSTABNROWS].type = tp;
  657.   mem_to_DU (REGULAR_VALUE, T_INT, 0, &nrows, du_arr + SYSTABNROWS);
  658.   if ((int_res = mod_data (scanid, 1, du_arr, &tp, NULL, &mlist)))
  659.     return int_res;
  660.   closescan (scanid);
  661.   return 0;
  662. } /* put_nrows */
  663. /*--------------------------------------------------------*/
  664. int
  665. get_tabid (i4_t untabid, Tabid *tabid)
  666.      /* this function gets all fields of tabid for table with this untabid *
  667.       * The result is 0 if o'k or negative if table doesn't exist          */
  668. {
  669.   i4_t int_res;
  670.   
  671.   IND_CLM_NUM (0, T_INT, &untabid);
  672.   RES_CLM (0, T_SRT, SYSTABSEGID);
  673.   RES_CLM (1, T_INT, SYSTABTABD);
  674.   int_res = IND_READ (SYSTABLESIND2ID, 1, 2);
  675.   if (int_res < 0)
  676.     return int_res;
  677.   
  678.   tabid->untabid = untabid;
  679.   GET_RES_NUM (0, &(tabid->segid));
  680.   GET_RES_NUM (1, &(tabid->tabd));
  681.   
  682.   return 0;
  683. } /* tabclnm */
  684. /*--------------------------------------------------------*/
  685. #define SEE_PVLG(type, j)                         
  686. {                                                 
  687.   u_need = r_need = 0;                            
  688.   for (i = 0, j = 1; (acttype[i]) && (j!=2); i++) 
  689.     if (!strchr (type, acttype[i]))               
  690.       switch (acttype[i])                         
  691. {                                         
  692. case 'U' :                                
  693.   if (un)                                 
  694.     if (strchr (type, 'u'))               
  695.       { j = 0; u_need ++; break; }        
  696.   j = 2;                                  
  697.   break;                                  
  698. case 'R' :                                
  699.   if (rn)                                 
  700.     if (strchr (type, 'r'))               
  701.       { j = 0; r_need ++; break; }        
  702.   j = 2;                                  
  703.   break;                                  
  704. default :                                 
  705.   j = 2;                                  
  706. }                                         
  707. }
  708. int
  709. tabpvlg (i4_t untabid, char *user, char *acttype,
  710.  i4_t un, i4_t *ulist,i4_t rn, i4_t *rlist)
  711. /*
  712. * checking access privilegies
  713. i4_t untabid   - table identifier
  714. char *user    - user name
  715. char *acttype - string with the following codes:
  716.                       * 'S' - SELECT,                     *
  717.                       * 'D' - DELETE,                     *
  718.       * 'U' - UPDATE,                     *
  719.       * 'I' - INSERT,                     *
  720.       * 'R' - REFERENCES                  *
  721.       * 'G' - GRANT OPTION                *
  722. i4_t un       - the number of rows to which the act "update"
  723.                is applied      
  724. i4_t *ulist   - array of column number to which the act "update"
  725.                is applied
  726. i4_t rn,      - the number of rows for which the act REFERENCES
  727.        is applied
  728. i4_t *rlist   - array of rows for which the act REFERENCES
  729.        is applied                                    */
  730. {
  731.   /* in SYSTABAUTH.tabauth : 'S','D','U','I','R','G' - rights *
  732.    * on all columns of table. 'u' and 'r' - there are not     *
  733.    * full rights but in table SYSCOLAUTH are described        *
  734.    * rights on some (not all) columns.                        */
  735.   
  736.   i4_t i, j, pvlg, u_need, r_need, int_res, int_res1;
  737.   char type[MAX_COLNO], *type1 = NULL, *type2 = NULL;
  738.   i2_t colno;
  739.   char * public = "PUBLIC";
  740.   
  741.   type[0] = 0;
  742.   CHECK_LEN (user);
  743.   
  744.   IND_CLM_NUM (0, T_INT, &untabid);
  745.   IND_CLM_STR (1, user);
  746.   RES_CLM (0, T_STR, SYSTABAUTHTABAUTH);
  747.   
  748.   int_res = IND_READ (SYSTABAUTHIND1ID, 2, 1);
  749.   
  750.   if (!int_res)
  751.     /* there are previlegies on the table for this user */
  752.     {
  753.       GET_RES_STR (0, type1);
  754.       SEE_PVLG (type1, pvlg);
  755.       /* pvlg == 0 => we should check information for columns    *
  756.        * pvlg == 1 => all wanted user rights were found          *
  757.        * pvlg == 2 => user have not all wanted rights            */
  758.       if (pvlg == 1)
  759. return 0;
  760.     }
  761.   if (type1)
  762.     strcpy (type, type1);
  763.   
  764.   IND_CLM_STR (1, public);
  765.   
  766.   int_res1 = IND_READ (SYSTABAUTHIND1ID, 2, 1);
  767.   if (int_res && int_res1)
  768.     return int_res;
  769.   if (!int_res1)
  770.     {
  771.       GET_RES_STR (0, type2);
  772.       if (type2)
  773. strcpy (type + strlen (type), type2);
  774.     }
  775.   SEE_PVLG (type, pvlg);
  776.   if (pvlg)
  777.     return pvlg - 1;
  778.   
  779. /*    check  rights UPDATE  or | and  REFERENCES for columns */
  780.   
  781.   IND_CLM_NUM (0, T_INT, &untabid);
  782.   IND_CLM_STR (2, user);
  783.   RES_CLM (0, T_STR, SYSCOLAUTHCOLAUTH);
  784.   if (u_need)
  785.     for (j = 0; j < un; j++)
  786.       {
  787. colno = ulist[j];
  788. IND_CLM_NUM (1, T_SRT, &colno);
  789. int_res = IND_READ (SYSCOLAUTHIND1ID, 3, 1);
  790. GET_RES_STR (0, type1);
  791.       
  792. if (int_res || !strchr (type1, 'U'))
  793.   return 1;
  794.       }
  795.   
  796.   if (r_need)
  797.     for (j = 0; j < rn; j++)
  798.       {
  799. colno = rlist[j];
  800. IND_CLM_NUM (1, T_SRT, &colno);
  801. int_res = IND_READ (SYSCOLAUTHIND1ID, 3, 1);
  802. GET_RES_STR (0, type1);
  803.       
  804. if (int_res || !strchr (type1, 'R'))
  805.   return 1;
  806.       }
  807.   
  808.   return 0;
  809. } /* tabpvlg */
  810. static TXTREF
  811. get_table(Tabid *tabid)
  812. {
  813.   extern void load_table __P((TXTREF ptbl));
  814.   TXTREF t;
  815.   for ( t = *(Root_ptr(Vcb_Root)); t ; t = RIGHT_TRN(t))
  816.     {
  817.       if (CODE_TRN(t) == ANY_TBL)
  818. load_table(t);
  819.       if ( (CODE_TRN(t) == TABLE) && ((TBL_TABID(t)).untabid == tabid->untabid))
  820. return t;
  821.     }
  822.   /* get_table_name for given tabid, create ANY_TBL and load_table */
  823.   return TNULL;
  824. }
  825. #define      INDFM  pind->Ind
  826. /* Checking of index existence for pointed table.
  827.    Function returns NULL when there are no indexes for
  828.    pointed table or pointer for list of index descriptions */
  829. TXTREF
  830. existind (Tabid * tabid)
  831. {
  832.   i2_t ncol;
  833.   i4_t i, int_res;
  834.   Indid  indid;
  835.   char *inxtype;
  836.   Scanid scanid = -1;
  837.   TXTREF ind_list = TNULL,tbl, cptrs;
  838.   
  839.   indid.tabid = *tabid;
  840.   
  841.   tbl = get_table(tabid);
  842.   if (!tbl)
  843.     return TNULL;
  844.   
  845.   IND_CLM_NUM (0, T_INT, &(tabid->untabid));
  846.   
  847.   RES_CLM (0,  T_STR, SYSINDEXTYPE);
  848.   RES_CLM (1,  T_SRT, SYSINDEXNCOL);
  849.   RES_CLM (2,  T_INT, SYSINDEXUNINDID);
  850.   RES_CLM (3,  T_SRT, SYSINDEXCOLNO1);
  851.   RES_CLM (4,  T_SRT, SYSINDEXCOLNO2);
  852.   RES_CLM (5,  T_SRT, SYSINDEXCOLNO3);
  853.   RES_CLM (6,  T_SRT, SYSINDEXCOLNO4);
  854.   RES_CLM (7,  T_SRT, SYSINDEXCOLNO5);
  855.   RES_CLM (8,  T_SRT, SYSINDEXCOLNO6);
  856.   RES_CLM (9,  T_SRT, SYSINDEXCOLNO7);
  857.   RES_CLM (10, T_SRT, SYSINDEXCOLNO8);
  858.   
  859.   for (;;)
  860.     {
  861.       cptrs = TNULL;
  862.       int_res = IND_NEXT_READ (SYSINDEXIND, 1, 11);
  863.       if (int_res < 0)
  864.         break;
  865.       
  866.       GET_RES_STR (0, inxtype);
  867.       GET_RES_NUM (1, &ncol);
  868.       GET_RES_NUM (2, &indid.unindid);
  869.       
  870.       for (i = ncol; i--;)
  871. {
  872.   i2_t col_no;
  873.   TXTREF cptr;
  874.   
  875.   GET_RES_NUM (3 + i, &col_no);
  876.   cptr = gen_colptr(find_column_by_number(tbl,col_no));
  877.   RIGHT_TRN(cptr) = cptrs;
  878.   cptrs = cptr;
  879. }
  880.       
  881.       {
  882. TXTREF ind;
  883. enum token code = INDEX;
  884. if (inxtype)
  885.           switch (inxtype[0])
  886.             {
  887.             case 'U' :
  888.               code = UNIQUE;
  889.               break;
  890.             case 'P' :
  891.               code = PRIMARY;
  892.               break;
  893.             default  :
  894.               break;
  895.             }
  896. ind = gen_parent(code,cptrs);
  897. /* assert(ARITY_TRN(ind) == ncol); */
  898. IND_INDID(ind) = indid;
  899. ind_list = join_list(ind_list,ind);
  900.       }
  901.     }/* for */
  902.   return ind_list;
  903. } /* existind */
  904. #define SAVE_CONSTR                           
  905. {                                             
  906.   if (pred_constr != NULL)                    
  907.     pred_constr->next = cur_constr;           
  908.   else                                        
  909.     constr_list = cur_constr;                 
  910.   pred_constr = cur_constr;                   
  911. }
  912. int
  913. new_ref_to_ind (Tabid *tabid, i2_t ncol, char *columns_fl, Scanid scanid)
  914.      /* searching for index to scan for costraint checking *
  915.       * and putting its identifier to SYSREFCONSTR         */
  916. {
  917.   TXTREF cur_ind, CurIndCol;
  918.   i4_t unindid, spn, mlist = SYSREFCONSTRINDTO;
  919.   sql_type_t tp;
  920.   DataUnit du_arr[SYSREFCONSTRINDTO+1];
  921.   
  922.   tp = pack_type(T_INT, 0, 0);
  923.   bzero (du_arr, sizeof (DataUnit) * (SYSREFCONSTRINDTO+1));
  924.   for (cur_ind = existind (tabid); cur_ind; cur_ind = RIGHT_TRN (cur_ind))
  925.     if (ARITY_TRN (cur_ind) == ncol)
  926.       {
  927.         i4_t eq_num = ncol;
  928. for (CurIndCol = DOWN_TRN (cur_ind);
  929.      CurIndCol; CurIndCol = RIGHT_TRN (CurIndCol))
  930.   if (columns_fl[COL_NO (OBJ_DESC (CurIndCol))])
  931.     eq_num--;
  932. if (!eq_num)
  933.   break;
  934.       }
  935.   
  936.   if (!cur_ind)
  937.     yyfatal ("Incorrect state of database: there is no index for columns from constraint");
  938.   
  939.   unindid = (IND_INDID (cur_ind)).unindid;
  940.   
  941.   du_arr[SYSREFCONSTRINDTO].type = tp;
  942.   mem_to_DU (REGULAR_VALUE, T_INT, 0, &unindid, du_arr + SYSREFCONSTRINDTO);
  943.   mod_data (scanid, 1, du_arr, &tp, &spn, &mlist);
  944.   return unindid;
  945. }
  946. Constr_Info *
  947. get_constraints (i4_t untabid, i4_t tab_clm_num)
  948. /* Gets information about constraints to table. *
  949.  * Returns the list constraints descriptions    *
  950.  * (it can be = NULL if the list is empty).     */
  951. {
  952.   i2_t ncol, cur_col;
  953.   i4_t *columns_from, *columns_to;
  954.   i4_t i, int_res, ref_untabid, ref_ind;
  955.   Constr_Info *constr_list = NULL, *cur_constr, *pred_constr = NULL;
  956.   VADR V_constr_ptr, V_ref_tabid, V_columns_from, V_columns_to, V_ref_indid;
  957.   S_Constraint *constr_ptr;
  958.   Tabid *ref_tabid;
  959.   Indid *ref_indid;
  960.   Scanid scanid = -1;
  961.   
  962.   /* checking when this table is referencing : */
  963.   
  964.   for (;;)
  965.     {
  966.       IND_CLM_NUM (0,  T_INT, &(untabid));
  967.   
  968.       RES_CLM (0,  T_INT, SYSREFCONSTRTABTO);
  969.       RES_CLM (1,  T_SRT, SYSREFCONSTRNCOLS);
  970.       RES_CLM (2,  T_SRT, SYSREFCONSTRCOLNOFR1);
  971.       RES_CLM (3,  T_SRT, SYSREFCONSTRCOLNOFR2);
  972.       RES_CLM (4,  T_SRT, SYSREFCONSTRCOLNOFR3);
  973.       RES_CLM (5,  T_SRT, SYSREFCONSTRCOLNOFR4);
  974.       RES_CLM (6,  T_SRT, SYSREFCONSTRCOLNOFR5);
  975.       RES_CLM (7,  T_SRT, SYSREFCONSTRCOLNOFR6);
  976.       RES_CLM (8,  T_SRT, SYSREFCONSTRCOLNOFR7);
  977.       RES_CLM (9,  T_SRT, SYSREFCONSTRCOLNOFR8);
  978.       RES_CLM (10, T_SRT, SYSREFCONSTRCOLNOTO1);
  979.       RES_CLM (11, T_SRT, SYSREFCONSTRCOLNOTO2);
  980.       RES_CLM (12, T_SRT, SYSREFCONSTRCOLNOTO3);
  981.       RES_CLM (13, T_SRT, SYSREFCONSTRCOLNOTO4);
  982.       RES_CLM (14, T_SRT, SYSREFCONSTRCOLNOTO5);
  983.       RES_CLM (15, T_SRT, SYSREFCONSTRCOLNOTO6);
  984.       RES_CLM (16, T_SRT, SYSREFCONSTRCOLNOTO7);
  985.       RES_CLM (17, T_SRT, SYSREFCONSTRCOLNOTO8);
  986.       RES_CLM (18, T_INT, SYSREFCONSTRINDTO);
  987.   
  988.       int_res = IND_UPD_READ (SYSREFCONSTRINDEX, 1, 19);
  989.       if (int_res < 0)
  990. break;
  991.   
  992.       cur_constr = GET_MEMC (Constr_Info, 1);
  993.       cur_constr->next = NULL;
  994.       cur_constr->mod_cols = GET_MEMC (char, tab_clm_num);
  995.       P_VMALLOC (constr_ptr, 1, S_Constraint);
  996.       cur_constr->constr = V_constr_ptr;
  997.       constr_ptr->constr_type = cur_constr->constr_type = FOREIGN;
  998.       
  999.       GET_RES_NUM (0,  &ref_untabid);
  1000.       GET_RES_NUM (1,  &ncol);
  1001.       GET_RES_NUM (18, &ref_ind);
  1002.       
  1003.       P_VMALLOC (columns_from, ncol, i4_t);
  1004.       P_VMALLOC (columns_to,   ncol, i4_t);
  1005.       constr_ptr->col_arg_list = V_columns_from;
  1006.       constr_ptr->col_ref_list = V_columns_to;
  1007.       constr_ptr->colnum = ncol;
  1008.       assert(ncol<=8 && ncol<=tab_clm_num);
  1009.       for (i = 0; i < ncol; i++)
  1010. {
  1011.   GET_RES_NUM (2 + i, &cur_col);
  1012.           assert(cur_col<tab_clm_num);
  1013.   columns_from[i] = cur_col;
  1014.   GET_RES_NUM (10 + i, &cur_col);
  1015.   columns_to[i] = cur_col;
  1016.   (cur_constr->mod_cols)[columns_to[i]] = TRUE;
  1017. }
  1018.       
  1019.       P_VMALLOC (ref_indid, 1, Indid);
  1020.       constr_ptr->object = V_ref_indid;
  1021.       get_tabid (ref_untabid, &(ref_indid->tabid));
  1022.       ref_indid->unindid = (ref_ind) ? ref_ind :
  1023. new_ref_to_ind (&(ref_indid->tabid), ncol, cur_constr->mod_cols, scanid);
  1024.       
  1025.       SAVE_CONSTR;
  1026.     } /* for */
  1027.   
  1028.   /* checking when this table is referenced : */
  1029.   
  1030.   for (;;)
  1031.     {
  1032.       IND_CLM_NUM (0,  T_INT, &(untabid));
  1033.       
  1034.       RES_CLM (0,  T_INT, SYSREFCONSTRTABFROM);
  1035.       RES_CLM (1,  T_SRT, SYSREFCONSTRNCOLS);
  1036.   
  1037.       int_res = IND_NEXT_READ (SYSREFCONSTRIND1, 1, 18);
  1038.       if (int_res < 0)
  1039. break;
  1040.   
  1041.       cur_constr = GET_MEMC (Constr_Info, 1);
  1042.       cur_constr->next = NULL;
  1043.       cur_constr->mod_cols = GET_MEMC (char, tab_clm_num);
  1044.       P_VMALLOC (constr_ptr, 1, S_Constraint);
  1045.       cur_constr->constr = V_constr_ptr;
  1046.       constr_ptr->constr_type = cur_constr->constr_type = REFERENCE;
  1047.       
  1048.       GET_RES_NUM (0,  &ref_untabid);
  1049.       GET_RES_NUM (1,  &ncol);
  1050.       assert(ncol<=8 && ncol<=tab_clm_num);
  1051.       
  1052.       P_VMALLOC (columns_from, ncol, i4_t);
  1053.       P_VMALLOC (columns_to,   ncol, i4_t);
  1054.       constr_ptr->col_arg_list = V_columns_from;
  1055.       constr_ptr->col_ref_list = V_columns_to;
  1056.       constr_ptr->colnum = ncol;
  1057.       for (i = 0; i < ncol; i++)
  1058. {
  1059.   GET_RES_NUM (10 + i, &cur_col);
  1060.           assert(cur_col<tab_clm_num);
  1061.   columns_from[i] = cur_col;
  1062.   GET_RES_NUM (2 + i, &cur_col);
  1063.   columns_to[i] = cur_col;
  1064.   (cur_constr->mod_cols)[columns_from[i]] = TRUE;
  1065. }
  1066.       
  1067.       P_VMALLOC (ref_tabid, 1, Tabid);
  1068.       constr_ptr->object = V_ref_tabid;
  1069.       get_tabid (ref_untabid, ref_tabid);
  1070.       
  1071.       SAVE_CONSTR;
  1072.     } /* for */
  1073.       
  1074.   IND_CLM_NUM (0,  T_INT, &(untabid));
  1075.   
  1076.   RES_CLM (0,  T_INT, SYSCHCONSTRCHCONID);
  1077.   RES_CLM (1,  T_INT, SYSCHCONSTRCONSIZE);
  1078.   RES_CLM (2,  T_SRT, SYSCHCONSTRNCOLS);
  1079.   RES_CLM (3,  T_SRT, SYSCHCONSTRCOLNO1);
  1080.   RES_CLM (4,  T_SRT, SYSCHCONSTRCOLNO2);
  1081.   RES_CLM (5,  T_SRT, SYSCHCONSTRCOLNO3);
  1082.   RES_CLM (6,  T_SRT, SYSCHCONSTRCOLNO4);
  1083.   RES_CLM (7,  T_SRT, SYSCHCONSTRCOLNO5);
  1084.   RES_CLM (8,  T_SRT, SYSCHCONSTRCOLNO6);
  1085.   RES_CLM (9,  T_SRT, SYSCHCONSTRCOLNO7);
  1086.   RES_CLM (10, T_SRT, SYSCHCONSTRCOLNO8);
  1087.   
  1088.   /* finding of all 'CHECK' constraints for this table : */
  1089.   
  1090.   for (;;)
  1091.     {
  1092.       int_res = IND_NEXT_READ (SYSCHCONSTRINDEX, 1, 11);
  1093.       if (int_res < 0)
  1094. break;
  1095.   
  1096.       cur_constr = GET_MEMC (Constr_Info, 1);
  1097.       cur_constr->next = NULL;
  1098.       cur_constr->mod_cols = GET_MEMC (char, tab_clm_num);
  1099.       cur_constr->constr = VNULL;
  1100.       cur_constr->constr_type = CHECK;
  1101.       
  1102.       GET_RES_NUM (0,  &(cur_constr->conid));
  1103.       GET_RES_NUM (1,  &(cur_constr->consize));
  1104.       GET_RES_NUM (2,  &ncol);
  1105.       assert(ncol<=8 && ncol<=tab_clm_num);
  1106.       
  1107.       for (i = 0; i < ncol; i++)
  1108. {
  1109.   GET_RES_NUM (3 + i, &cur_col);
  1110.           assert(cur_col<tab_clm_num);
  1111.   (cur_constr->mod_cols)[cur_col] = TRUE;
  1112. }
  1113.       
  1114.       SAVE_CONSTR;
  1115.     } /* for */
  1116.   return constr_list;
  1117. } /* get_constraints */
  1118. char *
  1119. get_chconstr (i4_t chconid, i4_t consize)
  1120.      /* gets the string for 'CHECK' constraint with identifier 'chconid' */
  1121. {
  1122.   char *string = NULL, *frag, *cur_in_string;
  1123.   i2_t fragno;
  1124.   i4_t int_res, fragsize;
  1125.   
  1126.   IND_CLM_NUM (0, T_INT, &chconid);
  1127.   RES_CLM (0, T_INT, SYSCHCONSTR2FRAGSIZE);
  1128.   RES_CLM (1, T_STR, SYSCHCONSTR2FRAG);
  1129.   
  1130.   cur_in_string = string = GET_MEMC (char, consize);
  1131.   
  1132.   for (fragno = 0; ; fragno++)
  1133.     {
  1134.       IND_CLM_NUM (1, T_SRT, &fragno);
  1135.       
  1136.       int_res = IND_READ (SYSCHCONSTRTWOIND, 2, 2);
  1137.       if (int_res < 0)
  1138. break;
  1139.       
  1140.       GET_RES_NUM (0, &fragsize);
  1141.       GET_RES_STR (1, frag);
  1142.       bcopy (frag, cur_in_string, fragsize);
  1143.       cur_in_string += fragsize;
  1144.     }
  1145.   assert (cur_in_string - string == consize);
  1146.   return string;
  1147. } /* get_chconstr */
  1148. /*--------------------------------------------------------*/
  1149. int
  1150. getview (i4_t untabid, char **res_segm)
  1151. /*
  1152.   receiving the  syntax tree  of view. Function returns
  1153.   the summary  size of memory  (in byte)>=0 in the case of
  1154.   success or negative value when the view doesn't exist.
  1155.    
  1156.       i4_t    untabid;   * unique view identifier              *
  1157.       char  **res_segm; * array of bytes with lenght "size"   *
  1158.                         *  which is used as answer parameter  *
  1159.                         *  of function.                       *
  1160. */
  1161. {
  1162.   static char  *buf = NULL;
  1163.   static i4_t    buf_size = 0;
  1164.   i4_t   size = 0, int_res, fragsize;
  1165.   i2_t fragno;
  1166.   char *frag;
  1167.   
  1168.   IND_CLM_NUM(0, T_INT, &untabid);
  1169.   RES_CLM ( 0, T_INT, SYSVIEWSFRAGSIZE);
  1170.   RES_CLM ( 1, T_STR, SYSVIEWSFRAG);
  1171.   for (fragno = 0; ; fragno++)
  1172.     {
  1173.       IND_CLM_NUM (1, T_SRT, &fragno);
  1174.       
  1175.       int_res = IND_READ (SYSVIEWSIND, 2, 2);
  1176.       if (int_res < 0)
  1177. break;
  1178.       
  1179.       GET_RES_NUM (0, &fragsize);
  1180.       size += fragsize;
  1181.       CHECK_ARR_ELEM (buf, buf_size, size, size, char);
  1182.       GET_RES_STR (1, frag);
  1183.       bcopy (frag, buf + size - fragsize, fragsize);
  1184.     }
  1185.   *res_segm = buf;
  1186.   return size;
  1187. }
  1188. #define DO(x) {if ((int_res = x)) return int_res;}
  1189. #define IND_DELROWS(ind, tab)             
  1190. {
  1191.   while (IND_DEL_READ (ind, 1, 0) >= 0)         
  1192.     {          
  1193.       handle_statistic (SYS##tab.untabid, tab##_COLNO, 0, NULL, 0); 
  1194.       DO (delrow (scanid, &spn));
  1195.     }          
  1196.   if (scanid >= 0)
  1197.     closescan (scanid);
  1198.   scanid = -1;
  1199. }
  1200. int
  1201. drop_table (i4_t untabid)
  1202. {
  1203.   Scanid scanid = -1, sv_scanid;
  1204.   char *tabtype;
  1205.   i4_t spn, int_res, conid;
  1206.   Tabid tabid;
  1207.   if (get_tabid (untabid, &tabid))
  1208.     return -NDR;
  1209.   /* references checking */
  1210.   IND_CLM_NUM (0, T_INT, &untabid);
  1211.   if (IND_READ (SYSREFCONSTRIND1, 1, 0) >= 0)
  1212.     /* there are still references to this table */
  1213.     return -ER_DRTAB;
  1214.   
  1215.   /* SYSTABLES handling */
  1216.   RES_CLM (0, T_STR, SYSTABTABTYPE);
  1217.   
  1218.   if (IND_DEL_READ (SYSTABLESIND2ID, 1, 1))
  1219.     return -NDR;
  1220.   GET_RES_STR (0, tabtype);
  1221.   if (tabtype[0] == 'B')    /* base table */
  1222.     DO (dropptab (&tabid, &spn))
  1223.   else
  1224.     {
  1225.       sv_scanid = scanid;
  1226.       scanid = -1;
  1227.       IND_DELROWS (SYSVIEWSIND, VIEWS);
  1228.       scanid = sv_scanid;
  1229.     }
  1230.   DO (delrow (scanid, &spn));
  1231.   handle_statistic (SYSTABLES.untabid, TABLES_COLNO, 0, NULL, 0);
  1232.   closescan (scanid);
  1233.   scanid = -1;
  1234.   
  1235.   IND_CLM_NUM (0, T_INT, &untabid);
  1236.   
  1237.   IND_DELROWS (SYSCOLUMNSIND2ID,  COLUMNS);
  1238.   IND_DELROWS (SYSCOLAUTHIND1ID,  COLAUTH);
  1239.   IND_DELROWS (SYSTABAUTHIND1ID,  TABAUTH);
  1240.   IND_DELROWS (SYSINDEXIND,       INDEXES);
  1241.   IND_DELROWS (SYSREFCONSTRINDEX, REFCONSTR);
  1242.   /* handling of tables with info about CHECK constraints */
  1243.   RES_CLM (0, T_INT, SYSCHCONSTRCHCONID);
  1244.   while (IND_DEL_READ (SYSCHCONSTRINDEX, 1, 1) >= 0)
  1245.     {
  1246.       GET_RES_NUM (0,  &conid);
  1247.       IND_CLM_NUM (0, T_INT, &conid);
  1248.       sv_scanid = scanid;
  1249.       scanid = -1;
  1250.       IND_DELROWS (SYSTABAUTHIND1ID, TABAUTH);
  1251.       scanid = sv_scanid;
  1252.       
  1253.       DO (delrow (scanid, &spn));
  1254.       handle_statistic (SYSCHCONSTR.untabid,
  1255.                         CHCONSTR_COLNO, 0, NULL, 0);
  1256.       IND_CLM_NUM (0, T_INT, &untabid);
  1257.     }
  1258.   if (scanid >= 0)
  1259.     closescan (scanid);
  1260.   return 0;
  1261. } /* drop_table */
  1262. #undef DO
  1263. #undef IND_DELROWS
  1264. /**************** THE E N D ****************/