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

SQL Server

开发平台:

Unix_Linux

  1. /*
  2.  *  binding.c - base binding (table and column binding)            
  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 Eugene W. Woynov,1994
  10.  *  Corrected by Michael Kimelman, 1995
  11.  *
  12.  *  This program is free software; you can redistribute it and/or modify
  13.  *  it under the terms of the GNU General Public License as published by
  14.  *  the Free Software Foundation; either version 2 of the License, or
  15.  *  (at your option) any later version.
  16.  *
  17.  *  This program is distributed in the hope that it will be useful,
  18.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  19.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  20.  *  GNU General Public License for more details.
  21.  *
  22.  *  You should have received a copy of the GNU General Public License
  23.  *  along with this program; if not, write to the Free Software
  24.  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  25.  *
  26.  *  Contacts:  gss@ispras.ru
  27.  *
  28.  */
  29. /* $Id: binding.k,v 1.246 1997/04/21 16:17:31 kml Exp $ */
  30. #include "global.h"
  31. #include "seman.h"
  32. #include "funall.h"
  33. #include "cycler.h"
  34. #include "tassert.h"
  35. #include <assert.h>
  36. /********************************************************************/
  37. /***    external variable           ***/
  38. /********************************************************************/
  39. static TXTREF *S_stack = NULL;
  40. static i4_t c_stack = 0, stack_size = 0;
  41. i2_t s_e_error    = 0;
  42. i2_t s_w_error    = 0;
  43. static void base_binding  __P((TXTREF));
  44. static void scan_binding (TXTREF); /* scan binding               */
  45.         /* (bypass subquery)          */
  46. static void connect_field (TXTREF); /* column binding             */
  47. static void find_subquery (TXTREF); /* subquery retrieval         */
  48. static TXTREF exist_column (LTRLREF n1, /* check of scan existing     */
  49.                             LTRLREF n2, /* in stack on column name    */
  50.                             LTRLREF n3);/* (scope by context.f_scope) */
  51. static void table_denaming (TXTREF); /* table denaming at list     */
  52. static void sem_add_stack (VCBREF); /* add stack                  */
  53. static void stack_recovery ();          /* stack recovery             */
  54. static void is_scan_uniq (VCBREF); /* check of scan unique       */
  55.                                         /* in stack                   */
  56. static TXTREF find_star  __P((TXTREF));
  57. void          load_table(TXTREF ptbl);
  58. static void   bind_schema_action  __P((enum token action, TXTREF ptbl));
  59. /********************************************************************/
  60. static f_grant = 0 ;
  61. static struct 
  62. {
  63.   TXTREF ref_order;
  64.   TXTREF star;
  65. } binding_seman =
  66. {TNULL, TNULL};
  67. /********************************************************************/
  68. int
  69. binding (void)
  70. {
  71.   TXTREF t, rt;
  72.   s_w_error = s_e_error = 0;
  73.   for (t = ROOT; t; t  = rt)
  74.     {
  75.       rt = RIGHT_TRN(t);
  76.       if ((ROOT == t) && (CODE_TRN(t) == CREATE || CODE_TRN(t) == ALTER))
  77.         if ( CREATE_OBJ(t)==TNULL)
  78.           ROOT = rt;
  79.       base_binding (t);
  80.       assert(c_stack == 0);
  81.     }
  82.   xfree(S_stack);
  83.   S_stack = NULL;
  84.   stack_size = 0;
  85.   errors += s_e_error;
  86.   s_e_error = 0;
  87.   return 0;
  88. } /* end binding */
  89. /**********************************************************************/
  90. static void
  91. base_binding (TXTREF txtref)
  92. {
  93.   TXTREF curr_ref = TNULL;
  94.   Tabid  tabid;
  95.   char   type;
  96. /**** scan find */
  97.   switch (CODE_TRN (txtref))
  98.     {
  99.     case DECL_CURS:
  100.       LOCAL_VCB_ROOT = STMT_VCB(txtref);
  101.       curr_ref = DOWN_TRN (txtref);
  102.      
  103.       if (RIGHT_TRN (curr_ref) && CODE_TRN (RIGHT_TRN (curr_ref)) == ORDER)
  104.         binding_seman.ref_order = RIGHT_TRN (curr_ref);
  105.       
  106.     case CUR_AREA:
  107.       base_binding (DOWN_TRN (txtref));
  108.       break;
  109.     case UNION:
  110.       for (curr_ref =DOWN_TRN (txtref); curr_ref;curr_ref =RIGHT_TRN (curr_ref))
  111.         base_binding (curr_ref);
  112.       break;
  113.       
  114.     case INSERT:
  115.     case UPDATE:
  116.     case DELETE:
  117.       curr_ref = txtref;
  118.     case SELECT:
  119.       LOCAL_VCB_ROOT = STMT_VCB(txtref);
  120.     case SUBQUERY:
  121.     case QUERY:
  122.       curr_ref = DOWN_TRN (txtref);
  123.       /* new stack frame */
  124.       sem_add_stack(TNULL);
  125.       table_denaming (curr_ref);
  126.       scan_binding (txtref);
  127.       
  128.       if(CODE_TRN(txtref)==SUBQUERY) 
  129.         {           /* result    from     subquery */
  130.           TXTREF res = RIGHT_TRN(DOWN_TRN(txtref));
  131.           TASSERT(CODE_TRN(res) == RESULT,txtref);
  132.           if (CODE_TRN(DOWN_TRN(res))==STAR)  
  133.             {  /* (select * from ....)  -> (select 0 from ...) */
  134.               TXTREF t;
  135.               free_node(DOWN_TRN(res));
  136.               for ( t = DOWN_TRN(DOWN_TRN(txtref)); t; t = RIGHT_TRN(t))
  137.                 if ( COR_COLUMNS(TABL_DESC(t)))
  138.                   break;
  139.               if (!t) /* if there is no scans with columns */
  140.                 {
  141.                   TXTREF sc,tbl;
  142.                   t = DOWN_TRN(DOWN_TRN(txtref));
  143.                   sc = TABL_DESC(t);
  144.                   tbl = COR_TBL(sc);
  145.                   TASSERT(TstF_TRN(tbl,CHECKED_F),txtref);
  146.                   add_column(sc, COL_NAME(TBL_COLS(tbl)));
  147.                 }
  148.               /*
  149.                * now t is a pointer to nonempty scan and we can replace
  150.                * '*' by the first column of the scan
  151.                */
  152.               DOWN_TRN(res) = #(ColPtr <COR_COLUMNS(TABL_DESC(t))>);
  153.             }
  154.         }
  155.       
  156.       if (binding_seman.ref_order)
  157.         {
  158.           scan_binding (binding_seman.ref_order);
  159.           binding_seman.ref_order = TNULL;
  160.         }
  161.       find_subquery (txtref);
  162.       stack_recovery ();
  163.       break;
  164.     case DROP:
  165.       load_table(CREATE_OBJ (txtref));
  166.       break;  
  167.     case CREATE:
  168.       if (CREATE_OBJ(txtref)==TNULL)
  169. {
  170.   if (!existsc (STRING (GL_AUTHOR)))
  171.             lperror("Error: schema %s has already exist",
  172.                     STRING (GL_AUTHOR));
  173. }
  174.       else if (existtb (STRING (TBL_FNAME (CREATE_OBJ (txtref))),
  175.                         STRING (TBL_NAME (CREATE_OBJ (txtref))),
  176.                         &tabid,
  177.                         &type))
  178.         {
  179.           TXTREF tbl = CREATE_OBJ (txtref);
  180.           file_pos = LOCATION_TRN(txtref);
  181.           lperror("Error: %s %s.%s has already existn",
  182.                   (CODE_TRN(tbl)==TABLE?"table":"view"),
  183.                   STRING (TBL_FNAME (tbl)),
  184.                   STRING (TBL_NAME (tbl)));
  185.         }
  186.     case ALTER:
  187.       if (CREATE_OBJ(txtref)==TNULL)
  188.         {
  189.           free_node(txtref);
  190.           return;
  191.         }
  192.       if (CODE_TRN(txtref)==ALTER)
  193.         yyfatal("ALTER table or view has not realized yet");
  194.       switch (CODE_TRN (CREATE_OBJ (txtref)))
  195.         {
  196.         case TABLE:
  197.           bind_schema_action (CODE_TRN(txtref), CREATE_OBJ (txtref));
  198.           break;
  199.         case VIEW:
  200.           base_binding (VIEW_QUERY (CREATE_OBJ (txtref)));
  201.         default:
  202.           break;
  203.         }
  204.       break;
  205.     case GRANT:
  206.       if (CODE_TRN (TABL_DESC (DOWN_TRN (txtref))) !=ANY_TBL &&
  207.           TstF_TRN(TABL_DESC (DOWN_TRN (txtref)),CHECKED_F))
  208.         break;
  209.       else
  210. {
  211.   f_grant = 1;
  212.   table_denaming (DOWN_TRN (txtref));
  213.   f_grant = 0;
  214. }
  215.       break;
  216.     default:
  217.       SFATAL_ERROR;
  218.     } /* end switch */
  219. } /* end base_binding */
  220. /**********************************************************************/
  221. /***    scan binding (bypass subquery)                              ***/
  222. /**********************************************************************/
  223. static void
  224. scan_binding (TXTREF parent)
  225. {
  226.   TXTREF txtref;
  227.   for (txtref = DOWN_TRN (parent);
  228.        txtref;
  229.        txtref = RIGHT_TRN (txtref))
  230.     switch(CODE_TRN(txtref))
  231.       {
  232.       case COLPTR:
  233.         connect_field(txtref);
  234.         break;
  235.       case SORT_COL:
  236.         connect_field(OBJ_DESC(txtref));
  237.         break;
  238.       case STAR:
  239.         if (binding_seman.star)
  240.           {
  241.             TXTREF scol, chain =TNULL, from = binding_seman.star, t;
  242.             
  243.             binding_seman.star =TNULL;
  244.             TASSERT(DOWN_TRN(parent)==txtref && ARITY_TRN(parent)==1,parent);
  245.             free_node (txtref);
  246.             DOWN_TRN(parent) = TNULL;
  247.             ARITY_TRN(parent) = 0;
  248.             
  249.             for (t = DOWN_TRN (from); t; t = RIGHT_TRN(t))
  250.               {
  251.                 check_scan_cols(t);
  252.                 for (scol = COR_COLUMNS(TABL_DESC (t));
  253.                      scol;
  254.                      scol = COL_NEXT(scol))
  255.                   {
  256.                     if (chain == TNULL)
  257.                       txtref = DOWN_TRN (parent) = chain = #(ColPtr <scol>);
  258.                     else
  259.                       chain  = RIGHT_TRN (chain) = #(ColPtr <scol>);
  260.                     ARITY_TRN(parent)++;
  261.                   }
  262.               }
  263.           }
  264.         break;
  265.       case QUERY:
  266.       case SUBQUERY:
  267.         continue;
  268.       default:
  269.         if (HAS_DOWN(txtref))
  270.           scan_binding (txtref);
  271.       }
  272. } /* end scan_binding */
  273. /********************************************************************/
  274. /***    subquery retrieval                                        ***/
  275. /********************************************************************/
  276. static void
  277. find_subquery (TXTREF node)
  278. {
  279.   TXTREF t;
  280.   enum token code;
  281.   for (t = DOWN_TRN (node);t; t = RIGHT_TRN (t))
  282.     {
  283.       code = CODE_TRN (t);
  284.       if ((code == QUERY) || (code == SUBQUERY))
  285.         base_binding (t);
  286.       else if (HAS_DOWN(t))
  287. find_subquery (t);
  288.     }
  289. } /* end find_subquery */
  290. /********************************************************************/
  291. /***    column binding                                            ***/
  292. /********************************************************************/
  293. static void
  294. connect_field (TXTREF colptr) /* txtref to COLPTR */
  295. {
  296.   TXTREF scol;
  297.   TASSERT (CODE_TRN (colptr) == COLPTR , colptr);
  298.   
  299.   scol = OBJ_DESC (colptr);
  300.   if (CODE_TRN (scol) == SCOLUMN)
  301.     return;
  302.   TASSERT (CODE_TRN (scol) == COLUMN_HOLE,colptr);
  303.   /* set posiiton for the case of following error report */
  304.   file_pos = LOCATION_TRN(colptr);  
  305.   
  306.   scol = exist_column (CHOLE_AUTHOR (scol),
  307.                        CHOLE_TNAME (scol),
  308.                        CHOLE_CNAME (scol));
  309.   free_node(OBJ_DESC(colptr));
  310.   OBJ_DESC(colptr) = scol;
  311.   return;
  312. } /* end connect_field */
  313. /**********************************************************************/
  314. /***  check of scan existing in stack on column name                ***/
  315. /**********************************************************************/
  316. static TXTREF
  317. exist_column (LTRLREF an, /* authorization name */
  318.       LTRLREF tn, /* table  name */
  319.       LTRLREF cn  /* column name */
  320.               )
  321. {
  322.   i4_t   stack;
  323.   for (stack = c_stack -1 ; stack >=0 ; stack--)
  324.     if (S_stack[stack])
  325.       {
  326.         TXTREF scn = S_stack[stack];
  327.         TXTREF tbl = COR_TBL(scn);
  328.         LTRLREF scan_name, tbl_an, tbl_tn;
  329.         scan_name = COR_NAME (scn);
  330.         tbl_an = TBL_FNAME (tbl);
  331.         tbl_tn = TBL_NAME (tbl);
  332.         if ( an )
  333.           if ( (an !=tbl_an) || (tn != tbl_tn) )
  334.               continue;
  335.         if ( tn )
  336.              if ((tn != scan_name) && ( (GL_AUTHOR!= tbl_an) && (tn !=tbl_tn)))
  337.                continue;
  338.         {
  339.           TXTREF c = find_column(tbl,cn);
  340.           if(c)
  341.             {
  342.               c = find_column(scn,cn);
  343.               if (!c)
  344.                 {
  345.                   add_column(scn,cn);
  346.                   c = find_column(scn,cn);
  347.                 }
  348.               return c;
  349.             }
  350.         }
  351.       }
  352.   lperror("There is no table containing '%s.%s.%s'",
  353.           STRING(an),STRING(tn),STRING(cn));
  354.   return TNULL;
  355. } /* end exist_column */
  356. void
  357. correct_tbl_ind_info (TXTREF cur_node)
  358. {
  359.   if (!cur_node)
  360.     return;
  361.   
  362.   if (CODE_TRN (cur_node) == TBLPTR)
  363.     {
  364.       TXTREF scan  = TABL_DESC (cur_node);
  365.       TXTREF table = COR_TBL (scan);
  366.       
  367.       if (!((TBL_TABID (table)).untabid))
  368.         {
  369.           if (!existtb (STRING (TBL_FNAME (table)),
  370.                         STRING (TBL_NAME (table)),
  371.                         &(TBL_TABID (table)), NULL))
  372.             yyfatal ("Incorrect system information about VIEW");
  373.           if (IND_INFO (table))
  374.             free_tree (IND_INFO (table));
  375.             
  376.           IND_INFO (table) = existind (&(TBL_TABID(table))); 
  377.         }      
  378.     }      
  379.   correct_tbl_ind_info (RIGHT_TRN (cur_node));
  380.   if (HAS_DOWN (cur_node))
  381.     correct_tbl_ind_info (DOWN_TRN (cur_node));
  382. } /* correct_tbl_ind_info */
  383. static void
  384. adjust_name(char *which_name, LTRLREF *l)
  385. {
  386.   if (strlen(STRING(*l)) > MAX_USER_NAME_LNG)
  387.     {
  388.       char buf[MAX_USER_NAME_LNG + 1];
  389.       bcopy (STRING(*l),buf,MAX_USER_NAME_LNG);
  390.       buf[MAX_USER_NAME_LNG]=0;
  391.       lperror("Warning: %s name '%s' is too long - adjusted to '%s'",
  392.               which_name, STRING (*l), buf);
  393.       errors--;
  394.       *l = ltr_rec(buf);
  395.     }
  396. }
  397. void 
  398. load_table(TXTREF ptbl)
  399. {
  400.   Tabid      tabid;
  401.   char       type;
  402.   i4_t        i,ncols;
  403.   sql_type_t column_type, *coltype = &column_type;
  404.   VCBREF     cl_new;
  405.   
  406.   if ( TstF_TRN (ptbl, CHECKED_F))
  407.     return;
  408.   adjust_name("table", &TBL_NAME (ptbl));
  409.   adjust_name("table owner", &TBL_FNAME (ptbl));
  410.   if (!existtb (STRING (TBL_FNAME (ptbl)), STRING (TBL_NAME (ptbl)), &tabid, &type))
  411.     { /* table was not found */
  412.       char 
  413. *a = STRING (TBL_FNAME (ptbl)),
  414. *c = STRING (TBL_NAME (ptbl));
  415.       i4_t is_fname = (a && *a), is_name = c && *c;
  416.       lperror("Error: table '%s%s%s' was not found",
  417.       is_fname ? a : "", is_fname ? "." : "",
  418.       is_name ? c : "(dummy)");
  419.       yyfatal("Abort");
  420.     }
  421.   /* table was found */
  422.   /* assert tabid, val_type, tabclnm in global vocab */
  423.   switch(CODE_TRN(ptbl))
  424.     {
  425.     case ANY_TBL: break;
  426.     case TABLE:   type = (type=='B'?'B':'E'); break;
  427.     case VIEW:    type = (type=='V'?'V':'E'); break;
  428.     default:      type = 'E';
  429.     }
  430.   if (type=='E')
  431.     {
  432.       /* table was not found or mismatchs to our expectation */
  433.       char 
  434. *a = STRING (TBL_FNAME (ptbl)),
  435. *c = STRING (TBL_NAME (ptbl));
  436.       i4_t is_fname = (a && *a), is_name = c && *c;
  437.       lperror("Error: Incorrect table '%s%s%s' type",
  438.       is_fname ? a : "", is_fname ? "." : "",
  439.       is_name ? c : "(dummy)");
  440.       yyfatal("Abort");
  441.     }
  442.   
  443.   switch(type)
  444.     {
  445.     case 'B': CODE_TRN(ptbl) = TABLE; TBL_TABID(ptbl) = tabid;         break;
  446.     case 'V': CODE_TRN(ptbl) = VIEW ; VIEW_UNID(ptbl) = tabid.untabid; break;
  447.     default:
  448.       fprintf (STDERR, "tInternal error at %s:%d:nt unexpected table"
  449.        " type received from existtb -'%c'(%d)n",
  450.        __FILE__, __LINE__, type, (i4_t) type);
  451.       yyfatal("Abort");
  452.     }
  453.   
  454.   i = ncols = tabclnm (&tabid, (i4_t *) &(TBL_NNULCOL (ptbl)));
  455.   while (i--)
  456.     {
  457.       char *cl_name =NULL, *defval =NULL, *defnull =NULL;
  458.       i4_t   def_func_id;
  459.       TXTREF defv = TNULL;
  460.       i4_t rc;
  461.       
  462.       if (find_column_by_number (ptbl , i) ) 
  463. continue;
  464.       /* insert column into global vocab */;
  465.       rc = tab_cl (&tabid, i, coltype, &cl_name, &defval, &defnull,&def_func_id);
  466.       if ( rc < 0)
  467. { /* If  column of table was not found; */
  468.   char *a = STRING (TBL_FNAME (ptbl));
  469.   char *c = STRING (TBL_NAME  (ptbl));
  470.   i4_t   is_fname = a && *a;
  471.           i4_t   is_name  = c && *c;
  472.           errno = rc;
  473.   lperror("Error: inconsistent information in DB of %d column"
  474.                   " of table '%s%s%s'",
  475.   i, is_fname ? a : "", is_fname ? "." : "",
  476.   is_name ? c : "(dummy)");
  477.           continue;
  478. }
  479.       cl_new = find_column (ptbl, ltr_rec (cl_name));
  480.       
  481.       if (defval)
  482. defv = #(Const <ltr_rec(defval)> <*coltype> <*coltype>) ;
  483.       else if ( def_func_id)
  484. switch (def_func_id)
  485.   {
  486.   case USERNAME : defv = gen_node (USERNAME); break;
  487.   default :
  488.     fprintf (STDERR,
  489.                      "t%s:%d: Internal error: unrecognized function name '%s'nt",
  490.      __FILE__, __LINE__,NAME(def_func_id));
  491.   }
  492.       else if ( *defnull==0 )
  493. defv = #(Null_vl <*coltype> ) ;
  494.       if (!cl_new)
  495.         {
  496.           cl_new = #(Column <ltr_rec(cl_name)> <i> <*coltype> <ptbl> <defv> );
  497.           cl_new = add_info(cl_new);
  498.         }
  499.       else /* if column has already in list */
  500.         { /* check that it was just a stub */
  501.           TASSERT(COL_NO(cl_new)==-1,ptbl);
  502.           /* and update parameters */
  503.           COL_NO(cl_new)      =  i;
  504.           COL_TYPE(cl_new)    = *coltype;
  505.           COL_DEFAULT(cl_new) =  defv;
  506.         }
  507.     }/* insert column into global vocab */
  508.   while ( TBL_NCOLS (ptbl) != ncols )
  509.     { /* if there are some unexpected columns */
  510.       TXTREF col = TBL_COLS(ptbl);
  511.       while (COL_NO(col) != -1)
  512.         col = RIGHT_TRN(col);
  513.       TASSERT(col,ptbl); /* we must find such column */
  514.       lperror("Column '%s' not found in '%s.%s'",
  515.               STRING(COL_NAME(col)),
  516.               STRING(TBL_FNAME(ptbl)),STRING(TBL_NAME(ptbl)));
  517.       del_info(col);
  518.     }
  519.   switch(CODE_TRN(ptbl))
  520.     {
  521.     case TABLE:
  522.       /* load index information */
  523.       IND_INFO(ptbl) = existind(&(TBL_TABID(ptbl))); 
  524.       break;
  525.     case VIEW:
  526.       {
  527.         /* load view query tree */
  528. TXTREF lvcb, sav_segm, tr_segm, vt;
  529. char  *beg_segm,*b;
  530. i4_t    len_segm;
  531.         
  532. lvcb = LOCAL_VCB_ROOT;
  533. LOCAL_VCB_ROOT= TNULL;
  534. len_segm = getview (VIEW_UNID(ptbl), &beg_segm);
  535.         b = xmalloc(len_segm);          /* vmemory will free memory later */
  536.         bcopy(beg_segm,b,len_segm);
  537. sav_segm = get_current_tree_segment ();
  538.         tr_segm = load_tree_segment (b,len_segm);
  539.         vt = resolve_local_reference ("VIEW_TREE");
  540. set_current_tree_segment (sav_segm);
  541. LOCAL_VCB_ROOT = TNULL;         /* VIEW_VCB(ptbl)                 */
  542. VIEW_QUERY(ptbl) = copy_tree (vt);
  543. VIEW_VCB(ptbl) = LOCAL_VCB_ROOT;
  544.         correct_tbl_ind_info (VIEW_QUERY(ptbl));
  545. LOCAL_VCB_ROOT = lvcb;
  546.         dispose_tree_segment (tr_segm); /* implies freeing memory         */
  547.         assert(sav_segm == get_current_tree_segment ());
  548.       }
  549.       break;
  550.     default: break;
  551.     }
  552.   sort_list_by_col_no(&(TBL_COLS(ptbl)),NULL,NULL,1,NULL,NULL);
  553.   SetF_TRN (ptbl, CHECKED_F);
  554. }
  555. /********************************************************************/
  556. /*  table denaming at list                                          */
  557. /********************************************************************/
  558. static void
  559. table_denaming (TXTREF t)
  560. {
  561.   VCBREF scan;
  562.   TXTREF ptbl;
  563.   
  564.     switch (CODE_TRN (t))
  565.       {
  566.       case TBLPTR:
  567. scan = TABL_DESC (t);
  568. if (f_grant)
  569.           ptbl = scan; 
  570. else
  571.           ptbl = COR_TBL (scan);
  572. file_pos = LOCATION_TRN(t);
  573. load_table(ptbl);
  574. if (!f_grant)
  575.           {
  576.             is_scan_uniq (scan);
  577.             sem_add_stack (scan);
  578.           }
  579. break;
  580.       case FROM:
  581.         {
  582.           TXTREF op;
  583.           binding_seman.star = find_star (t);
  584.           for (op = DOWN_TRN (t); op ; op = RIGHT_TRN (op))
  585.             table_denaming (op);
  586.         }
  587.         break;
  588.       default:
  589.         {
  590.           debug_trn(t);
  591.           yyfatal("Unexpected node in tblptr's list");
  592.         }
  593.       } /* end switch */
  594. } /* end table_denaming */
  595. /********************************************************************/
  596. /***   add stack                                                  ***/
  597. /********************************************************************/
  598. static void
  599. sem_add_stack (VCBREF txtref)
  600. {
  601.   if (c_stack >= stack_size)
  602.     {
  603.       stack_size +=100*sizeof(TXTREF);
  604.       if (S_stack)
  605.         S_stack = (TXTREF*)xrealloc(S_stack,stack_size);
  606.       else
  607.         S_stack = (TXTREF*)xmalloc(stack_size);
  608.     }
  609.   S_stack[c_stack++] = txtref;
  610. } /* end sem_add_stack */
  611. /********************************************************************/
  612. /***    check of scan unique in stack                             ***/
  613. /********************************************************************/
  614. static void
  615. is_scan_uniq (TXTREF scan)
  616. {
  617.   i4_t i;
  618.   LTRLREF name_scan, autor, name_table;
  619. #define IS_EQ(s,s1) (!strcmp (STRING (s), STRING (s1)))
  620. #define EXIT(msg)   {lperror(msg,STRING (name_scan));return;}
  621.                                 
  622.   name_scan = COR_NAME (scan);
  623.   autor = TBL_FNAME (COR_TBL (scan));
  624.   name_table = TBL_NAME (COR_TBL (scan));
  625.   for (i = c_stack; S_stack[i - 1] != TNULL; i--)
  626.     {
  627.       TXTREF s = S_stack[i - 1], t = COR_TBL(s);
  628.       LTRLREF sn = COR_NAME(s);
  629.       
  630.       if (name_scan)
  631. if (sn)
  632.   {
  633.     if (IS_EQ(name_scan,sn))
  634.       EXIT("Error : Umbigous correlation name '%s'");
  635.   }
  636. else
  637.   {
  638.     if (IS_EQ(GL_AUTHOR,TBL_FNAME (t)) &&
  639. IS_EQ(name_scan,TBL_NAME  (t)))
  640.       EXIT("Error : Umbigous correlation name '%s' -"
  641.                    "conflict with table name");
  642.   }
  643.       else
  644. {
  645.   if (sn)
  646.     {
  647.       if (IS_EQ(sn   ,name_table)  &&
  648.   IS_EQ(autor,GL_AUTHOR ))
  649. EXIT("Error : Umbigous correlation name '%s' -"
  650.                      "conflict with table name");
  651.     }
  652.   else
  653.     {
  654.       if (IS_EQ(TBL_NAME (t) ,name_table) &&
  655.   IS_EQ(TBL_FNAME (t),autor     ))
  656. {
  657.                   lperror("Error : Umbigous table name '%s.%s'",
  658.                           STRING (autor),
  659.                           STRING (name_table));
  660.   return;
  661. }
  662.     }
  663. }
  664.     }
  665. #undef IS_EQ
  666. #undef EXIT
  667. } /* end is_scan_uniq */
  668. /********************************************************************/
  669. /***   stack recovery                                             ***/
  670. /********************************************************************/
  671. static void
  672. stack_recovery ()
  673. {
  674.   if (!c_stack)
  675.     SINT_ERROR;
  676.   while (S_stack[c_stack - 1])
  677.     {
  678.       TXTREF sc = S_stack[c_stack - 1];
  679.       if ((CODE_TRN(sc) == SCAN) && (COR_COLUMNS(sc) == TNULL))
  680.         {
  681.           TXTREF tbl = COR_TBL(sc);
  682.           TASSERT(TstF_TRN(tbl,CHECKED_F),sc);
  683.           add_column(sc, COL_NAME(TBL_COLS(tbl)));
  684.         }
  685.       c_stack--;
  686.     }
  687.   c_stack--;
  688. } /* end stack_recovery */
  689. /********************************************************************/
  690. /*** find star                                                    ***/
  691. /********************************************************************/
  692. static TXTREF
  693. find_star (TXTREF txtref)
  694. {
  695.   TXTREF curr_ref;
  696.   
  697.   if (!RIGHT_TRN (txtref)) return (TNULL);
  698.   if (CODE_TRN (curr_ref =RIGHT_TRN (txtref)) == SELECTION)
  699.     if (CODE_TRN (DOWN_TRN (curr_ref)) ==STAR)
  700.       return (txtref);
  701.     
  702.   return (TNULL);
  703. } /* end find_star */
  704. /********************************************************************/
  705. /***                                                              ***/
  706. /********************************************************************/
  707. static void
  708. bind_schema_action (enum token action, TXTREF ptbl)
  709. {
  710.   TXTREF checks,tcol;
  711.   assert(action == CREATE);             /* ALTER is much more unclear */
  712.   TASSERT(CODE_TRN(ptbl)==TABLE,ptbl);
  713.   adjust_name("table", &TBL_NAME (ptbl));
  714.   adjust_name("table owner", &TBL_FNAME (ptbl));
  715.   for (tcol = TBL_COLS(ptbl); tcol; tcol = COL_NEXT(tcol))
  716.     adjust_name("column", &COL_NAME (tcol));
  717.   for (checks = TBL_CONSTR(ptbl); checks; checks=RIGHT_TRN(checks))
  718.     if (CODE_TRN(checks) == FOREIGN)
  719.       {
  720.         /*
  721.          * (Foreign {
  722.          *   (Locallist { (ColPtr (Column))...(ColPtr..) })
  723.          *   (Reference { (OPtr (Table))
  724.          *                (Noop { (Colptr (Column_hole|Column)) ... }) })
  725.          * } ) 
  726.          */
  727.         TXTREF local    = DOWN_TRN  (checks);         /* referenced column list     */
  728.         TXTREF refer    = RIGHT_TRN (local);          /* reference node             */
  729.         TXTREF reftbl   = OBJ_DESC(DOWN_TRN(refer));  /* referenced table           */
  730.         TXTREF ind_cols = RIGHT_TRN(DOWN_TRN(refer)); /* referenced index cols list */
  731.         TXTREF index;
  732.         i4_t    ind_col_n = ARITY_TRN(ind_cols);
  733.         load_table(reftbl);
  734.         file_pos = LOCATION_TRN(refer);
  735.         for (index = IND_INFO(reftbl); index; index = RIGHT_TRN(index))
  736.           if (CODE_TRN(index)!=INDEX)
  737.             {
  738.               if  (ind_col_n==ARITY_TRN(index))
  739.                 { /* compare col list */
  740.                   TXTREF icol,rcol;
  741.                   for (icol = DOWN_TRN(index),rcol = DOWN_TRN(ind_cols);
  742.                        icol && rcol;
  743.                        icol = RIGHT_TRN(icol),rcol = RIGHT_TRN(rcol))
  744.                     {
  745.                       TXTREF r = OBJ_DESC(rcol);
  746.                       if ( ((CODE_TRN(r) == COLUMN)?COL_NAME(r):CHOLE_CNAME(r)) !=
  747.                            COL_NAME(OBJ_DESC(icol)))
  748.                         break;
  749.                         
  750.                     }
  751.                   if (!icol && !rcol) /* if lists are equal */
  752.                     break;;
  753.                 }
  754.               else if (ind_col_n==0 && CODE_TRN(index)==PRIMARY )
  755.                 break;
  756.             }
  757.         if (!index) /* if index not found */
  758.           {
  759.             lperror("There is illegal reference on table '%s.%s' ",
  760.                     STRING(TBL_FNAME(reftbl)),STRING(TBL_NAME(reftbl)));
  761.             break;
  762.           }
  763.         /* we found appropriate index - now we can check reference correctness */
  764.         if (ARITY_TRN(local) != ARITY_TRN(index))
  765.           {
  766.             lperror("number of referenced columns mismath to number of "
  767.                     "columns in index");
  768.             break;
  769.           }
  770.         {
  771.           TXTREF icol,rcol;
  772.           for (icol = DOWN_TRN(index),rcol = DOWN_TRN(local);
  773.                icol && rcol;
  774.                icol = RIGHT_TRN(icol),rcol = RIGHT_TRN(rcol))
  775.             if ( type2long(COL_TYPE(OBJ_DESC(rcol))) !=
  776.                  type2long(COL_TYPE(OBJ_DESC(icol))))
  777.               lperror("Column '%s.%s.%s' type (%s) mismaths to type of "
  778.                       "referenced  column '%s.%s.%s'",
  779.                       STRING(TBL_FNAME(ptbl)),STRING(TBL_NAME(ptbl)),
  780.                       STRING(COL_NAME(OBJ_DESC(rcol))),
  781.                       type2str(COL_TYPE(OBJ_DESC(rcol))),
  782.                       STRING(TBL_FNAME(reftbl)),STRING(TBL_NAME(reftbl)),
  783.                       STRING(COL_NAME(OBJ_DESC(icol))));
  784.           assert (!icol && !rcol);
  785.         }
  786.         if (errors)
  787.           break;
  788.         /* if everything ok */
  789.         /* restruct refernce structure */
  790.         RIGHT_TRN(local) = #(OPtr <index>);
  791.         free_tree(refer);
  792.         /* add new index creation */
  793.         index = copy_tree(local);  /* copy column reference list */
  794.         CODE_TRN(index) = INDEX;   /* rename parent node         */
  795.         add_info(index);           /* add it to table list       */
  796.       }
  797. }