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

SQL Server

开发平台:

Unix_Linux

  1. /*
  2.  *  codegen.c - functions of synthesator 
  3.  *              (last part of compilator: result module generation).
  4.  *
  5.  *  Copyright (c) 1996, 1997, Free Software Foundation, Inc
  6.  *  Developed at the Institute of System Programming
  7.  *  This file is written by Konstantin Dyshlevoj
  8.  *
  9.  *  This program is free software; you can redistribute it and/or modify
  10.  *  it under the terms of the GNU General Public License as published by
  11.  *  the Free Software Foundation; either version 2 of the License, or
  12.  *  (at your option) any later version.
  13.  *
  14.  *  This program is distributed in the hope that it will be useful,
  15.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  16.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17.  *  GNU General Public License for more details.
  18.  *
  19.  *  You should have received a copy of the GNU General Public License
  20.  *  along with this program; if not, write to the Free Software
  21.  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  22.  *
  23.  *  Contacts: gss@ispras.ru
  24.  *
  25.  */
  26. /* $Id: codegen.c,v 1.249 1997/04/21 16:17:10 kml Exp $ */
  27.   
  28. #include "global.h"
  29. #include "syndef.h"
  30. #include <assert.h>
  31. #include "tassert.h"
  32. #include "exti.h"
  33. #include "inprtyp.h"
  34. #include "const.h"
  35. #include "kitty.h"
  36. #define OPTIM           1
  37. #define DROP_ARR_DELTA  5
  38. #define SCAN_ARR_DELTA  5
  39. #define SECT_ARR_DELTA  10
  40. #define PROC_ARR_DELTA  5
  41. #define TRPTR_ARR_DELTA 5
  42. #define CHECK_TYPE_ARR(name)
  43. { if (!V_type_arr_##name) {
  44.     sql_type_t *type_arr_##name;
  45.     P_VMALLOC (type_arr_##name, name##_COLNO, sql_type_t); 
  46.     bcopy (name##_COLTYPES, type_arr_##name,
  47.            sizeof (sql_type_t) * name##_COLNO);
  48. } }
  49. extern DataUnit *data_st;
  50. extern i4_t   static_sql_fl;   /* == 0 for dynamic SQL */
  51. extern i4_t  dt_ind, dt_max;
  52. extern sql_type_t INDEXES_COLTYPES [INDEXES_COLNO];
  53. extern sql_type_t CHCONSTR_COLTYPES [CHCONSTR_COLNO];
  54. extern sql_type_t VIEWS_COLTYPES [VIEWS_COLNO];
  55. extern sql_type_t CHCONSTRTWO_COLTYPES [CHCONSTRTWO_COLNO];
  56. extern sql_type_t REFCONSTR_COLTYPES [REFCONSTR_COLNO];
  57. extern sql_type_t TABLES_COLTYPES [TABLES_COLNO];
  58. extern sql_type_t COLUMNS_COLTYPES [COLUMNS_COLNO];
  59. extern sql_type_t TABAUTH_COLTYPES [TABAUTH_COLNO];
  60. extern sql_type_t COLAUTH_COLTYPES [COLAUTH_COLNO];
  61. VADR V_type_arr_INDEXES = VNULL;
  62. VADR V_type_arr_CHCONSTR = VNULL;
  63. VADR V_type_arr_VIEWS = VNULL;
  64. VADR V_type_arr_CHCONSTRTWO = VNULL;
  65. VADR V_type_arr_REFCONSTR = VNULL;
  66. VADR V_type_arr_TABLES = VNULL;
  67. VADR V_type_arr_COLUMNS = VNULL;
  68. VADR V_type_arr_TABAUTH = VNULL;
  69. VADR V_type_arr_COLAUTH = VNULL;
  70. i4_t PRCD_DEBUG = 0;
  71. i4_t   *chconstr_col_use = NULL;
  72. i4_t    ch_col_use_num;
  73. VADR *ProcTable; /* beginning of array of virtual       *
  74.   * addresses for additional procedures */
  75. i4_t ProcMax = 0, ProcNum = 0;
  76. VCBREF real_insert_scan = TNULL;
  77. /* is used (!= TNULL) for operator INSERT */
  78. VADR DelCurConstr = VNULL;
  79. /* is used (!= VNULL) for DELETE CURRENT operator */
  80. i4_t drop_max = 0;      /* current number of available elements in drop_arr */
  81. i4_t drop_cnt = -1;      /* number of temporary tables in cursor          *
  82.         * this variable is used only if it != -1        */
  83. VADR *drop_arr = NULL; /* array of addresses of Tabid for temp. tables  *
  84.         * in cursor (is being filled if drop_cnt != -1) */
  85. i4_t scan_max = 0;      /* current number of available elements in scan_arr */
  86. i4_t scan_cnt = -1;     /* number of scans in cursor -         *
  87.         * is used only if it != -1            */
  88. VADR *scan_arr = NULL; /* array of addresses of scans         *
  89.         * (is being filled if scan_cnt != -1) */
  90. SH_Info *sh_arr = NULL, *tr_arr = NULL;
  91. i4_t tr_cnt = -1, tr_max = 0; /* is used in operators */
  92. i4_t sh_cnt = -1, sh_max = 0; /* is used in operators */
  93. i4_t uniqnm (void);
  94. /*---------------------------------------------------------------------*/
  95. VADR
  96. codegen (void)
  97. /* ROOT - pointer to entrance tree;                       *
  98.  * Returns virtual address of section with module created */
  99. {
  100.   TXTREF Opern;
  101.   VADR SegBeg, SecTabOff;
  102.   VADR *SectTable; /* beginning of array of virtual  *
  103.     * addresses for basic procedures */
  104.   VADR *SectArr = NULL, V_SectTable;
  105.   i4_t SectMax = 0, SectNum = 0; /* !! First segment number is 1 !! */
  106.   MASK Depend = 0;
  107.   
  108.   if (!(Opern = ROOT))
  109.     return VNULL;
  110.   
  111.   InitDat;
  112. /* work with segment initialization : */
  113.   SegBeg = create_segment ();
  114.   if ((SecTabOff = vmalloc (4)) != 4)
  115.     yyfatal ("First vmalloc(4) doesn't return 4 !!");
  116.   ProcAdr = VNULL;
  117.   CurPg = VNULL;
  118.   MaxPg = VNULL;
  119.   FuncExit = NULL;
  120.   V_type_arr_INDEXES = VNULL;
  121.   V_type_arr_CHCONSTR = VNULL;
  122.   V_type_arr_VIEWS = VNULL;
  123.   V_type_arr_CHCONSTRTWO = VNULL;
  124.   V_type_arr_REFCONSTR = VNULL;
  125.   V_type_arr_TABLES = VNULL;
  126.   V_type_arr_COLUMNS = VNULL;
  127.   V_type_arr_TABAUTH = VNULL;
  128.   V_type_arr_COLAUTH = VNULL;
  129.   do
  130.     {
  131.       CurBit = 1;
  132.       tr_cnt = 0;
  133.       sh_cnt = 0;
  134.       
  135.       SectNum++;
  136.       CHECK_ARR_ELEM (SectArr, SectMax, SectNum, SECT_ARR_DELTA, VADR);
  137.       SectArr[SectNum] = ProcHandle (Opern, VNULL, TNULL,
  138.      SectNum, &Depend, NULL, NULL);
  139.       assert (!Depend);
  140.     }
  141.   while ((Opern = RIGHT_TRN (Opern)) != TNULL);
  142.   P_VMALLOC (SectTable, SectNum + ProcNum + 2, VADR);
  143.   TYP_COPY (SectArr, SectTable, SectNum + 1, VADR);
  144.   if (ProcNum)
  145.     {
  146.       TYP_COPY (ProcTable, SectTable + SectNum + 1, ProcNum, VADR);
  147.       xfree (ProcTable);
  148.       ProcTable = NULL;
  149.     }
  150.   assert(ProcTable==NULL);
  151.   xfree (SectArr);
  152.   
  153.   /* in the beginning of array SectTable is its length  *
  154.    * the pointer to SectTable is in virtual address 4   */
  155.   *((i4_t*)&SectTable[0]) = SectNum;
  156.   *V_PTR (SecTabOff, VADR) = V_SectTable;
  157.   return SegBeg;
  158. } /* GlobHandle */
  159. /*---------------------------------------------------------------------*/
  160. VADR
  161. ProcHandle (TXTREF BegNode, VADR BO_Tid, VCBREF ResScan,
  162.     i2_t ProcN, MASK *Depend, float *sq_cost, i4_t *res_row_num)
  163. /* procedure designing: for basic procedure ProcN >=1   *
  164.  * & for auxiliary procedure ProcN = 0.                 *
  165.  * Returns virtual address of procedure beginning       *
  166.  * To Depend are putted MASK bits for all external      *
  167.  * tables in current procedure.                         *
  168.  * If sq_cost != NULL & BegNode - SubQuery => the       *
  169.  * estimated cost of this SubQuery is putted to sq_cost */
  170. {
  171.   VADR OldProcAdr = ProcAdr, OldCurPg = CurPg, OldMaxPg = MaxPg;
  172.   VADR BegPg, V_SetH = VNULL;
  173.   i4_t i, j, trptr_cnt;
  174.   i4_t Old_drop_cnt = drop_cnt, Old_scan_cnt = scan_cnt;
  175.   i4_t Old_drop_max = drop_max, Old_scan_max = scan_max;
  176.   VADR *Old_drop_arr = drop_arr, *Old_scan_arr = scan_arr;
  177.   MASK CurMask, ExtDep, IntDep = 0;
  178.   static PSECT_PTR *trptr_arr = NULL;
  179.   static i4_t trptr_max = 0;
  180.   
  181.   drop_arr = scan_arr = VNULL; /* kml */
  182.   drop_cnt = scan_cnt = -1;
  183.   drop_max = scan_max = 0;
  184.   /* CurPg is always suitable for type "i4_t" */
  185.   ProcAdr = CurPg = BegPg = VMALLOC (INTERP_MODULE_DELTA, char);
  186.   MaxPg = CurPg + INTERP_MODULE_DELTA;
  187.   
  188.   if (!ProcN)
  189.     STEP_CMD (V_SetH, SetHandle);
  190.   Handle (BegNode, BO_Tid, ResScan, sq_cost, res_row_num);
  191.   SET_END;
  192.   
  193.   *Depend = 0;
  194.   /* filling of SetHandle for trees with external references */
  195.   if (!ProcN)
  196.     {
  197. #define SH  V_PTR (V_SetH, struct S_SetHandle)
  198.       
  199.       SH->flag = 'n';
  200.       /* memory allocation for placing of tree pointers     *
  201.        * (here we think that it is necessary for all trees) */
  202.       SH->Bit = 0;
  203.       
  204.       for (i = 0; i < sh_cnt; i++)
  205. if (sh_arr[i].PrAdr == ProcAdr)
  206.   IntDep = BitOR (IntDep, sh_arr[i].Depend);
  207.       /* IntDep contains bits for all internal tables for this procedure now */
  208.       
  209.       IntDep = BitNOT (IntDep);
  210.       for (j = 0, trptr_cnt = 0; j < tr_cnt; j++)
  211. if ((tr_arr[j].PrAdr == ProcAdr) &&
  212.     (ExtDep = BitAND (IntDep, tr_arr[j].Depend)))
  213.   /* Putting of bits for external tables       *
  214.    * of j-th tree in the procedure to Depend : */
  215.   { 
  216.     *Depend = BitOR (*Depend, ExtDep);
  217.             CHECK_ARR_ELEM (trptr_arr, trptr_max, trptr_cnt,
  218.                             TRPTR_ARR_DELTA, PSECT_PTR);
  219.             
  220.     trptr_arr[trptr_cnt++].off = tr_arr[j].Place;
  221.   }
  222.       
  223.       SH->TrCnt = trptr_cnt;
  224.       if (trptr_cnt)
  225.         {
  226.           SH->Trees.off = VMALLOC (trptr_cnt, PSECT_PTR);
  227.           TYP_COPY (trptr_arr, V_PTR (SH->Trees.off, PSECT_PTR),
  228.                     trptr_cnt, PSECT_PTR);
  229.         }
  230.       
  231. #undef SH      
  232.     }
  233.   /* making of all commands SetHandle in current procedure */
  234.   for (i = 0; i < sh_cnt; i++)
  235.     if (sh_arr[i].PrAdr == ProcAdr)
  236.       {  
  237. #define SH  V_PTR (sh_arr[i].Place, struct S_SetHandle)
  238. CurMask = sh_arr[i].Depend;
  239. SH->flag = 'n';
  240. SH->Bit = CurMask;
  241. for (j = 0, trptr_cnt = 0; j < tr_cnt; j++)
  242.   if ((BitAND (tr_arr[j].Depend, CurMask) == CurMask) &&
  243.       (tr_arr[j].PrAdr == ProcAdr))
  244.             {
  245.               CHECK_ARR_ELEM (trptr_arr, trptr_max, trptr_cnt,
  246.                               TRPTR_ARR_DELTA, PSECT_PTR);
  247.               trptr_arr[trptr_cnt++].off = tr_arr[j].Place;
  248.             }
  249. SH->TrCnt = trptr_cnt;
  250.         if (trptr_cnt)
  251.           {
  252.             SH->Trees.off = VMALLOC (trptr_cnt, PSECT_PTR);
  253.             TYP_COPY (trptr_arr, V_PTR (SH->Trees.off, PSECT_PTR),
  254.                       trptr_cnt, PSECT_PTR);
  255.           }
  256. #undef SH      
  257.       }
  258.   /* Bits for all external tables used in procedure are now in Depend */
  259.   
  260.   xfree (drop_arr);
  261.   xfree (scan_arr);
  262.   scan_cnt = Old_scan_cnt;
  263.   scan_max = Old_scan_max;
  264.   scan_arr = Old_scan_arr;
  265.   drop_cnt = Old_drop_cnt;
  266.   drop_max = Old_drop_max;
  267.   drop_arr = Old_drop_arr;
  268.   ProcAdr  = OldProcAdr;
  269.   CurPg    = OldCurPg;
  270.   MaxPg    = OldMaxPg;
  271.   
  272.   /* additional procedure registration */
  273.   if (!ProcN)
  274.     {
  275.       CHECK_ARR_ELEM (ProcTable, ProcMax, ProcNum, PROC_ARR_DELTA, VADR);
  276.       ProcTable[ProcNum++] = BegPg;
  277.     }
  278.   return BegPg;
  279. } /* ProcHandle */
  280. /*---------------------------------------------------------------------*/
  281. VADR
  282. ScanHandle (VCBREF ScanNode, VADR * Scan, MASK * Msk, float *sq_cost, i4_t *res_row_num)
  283. /* returns address of Tabid for table                        *
  284.  *                 or NULL if Scanid was already filled      *
  285.  * if Scan!=NULL && *Scan == NULL => address of Scanid is    *
  286.  * putting to Scan. This putted address may be = VNULL if    *
  287.  * there is not scanning table : result is a single row      *
  288.  * if Msk!=NULL, mask for table is creating & pitting to Msk */
  289. {
  290.   VCBREF TblNode, CurClm;
  291.   TXTREF TabQuery;
  292.   VADR Tbid = VNULL;
  293.   VADR V_sc;
  294.   Scanid *sc;
  295.   i4_t res = 0;
  296.   char need_tbid = (!Scan || (*Scan == VNULL));
  297.   
  298.   TASSERT(ScanNode && (CODE_TRN (ScanNode) == SCAN),ScanNode);
  299.   TblNode = COR_TBL (ScanNode);
  300.   Tbid = COR_TID (ScanNode);
  301.   
  302.   if (!Tbid)
  303.     {
  304.       COR_TID (ScanNode) = Tbid = VMALLOC (1, UnId);
  305.       if (CODE_TRN (TblNode) == TMPTABLE)
  306. {
  307.   TabQuery = VIEW_QUERY (TblNode);
  308.           switch (CODE_TRN (TabQuery))
  309.             {
  310.             case SORTER:
  311.             case MAKEGROUP:
  312.               break;
  313.               
  314.             case UNION:
  315.               TASSERT (TstF_TRN (TabQuery, ALL_F), TabQuery);
  316.             case DELETE:
  317.             case QUERY:
  318.       Pr_TMPCRE (Tbid, (TBL_COLS (TblNode)) ? TBL_COLS (TblNode) :
  319.  COR_COLUMNS (ScanNode), TBL_NNULCOL (TblNode));
  320.       if (drop_cnt >= 0)
  321. {
  322.   CHECK_ARR_ELEM (drop_arr, drop_max, drop_cnt, DROP_ARR_DELTA, VADR);
  323.   drop_arr[drop_cnt++] = Tbid;
  324. }
  325.               break;
  326.             default:
  327.               lperror("Unexpected code (%s) of table expression",
  328.                       NAME(CODE_TRN(TabQuery))); 
  329.     }
  330.           
  331.   res = Handle (TabQuery, Tbid, ScanNode,
  332. &BUILD_COST (TblNode), &NROWS_EST (TblNode));
  333.   /* res == 1 <==> there is not scanning table : *
  334.    * result is a single row. This situation is   *
  335.    * fixed in COR_TID(ScanNode) :                */
  336.   if (res)
  337.     {
  338.       vmfree (Tbid);
  339.       COR_TID (ScanNode) = Tbid = 1;
  340.     }
  341. }
  342.       else
  343. {
  344.   TASSERT (CODE_TRN (TblNode) == TABLE, ScanNode);
  345.   V_PTR (Tbid, UnId)->t = TBL_TABID (TblNode);
  346.   for (CurClm = COR_COLUMNS (ScanNode); CurClm; CurClm = COL_NEXT (CurClm))
  347.     if (!COL_ADR (CurClm))
  348.       COL_ADR (CurClm) = prepare_HOLE (COL_TYPE (CurClm));
  349.   
  350. }
  351.     }
  352.       
  353.   if (CODE_TRN (TblNode) == TMPTABLE)
  354.     {
  355.       if (sq_cost)
  356. *sq_cost = BUILD_COST (TblNode);
  357.       if (res_row_num)
  358. *res_row_num = NROWS_EST (TblNode);
  359.     }
  360.       
  361.   if (Msk)
  362.     {
  363.       if (!COR_MASK (ScanNode))
  364. COR_MASK (ScanNode) = NEXT_BIT;
  365.       *Msk = COR_MASK (ScanNode);
  366.     }
  367.   
  368.   if (Tbid == 1)
  369.     {
  370.       if (Scan && !(*Scan))
  371. *Scan = VNULL;
  372.       return VNULL;
  373.     }
  374.   else
  375.     if (Scan && !(*Scan))
  376.       {
  377. if (!COR_SCANID (ScanNode))
  378.   {
  379.     P_VMALLOC (sc, 1, Scanid);
  380.     if (scan_cnt >= 0)
  381.       {
  382. CHECK_ARR_ELEM (scan_arr, scan_max, scan_cnt, SCAN_ARR_DELTA, VADR);
  383. scan_arr[scan_cnt++] = V_sc;
  384.       }
  385.     COR_SCANID (ScanNode) = V_sc;
  386.     *sc = -1; /* value before scan opening */
  387.   }
  388. *Scan = COR_SCANID (ScanNode);
  389.       }
  390.   
  391.   return (need_tbid) ? Tbid : VNULL;
  392. } /* ScanHandle */
  393. /*---------------------------------------------------------------------*/
  394. VADR
  395. CrInd (i4_t ind_num, char *ind_typ, VADR V_Tbd, VADR V_tabname,
  396.        VADR V_owner, VCBREF Node, i4_t clmcnt)
  397. /* handling of index creation for table with Tabid Tbd. *
  398.  * (this index has number ind_num)                      *
  399.  * Information for creation is from Node.               *
  400.  * Returns virtual address of unindid of created index. */
  401. {
  402.     VCBREF Cur;
  403.     VADR V_inxname, V_inxtype = VNULL, V_colno;
  404.     VADR V_credate, V_cretime, V_ncol;
  405.     VADR V_clmlist, V_indid;
  406.     char *inxname, *inxtype;
  407.     i2_t *colno;
  408.     i2_t *ncol;
  409.     VADR *colval, V_colval;
  410.     UnId *indid, *sysind;
  411.     VADR V_sysind;
  412.     i4_t i, *clmlist, unindid_off;
  413.     
  414.     assert(clmcnt<=8);
  415.     /* it may not be more than 8 columns for index */ 
  416.     
  417.     P_VMALLOC (sysind, 1, UnId);
  418.     sysind->t=sysindtabid;
  419.     
  420.     P_VMALLOC (clmlist, clmcnt, i4_t);
  421.     for (Cur=Node, i=0; Cur; i++, Cur=RIGHT_TRN(Cur))
  422. clmlist[i]=COL_NO( OBJ_DESC (Cur));
  423.     
  424.     P_VMALLOC (indid, 1, UnId);
  425.     unindid_off = (char *)( &(indid->i.unindid)) - (char *)indid;
  426.     
  427.     Pr_CREIND (V_Tbd, V_indid, (ind_typ?1:0), clmcnt, V_clmlist);
  428.     
  429.     P_VMALLOC (inxname, 24, char);
  430.     sprintf(inxname,"%sIND%d", V_PTR (V_tabname, char), ind_num);
  431.     
  432.     V_credate = VMALLOC (9, char);
  433.     V_cretime = VMALLOC (9, char);
  434.     P_VMALLOC (ncol, 1, i2_t);
  435.     *ncol = clmcnt;
  436.     
  437.     V_colno = VMALLOC (clmcnt, i2_t);
  438.     if (ind_typ)
  439.       {
  440. P_VMALLOC (inxtype, 3, char);
  441. strncpy (inxtype, ind_typ, 2);
  442. inxtype[2] = 0;
  443.       }
  444.     /* adding record about index into SYSINDEXES */
  445.     P_VMALLOC (colval, 16, VADR);
  446.     
  447.     colval[0] = V_Tbd;
  448.     colval[1] = V_inxname;
  449.     colval[2] = V_owner;
  450.     colval[3] = (ind_typ) ? V_inxtype : VNULL;
  451.     colval[4] = V_ncol;
  452.     colval[13] = V_credate;
  453.     colval[14] = V_cretime;
  454.     colval[15] = V_indid + unindid_off;
  455.     
  456.     colno   = V_PTR (V_colno, i2_t);
  457.     clmlist = V_PTR (V_clmlist, i4_t);
  458.     for (i=0; i<clmcnt; i++)
  459.       {
  460. colno[i] = clmlist[i];
  461. colval[5+i] = V_colno + i * SZ_SHT;
  462.       }
  463.     for (i=clmcnt+5; i<13; i++)
  464.       colval[i]=VNULL;
  465.     
  466.     CHECK_TYPE_ARR (INDEXES);
  467.     Pr_INSLIST (V_sysind, 16, V_type_arr_INDEXES, 
  468. VNULL, V_colval, V_credate, V_cretime);
  469.     return colval[15]; /* address of unindid */
  470. } /* CrInd */
  471. void
  472. make_str_parts (VADR V_id, i4_t is_cre_tab, char *seg_ptr, i4_t seg_lng)
  473. /* preparing of table SYSCHCONSTRTWO (is_cre_tab == TRUE) *
  474.    or SYSVIEWS (is_cre_tab == FALSE) filling              */
  475. {
  476.   i4_t *fragsize, i, rest_len;
  477.   i2_t *fragno;
  478.   char *end_ptr, *cur_ptr, *frag;
  479.   VADR V_fragno, V_fragsize;
  480.   VADR *colval, V_colval, V_len, V_into_tab, V_frag;
  481.   UnId *into_tab;
  482.   i2_t *len;
  483.   P_VMALLOC (into_tab, 1, UnId);
  484.   into_tab->t = (is_cre_tab == TRUE) ? chcontwotabid : viewstabid;
  485.   
  486.   end_ptr = seg_ptr + seg_lng;
  487.   for (i = 0, cur_ptr = seg_ptr; cur_ptr < end_ptr; i++, cur_ptr += *fragsize)
  488.     {
  489.       rest_len = end_ptr - cur_ptr;
  490.       P_VMALLOC (fragno, 1, i2_t);
  491.       *fragno = i;
  492.       
  493.       P_VMALLOC (fragsize, 1, i4_t);
  494.       *fragsize = (rest_len < MAX_STR_LNG) ? rest_len : MAX_STR_LNG;
  495.       
  496.       P_VMALLOC (frag, *fragsize, char);
  497.       bcopy (cur_ptr, frag, *fragsize);
  498.       
  499.       P_VMALLOC (len, 4, i2_t);
  500.       len[3] = *fragsize;
  501.   
  502.       P_VMALLOC (colval, 4, VADR);
  503.       colval[0] = V_id;
  504.       colval[1] = V_fragno;
  505.       colval[2] = V_fragsize;
  506.       colval[3] = V_frag;
  507.       if (is_cre_tab == TRUE) /* table creation */
  508.         CHECK_TYPE_ARR (CHCONSTRTWO)
  509.       else                    /* view  creation */
  510.         CHECK_TYPE_ARR (VIEWS);
  511.         
  512.       Pr_INSLIST (V_into_tab, 4, (is_cre_tab == TRUE) ?
  513.                   V_type_arr_CHCONSTRTWO : V_type_arr_VIEWS,
  514.                   V_len, V_colval, VNULL, VNULL);
  515.     }
  516. } /* make_str_parts */
  517. /*---------------------------------------------------------------------*/
  518. void
  519. CrCheckConstr (VADR V_Tbd, i4_t tbl_col_num, TXTREF tree)
  520. {
  521.   i4_t *chconid, *seg_size, i, j;
  522.   i2_t *ncols, *colno;
  523.   VADR V_ncols, V_chconid, V_seg_size, V_cur_colno, V_colno;
  524.   VADR cur_seg, seg, tree_ptr;
  525.   MASK Depend;
  526.   char *seg_ptr;
  527.   VADR *colval, V_colval, V_syschconstr;
  528.   UnId *syschconstr;
  529.   
  530.   P_VMALLOC (syschconstr, 1, UnId);
  531.   syschconstr->t = chconstrtabid;
  532.   
  533.   P_VMALLOC (chconid, 1, i4_t);
  534.   *chconid = uniqnm ();
  535.   
  536.   chconstr_col_use = TYP_ALLOC (tbl_col_num, i4_t);
  537.   ch_col_use_num = 0;
  538.   
  539.   /* VM-segment with tree (check condition) creating */
  540.   
  541.   cur_seg = get_vm_segment_id (0);
  542.   seg = create_segment ();
  543.   switch_to_segment (seg);
  544.   
  545.   if ((tree_ptr = vmalloc (4)) != 4)
  546.     yyfatal ("First vmalloc(4) doesn't return 4 !!");
  547.   *V_PTR (tree_ptr, VADR) = Tr_RecLoad (tree, &Depend, 0, NULL);
  548.   /* in new segment in virtual address 4 there is now VADR for tree beginning */
  549.   switch_to_segment (cur_seg);
  550.   P_VMALLOC (ncols, 1, i2_t);
  551.   assert ((*ncols = ch_col_use_num) <= 8);
  552.   
  553.   P_VMALLOC (seg_size, 1, i4_t);
  554.   seg_ptr = (char *) export_segment (seg, seg_size, 1);
  555.   assert (seg_ptr && *seg_size);
  556.   
  557.   /* preparing of table SYSCHCONSTR filling : */
  558.   
  559.   P_VMALLOC (colval, 12, VADR);
  560.   colval[0] = V_Tbd;
  561.   colval[1] = V_chconid;
  562.   colval[2] = V_seg_size;
  563.   colval[3] = V_ncols;
  564.   
  565.   P_VMALLOC (colno, *ncols, i2_t);
  566.   for (i = 0, j = 4, V_cur_colno = V_colno; i < tbl_col_num; i++)
  567.     if (chconstr_col_use [i])
  568.       {
  569. colno[j-4] = i;
  570. colval[j++] = V_cur_colno;
  571. V_cur_colno += SZ_SHT;
  572.       }
  573.   
  574.   for (j = 4 + ch_col_use_num; j < 12; j++)
  575.     colval[j] = VNULL;
  576.   
  577.   CHECK_TYPE_ARR (CHCONSTR);
  578.   Pr_INSLIST (V_syschconstr, 12, V_type_arr_CHCONSTR,
  579.       VNULL, V_colval, VNULL, VNULL);
  580.   
  581.   /* preparing of table SYSCHCONSTRTWO filling */
  582.   make_str_parts (V_chconid, TRUE, seg_ptr, *seg_size);
  583.   
  584.   xfree (chconstr_col_use);
  585.   chconstr_col_use = NULL;
  586. }
  587. /* CrCheckConstr */
  588. /*---------------------------------------------------------------------*/
  589. void
  590. CrRefConstr (VADR V_Tbd, i2_t colno, TXTREF BegClmFrom, TXTREF BegClmTo)
  591. {
  592.   VADR V_tabid_to, V_ind_to, V_sysrc;
  593.   VADR *colval;
  594.   i2_t *num_to, *num_from;
  595.   VADR V_colval, V_num_to, V_num_from, V_cur_num;
  596.   i2_t *ncols;
  597.   VADR V_ncols;
  598.   UnId *sysrc;
  599.   i4_t i, j, *tabid_to, *ind_to;
  600.   TXTREF CurClm, tbl_to;
  601.   
  602.   P_VMALLOC (sysrc, 1, UnId);
  603.   sysrc->t=refconstrtabid;
  604.   
  605.   P_VMALLOC (ncols, 1, i2_t);
  606.   *ncols = colno;
  607.   
  608.   V_num_to = VMALLOC (colno, i2_t);
  609.   V_num_from = VMALLOC (colno, i2_t);
  610.   
  611.   tbl_to = COL_TBL (OBJ_DESC (BegClmTo));
  612.   if ((TBL_TABID (tbl_to)).untabid)
  613.     {
  614.       /* this table already exists => we have Tabid */
  615.       P_VMALLOC (tabid_to, 1, i4_t);
  616.       *tabid_to = (TBL_TABID (tbl_to)).untabid;
  617.     }
  618.   else /* table from the same schema => Tabid is not created yet */
  619.     V_tabid_to = TBL_VADR (tbl_to);
  620.   P_VMALLOC (ind_to, 1, i4_t);
  621.   *ind_to = 0;
  622.   
  623.   P_VMALLOC (colval, 20, VADR);
  624.   
  625.   colval[0] = V_Tbd;
  626.   colval[1] = V_tabid_to;
  627.   colval[2] = V_ind_to;
  628.   colval[3] = V_ncols;
  629.   
  630.   num_from = V_PTR (V_num_from, i2_t);
  631.   for (i = 4, CurClm = BegClmFrom, V_cur_num = V_num_from;
  632.        i < colno + 4; i++, CurClm = RIGHT_TRN (CurClm))
  633.     {
  634.       TASSERT (CODE_TRN (CurClm) == COLPTR, CurClm);
  635.       
  636.       num_from[i-4] = COL_NO (OBJ_DESC (CurClm));
  637.       colval[i] = V_cur_num;
  638.       V_cur_num += SZ_SHT;
  639.     }
  640.   
  641.   num_to = V_PTR (V_num_to, i2_t);
  642.   for (i = 12, CurClm = BegClmTo, V_cur_num = V_num_to;
  643.        i < colno + 12; i++, CurClm = RIGHT_TRN (CurClm))
  644.     {
  645.       TASSERT (CODE_TRN (CurClm) == COLPTR, CurClm);
  646.       
  647.       num_to[i-12] = COL_NO (OBJ_DESC (CurClm));
  648.       colval[i] = V_cur_num;
  649.       V_cur_num += SZ_SHT;
  650.     }
  651.   for (i = colno + 4, j = colno + 12; i < 12; i++, j++)
  652.     colval[i] = colval[j] = VNULL;
  653.   
  654.   CHECK_TYPE_ARR (REFCONSTR);
  655.   Pr_INSLIST (V_sysrc, 20, V_type_arr_REFCONSTR,
  656.       VNULL, V_colval, VNULL, VNULL);
  657. } /* CrRefConstr */
  658. /*---------------------------------------------------------------------*/
  659. void
  660. CrTab (VCBREF Tab)
  661. /* handling of table or view creation */
  662. {
  663.   i4_t i, *nncolnum, colnum = TBL_NCOLS (Tab);
  664.   VCBREF FirClm = TBL_COLS (Tab), Nd;
  665.   VCBREF CurClm, Constr, NextEl, PredEl, Obj, Obj_rh, DefNd;
  666.   char *ind_flag = GET_MEMC (char, colnum)
  667.     /* ind_flag[i] = flag of index existing for only this (i) column */
  668.     i4_t ind_cnt = 0;
  669.   UnId *systab,*syscol;
  670.   VADR V_systab, V_syscol, V_primindid=VNULL;
  671.   VADR V_tabname, V_owner, V_defval, resindid, V_Tbd;
  672.   VADR V_colval, V_tabtype, V_credate, V_cretime;
  673.   VADR V_ncols, V_nrows, V_colname, V_colno, V_nncolnum;
  674.   VADR V_coltype, V_coltype1, V_coltype2, V_defnull;
  675.   VADR *colval;
  676.   char *tabname, *owner, *defval;
  677.   char *tabtype, *def_val_ptr;
  678.   char *colname, *coltype, *defnull;
  679.   i2_t *ncols, *colno;
  680.   i4_t *nrows, *coltype1, *coltype2;
  681.   i4_t ow_leng;
  682.   i4_t prim_exist = 0;
  683.   Tabid tbd;
  684.   static i4_t nnul_arr_lng = 0;
  685.   static char *nnul_fl = NULL;
  686.   i4_t is_cre_tab = (CODE_TRN (Tab) == TABLE);
  687.   assert ((V_Tbd = TBL_VADR (Tab)));
  688.   CHECK_ARR_SIZE (nnul_fl, nnul_arr_lng, colnum, char);
  689.   bzero (nnul_fl, colnum);
  690.   
  691.   P_VMALLOC (systab, 1, UnId);
  692.   systab->t=systabtabid;
  693.   P_VMALLOC (syscol, 1, UnId);
  694.   syscol->t=syscoltabid;
  695.   
  696.   ow_leng = strlen (STRING (TBL_NAME (Tab)));
  697.   if (ow_leng > MAX_USER_NAME_LNG)
  698.     {
  699.       lperror("Table name '%s' is too long",STRING (TBL_NAME (Tab)));
  700.       errors--;
  701.       ow_leng = MAX_USER_NAME_LNG;
  702.     }
  703.   P_VMALLOC (tabname, ow_leng+1, char);
  704.   bcopy (STRING (TBL_NAME (Tab)), tabname, ow_leng);
  705.   tabname[ow_leng] = 0;
  706.   
  707.   ow_leng = strlen (STRING (TBL_FNAME (Tab)));
  708.   if (ow_leng > MAX_USER_NAME_LNG)
  709.     {
  710.       lperror("Authorization name '%s' is too long",
  711.               STRING (TBL_FNAME (Tab))); 
  712.       errors--;
  713.       ow_leng = MAX_USER_NAME_LNG;
  714.     }
  715.   P_VMALLOC (owner, ow_leng+1, char);
  716.   bcopy (STRING (TBL_FNAME (Tab)), owner, ow_leng);
  717.   owner[ow_leng] = 0;
  718.   P_VMALLOC (tabtype, 2, char);
  719.   tabtype[0] = (is_cre_tab) ? 'B' : 'V';
  720.   tabtype[1] = 0;
  721.   
  722.   V_credate = VMALLOC (9, char);
  723.   V_cretime = VMALLOC (9, char);
  724.   
  725.   P_VMALLOC (ncols, 1, i2_t);
  726.   *ncols = colnum;
  727.   
  728.   P_VMALLOC (nrows, 1, i4_t);
  729.   *nrows = 0;
  730.   
  731.   P_VMALLOC (nncolnum, 1, i4_t);
  732.   if (is_cre_tab) /* for CREATE TABLE */
  733.     {
  734.       /* finding the number of the beginning columns with NOT NULL predicate */
  735.       for (Constr = TBL_CONSTR (Tab); Constr; Constr = RIGHT_TRN (Constr))
  736.         if ((CODE_TRN (Constr) == CHECK) &&
  737.             ( (CODE_TRN (Nd = (DOWN_TRN (Constr))) == ISNOTNULL) ||
  738.               ( (CODE_TRN (DOWN_TRN (Constr)) == NOT) &&
  739.                 (CODE_TRN (Nd = DOWN_TRN (DOWN_TRN (Constr))) == ISNULL) ) )
  740.             )
  741.           {
  742.             TASSERT (CODE_TRN (Nd = DOWN_TRN (Nd)) == COLPTR, Nd);
  743.             nnul_fl[COL_NO (OBJ_DESC (Nd))] = TRUE;
  744.           }
  745.       for (*nncolnum = 0; *nncolnum < colnum; (*nncolnum)++)
  746.         if (!nnul_fl[*nncolnum])
  747.           break;
  748.   
  749.       /* removing NOT NULL predicates for first *nncolnum columns */
  750.       for (Constr = TBL_CONSTR (Tab), PredEl = TNULL; Constr; Constr = NextEl)
  751.         {
  752.           NextEl = RIGHT_TRN (Constr);
  753.           if ((CODE_TRN (Constr) == CHECK) &&
  754.               ( (CODE_TRN (Nd = (DOWN_TRN (Constr))) == ISNOTNULL) ||
  755.                 ( (CODE_TRN (DOWN_TRN (Constr)) == NOT) &&
  756.                   (CODE_TRN (Nd = DOWN_TRN (DOWN_TRN (Constr))) == ISNULL) ) ) &&
  757.               (COL_NO (OBJ_DESC (Nd = DOWN_TRN (Nd))) < *nncolnum))
  758.             {
  759.               if (PredEl)
  760.                 RIGHT_TRN (PredEl) = NextEl;
  761.               else
  762.                 TBL_CONSTR (Tab) = NextEl;
  763.               RIGHT_TRN (Constr) = TNULL;
  764.               free_tree (Constr);
  765.             }
  766.           else
  767.             PredEl = Constr;
  768.         }
  769.   
  770.       Pr_CRETAB (V_tabname, V_owner, 1, colnum, *nncolnum, FirClm, V_Tbd);
  771.   
  772.       ind_cnt=0;
  773.       /* reorder indexes */
  774.       {
  775.         TXTREF prim,uniq,ind;
  776.         TXTREF priml,uniql,indl;
  777.         prim = uniq = ind = TNULL;
  778.         priml = uniql = indl = TNULL;
  779.         for (Constr = IND_INFO (Tab); Constr; Constr = RIGHT_TRN (Constr))
  780.           switch (CODE_TRN (Constr))
  781.             {
  782.             case PRIMARY : 
  783.               if (prim) priml = RIGHT_TRN(priml) = Constr ;
  784.               else      priml = prim = Constr ;
  785.               break;
  786.             case UNIQUE  :
  787.               if (uniq) uniql = RIGHT_TRN(uniql) = Constr ;
  788.               else      uniql = uniq = Constr ;
  789.               break;
  790.             case INDEX   :
  791.               if (ind)  indl = RIGHT_TRN(indl) = Constr ;
  792.               else      indl = ind = Constr ;
  793.               break;
  794.             default :
  795.               debug_trn(Constr);
  796.               yyfatal("Unexpected index code");
  797.             }
  798.         if (indl)   RIGHT_TRN(indl)  = TNULL;
  799.         if (uniql)  RIGHT_TRN(uniql) = ind;
  800.         else uniq = ind;
  801.         if (priml)  RIGHT_TRN(priml) = uniq;
  802.         else prim = uniq; 
  803.         IND_INFO (Tab) = prim;
  804.       }
  805.       /* indexes creation */
  806.       for (Constr = IND_INFO (Tab); Constr; Constr = RIGHT_TRN (Constr))
  807.         {
  808.           char *ind_t = NULL;
  809.           switch (CODE_TRN (Constr))
  810.             {
  811.             case PRIMARY : ind_t = "P"; break;
  812.             case UNIQUE  : ind_t = "U"; break;
  813.             case INDEX   :              continue;
  814.               
  815.             default :
  816.               debug_trn(Constr);
  817.               yyfatal("Unexpected index code");
  818.             } /* switch: CODE_TRN (Constr) */
  819.           assert( ind_t ); /* ununique index is not carefully tested yet */
  820.           Obj = DOWN_TRN (Constr);
  821.           if ((CODE_TRN (Obj) == COLPTR) && (!RIGHT_TRN (Obj)) &&
  822.               ( ind_flag[COL_NO (OBJ_DESC (Obj))]++ ))
  823.             continue; /* such index already exist */
  824.           resindid = CrInd (++ind_cnt, ind_t, V_Tbd, V_tabname,
  825.                             V_owner, Obj, ARITY_TRN(Constr));
  826.           if (CODE_TRN (Constr) == PRIMARY)
  827.             {
  828.               V_primindid = resindid;
  829.               prim_exist = 1;
  830.             }
  831.         }
  832.       /* ind_cnt = count of indexes for table */
  833.   
  834.       for (Constr = TBL_CONSTR (Tab); Constr; Constr = RIGHT_TRN (Constr))
  835.         switch (CODE_TRN (Constr))
  836.           {
  837.           case FOREIGN :
  838.             /* (Foreign {
  839.              *    (LocalList { (ColPtr ..) ...})
  840.              *    (OPtr { 
  841.              *      (Uniqie|Primary { (ColPtr ..) ...})
  842.              *    })
  843.              * }) 
  844.              */
  845.             Obj = DOWN_TRN (Constr);
  846.             TASSERT (Obj && CODE_TRN (Obj) == LOCALLIST, Constr);
  847.             Obj_rh = RIGHT_TRN (Obj);
  848.             TASSERT (Obj_rh && CODE_TRN (Obj_rh) == OPTR, Constr);
  849.             CrRefConstr (V_Tbd, ARITY_TRN (Obj),
  850.                          DOWN_TRN (Obj), DOWN_TRN(OBJ_DESC(Obj_rh)));
  851.             break;
  852.   
  853.           case CHECK :
  854.             CrCheckConstr (V_Tbd, TBL_NCOLS(Tab), DOWN_TRN (Constr));
  855.             break;
  856.   
  857.           default :
  858.             debug_trn(Constr);
  859.             yyfatal("Unexpected constraint code");
  860.           } /* switch: CODE_TRN (Constr) */
  861.     } /* if (is_cre_tab) */
  862.   else /* for CREATE VIEW */
  863.     {
  864.       i4_t seg_size;
  865.       TXTREF sav_segm, tr_segm, tree, lvcb = LOCAL_VCB_ROOT,
  866.         query = TNULL, where;
  867.       VADR   code_segm;
  868.       char *seg_ptr;
  869.       LOCAL_VCB_ROOT = TNULL;
  870.       TASSERT (CODE_TRN (Tab) == VIEW && (query = VIEW_QUERY (Tab)), Tab);
  871.       
  872.       /*        Where    Selection    From    Query   */
  873.       where = RIGHT_TRN (RIGHT_TRN (DOWN_TRN (query)));
  874.       if (where)
  875.         TASSERT (CODE_TRN (where) == WHERE, query);
  876.       if (TstF_TRN (Tab, CHECK_OPT_F) && where)
  877.         CrCheckConstr (V_Tbd,
  878.                        /*          Table      Scan     TblPtr    From     Query    */
  879.                        TBL_NCOLS (COR_TBL (TABL_DESC (DOWN_TRN (DOWN_TRN (query))))),
  880.                        DOWN_TRN (where));
  881.         
  882.       code_segm = GET_CURRENT_SEGMENT_ID;
  883.       sav_segm = get_current_tree_segment ();
  884.       tr_segm  = create_tree_segment ();
  885.       tree = copy_tree (query);
  886.       register_export_address (tree, "VIEW_TREE");
  887.          
  888.       seg_ptr = extract_tree_segment (tr_segm, &seg_size);
  889.       assert (seg_ptr && seg_size);
  890.       set_current_tree_segment (sav_segm);
  891.       switch_to_segment(code_segm);
  892.       LOCAL_VCB_ROOT = lvcb;
  893.       /* preparing of table SYSVIEWS filling */
  894.       make_str_parts (V_Tbd, FALSE, seg_ptr, seg_size);
  895.     }
  896.   
  897.   for (i=0; i < colnum; i++)
  898.     ind_flag[i]=0;
  899.   /* adding record about table into SYSTABLES */
  900.   P_VMALLOC (colval, 13, VADR);
  901.   
  902.   colval[0] = V_tabname;
  903.   colval[1] = V_owner;
  904.   colval[2] = V_Tbd;
  905.   colval[3] = (is_cre_tab) ?
  906.     V_Tbd+((char *)(&tbd.segid) - (char *)(&tbd)) : VNULL;
  907.   colval[4] = (is_cre_tab) ?
  908.     V_Tbd+((char *)(&tbd.tabd) - (char *)(&tbd)) : VNULL;
  909.   colval[5] = VNULL;
  910.   colval[6] = (prim_exist) ? V_primindid : VNULL;
  911.   colval[7] = V_tabtype;
  912.   colval[8] = V_credate;
  913.   colval[9] = V_cretime;
  914.   colval[10] = V_ncols;
  915.   colval[11] = V_nrows;
  916.   colval[12] = V_nncolnum;
  917.     
  918.   CHECK_TYPE_ARR (TABLES);
  919.   Pr_INSLIST (V_systab, 13, V_type_arr_TABLES,
  920.       VNULL, V_colval, V_credate, V_cretime);
  921.   /* insertion information about table  *
  922.    * columns into the table  SYSCOLUMNS */
  923.   CurClm = FirClm;
  924.   for (i = 0; i < colnum; i++, CurClm = COL_NEXT (CurClm))
  925.     {
  926.       if (strlen (STRING (COL_NAME (CurClm))) >= MAX_USER_NAME_LNG)
  927. yyfatal ("Length of column name is too big");
  928.       P_VMALLOC (colname, MAX_USER_NAME_LNG, char);
  929.       strcpy (colname, STRING (COL_NAME (CurClm)));
  930.       
  931.       P_VMALLOC (colno, 1, i2_t);
  932.       *colno = COL_NO (CurClm);
  933.       
  934.       P_VMALLOC (coltype1, 1, i4_t);
  935.       *coltype1 = (COL_TYPE (CurClm)).len;
  936.       
  937.       P_VMALLOC (coltype2, 1, i4_t);
  938.       *coltype2 = (COL_TYPE (CurClm)).prec;
  939.       
  940.       P_VMALLOC (coltype, 2, char);
  941.       coltype[0]  = (COL_TYPE (CurClm)).code;
  942.       coltype[1]  = 0;
  943.       
  944.       P_VMALLOC (defnull, 2, char);
  945.       defnull[0] = (nnul_fl[COL_NO (CurClm)]) ? '1' : '0';
  946.       defnull[1] = 0;
  947.       
  948.       defval=NULL; V_defval=VNULL;
  949.       if ((DefNd = COL_DEFAULT (CurClm)))
  950. {
  951.   if (CODE_TRN (DefNd) == CONST)
  952.     {
  953.       def_val_ptr = STRING (CNST_NAME (DefNd));
  954.       P_VMALLOC (defval, strlen(def_val_ptr)+1, char);
  955.       strcpy (defval, def_val_ptr);
  956.     }
  957.   else
  958.     if (CODE_TRN (DefNd) == USERNAME)
  959.       *V_PTR (V_coltype2, i4_t) = USERNAME;
  960. }
  961.       
  962.       P_VMALLOC (colval, 11, VADR);
  963.       
  964.       colval[0] = V_colname;
  965.       colval[1] = V_Tbd;
  966.       colval[2] = V_colno;
  967.       colval[3] = V_coltype;
  968.       colval[4] = V_coltype1;
  969.       colval[5] = V_coltype2;
  970.       colval[6] = (V_defval) ? V_defval : VNULL;
  971.       colval[7] = V_defnull;
  972.       colval[8] = VNULL;
  973.       colval[9] = VNULL;
  974.       colval[10] = VNULL;
  975.       CHECK_TYPE_ARR (COLUMNS);
  976.       Pr_INSLIST (V_syscol, 11, V_type_arr_COLUMNS,
  977.   VNULL, V_colval, VNULL, VNULL);
  978.     } /* for */
  979. } /* CrTab */
  980. void
  981. GrantHandle (TXTREF GrNode)
  982. {
  983.   TXTREF Tbl_Ptr, Tbl, Priv, PrivCur, Grntee, GrCur;
  984.   TXTREF FirUpdCol, FirRefCol;
  985.   TXTREF UpdCur, RefCur;
  986.   UnId *stabauth,*scolauth;
  987.   VADR V_stabauth, V_scolauth;
  988.   VADR V_untabid, V_chckauth = VNULL, V_tabauth;
  989.   VADR V_colval, V_grantor, V_owner, V_colno; 
  990.   VADR V_updcols = VNULL, V_refcols = VNULL, V_ur, V_grntee_nm;
  991.   VADR *colval, u_r_ur[3];
  992.   i2_t *colno;
  993.   i4_t *untabid, updcnt = 0, refcnt = 0, col_max = -1, grntee_len;
  994.   /* col_max - the biggest column's number in lists of UPDATE & REFERENCES */
  995.   i4_t *updcols = NULL, *refcols = NULL, gr_len = strlen (STRING (GL_AUTHOR));
  996.   i4_t i;
  997.   char *owner;
  998.   char auth[9], *chckauth, *tabauth, *grantor, *grntee_nm, n_own_fl;
  999.   char *col_fl = NULL, *ur; /* ur will be used for 2 chars : 'U' and 'R' *
  1000.                              * for columns authorisation coding          */
  1001.   auth[0]   = 0;
  1002.   chckauth  = NULL;
  1003.   FirUpdCol = TNULL;
  1004.   FirRefCol = TNULL;
  1005.   TASSERT ((Tbl_Ptr = DOWN_TRN (GrNode)) && 
  1006.    (CODE_TRN (Tbl_Ptr) ==TBLPTR), GrNode);
  1007.   TASSERT ((Tbl = TABL_DESC (Tbl_Ptr)) && 
  1008.    ((CODE_TRN (Tbl) == TABLE) || (CODE_TRN (Tbl) == VIEW)), GrNode);
  1009.   TASSERT ((Priv = RIGHT_TRN (Tbl_Ptr)) && 
  1010.    (CODE_TRN (Priv) == PRIVILEGIES), GrNode);
  1011.   TASSERT ((Grntee = RIGHT_TRN (Priv)) && 
  1012.    (CODE_TRN (Grntee) == GRANTEES), GrNode);
  1013.   
  1014.   /* grantor != table owner ? */
  1015.   P_VMALLOC (owner, strlen (STRING (TBL_FNAME (Tbl))) + 1, char);
  1016.   strcpy (owner, STRING(TBL_FNAME (Tbl)));
  1017.   n_own_fl = strcmp (STRING (GL_AUTHOR), owner);
  1018.   
  1019.   P_VMALLOC (stabauth, 1, UnId);
  1020.   stabauth->t=tabauthtabid;
  1021.   P_VMALLOC (scolauth, 1, UnId);
  1022.   scolauth->t=colauthtabid;
  1023.     
  1024.   P_VMALLOC (ur, 7, char);
  1025.   /* putting to ur : URUR */
  1026.   ur[1] = ur[3] = ur[6] = 0;
  1027.   ur[0] = ur[4] = 'U';
  1028.   ur[2] = ur[5] = 'R';
  1029.   u_r_ur[0] = V_ur;     /* pointer to "U"  */
  1030.   u_r_ur[1] = V_ur + 2; /* pointer to "R"  */
  1031.   u_r_ur[2] = V_ur + 4; /* pointer to "UR" */
  1032.   
  1033.   P_VMALLOC (grantor, gr_len + 1, char);
  1034.   strcpy (grantor, STRING (GL_AUTHOR));
  1035.   if (gr_len > MAX_USER_NAME_LNG)
  1036.     grantor[MAX_USER_NAME_LNG] = 0;
  1037.   if (n_own_fl)
  1038.     P_VMALLOC (chckauth, 9, char);
  1039.   
  1040.   {
  1041.     i4_t un_id;
  1042.     if ( CODE_TRN(Tbl)==TABLE )
  1043.       un_id = (TBL_TABID (Tbl)).untabid;
  1044.     else
  1045.       un_id = VIEW_UNID(Tbl);
  1046.     
  1047.     if (un_id)
  1048.       {
  1049.         /* this table already exists => we have Tabid */
  1050.         P_VMALLOC (untabid, 1, i4_t);
  1051.         *untabid = un_id;
  1052.       }
  1053.     else /* table from the same schema => Tabid is not created yet */
  1054.       V_untabid = TBL_VADR (Tbl);
  1055.   }
  1056.   
  1057.   for (PrivCur = DOWN_TRN (Priv); PrivCur; PrivCur = RIGHT_TRN (PrivCur))
  1058.     switch (CODE_TRN (PrivCur))
  1059.       {
  1060.       case SELECT :
  1061. sprintf (auth, "%sS", auth);
  1062. break;
  1063.       case INSERT :
  1064. sprintf (auth, "%sI", auth);
  1065. break;
  1066.       case DELETE :
  1067. sprintf (auth, "%sD", auth);
  1068. break;
  1069.       case UPDATE :
  1070. updcnt = ARITY_TRN (PrivCur);
  1071. if (updcnt)
  1072.   FirUpdCol = DOWN_TRN (PrivCur);
  1073. else
  1074.   sprintf (auth, "%sU", auth);
  1075. break;
  1076.       case REFERENCE :
  1077. refcnt = ARITY_TRN (PrivCur);
  1078. if (refcnt)
  1079.   FirRefCol = DOWN_TRN (PrivCur);
  1080. else
  1081.   sprintf (auth, "%sR", auth);
  1082. break;
  1083.   
  1084.       default :
  1085. yyfatal ("unrecognized privilege code");
  1086.       }
  1087.   
  1088.   if (n_own_fl)
  1089.     sprintf (chckauth, "%sG", auth);
  1090.   P_VMALLOC (tabauth, 9, char);
  1091.   tabauth[0] = (TstF_TRN (GrNode, GRANT_OPT_F)) ? 'G' : 0;
  1092.   tabauth[1] = 0;
  1093.   sprintf (tabauth, "%s%s", tabauth, auth);
  1094.   
  1095.   if (updcnt) /* there is a list of columns for UPDATE */
  1096.     {
  1097.       if (n_own_fl)
  1098. strcat(chckauth, "U");      
  1099.       sprintf (tabauth,  "%su", tabauth);      
  1100.       P_VMALLOC (updcols, updcnt, i4_t);
  1101.       for (i = 0, UpdCur = FirUpdCol; UpdCur; 
  1102.       UpdCur = RIGHT_TRN (UpdCur), i++)
  1103. {
  1104.   updcols[i] = COL_NO (OBJ_DESC (UpdCur));
  1105.   if (col_max < updcols[i])
  1106.     col_max = updcols[i];
  1107. }
  1108.     }
  1109.   
  1110.   if (refcnt) /* there is a list of columns for REFERENCES */
  1111.     {
  1112.       if (n_own_fl)
  1113. strcat (chckauth, "R");
  1114.       tabauth = V_PTR (V_tabauth, char);
  1115.       sprintf (tabauth,  "%sr", tabauth);      
  1116.       P_VMALLOC (refcols, refcnt, i4_t);
  1117.       for (i = 0, RefCur = FirRefCol; RefCur; 
  1118.       RefCur = RIGHT_TRN (RefCur), i++)
  1119. {
  1120.   refcols[i] = COL_NO (OBJ_DESC (RefCur));
  1121.   if (col_max < refcols[i])
  1122.     col_max = refcols[i];
  1123. }
  1124.     }
  1125.       
  1126.   /* Strings of privelegies' codes for rights checking (chckauth) *
  1127.    * and adding the row to SYSTABAUTH (tabauth) are complited.    */ 
  1128.   Pr_PRIVLG (V_untabid, V_owner, V_grantor, V_chckauth,
  1129.      updcnt, V_updcols, refcnt, V_refcols);
  1130.   
  1131.   if (col_max+1)
  1132.     {
  1133.       col_fl = (char *) xmalloc (col_max+1);
  1134.       updcols = V_PTR (V_updcols, i4_t);
  1135.       for (i = 0; i < updcnt; i++)
  1136. col_fl[updcols[i]] = 1;
  1137.       refcols = V_PTR (V_refcols, i4_t);
  1138.       for (i = 0; i < refcnt; i++)
  1139. col_fl[refcols[i]] |= 2;
  1140.     }
  1141.   
  1142.   for (GrCur = DOWN_TRN (Grntee); GrCur; GrCur = RIGHT_TRN (GrCur))
  1143.     {
  1144.       TASSERT (CODE_TRN (GrCur) == USERNAME, Grntee);
  1145.       
  1146.       grntee_len = strlen (STRING(USR_NAME (GrCur)));
  1147.       
  1148.       P_VMALLOC (grntee_nm, grntee_len+1, char);
  1149.       strcpy (grntee_nm, STRING(USR_NAME (GrCur)));
  1150.       if (grntee_len > MAX_USER_NAME_LNG)
  1151. grntee_nm[MAX_USER_NAME_LNG] = 0;
  1152.       
  1153.       P_VMALLOC (colval, 4, VADR);
  1154.       /* data preparation for adding row to SYSTABAUTH */ 
  1155.       colval[0] = V_untabid;
  1156.       colval[1] = V_grntee_nm;
  1157.       colval[2] = V_grantor;
  1158.       colval[3] = V_tabauth;
  1159.   
  1160.       CHECK_TYPE_ARR (TABAUTH);
  1161.       Pr_INSLIST (V_stabauth, 4, V_type_arr_TABAUTH,
  1162.   VNULL, V_colval, VNULL, VNULL);
  1163.   
  1164.       /* data preparation for adding rows to SYSCOLAUTH */ 
  1165.       for (i = 0; i <= col_max; i++)
  1166. {
  1167.   if (!col_fl[i]) /* this column isn't included to any       *
  1168.    * columns' list (for UPDATE & REFERENCES) */
  1169.     continue;
  1170.   P_VMALLOC (colno, 1, i2_t);
  1171.   *colno = i;
  1172.   
  1173.   P_VMALLOC (colval, 5, VADR);
  1174.   colval[0] = V_untabid;
  1175.   colval[1] = V_colno;
  1176.   colval[2] = V_grntee_nm;
  1177.   colval[3] = V_grantor;
  1178.   colval[4] = u_r_ur[col_fl[i]-1];
  1179.   
  1180.   CHECK_TYPE_ARR (COLAUTH);
  1181.   Pr_INSLIST (V_scolauth, 5, V_type_arr_COLAUTH,
  1182.       VNULL, V_colval, VNULL, VNULL);
  1183. }
  1184.     } /* for */
  1185. } /* GrantHandle */
  1186. void
  1187. ins_val ( Tabid *tid, i4_t clmcnt, TXTREF FirVal, VCBREF FirClm)
  1188.      /* operator INSERT VALUE handling :          *
  1189.       * INTO table tid with clmcnt; FirVal - list *
  1190.       * of trees of expressions to insert         */
  1191. {
  1192.   VADR Tbid, InsList;
  1193.   i4_t i;
  1194.   TXTREF CurVal;
  1195.   MASK Dep;
  1196.   
  1197.   InsList = VMALLOC (clmcnt, PSECT_PTR);
  1198.   Tbid = VMALLOC (1, UnId);
  1199.   V_PTR (Tbid, UnId)->t=*tid;
  1200.   
  1201.   for (CurVal = FirVal, i = 0; CurVal; CurVal = RIGHT_TRN (CurVal), i++)
  1202.     {
  1203.       /* column & insert constant descriptions must be present *
  1204.        * for all columns of table (where to insert)            */
  1205.       (V_PTR (InsList, PSECT_PTR)[i]).off =
  1206. Tr_RecLoad (CurVal, &Dep, FALSE, NULL);  
  1207.     }
  1208.   
  1209.   assert (real_insert_scan);
  1210.   Pr_INSROW (Tbid, clmcnt, InsList, FirClm,
  1211.      real_insert_scan, 0, VNULL, VNULL);
  1212. } /* ins_val */
  1213. void
  1214. SQ_Handle (TXTREF CmdNode, TXTREF SelectTree, i4_t arity)
  1215. {
  1216.   VADR old_val_hole = VAL_HOLE (CmdNode);
  1217.   
  1218.   VAL_HOLE (CmdNode) = 1;
  1219.   switch (CODE_TRN (CmdNode))
  1220.     {
  1221.     case EXISTS :
  1222.       ARITY_TRN (CmdNode) = 0;
  1223.       DOWN_TRN (CmdNode) = TNULL;
  1224.       break;
  1225.       
  1226.     case SUBQUERY : /* comparison predicate */
  1227.       ARITY_TRN (CmdNode) = arity;
  1228.       DOWN_TRN (CmdNode) = SelectTree;
  1229.       break;
  1230.       
  1231.     default : /* ALL | SOME */
  1232.       /* changing right pointer of LeftOperand of predicate */
  1233.       RIGHT_TRN (DOWN_TRN (DOWN_TRN (CmdNode))) = SelectTree;
  1234.       break;
  1235.     }
  1236.   Pr_COND_EXIT (CmdNode);
  1237.   VAL_HOLE (CmdNode) = old_val_hole;
  1238. } /* SQ_Handle */
  1239. void
  1240. ScanTable (TXTREF CurTab, TXTREF UntilPtr, i4_t AndNum,
  1241.    VADR *AndTree, MASK *AndMasks, MASK MskDone, 
  1242.    TXTREF SelectNode, VADR BO_Tid, VCBREF ResScan, TXTREF CmdNode)
  1243. /* Table scanning forming .                                     *
  1244.  * CurTab - pointer to node TBLPTR for current table            *
  1245.  * UntilPtr - ponter to head of Until tree                      *
  1246.  * AndNum - number of elements in array AndTree                 *
  1247.  * AndTree - pointer to array of  subtrees - arguments of AND   *
  1248.  * ( some element = NULL when it is already used in UNTIL tree) *
  1249.  * AndMasks - array of masks for AND elements                   *
  1250.  * MskDone - masks of all tables handled before current table   *
  1251.  * BO_Tid - address of Tabid for temp. table, if result of this *
  1252.  *      query must be placed to this table (else == NULL)       *
  1253.  * If BO_Tid==NULL && CmdNode==(NULL || SELECT) => RetPar;      *
  1254.  *      else - CmdNode points to node UPDATE or  DELETE         *
  1255.  * ResScan - pointer to SCAN of result temporary table          *
  1256.  * (NULL -if not use)                                           */
  1257. {
  1258.   TXTREF SelItem;
  1259.   i4_t nr = 0, nm = 0, TreeN, ClmNum;
  1260.   VCBREF Tab, CurClm, ClmTo, ScanNode;
  1261.   i4_t *Rlist, *addrs;
  1262.   i4_t i, nl = 0, ic = 0, UntCnt = 0;
  1263.   VADR Ex, ExOp, TreeTab = VNULL;
  1264.   VADR OpScPoint = VNULL, SHPoint, FndrPoint= VNULL, UntPoint= VNULL;
  1265.   VADR WhereNode = VNULL, Tbid, Scan = VNULL, FirEl = VNULL, PredEl = VNULL;
  1266.   VADR V_Rlist = VNULL, V_addrs = VNULL, V_mlist = VNULL;
  1267.   MASK Msk, AllMsk, Depend, AllDep = 0;
  1268.   char sc_mode = RSC; /* READ */
  1269.   char del_cur_fl = 0;  /* = 1 if there is operator DELETE CURRENT OF CURSOR */
  1270.   char sel_stmt_fl = 0; /* = 1 if it's operator SELECT                   */
  1271.   
  1272.   ScanNode = TABL_DESC (CurTab);
  1273.   TASSERT(ScanNode!=TNULL,CurTab);
  1274.   Tab = COR_TBL (ScanNode);
  1275.   TASSERT(Tab!=TNULL,CurTab);
  1276.   ClmNum = TBL_NCOLS (Tab);
  1277.   
  1278.   if (TstF_TRN (CurTab, DEL_CUR_F))
  1279.     {
  1280.       sc_mode = DSC; /* DELETE CURRENT */
  1281.       del_cur_fl++;
  1282.     }
  1283.   
  1284.   if (CmdNode)
  1285.     switch (CODE_TRN (CmdNode))
  1286.       {
  1287.       case SELECT:
  1288. sel_stmt_fl++;
  1289. break;
  1290.   
  1291.       case UPDATE:
  1292. if (UPD_CURS (CmdNode))
  1293.           {
  1294.             char *cursor_name = STRING (CUR_NAME (UPD_CURS (CmdNode)));
  1295.             Scan = external_reference (cursor_name);
  1296.             UPD_CURS (CmdNode) = TNULL;
  1297.           }
  1298. break;
  1299.       case DELETE:
  1300. sc_mode = DSC;
  1301. break;
  1302.       default:
  1303. break;
  1304.       }
  1305.   
  1306.   Tbid = ScanHandle (ScanNode, &Scan, &Msk, NULL, NULL);
  1307.   
  1308.   /* if it's operator UPDATE CURRENT OF CURSOR =>          *
  1309.    *         Tbid = VNULL, Scan != VNULL;                  *
  1310.    * if there is not scanning table => Tbid = Scan = VNULL */
  1311.   
  1312.   if (del_cur_fl)
  1313.     /* DELETE CURRENT */
  1314.     {
  1315.       assert (!DelCurConstr);
  1316.       DelCurConstr = Pr_Constraints (ScanNode, Scan, DELETE, 0, NULL);
  1317.     }
  1318.   
  1319.   AllMsk = BitOR(MskDone, Msk); /* AllMsk - masks for current table & *
  1320.          * for all tables handled before      */
  1321.   
  1322.   if (Scan)
  1323.     {
  1324.       CurClm = COR_COLUMNS (ScanNode);
  1325.       while (CurClm)
  1326. {
  1327.   nr++;
  1328.   CurClm = COL_NEXT (CurClm);
  1329. }
  1330.       V_Rlist = VMALLOC (nr, i4_t);
  1331.       V_addrs = VMALLOC (nr, i4_t);
  1332.       Rlist = V_PTR (V_Rlist, i4_t);
  1333.       addrs = V_PTR (V_addrs, i4_t);
  1334.       
  1335.       CurClm = COR_COLUMNS (ScanNode);
  1336.       for (i = 0; i < nr; i++)
  1337. {
  1338.   Rlist[i] = COL_NO (CurClm);
  1339.   addrs[i] = COL_ADR (CurClm);
  1340.   CurClm = COL_NEXT (CurClm);
  1341. }
  1342.       nl = 0;
  1343.       ic = 0;
  1344.       if (COR_TAB_SP (ScanNode))
  1345. {
  1346.   VADR *Tab_SP = V_PTR (COR_TAB_SP (ScanNode), VADR);
  1347.   
  1348.   for (i = 0; i < ClmNum; i++)
  1349.     if (Tab_SP[i])
  1350.       nl = i;
  1351.   nl++;
  1352. }
  1353.       if (COR_IND_SP (ScanNode))
  1354. {
  1355.   VADR *Ind_SP = V_PTR (COR_IND_SP (ScanNode), VADR);
  1356.   
  1357.   for (i = 0; i < IND_CLM_CNT (ScanNode); i++)
  1358.     if (Ind_SP[i])
  1359.       ic = i;
  1360.   ic++;
  1361. }
  1362.       
  1363.       if (Tbid)
  1364. {
  1365.   assert (nr);
  1366.   STEP_CMD (OpScPoint, OPSCAN);
  1367.   STEP_CMD (FndrPoint, FINDROW);
  1368. }
  1369.       else /* operator UPDATE CURRENT OF CURSOR */
  1370. if (nr)
  1371.   Pr_READROW (Scan, nr, V_addrs, V_Rlist);
  1372.     }
  1373.   STEP_CMD (SHPoint, SetHandle);
  1374.   SET (sh, SHPoint, Msk);
  1375.   
  1376.   /* UNTIL tree forming for current table : */
  1377.   for (i = 0; i < AndNum; i++)
  1378.     if (AndTree[i] /* element from AndTree (number i) was not used */ &&
  1379. CAN_BE_USED (AndMasks[i], AllMsk) /* this element can be used now */)
  1380.       {
  1381. if (FirEl)
  1382.   V_PTR (PredEl, TRNode)->Rh.off = AndTree[i];
  1383. else
  1384.   FirEl = AndTree[i];
  1385. PredEl = AndTree[i];
  1386. AndTree[i] = VNULL;
  1387. AllDep = BitOR (AndMasks[i], AllDep);
  1388. /* UntCnt - number elements from AND for current position */
  1389. UntCnt++; 
  1390.       }
  1391.   if (PredEl)
  1392.     V_PTR (PredEl, TRNode)->Rh.off = VNULL;
  1393.    
  1394.   if (UntCnt)
  1395.     {
  1396.       if (UntCnt == 1)
  1397. WhereNode = FirEl;
  1398.       else /* there are some (more than 1) AND arguments */
  1399. {
  1400.   TRNode *and_trn;
  1401.   
  1402.   WhereNode = Tr_RecLoad(UntilPtr, &Depend, FALSE, NULL);
  1403.   and_trn = V_PTR (WhereNode, TRNode);
  1404.   and_trn -> Arity = UntCnt;
  1405.   and_trn -> Dn.off = FirEl;
  1406.   and_trn -> Depend = AllDep;
  1407. }
  1408.       SET (tr, WhereNode, AllDep);
  1409.       if (FndrPoint)
  1410. Pr_UNTIL (WhereNode, WHAT_IS_BEG_CMD (FndrPoint), VNULL);
  1411.       else
  1412. STEP_CMD (UntPoint, until);
  1413.     }
  1414.   
  1415.   if (RIGHT_TRN (CurTab))
  1416.     ScanTable (RIGHT_TRN (CurTab), UntilPtr, AndNum, AndTree,
  1417.        AndMasks, AllMsk, SelectNode, BO_Tid, ResScan, CmdNode);
  1418.   else
  1419.     {
  1420.       /* here is a body of all circles : codes for *
  1421.        * current query row handling                */
  1422.       if (!CmdNode || sel_stmt_fl || !Is_SQPredicate_Code (CODE_TRN (CmdNode)))
  1423. TreeTab = SelArr (SelectNode, &TreeN);
  1424.       if (BO_Tid)
  1425. {
  1426.   if (CmdNode)
  1427.     /* UPDATE operation was replaced by using of temporary table */
  1428.     prepare_UPD (CmdNode, &nm, &V_mlist);
  1429.   Pr_INSROW (BO_Tid, TreeN, TreeTab, TBL_COLS (COR_TBL (ResScan)) ?
  1430.      TBL_COLS (COR_TBL (ResScan)) : COR_COLUMNS (ResScan),
  1431.      real_insert_scan, nm, V_mlist, Scan);
  1432.   /* columns descriptors ( for query result) are changing: */
  1433.   SelItem = DOWN_TRN (SelectNode); /* current element of SELECT */
  1434.   ClmTo = COR_COLUMNS (ResScan);   /* current column descriptor */
  1435.   for (i = 0; ClmTo && (i < TreeN); i++)
  1436.     {
  1437.       if ( (CODE_TRN (SelItem) == COLPTR) &&
  1438.    (COL_ADR (OBJ_DESC (SelItem))) )
  1439. COL_ADR (ClmTo) = COL_ADR (OBJ_DESC (SelItem));
  1440.       else
  1441. COL_ADR (ClmTo) = prepare_HOLE (COL_TYPE (ClmTo));
  1442.       ClmTo = COL_NEXT (ClmTo);
  1443.       SelItem = RIGHT_TRN (SelItem);
  1444.     } /* for */
  1445. }
  1446.       else
  1447. if (!CmdNode || sel_stmt_fl)
  1448.   Pr_RetPar (TreeTab, TreeN, !sel_stmt_fl);
  1449.       
  1450.       if (CmdNode && !sel_stmt_fl) 
  1451. if (Is_SQPredicate_Code (CODE_TRN (CmdNode)))
  1452.   SQ_Handle (CmdNode, DOWN_TRN (SelectNode), ARITY_TRN (SelectNode));
  1453. else
  1454.   switch (CODE_TRN (CmdNode))
  1455.     {
  1456.     case DELETE :
  1457.       Pr_DELETE (Scan, (real_insert_scan) ? VNULL : ScanNode);
  1458.       break;
  1459.       
  1460.     case UPDATE :
  1461.       sc_mode = (sc_mode == DSC) ? WSC : MSC; /* MODIFICATION */
  1462.       prepare_UPD (CmdNode, &nm, &V_mlist);
  1463.       Pr_UPDATE (Scan, nm, TreeTab, ScanNode, V_mlist);
  1464.       break;
  1465.       
  1466.     default :
  1467.       TASSERT (0, CmdNode);
  1468.     }
  1469.     }
  1470.   
  1471.   if (Tbid) /* There is table scanning */
  1472.     {
  1473.       Pr_GoTo (WHAT_IS_BEG_CMD (FndrPoint), VNULL);
  1474.       Ex = CurPg;
  1475.       Pr_CLOSE (Scan);
  1476.       ExOp = CurPg;
  1477.       
  1478.       if (CODE_TRN (COR_TBL (ScanNode)) == TMPTABLE)
  1479. Pr_DROPTTAB (Tbid);
  1480.   
  1481.       Pr_SCAN (Tbid, Scan, COR_IND_SP (ScanNode) ? IND_VW : SEC_VW,
  1482.        sc_mode , nr, V_Rlist, nl, COR_TAB_SP (ScanNode),
  1483.        ic, COR_IND_SP (ScanNode), nm, V_mlist, ExOp, OpScPoint);
  1484.       Pr_FINDROW (Scan, nr, V_addrs, Ex, FndrPoint);
  1485.     }
  1486.   else
  1487.     if (!Scan)
  1488.       {
  1489. if (FuncExit) /* it's the place where to put address     *
  1490.        * of command "ERROR" (if exists) OR "END" */
  1491.   {
  1492.     *FuncExit = CurPg;
  1493.     FuncExit = NULL;
  1494.   }
  1495. Pr_ERROR (-EOSCAN);
  1496. if (UntPoint)
  1497.   Pr_UNTIL (WhereNode, *FuncExit, UntPoint);
  1498.       }
  1499. } /* ScanTable */
  1500. /*---------------------------------------------------------------------*/
  1501. float
  1502. Query (TXTREF FromNode, VADR BO_Tid, VCBREF ResScan, TXTREF CmdNode, i4_t *res_row_num)
  1503. /* Query handling ( beginning - FROM) .                         *
  1504.  * BO_Tid - address of Tabid for temp. table, if result of this *
  1505.  * query must be placed to this table (else == NULL)            *
  1506.  * If BO_Tid==NULL && CmdNode==(NULL || SELECT)  =>  RetPar;    *
  1507.  *      else - CmdNode points to node UPDATE or  DELETE         *
  1508.  * ResScan - pointer to SCAN of result temporary table          *
  1509.  * (NULL -if not use)                                           *
  1510.  * Returns estimated cost of the query.                         *
  1511.  * If res_row_num != NULL => the estimated rows' number         *
  1512.  * in the result of Query is putted to *res_row_num.            */
  1513. {
  1514.   TXTREF TabPtr, SelectNode, WhereNode, CurAnd;
  1515.   i4_t i, AndNum = 0;
  1516.   VADR *AndArr= NULL, *Save_FuncExit = FuncExit;
  1517.   MASK Msk, AllMsk = 0, AllTrDep = 0, *AndMasks = NULL;
  1518.   float cost = 0;
  1519.   
  1520.   FuncExit = NULL;
  1521.   assert(FromNode);
  1522.   if (res_row_num)
  1523.     *res_row_num = 1;
  1524.   TASSERT (CODE_TRN (FromNode) == FROM, FromNode);
  1525.   TabPtr = DOWN_TRN (FromNode);
  1526.   TASSERT (TabPtr, FromNode);
  1527.   
  1528.   /* mask creating for tables & making places for columns' values : */
  1529.   do
  1530.     {
  1531.       TASSERT (CODE_TRN (TabPtr) == TBLPTR, TabPtr);
  1532.       ScanHandle (TABL_DESC (TabPtr), NULL, &Msk, NULL, NULL);
  1533.       AllMsk = BitOR (AllMsk, Msk);
  1534.     }
  1535.   while ((TabPtr = RIGHT_TRN (TabPtr)));
  1536.   /* Bits for all tables in current query are in AllMsk now */
  1537.   
  1538.   if (OPTIM)
  1539.     cost = opt_query (FromNode, res_row_num);
  1540.   
  1541.   SelectNode = RIGHT_TRN (FromNode);
  1542.   WhereNode = (SelectNode) ? RIGHT_TRN (SelectNode) : TNULL;
  1543.   if (WhereNode && CODE_TRN (WhereNode) != WHERE)
  1544.     {
  1545.       TASSERT (CODE_TRN (WhereNode) == INTO, WhereNode);
  1546.       fprintf (STDERR, "What is node INTO doing in QUERY ?n");
  1547.       WhereNode = RIGHT_TRN (WhereNode);
  1548.     }
  1549.   TASSERT ((WhereNode==TNULL) || (CODE_TRN (WhereNode) == WHERE), WhereNode);
  1550.   
  1551.   if (WhereNode)
  1552.     WhereNode = DOWN_TRN (WhereNode);
  1553.   
  1554.   if (WhereNode)
  1555.     {
  1556.       AndNum = (CODE_TRN (WhereNode) == AND) ? ARITY_TRN(WhereNode) : 1;
  1557.       TASSERT (AndNum, WhereNode);
  1558.       AndArr = GET_MEMC(VADR, AndNum);
  1559.       AndMasks = GET_MEMC(MASK, AndNum);
  1560.       
  1561.       if (CODE_TRN (WhereNode) == AND)
  1562. {
  1563.   for (i = 0, CurAnd = DOWN_TRN (WhereNode); 
  1564.        CurAnd; i++, CurAnd = RIGHT_TRN (CurAnd))
  1565.     {
  1566.       AndArr[i] = Tr_RecLoad (CurAnd, AndMasks + i, FALSE, NULL);
  1567.       AllTrDep = BitOR (AllTrDep, AndMasks[i]);
  1568.     }
  1569.   ARITY_TRN (WhereNode) = 0;
  1570.   DOWN_TRN (WhereNode) = TNULL;
  1571. }
  1572.       else
  1573. {
  1574.   AndArr[0] = Tr_RecLoad (WhereNode, AndMasks, FALSE, NULL);
  1575.   AllTrDep = BitOR (AllTrDep, AndMasks[0]);
  1576. }
  1577.     }
  1578.   /* All dependence bits for until-tree are in AllTrDep now */
  1579.   
  1580.   /* For table handling all external tables are already handled */
  1581.      
  1582.   ScanTable (DOWN_TRN (FromNode), WhereNode, AndNum, AndArr, AndMasks, 
  1583.      BitAND (AllTrDep, BitNOT (AllMsk)), SelectNode, BO_Tid, ResScan, CmdNode);
  1584.   
  1585.   FuncExit = Save_FuncExit;
  1586.   return cost;
  1587. } /* Query */
  1588. /*---------------------------------------------------------------------*/
  1589. #define DR V_PTR (V_DR, struct S_Drop_Reg)
  1590. void
  1591. Fill_Drop_Reg (VADR V_DR)
  1592. {
  1593.   VADR V_arr, *arr;
  1594.   
  1595.   DR->TabdNum = drop_cnt;
  1596.   if (drop_cnt > 0)
  1597.     {
  1598.       P_VMALLOC (arr, drop_cnt, VADR);
  1599.       DR->Tabd = V_arr;
  1600.       TYP_COPY (drop_arr, arr, drop_cnt, VADR);
  1601.     }
  1602.   
  1603.   DR->ScanNum = scan_cnt;
  1604.   if (scan_cnt > 0)
  1605.     {
  1606.       P_VMALLOC (arr, scan_cnt, VADR);
  1607.       DR->Scan = V_arr;
  1608.       TYP_COPY (scan_arr, arr, scan_cnt, VADR);
  1609.     }
  1610. } /* Fill_Drop_Reg */
  1611. #undef DR
  1612. /*---------------------------------------------------------------------*/
  1613. int
  1614. Handle (TXTREF CurNode, VADR BO_Tid, VCBREF ResScan, float *sq_cost, i4_t *res_row_num)
  1615.      
  1616. /* returns : 0 - if O'K, 1 - scanning result is single     *
  1617.  * row (for example in FUNC) => there is not table-result, *
  1618.  * < 0 - error                                             */
  1619.      
  1620. /* work with nodes of tree (it is the working plan)        *
  1621.  * BO_Tid - address of Tabid for temp. table, if it's      *
  1622.  * known that this table must be created, else BO_Tid=NULL *
  1623.  * ResScan - pointer to SCAN of table-result               *
  1624.  * (NULL - if it is not used)                              *
  1625.  * If CurNode - SubQuery =>                                *
  1626.  * 1) if sq_cost != NULL => the estimated cost of this     *
  1627.  * SubQuery is putted to *sq_cost;                         *
  1628.  * 2) if res_row_num != NULL => the estimated rows' number *
  1629.  * in the result of SubQuery is putted to *res_row_num.    */
  1630. {
  1631.   TXTREF DnNode, SQNode, CurQuery, CurTbl, CurEl, cre_obj;
  1632.   VCBREF ClmTo, ClmToBeg, ClmFrom, ClmBeg, ScNode, Tab, TmpTab;
  1633.   i4_t i, j;
  1634.   i4_t clm_nmb, func_nmb;
  1635.   i4_t *clm_nums, *Tbd;
  1636.   VADR clm_arr, func_clm_arr; /* i4_t [] */
  1637.   VADR func_arr; /* char [] */
  1638.   VADR Tbid, Tbid_1, Tbid_2, V_colval = VNULL, V_Tbd, V_DR, V_CH;
  1639.   float cost = 0.0, cur_cost;
  1640.   i4_t row_num = 0, cur_row_num;
  1641.   VCBREF old_real_insert_scan;
  1642.   struct S_CursorHeader *CH;
  1643.   
  1644.   if (sq_cost)
  1645.     *sq_cost = 0.0;
  1646.   if (res_row_num)
  1647.     *res_row_num = 0;
  1648.   
  1649.   ClmToBeg = ClmTo = (ResScan) ? COR_COLUMNS (ResScan) : TNULL;
  1650.   DnNode = (CurNode && HAS_DOWN (CurNode)) ? DOWN_TRN (CurNode) : TNULL;
  1651.   switch (CODE_TRN (CurNode))
  1652.     {
  1653.     case CUR_AREA :
  1654.       /* copying pointer to cursor name */
  1655.       if (DnNode && CODE_TRN (DnNode) == DECL_CURS)
  1656. SCAN_PTR (DnNode) = STMT_VCB (CurNode);
  1657.       Handle (DnNode, BO_Tid, ResScan, sq_cost, res_row_num);
  1658.       break;
  1659.       
  1660.     case DECL_CURS:
  1661.       STEP_CMD (V_CH, CursorHeader);
  1662.       STEP_CMD (V_DR, Drop_Reg);
  1663.       
  1664.       Pr_SavePar (STMT_VCB (CurNode));
  1665.       /* there may be no DECL_CURS, included in another DECL_CURS */
  1666.       assert (drop_cnt == -1 && scan_cnt == -1);
  1667.       drop_cnt = scan_cnt = 0;
  1668.       
  1669.       /* down to DECL_CURS are always : QUERY, FROM, TBLPTR, SCAN */
  1670.       if ( TstF_TRN (CurNode, DEL_CUR_F) ||
  1671.           (!static_sql_fl && !TstF_TRN(CurNode,RO_F)))
  1672.         {
  1673.           TXTREF NextDn = DnNode;
  1674.           
  1675.           TASSERT (CODE_TRN (NextDn) == QUERY, DnNode);
  1676.           NextDn = DOWN_TRN (NextDn);
  1677.           TASSERT (CODE_TRN (NextDn) == FROM , DnNode);
  1678.           NextDn = DOWN_TRN (NextDn);
  1679.           TASSERT (CODE_TRN (NextDn) == TBLPTR, DnNode);
  1680.           SetF_TRN (NextDn, DEL_CUR_F);
  1681.         }
  1682.       Handle (DnNode, BO_Tid, ResScan, sq_cost, res_row_num);
  1683.       
  1684.       /* in case of joining of some tables operation CLOSE CURSOR *
  1685.        * mean some scans closing & some temp. tables dropping     */
  1686.       TASSERT (scan_cnt > 0, CurNode);
  1687.       register_export_address (scan_arr[0],
  1688.                                STRING (CUR_NAME (SCAN_PTR (CurNode))));
  1689.       CH = V_PTR (V_CH, struct S_CursorHeader);
  1690.       CH->DelCurConstr = DelCurConstr;
  1691.       CH->Cur = NULL;
  1692.       CH->OpFl = 0;
  1693.       DelCurConstr = VNULL;
  1694.       Fill_Drop_Reg (V_DR);
  1695.       break;
  1696.     case INSERT:
  1697.       Pr_SavePar (STMT_VCB (CurNode));
  1698.       
  1699.       ScNode = SCAN_PTR (CurNode);
  1700.       TASSERT (CODE_TRN (ScNode) == SCAN && DnNode,CurNode);
  1701.       Tab = COR_TBL (ScNode);
  1702.       
  1703.       real_insert_scan = ScNode;
  1704.       switch (CODE_TRN (DnNode))
  1705. {
  1706. case IVALUES :
  1707.   ins_val (&TBL_TABID (Tab), TBL_NCOLS (Tab),
  1708.    DOWN_TRN (DnNode), TBL_COLS (Tab));
  1709.   break;
  1710.   
  1711. case QUERY :
  1712.   Tbid = ScanHandle (ScNode, NULL, NULL, sq_cost, res_row_num);
  1713.   cost = Query (DOWN_TRN (DnNode), Tbid, ScNode, TNULL, res_row_num);
  1714.   break;
  1715.   
  1716. case TBLPTR :
  1717.   Tbid_1 = ScanHandle (ScNode, NULL, NULL, NULL, NULL);
  1718.   TmpTab = COR_TBL (TABL_DESC (DnNode));
  1719.   TBL_NNULCOL (TmpTab) = TBL_NNULCOL (Tab);
  1720.   TBL_COLS (TmpTab) = TBL_COLS (Tab);
  1721.   Tbid_2 = ScanHandle (TABL_DESC (DnNode), NULL, NULL, sq_cost, res_row_num);
  1722.   
  1723.   Pr_INSTAB (Tbid_2, Tbid_1);
  1724.   TBL_COLS (TmpTab) = TNULL;
  1725.   break;
  1726.   
  1727. default :
  1728.   TASSERT (0, CurNode);
  1729. }
  1730.       real_insert_scan = TNULL;
  1731.       break;
  1732.     case SELECT:
  1733.       Pr_SavePar (STMT_VCB (CurNode));
  1734.       cost = Query (DnNode, VNULL, TNULL, CurNode, res_row_num);
  1735.       break;
  1736.       
  1737.     case DELETE:
  1738.     case UPDATE:
  1739.       Pr_SavePar (STMT_VCB (CurNode));
  1740.       cost = Query (DOWN_TRN (DnNode), BO_Tid, ResScan, CurNode, res_row_num);
  1741.       break;
  1742.       
  1743.     case UNION :
  1744.       if (TstF_TRN (CurNode, ALL_F))
  1745. /* ALL TUPLES */
  1746. for (CurQuery = DnNode; CurQuery; CurQuery = RIGHT_TRN (CurQuery))
  1747.   {
  1748.     Handle (CurQuery, BO_Tid, ResScan, &cur_cost, &cur_row_num);
  1749.     cost    += cur_cost;
  1750.     row_num += cur_row_num;
  1751.   }
  1752.       else /* DISTINCT */
  1753. {
  1754.   assert (BO_Tid && ClmTo);
  1755.   TASSERT (DnNode && (CODE_TRN (DnNode) == TBLPTR), CurNode);
  1756.   ScNode = TABL_DESC (DnNode);
  1757.   Tbid_1 = ScanHandle (ScNode, NULL, NULL, &cur_cost, &cur_row_num);
  1758.   cost +=  cur_cost;
  1759.   row_num += cur_row_num;
  1760.   
  1761.   /* making information about result columns */
  1762.   ClmFrom = COR_COLUMNS (ScNode);
  1763.   while (ClmTo)
  1764.     {
  1765.       COL_ADR (ClmTo) = COL_ADR (ClmFrom);
  1766.       ClmTo = COL_NEXT (ClmTo);
  1767.       ClmFrom = COL_NEXT (ClmFrom);
  1768.     }
  1769.   
  1770.   /* making commands for UNION */
  1771.   for (CurTbl = RIGHT_TRN (DnNode); CurTbl;)
  1772.     {
  1773.       TASSERT (CODE_TRN (CurTbl) == TBLPTR, CurTbl);
  1774.       Tbid_2 = ScanHandle (TABL_DESC (CurTbl), NULL, NULL,
  1775.    &cur_cost, &cur_row_num);
  1776.       cost +=  cur_cost;
  1777.       row_num += cur_row_num;
  1778.       
  1779.       CurTbl = RIGHT_TRN (CurTbl);
  1780.       Tbid = (CurTbl) ? VMALLOC (1, UnId) : BO_Tid;
  1781.       assert (Tbid_1 && Tbid_2 && Tbid);
  1782.       Pr_MKUNION (Tbid_1, Tbid_2, Tbid);
  1783.       Tbid_1 = Tbid;
  1784.     }
  1785.   /* the estimation of rows' number in the result in case of "DISTINCT" *
  1786.    * is dirty (as a sum of rows' numbers of all arg tables) because     *
  1787.    * we can't predict the number of dublicates in tables                */
  1788. }
  1789.       break;
  1790.       
  1791.     case SORTER:
  1792.       ScNode = TABL_DESC (CurNode);
  1793.       /* here we must to check background table */
  1794.       if (CODE_TRN (COR_TBL (ScNode)) == TABLE)
  1795.         {
  1796.           /* sorting of base table is not allowed by engine */
  1797.           extern TXTREF query_on_scan __P((TXTREF scan));
  1798.           extern TXTREF make_scan __P(( TXTREF list,TXTREF qexpr));
  1799.           ScNode = TABL_DESC(CurNode) = make_scan(TNULL,query_on_scan(ScNode));
  1800.         }
  1801.       
  1802.       Tbid = ScanHandle (ScNode, NULL, NULL, sq_cost, res_row_num);
  1803.       TASSERT (BO_Tid && Tbid, CurNode);
  1804.       
  1805.       /* making information about result columns */
  1806.       ClmFrom = COR_COLUMNS (ScNode);
  1807.       while (ClmTo)
  1808. {
  1809.   COL_ADR (ClmTo) = COL_ADR (ClmFrom);
  1810.   ClmTo = COL_NEXT (ClmTo);
  1811.   ClmFrom = COL_NEXT (ClmFrom);
  1812. }
  1813.       prepare_SRT (CurNode, &clm_nmb, &clm_arr);
  1814.       Pr_SORTTBL (Tbid, BO_Tid, clm_nmb, clm_arr,
  1815.        (TstF_TRN (CurNode, DISTINCT_F)) ? CH_UNIC : CH_ALL, 'A');
  1816.       if (CODE_TRN (COR_TBL (ScNode)) == TMPTABLE)
  1817. Pr_DROPTTAB (Tbid);
  1818.       break;
  1819.     case QUERY:
  1820.       cost = Query (DnNode, BO_Tid, ResScan, TNULL, res_row_num);
  1821.       break;
  1822.     case MAKEGROUP: /* BO_Tid - address of Tabid for temp. table -       *
  1823.      * result of GB. Columns descriptors for this        *
  1824.      * table are used also for columns - arguments of GB */
  1825.       ScNode = TABL_DESC (CurNode);
  1826.       TASSERT (BO_Tid, CurNode);
  1827.       Tbid = ScanHandle (ScNode, NULL, NULL, sq_cost, res_row_num);
  1828.       prepare_MG (CurNode, &clm_nmb, &clm_arr,
  1829.   &func_nmb, &func_arr, &func_clm_arr);
  1830.       
  1831.       if (!clm_nmb) /* there are only functions */
  1832. {
  1833.   assert (func_nmb);
  1834.   V_colval = VMALLOC (func_nmb, VADR);
  1835. }
  1836.       
  1837.       clm_nums = V_PTR (clm_arr, i4_t);
  1838.       ClmBeg = COR_COLUMNS (ScNode);
  1839.       for (i = 0; i < clm_nmb; i++)
  1840. {
  1841.   ClmFrom = ClmBeg;
  1842.   for (j = 0; j < clm_nums[i]; j++)
  1843.     ClmFrom = COL_NEXT (ClmFrom);
  1844.   COL_ADR (ClmTo) = COL_ADR (ClmFrom);
  1845.   ClmTo = COL_NEXT (ClmTo);
  1846. }
  1847.       for (i = 0; i < func_nmb; i++)
  1848. {
  1849.   COL_ADR (ClmTo) = prepare_HOLE (COL_TYPE (ClmTo));
  1850.   if (!clm_nmb)
  1851.     V_PTR (V_colval, VADR)[i] = COL_ADR (ClmTo);
  1852.   ClmTo = COL_NEXT (ClmTo);
  1853. }
  1854.       
  1855.       if (clm_nmb) 
  1856.         /* there are GROUP BY columns */
  1857. {
  1858.   Pr_GROUP (Tbid, BO_Tid, clm_nmb, clm_arr, 'A',
  1859.     func_nmb, func_clm_arr, func_arr);
  1860.   if (CODE_TRN (COR_TBL (ScNode)) == TMPTABLE)
  1861.     Pr_DROPTTAB (Tbid);
  1862. }
  1863.       else /* there are only functions */
  1864. {
  1865.   Pr_FUNC (Tbid, CH_TAB, 0, VNULL, 0, VNULL, V_colval,
  1866.    func_nmb, func_clm_arr, func_arr, VNULL, ClmToBeg);
  1867.   if (res_row_num)
  1868.     *res_row_num = 1;
  1869.   return 1;
  1870.   
  1871. }
  1872.       break;
  1873.     case EXISTS:
  1874.     case SUBQUERY: /* comparison predicate */
  1875.     case ALL:
  1876.     case SOME:
  1877.       /*
  1878.         SQNode = (CODE_TRN (CurNode) == EXISTS) ? DnNode :
  1879.         RIGHT_TRN (DOWN_TRN (DnNode));
  1880.         */
  1881.       if (CODE_TRN (CurNode) == SUBQUERY)
  1882. SQNode = CurNode;
  1883.       else
  1884. if (CODE_TRN (CurNode) == EXISTS)
  1885.   SQNode = DnNode;
  1886. else
  1887.   SQNode = RIGHT_TRN (DOWN_TRN (DnNode));
  1888.       TASSERT (CODE_TRN (SQNode) == SUBQUERY,SQNode);
  1889.       
  1890.       STEP_CMD (V_DR, Drop_Reg);
  1891.       assert (drop_cnt == -1 && scan_cnt == -1);
  1892.       drop_cnt = scan_cnt = 0;
  1893.       
  1894.       old_real_insert_scan = real_insert_scan;
  1895.       real_insert_scan = TNULL;
  1896.       
  1897.       /* down to predicate are here : SUBQUERY, FROM, TBLPTR, SCAN */
  1898.       cost = Query (DOWN_TRN (SQNode), BO_Tid, ResScan, CurNode, res_row_num);
  1899.       
  1900.       real_insert_scan = old_real_insert_scan;
  1901.       
  1902.       Fill_Drop_Reg (V_DR);
  1903.       break;
  1904.     case CREATE:
  1905.       /* virtual addresses of Tabids for all creating tables are  *
  1906.        * being saved for possible GRANT operators and references; *
  1907.        * unique identifiers for views are being created.          */
  1908.       if (!TBL_VADR (CREATE_OBJ (CurNode)))
  1909. /* the first table is current */
  1910. for (CurEl = CurNode; CurEl; CurEl = RIGHT_TRN (CurEl))
  1911.   if (CODE_TRN (CurEl) == CREATE)
  1912.             {
  1913.               cre_obj = CREATE_OBJ (CurEl);
  1914.               if (CODE_TRN (cre_obj) == TABLE)
  1915.                 V_Tbd = VMALLOC (1, UnId);
  1916.               else
  1917.                 {
  1918.                   TASSERT (CODE_TRN (cre_obj) == VIEW, CurEl);
  1919.                   P_VMALLOC (Tbd, 1, i4_t);
  1920.                   *Tbd = uniqnm ();
  1921.                 }
  1922.               TBL_VADR (cre_obj) = V_Tbd;
  1923.             }
  1924.       
  1925.       CrTab (CREATE_OBJ (CurNode));
  1926.       break;
  1927.     case DROP:
  1928.       Tab = CREATE_OBJ (CurNode);
  1929.       Pr_DROP ((CODE_TRN (Tab) == TABLE) ? (TBL_TABID (Tab)).untabid :
  1930.                VIEW_UNID (Tab));
  1931.       break;
  1932.       
  1933.     case GRANT:
  1934.       GrantHandle (CurNode);
  1935.       break;
  1936.     default:
  1937.       fprintf (stderr, "Unexpected node at %s:%d: '%s'n", __FILE__, __LINE__,
  1938.        NAME (CODE_TRN (CurNode)));
  1939.     } /* switch */
  1940.   if (sq_cost && cost)
  1941.     *sq_cost = cost;
  1942.   if (res_row_num && row_num)
  1943.     *res_row_num = row_num;
  1944.   return 0;
  1945. } /* Handle */