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

SQL Server

开发平台:

Unix_Linux

  1. %{
  2. /* 
  3.  *  parse.y   -   SQL grammar (ANSI SQL'89 + some extention) 
  4.  *                of GNU SQL compiler
  5.  *
  6.  *  This file is a part of GNU SQL Server
  7.  *
  8.  *  Copyright (c) 1996, 1997, Free Software Foundation, Inc
  9.  *  Developed at the Institute of System Programming
  10.  *  This file is written by Michael Kimelman.
  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.  *  Contact:  gss@ispras.ru
  27.  *
  28.  */
  29. /* $Id: parse.y,v 1.245 1997/03/31 03:46:38 kml Exp $ */
  30. #include "trl.h"
  31. #include "tree_gen.h"
  32. #include "cycler.h"
  33. #include "sql_decl.h"
  34. #include "xmem.h"
  35. #include "type_lib.h"
  36. #include "svr_lib.h"
  37. #include <assert.h>
  38. #include "tassert.h"
  39. char *dyn_sql_stmt_name  = NULL;
  40. i4_t   dyn_sql_section_id = 0;
  41. static TN      tblnm;
  42. static i4_t     del_local_vcb    = 0;
  43. static char   *label_nf         = NULL;
  44. static char   *label_er         = NULL;
  45. static i4_t     subquery         = 0;
  46. static TXTREF  new_table        = TNULL;
  47. static i4_t     new_table_col_no = 0;
  48. static call_t  call;
  49. static enum 
  50. {
  51.   Esql,
  52.   Module,
  53.   Schema,
  54.   Dynamic
  55. } parse_mode=Esql;
  56. #ifdef stderr
  57. #  undef stderr
  58. #endif
  59. #ifdef stdout
  60. #  undef stdout
  61. #endif
  62. #define stderr STDERR
  63. #define stdout STDOUT
  64. #define FICTIVE_NODE  (TXTREF)(-1L)
  65. #define FREE_VCB   free_line(LOCAL_VCB_ROOT)
  66. #define YYERROR_VERBOSE
  67. #define YYERROK { new_table = TNULL; yyerrok; }
  68. i4_t yylex (void);
  69. static void   check_not_null __P((TXTREF ind));
  70. static void   free_tail __P((void));
  71. static TXTREF replace_column_holes __P((TXTREF rb,VCBREF tbl));
  72. static void   add_table_column(enum token tbl_code, LTRLREF ltrp,
  73.                                sql_type_t type, TXTREF def,TXTREF constr);
  74. static void   emit_module_proc __P((VCBREF parmlist,LTRLREF procname));
  75. static void   emit_call __P((TXTREF vcb,i4_t object_id, i4_t method_id));
  76. #define add_base_column(ltrp,type,def,constr) 
  77.      add_table_column(TABLE,ltrp,type,def,constr)
  78. #define add_view_column(ltrp,type) 
  79.      add_table_column(VIEW,ltrp,type,TNULL,TNULL)
  80. %}
  81. %union {
  82.   LTRLREF  ltrp;
  83.   TXTREF   node;
  84.   i4_t      code;
  85.   sql_type_t     type;
  86.   void     *ptr;
  87. }
  88. /*
  89.   token declarations
  90. */
  91. %token TOK_ALL
  92. %token TOK_ALTER
  93. %token TOK_ANY
  94. %token TOK_AS
  95. %token TOK_ASC
  96. %token TOK_AUTHORIZATION
  97. %token TOK_BEGIN  
  98. %token TOK_BETWEEN
  99. %token TOK_BY
  100. %token TOK_CHECK
  101. %token TOK_CLOSE
  102. %token TOK_COBOL_LANG
  103. %token TOK_C_LANG
  104. %token TOK_COMMIT
  105. %token TOK_CONTINUE
  106. %token TOK_CREATE
  107. %token TOK_CURRENT
  108. %token TOK_CURSOR
  109. %token TOK_DECLARE
  110. %token TOK_DEFAULT       
  111. %token TOK_DELETE
  112. %token TOK_DESC
  113. %token TOK_DISTINCT
  114. %token TOK_DROP
  115. %token TOK_END          
  116. %token TOK_ESCAPE
  117. %token TOK_EXISTS
  118. %token TOK_FETCH
  119. %token TOK_FOR
  120. %token TOK_FOREIGN       
  121. %token TOK_FORTRAN_LANG
  122. %token TOK_FOUND      
  123. %token TOK_FROM
  124. %token TOK_GOTO 
  125. %token TOK_GRANT
  126. %token TOK_GROUP
  127. %token TOK_HAVING
  128. %token TOK_IN
  129. %token TOK_INDICATOR
  130. %token TOK_INSERT
  131. %token TOK_INTO
  132. %token TOK_IS
  133. %token TOK_KEY     
  134. %token TOK_LANGUAGE
  135. %token TOK_LIKE
  136. %token TOK_MODULE
  137. %token TOK_NULL
  138. %token TOK_OF
  139. %token TOK_ON
  140. %token TOK_OPEN
  141. %token TOK_OPTION
  142. %token TOK_ORDER
  143. %token TOK_PASCAL_LANG
  144. %token TOK_PL1_LANG
  145. %token TOK_PRIMARY       
  146. %token TOK_INDEX         
  147. %token TOK_PRIVILEGES
  148. %token TOK_PROCEDURE
  149. %token TOK_PUBLIC
  150. %token TOK_REFERENCES    
  151. %token TOK_REVOKE
  152. %token TOK_ROLLBACK
  153. %token TOK_SCHEMA
  154. %token TOK_SECTION       
  155. %token TOK_SELECT
  156. %token TOK_SET
  157. %token TOK_SOME
  158. %token TOK_SQLCODE
  159. %token TOK_SQLERROR      
  160. %token TOK_TABLE
  161. %token TOK_TO
  162. %token TOK_UNION
  163. %token TOK_UNIQUE
  164. %token TOK_UPDATE
  165. %token TOK_USER
  166. %token TOK_VALUES
  167. %token TOK_VIEW
  168. %token TOK_WHENEVER      
  169. %token TOK_WHERE
  170. %token TOK_WITH
  171. %token TOK_WORK
  172. %token TOK_AND
  173. %token TOK_OR
  174. %token TOK_NOT
  175. %token TOK_NE
  176. %token TOK_GE
  177. %token TOK_LE
  178. %token TOK_AVG
  179. %token TOK_MAX
  180. %token TOK_MIN
  181. %token TOK_SUM
  182. %token TOK_COUNT
  183. %token <ltrp> TOK_IDENTIFIER
  184. %token <ltrp> TOK_PARAM
  185. %token <node> TOK_INTEGER_CONST
  186. %token <node> TOK_NUM_CONST
  187. %token <node> TOK_REAL_CONST
  188. %token <node> TOK_STRING_CONST
  189. %token TOK_T_CHAR
  190. %token TOK_T_NUM
  191. %token TOK_T_INT
  192. %token TOK_T_SINT
  193. %token TOK_T_FLT
  194. %token TOK_T_DOUBLE
  195. %token TOK_T_PRECISION
  196. %token TOK_T_REAL
  197. %token UNARY BRACETS 
  198. %left ','
  199. %left TOK_ALL
  200. %left TOK_UNION
  201. %left TOK_OR
  202. %left TOK_AND
  203. %left TOK_NOT
  204. %left '+' '-'
  205. %left '*' '/'
  206. %left UNARY
  207. %nonassoc BRACETS
  208. %left '.'
  209. %start sql_compiled
  210. %%
  211. sql_compiled
  212.   : schema_title
  213.     { 
  214.       if (progname && *progname)
  215.         yyerror ("Unexpected schema operation in static mode compilation ");
  216.       else if (parse_mode==Module)
  217.         yyerror ("Unexpected schema operation inside module");
  218.       if($<code>1)
  219.         parse_mode=Schema;
  220.     }
  221.   | schema_element /* MUST be in dynamic compilation mode */
  222.     { 
  223.       if (progname && *progname)
  224.         yyerror ("Unexpected schema operation in static mode compilation ");
  225.       else if (parse_mode==Module)
  226.         yyerror ("Unexpected schema operation inside module");
  227.     }
  228.   | module_header
  229.     { if ($<code>1) parse_mode=Module; }
  230.   | cursor
  231.     { ; }
  232.   | procedure
  233.     { 
  234.       if(parse_mode!=Module)
  235.         yyerror("Unexpected module operation outside module");
  236.     }
  237.   | embedded_spec
  238.     { ; }
  239.   | statement
  240.     {
  241.       if(parse_mode==Esql)
  242.         {
  243.           free_tail();
  244.           $<code>$=0;
  245.         }
  246.     }
  247.   | dynamic {}
  248.   | error 
  249.     {
  250.       yyerror("Error: unrecognizable SQL construction in input file");
  251.       free_tail();
  252.       YYERROK; yyclearin;
  253.       YYACCEPT;
  254.     }
  255.   ;
  256. /*
  257.  *  dynamic additions
  258.  */
  259. tbl_or_view
  260.   : TOK_TABLE { $<code>$ = TABLE; }
  261.   | TOK_VIEW  { $<code>$ = VIEW;  }
  262.   ;
  263. dynamic 
  264.   : queryexpr
  265.     {
  266.       TXTREF c,d = gen_parent(DECL_CURS,$<node>1);
  267.       STMT_VCB(d) = LOCAL_VCB_ROOT;
  268.       SetF_TRN(d,HAS_VCB_F);
  269.       LOCAL_VCB_ROOT = TNULL;
  270.       c = gen_parent(CUR_AREA,d);
  271.       add_statement(c);
  272.       d = gen_node(CURSOR);
  273.       if (dyn_sql_stmt_name)
  274.         CUR_NAME(d) = ltr_rec(dyn_sql_stmt_name);
  275.       else
  276.         yyfatal("Attemp to compile unnamed statement");
  277.       CUR_DECL(d) = c;
  278.       STMT_VCB(c) = d;
  279.       $<code>$ = 0;
  280.     }
  281.   | TOK_DROP tbl_or_view table_desc
  282.      {
  283.        TXTREF d = gen_object(DROP,@1);
  284.        CREATE_OBJ(d) = $<node>3;
  285.        CODE_TRN($<node>3) = $<code>2;
  286.        add_statement(d);
  287.      }
  288.   ; 
  289. /*
  290.   schema definition
  291. */
  292. schema_title
  293.   : schema_action TOK_SCHEMA autoriz_clause
  294.    { {
  295.      add_statement(gen_object($<code>1,@2));
  296.      $<code>$ = 0;
  297.    } }
  298.   ;
  299. schema_element
  300.   : basetable
  301.   | view
  302.   | privilege
  303.   ;
  304. schema_action
  305.   : TOK_CREATE
  306.     { $<code>$=CREATE; }
  307.   | TOK_ALTER
  308.     { $<code>$=ALTER; }
  309.   ;
  310.   
  311. basetable
  312.   : schema_action basetable_def
  313.      {
  314.        register TXTREF e=gen_object($<code>1,@1);
  315.        CREATE_OBJ(e)=$<node>2;
  316.        add_statement(e);
  317.        $<code>$=STMT_UID(e);
  318.      }
  319.   ;
  320. basetable_def
  321.   :TOK_TABLE table_def '(' basetableelement_list ')'
  322.     {
  323.       register TXTREF t=$<node>2,e=$<node>4;
  324.       if (!t)
  325.         free_line (e);
  326.       else if (new_table != t)
  327.         yyfatal ("Internal error: unexpected 'new_table'");
  328.       else
  329.         {
  330.           CODE_TRN (t) = TABLE;
  331.   TBL_NCOLS(t) = new_table_col_no;
  332.           SetF_TRN (t, CHECKED_F);
  333.           new_table = TNULL;
  334.         }
  335.       $<node>$=t;
  336.     }
  337.   ;
  338. basetableelement_list
  339.   : basetableelement
  340.     { $<node>$=$<node>1;}
  341.   | basetableelement_list ',' basetableelement
  342.     { $<node>$=join_list($<node>1,$<node>3);}
  343.   ;
  344. basetableelement
  345.   : column_descr   { $<node>$=$<node>1; }
  346.   | table_constr   { $<node>$=$<node>1; }
  347.   ;
  348. column_descr                                     /*==*/
  349.   : TOK_IDENTIFIER type default_clause column_constrts
  350.     {
  351.       if(new_table)
  352.         add_base_column($<ltrp>1,$<type>2,$<node>3,$<node>4);
  353.       $<node>$ = TNULL;
  354.     }
  355.   ;
  356. default_clause
  357.   :  { $<node>$ = TNULL;     }
  358.   | TOK_DEFAULT def_clause  
  359.      { $<node>$ = $<node>2; }
  360.   ;
  361. def_clause
  362.   : TOK_USER
  363.     {
  364.       $<node>$ = gen_object (USERNAME, @1);
  365.       USR_NAME ($<node>$) = $<ltrp>1;
  366.     }
  367.   | TOK_NULL
  368.     { $<node>$ = gen_object (NULL_VL, @1); }
  369.   | constant
  370.     { $<node>$ = $<node>1; }
  371.   ;
  372. column_constrts
  373.   :
  374.     { $<node>$ = TNULL;        }
  375.   | constr_list 
  376.     { $<node>$ = $<node>1; }
  377.   ;
  378. constr_list
  379.   : column_constr
  380.     { $<node>$ = $<node>1; }
  381.   | constr_list column_constr
  382.     { $<node>$ = join_list($<node>1,$<node>2); }
  383.   ;
  384. column_constr
  385.   : TOK_NOT TOK_NULL
  386.     { $<node>$ = gen_object (NULL_VL, @2); }
  387.   | TOK_NOT TOK_NULL unique_spec
  388.     { $<node>$ = gen_object ($<code>3, @3); } 
  389.   | refer_spec
  390.     { $<node>$ = $<node>1; }
  391.   | TOK_CHECK cond
  392.     {
  393.       $<node>$ = gen_up_node (CHECK, $<node>2, @1);
  394.     }
  395.   ;
  396. table_constr
  397.   : table_constr1
  398.     {{
  399.       if(!new_table)
  400.         yyerror("Unexpected constraints");
  401.       else
  402. switch(CODE_TRN($<node>1))
  403.   {
  404.           case NULL_VL:
  405.             yyfatal("Unexpected NULL_VL node");
  406.             break;
  407.   case PRIMARY:
  408.   case UNIQUE:
  409.             check_not_null($<node>1);
  410.   case INDEX:
  411.     IND_INFO(new_table)=
  412.       join_list(IND_INFO(new_table),$<node>1);
  413.     break;
  414.   default:
  415.             RIGHT_TRN($<node>1) = TNULL;
  416.     TBL_CONSTR(new_table)=
  417.       join_list(TBL_CONSTR(new_table),$<node>1);
  418.   }
  419.       $<node>$ = TNULL;
  420.     }}
  421.   ;
  422. table_constr1
  423.   : unique_spec  '(' column_name_list ')'
  424.     {
  425.       $<node>$=gen_up_node($<code>1,
  426.                            replace_column_holes($<node>3,new_table),
  427.                            @1);
  428.     }
  429.   | TOK_FOREIGN TOK_KEY '(' column_name_list ')' refer_spec
  430.     {
  431.       $<node>$=
  432.         gen_up_node(FOREIGN,
  433.                     join_list(gen_parent(LOCALLIST,
  434.                                          replace_column_holes($<node>4,
  435.                                                               new_table)),
  436.                               $<node>6),
  437.                     @1);
  438.     }
  439.   | TOK_CHECK cond
  440.     {
  441.       $<node>$=gen_up_node(CHECK,
  442.                            replace_column_holes($<node>2,
  443.                                                 new_table),
  444.                            @1);
  445.     }
  446.   ;
  447. unique_spec
  448.   : TOK_UNIQUE           { $<code>$=UNIQUE; }
  449.   | TOK_PRIMARY TOK_KEY  { $<code>$=PRIMARY; }
  450.   | TOK_INDEX            { $<code>$=INDEX; }
  451.   ;
  452. refer_spec 
  453.   : TOK_REFERENCES table_desc opt_column_name_list
  454.     { {
  455.       TXTREF t = gen_object(OPTR,@1);
  456.       OBJ_DESC(t)  = $<node>2;
  457.       $<node>$ = gen_up_node(REFERENCE,
  458.                              join_list(t,gen_parent(NOOP,$<node>3)),
  459.                              @1);
  460.     } }
  461.   ;
  462. opt_column_name_list
  463.   : { $<node>$=0; }
  464.   |'(' column_name_list ')'
  465.     { $<node>$=$<node>2;}
  466.   ;
  467. column_name_list
  468.   : TOK_IDENTIFIER
  469.     {
  470.       $<node>$=gen_column(NULL,$<ltrp>1,@1);
  471.     }
  472.   | column_name_list ',' TOK_IDENTIFIER
  473.     {
  474.       $<node>$=join_list($<node>1,gen_column(NULL,$<ltrp>3,@3));
  475.     }
  476.   ;
  477. view
  478.   : TOK_CREATE view_definition
  479.     {
  480.       register TXTREF e;
  481.       e=gen_object(CREATE,@1);
  482.       CREATE_OBJ(e)=$<node>2;
  483.       add_statement(e);
  484.       $<code>$=STMT_UID(e);
  485.     }
  486.   ;
  487. view_definition
  488.   : TOK_VIEW table_def opt_column_name_list
  489.     TOK_AS queryspec opt_check_option
  490.     {
  491.       register TXTREF t = $<node>2, e= $<node>3;
  492.       if(!t)
  493.         free_line (e);
  494.       else
  495.         {
  496.           TXTREF     c;
  497.           sql_type_t type  = pack_type(SQLType_0,0,0);
  498.           i4_t        e_cnt = count_list (e);
  499.           
  500.           TXTREF sel_node = RIGHT_TRN (DOWN_TRN ($<node>5));
  501.           
  502.           CODE_TRN (t) = VIEW;
  503.           if (e)
  504.             if (e_cnt != ARITY_TRN (sel_node))
  505.               {
  506.                 yyerror("Incorrect number of columns in VIEW defenition");
  507.                 free_line(e);
  508.                 e = TNULL;
  509.               }
  510.           if (e)
  511.             {
  512.               for ( c = e ; c ; c = RIGHT_TRN(c))
  513.                 add_view_column(CHOLE_CNAME(OBJ_DESC(c)),type);
  514.               free_line (e);
  515.             }
  516.           else
  517.             {
  518.               for ( c = DOWN_TRN(sel_node) ; c ; c = RIGHT_TRN(c))
  519.                 {
  520.                   if (CODE_TRN(c) == COLPTR)
  521.                     add_view_column(CHOLE_CNAME(OBJ_DESC(c)),type);
  522.                   else
  523.                     yyerror("Expressions aren't allowed in selection list"
  524.                             " of anonimous view");
  525.                 }
  526.             }
  527.           /* TASSERT(new_table_col_no == ARITY_TRN(sel_node),sel_node); */
  528.   TBL_NCOLS(t) = ARITY_TRN(sel_node);
  529.             
  530.           VIEW_QUERY (t) = $<node>5;
  531.           if($<code>6) SetF_TRN (t, CHECK_OPT_F);
  532.           SetF_TRN (t, CHECKED_F);
  533.           VIEW_VCB (t) = LOCAL_VCB_ROOT;
  534.           LOCAL_VCB_ROOT = TNULL;
  535.           new_table = TNULL;
  536.         }
  537.       $<node>$=t;
  538.     }
  539.   ;
  540. opt_check_option
  541.   :                                { $<code>$=0; }
  542.   |TOK_WITH TOK_CHECK TOK_OPTION   { $<code>$=1; }
  543.   ;
  544. privilege_action
  545.   : TOK_GRANT
  546.     { $<code>$=GRANT; }
  547.   | TOK_REVOKE
  548.     { $<code>$=REVOKE; }
  549.   ;
  550. privilege
  551.   : privilege_action privileges TOK_ON table_desc TOK_TO grantees
  552.     opt_grant
  553.     {
  554.       register TXTREF p,g;
  555.       register i4_t    err = errors;
  556.       
  557.       p=replace_column_holes($<node>2,$<node>4);
  558.       p = gen_parent(PRIVILEGIES, p);
  559.       if (errors != err) /* if there was some error in the tree */
  560.         {
  561.           g =  gen_parent(GRANTEES, $<node>6);
  562.           debug_trn(p);
  563.           free_tree(p);
  564.           debug_trn(g);
  565.           free_tree(g);
  566.         }
  567.       else
  568.         {
  569.           g=gen_node(TBLPTR);
  570.           TABL_DESC(g) = $<node>4;
  571.           g=gen_up_node($<code>1,
  572.                         join_list(g,       
  573.                                   join_list(p,
  574.                                             gen_parent(GRANTEES,
  575.                                                        $<node>6))),
  576.                         @1);
  577.           if($<code>7)
  578.             SetF_TRN(g,GRANT_OPT_F);
  579.           add_statement(g);
  580.           $<code>$=STMT_UID(g);
  581.         }
  582.     }
  583.   ;
  584. opt_grant
  585.   :                               { $<code>$=0; }
  586.   | TOK_WITH TOK_GRANT TOK_OPTION { $<code>$=1; }
  587.   ;
  588. privileges
  589.   : TOK_ALL TOK_PRIVILEGES    { $<node>$=0; }
  590.   | operation_list            { $<node>$=$<node>1; }
  591.   ;
  592. operation_list
  593.   : operation                     { $<node>$=$<node>1;}
  594.   | operation_list ',' operation  { $<node>$=join_list($<node>1,$<node>3);}
  595.   ;
  596. operation
  597.   : TOK_SELECT    
  598.     { $<node>$ = gen_object(SELECT,@1); }   
  599.   | TOK_INSERT
  600.     { $<node>$ = gen_object(INSERT,@1); }   
  601.   | TOK_DELETE
  602.     { $<node>$ = gen_object(DELETE,@1); }   
  603.   | TOK_UPDATE     opt_column_name_list
  604.     { $<node>$ = gen_up_node(UPDATE,$<node>2,@1); }   
  605.   | TOK_REFERENCES opt_column_name_list
  606.     { $<node>$ = gen_up_node(REFERENCE,$<node>2,@1); }
  607.   ;
  608. grantees
  609.   : grantee_list              { $<node>$ = $<node>1;                  }
  610.   | TOK_PUBLIC                
  611.     {
  612.       register TXTREF u=gen_object(USERNAME,@1);
  613.       USR_NAME(u)=ltr_rec("PUBLIC");
  614.       $<node>$=u;
  615.     }
  616.   ;
  617. grantee_list
  618.   : grantee                   { $<node>$=$<node>1;}
  619.   | grantee_list ',' grantee  { $<node>$=join_list($<node>1,$<node>3);}
  620.   ;
  621. grantee
  622.   : TOK_IDENTIFIER  /* user */
  623.     {
  624.       register TXTREF u=gen_object(USERNAME,@1);
  625.       USR_NAME(u)=$<ltrp>1;
  626.       $<node>$=u;
  627.     }
  628.   ;
  629. /*=======================================================================
  630. |                       embedded statements                              |
  631. =======================================================================*/
  632. embedded_spec
  633.   : declare_section  { ; }
  634.   | exception        { ; }
  635.   ;
  636. declare_section
  637.   : TOK_BEGIN TOK_DECLARE TOK_SECTION  { $<code>$=1; }
  638.   | TOK_END TOK_DECLARE TOK_SECTION    { $<code>$=0; }
  639.   ;
  640. exception
  641.   : TOK_WHENEVER exc_cond exc_do
  642.    {
  643.      *( $<code>2 ? &label_nf : &label_er ) =
  644.        ( $<ltrp>3 ? (STRING($<ltrp>3)) : NULL );
  645.    }
  646.   ;
  647. exc_cond
  648.   : TOK_NOT TOK_FOUND                  { $<code>$=1; }
  649.   | TOK_SQLERROR                       { $<code>$=0; }
  650.   ;
  651. exc_do
  652.   : TOK_CONTINUE                       { $<ltrp>$=0; }
  653.   | TOK_GOTO TOK_IDENTIFIER            { $<ltrp>$=$<ltrp>2; }
  654.   ;
  655. /*=======================================================================
  656. |                       modules                                          |
  657. =======================================================================*/
  658. module_header
  659.   : module_titl lang_clause autoriz_clause
  660.     { $<code>$=1; }
  661.   | module_titl error
  662.     {
  663.       YYERROK;
  664.       yyerror("Error in module title");
  665.       $<code>$=0;
  666.     }
  667.     ;
  668. module_titl
  669.   : TOK_MODULE TOK_IDENTIFIER  
  670.     { $<code>$=0; }
  671.   | TOK_MODULE
  672.     { $<code>$=0; }
  673.   ;
  674. lang_clause
  675.   : TOK_LANGUAGE TOK_IDENTIFIER
  676.     {
  677.       if (strncmp("C",STRING($<ltrp>2),1)==0)
  678.         $<code>$=0;
  679.       else
  680.         {
  681.           lperror("SQL module for %s program can't be processed yet",
  682.                   STRING($<ltrp>2));
  683.           YYABORT;
  684.         }
  685.     }
  686.   ;
  687. autoriz_clause
  688.   : TOK_AUTHORIZATION TOK_IDENTIFIER
  689.    { {
  690.      extern char *current_user_login_name;
  691.      char *s, *s1;
  692.      s1 = current_user_login_name;
  693.      current_user_login_name = NULL;
  694.      s = get_user_name ();
  695.      current_user_login_name = s1;
  696.      
  697.      if(GL_AUTHOR && (GL_AUTHOR!=$<ltrp>2) && s &&
  698.         (strcmp(STRING(GL_AUTHOR),s)))
  699.        yyerror("Incorrect user identifier");
  700.      else
  701.        GL_AUTHOR=$<ltrp>2;
  702.    } }
  703.   ;
  704. cursor
  705.   : TOK_DECLARE TOK_IDENTIFIER TOK_CURSOR TOK_FOR /* cursor - IDENTIFIER */
  706.     queryexpr
  707.     orderby
  708.     {
  709.       register TXTREF c,d;
  710.       d=gen_up_node(DECL_CURS,join_list($<node>5,$<node>6),@1);
  711.       STMT_VCB(d)=LOCAL_VCB_ROOT;
  712.       SetF_TRN(d,HAS_VCB_F);
  713.       LOCAL_VCB_ROOT = TNULL;
  714.       d=gen_up_node(CUR_AREA,d,@1);
  715.       add_statement(d);
  716.       c=gen_node(CURSOR);
  717.       CUR_DECL(c)=d;
  718.       CUR_NAME(c)=$<ltrp>2;
  719.       STMT_VCB(d)=c;
  720.       if(find_info(CURSOR,CUR_NAME(c)))
  721.         {
  722.           char cn[512];
  723.           lperror("Static cursor name '%s' redeclaration",STRING(CUR_NAME(c)));
  724.           sprintf(cn,"%s_1",STRING(CUR_NAME(c)));
  725.           CUR_NAME(c) = ltr_rec(cn);
  726.         }
  727.       add_info(c);
  728.       $<code>$=0;
  729.     }
  730.     ;
  731. procedure
  732.   : TOK_PROCEDURE TOK_IDENTIFIER parameter_list ';' statement ';'
  733.     {
  734.       emit_module_proc($<node>3,$<ltrp>2);
  735.       free_line($<node>3);
  736.       $<code>$=0;
  737.     }
  738.   | TOK_PROCEDURE TOK_IDENTIFIER ';' statement ';'
  739.     {
  740.       emit_module_proc(LOCAL_VCB_ROOT,$<ltrp>2);
  741.       $<code>$=0;
  742.     }
  743.   | TOK_PROCEDURE TOK_IDENTIFIER ';' error ';'
  744.     {
  745.       YYERROK;
  746.       yyerror("Error in procedure's body");
  747.     }
  748.   | TOK_PROCEDURE TOK_IDENTIFIER parameter_list ';' error ';'
  749.     {
  750.       YYERROK;
  751.       yyerror("Error in procedure's body");
  752.     }
  753.   | TOK_PROCEDURE error ';'
  754.     {
  755.       YYERROK;
  756.       yyerror("Error in procedure's title");
  757.     }
  758.   | error ';'
  759.     {
  760.       YYERROK;
  761.       yyerror("Error: unexpected ';' found before procedure title");
  762.     }
  763.   ;
  764. orderby
  765.   : { $<node>$ = TNULL;}
  766.   | TOK_ORDER TOK_BY orderspec_list
  767.     { $<node>$ = gen_up_node (ORDER, $<node>3, @1); }
  768.   ;
  769. orderspec_list
  770.   : orderspec                     { $<node>$=$<node>1;}
  771.   | orderspec_list ',' orderspec  { $<node>$=join_list($<node>1,$<node>3);}
  772.   ;
  773. orderspec
  774.   : sort_obj sort_order
  775.     {
  776.       if($<code>2)SetF_TRN($<node>1,DESC_F);
  777.       $<node>$=$<node>1;
  778.     }
  779.   ;
  780. sort_obj
  781.   : TOK_INTEGER_CONST
  782.     { register TXTREF n=gen_object(SORT_POS,@1);
  783.       SORT_IND(n)= atol(STRING(CNST_NAME($<node>1))) - 1;
  784.       free_node($<node>1);
  785.       $<node>$=n;
  786.     }
  787.   | column
  788.     {
  789.       register TXTREF s=gen_node(SORT_COL);
  790.       SORT_CLM(s)=$<node>1;
  791.       $<node>$=s;
  792.     }
  793.   ;
  794. sort_order
  795.   :          { $<code>$=0; }
  796.   | TOK_ASC  { $<code>$=0; }
  797.   | TOK_DESC { $<code>$=1; }
  798.   ;
  799. parameter_list
  800.   : parameter                    { $<node>$=$<node>1;              }
  801.   | parameter_list ',' parameter { $<node>$=join_list($<node>1,$<node>3);}
  802.   ;
  803. parameter
  804.   : TOK_IDENTIFIER type
  805.    {
  806.      register TXTREF n;
  807.      n=get_param($<ltrp>1,0,@1);
  808.      if(!n)
  809.        yyfatal("can`t add parameter");
  810.      if(TstF_TRN(n,CHECKED_F))
  811.        $<node>$ = TNULL;
  812.      else
  813.        {
  814.          PAR_STYPE(n)=$<type>2;
  815.          SetF_TRN(n,CHECKED_F);
  816.          n=copy_trn(n);
  817.          RIGHT_TRN(n)=0;
  818.          ClrF_TRN(n,VCB_F);
  819.          $<node>$=n;
  820.        }
  821.    }
  822.   | TOK_SQLCODE
  823.    {
  824.      register TXTREF n;
  825.      n=get_param(ltr_rec("SQLCODEP"),0,@1);
  826.      if(!n)
  827.        yyfatal("can`t add parameter");
  828.      if(TstF_TRN(n,CHECKED_F))
  829.        $<node>$ = TNULL;
  830.      else
  831.        {
  832.          PAR_STYPE(n)=pack_type(SQLType_Int,0,0);
  833.          SetF_TRN(n,CHECKED_F);
  834.          SetF_TRN(n,OUT_F);
  835.          n=copy_trn(n);
  836.          RIGHT_TRN(n)=0;
  837.          ClrF_TRN(n,VCB_F);
  838.          $<node>$=n;
  839.        }
  840.    }
  841.   ;
  842. /*
  843.   statements
  844. */
  845. statement
  846.   : statement_body
  847.     {
  848.       register TXTREF u=$<node>1;
  849.       if(subquery)
  850.         fprintf(stderr,
  851.                 "Internal warning parse.y: Subquery flag not processedn");
  852.       subquery=0;
  853.       if (u != FICTIVE_NODE)
  854.         {
  855.           if (u)
  856.             {
  857.               STMT_VCB(u)=LOCAL_VCB_ROOT;
  858.               add_statement(u);
  859.               emit_call(LOCAL_VCB_ROOT,STMT_UID(u),0);
  860.               del_local_vcb=0;
  861.             }
  862.           else
  863.             {
  864.               $<node>$ = TNULL;
  865.               /* dummy operator */
  866.             }
  867.         }
  868.       $<node>$=$<node>1;
  869.     }
  870.   ;
  871. statement_body
  872.   : close_stmt
  873.   | commit_stmt
  874.   | delete_stmt
  875.   | fetch_stmt
  876.   | insert_stmt
  877.   | open_stmt
  878.   | roll_stmt
  879.   | select_stmt
  880.   | update_stmt
  881.   ;
  882. close_stmt
  883.   : TOK_CLOSE cursor_name
  884.     {
  885.       if(!$<node>2)
  886.         $<node>$ = TNULL;
  887.       else
  888.         {
  889.           emit_call (TNULL, STMT_UID(CUR_DECL($<node>2)), 2);
  890.           $<node>$=FICTIVE_NODE;
  891.           del_local_vcb=1;
  892.         }
  893.     }
  894.   ;
  895. commit_stmt
  896.   : TOK_COMMIT TOK_WORK
  897.     {
  898.       dyn_sql_section_id = -2; /* !! */
  899.       del_local_vcb=1;
  900.       emit_call (TNULL,dyn_sql_section_id,2);
  901.       $<node>$=FICTIVE_NODE;
  902.     }
  903.   ;
  904. delete_stmt
  905.   : TOK_DELETE TOK_FROM host_scan where_d
  906.     {
  907.       register TXTREF u=$<node>3;
  908.       u=gen_up_node(DELETE,u,@1);
  909.       add_child(u,$<node>4);
  910.       $<node>$=u;
  911.     }
  912.   | TOK_DELETE                    where_cur
  913.     {
  914.       $<node>$ = TNULL;
  915.       if($<node>2)
  916.         {
  917.           register TXTREF c,d;
  918.           c = $<node>2;
  919.           emit_call(LOCAL_VCB_ROOT,STMT_UID(CUR_DECL(c)),3);
  920.           d = gen_up_node (DELETE, TNULL, @1);
  921.           UPD_CURS(d) = c;
  922.           STMT_VCB(d) = LOCAL_VCB_ROOT;
  923.           LOCAL_VCB_ROOT = TNULL;
  924.           add_statement(d);
  925.           $<node>$ = FICTIVE_NODE;
  926.         }
  927.       else
  928.         {
  929.           free_tree($<node>2);
  930.           FREE_VCB;
  931.         }
  932.     }
  933.   | TOK_DELETE TOK_FROM host_scan where_cur
  934.     {
  935.       $<node>$ = TNULL;
  936.       if($<node>4)
  937.         {
  938.           register TXTREF c,d;
  939.           c = $<node>4;
  940.           emit_call(LOCAL_VCB_ROOT,STMT_UID(CUR_DECL(c)),3);
  941.           d = gen_up_node (DELETE, $<node>3, @1);
  942.           UPD_CURS(d) = c;
  943.           STMT_VCB(d) = LOCAL_VCB_ROOT;
  944.           LOCAL_VCB_ROOT = TNULL;
  945.           add_statement(d);
  946.           $<node>$ = FICTIVE_NODE;
  947.         }
  948.       else
  949.         {
  950.           free_tree($<node>3);
  951.           FREE_VCB;
  952.         }
  953.     }
  954.   ;
  955. fetch_stmt
  956.   : TOK_FETCH cursor_name TOK_INTO target_list /* cursor */
  957.     {
  958.       $<node>$ = TNULL;
  959.       if($<node>2)
  960.         {
  961.           register TXTREF u;
  962.           $<node>$=FICTIVE_NODE;
  963.           u=gen_object(FETCH,@1);
  964.           STMT_VCB(u)=LOCAL_VCB_ROOT;
  965.           SetF_TRN(u,HAS_VCB_F);
  966.           STMT_UID(u) = ARITY_TRN(CUR_DECL($<node>2));
  967.           add_child(CUR_DECL($<node>2),u);
  968.           emit_call(LOCAL_VCB_ROOT,STMT_UID(CUR_DECL($<node>2)),1);
  969.           LOCAL_VCB_ROOT = TNULL;
  970.         }
  971.       free_line($<node>4);
  972.       if ($<node>$ == TNULL)
  973.         {
  974.           FREE_VCB;
  975.         }
  976.     }
  977.    ;
  978. insert_stmt
  979.   : TOK_INSERT TOK_INTO host_scan opt_column_name_list insrt_tail
  980.      {
  981.        register TXTREF i;
  982.        i=gen_object(INSERT,@1);
  983.        add_child(i,$<node>3);
  984.        if($<node>4)
  985.          {
  986.            add_child(i,gen_parent(INTO,$<node>4));
  987.            SetF_TRN(i,COLUMNS_F);
  988.          }
  989.        add_child(i,$<node>5);
  990.        if(CODE_TRN($<node>5)==QUERY)SetF_TRN(i,QUERY_F);
  991.        $<node>$=i;
  992.      }
  993.   ;
  994. insrt_tail
  995.   : TOK_VALUES '(' insertvalue_list ')'
  996.     { $<node>$=gen_up_node(IVALUES,$<node>3,@1); }
  997.   | queryspec
  998.     { $<node>$=$<node>1;}
  999.   ;
  1000. insertvalue_list
  1001.   : ins_value                       { $<node>$=$<node>1;}
  1002.   | insertvalue_list ',' ins_value  { $<node>$=join_list($<node>1,$<node>3);}
  1003.   ;
  1004. ins_value
  1005.   : expr_or_null   { $<node>$=$<node>1;  }
  1006.   ;
  1007. open_stmt
  1008.   : TOK_OPEN cursor_name
  1009.     {
  1010.      if(!$<node>2)
  1011.        $<node>$ = TNULL;
  1012.      else
  1013.        {
  1014.          register TXTREF u=$<node>2,v;
  1015.          register TXTREF vcb=LOCAL_VCB_ROOT;
  1016.          u=STMT_VCB (DOWN_TRN (CUR_DECL(u)));
  1017.          LOCAL_VCB_ROOT=u;
  1018.          for(v=vcb;v;v=RIGHT_TRN(v))
  1019.            if(CODE_TRN(v)==PARAMETER)
  1020.              {
  1021.                u=find_info(PARAMETER,PAR_NAME(v));
  1022.                if(!u)
  1023.                  continue;
  1024.                if(PAR_STYPE(u).code==0)
  1025.                  PAR_STYPE(u)=PAR_STYPE(v);
  1026.                else if (PAR_STYPE(u).code!=PAR_STYPE(v).code)
  1027.                  yyerror("Error: Mismath operand types");
  1028.              }
  1029.          emit_call(LOCAL_VCB_ROOT,STMT_UID(CUR_DECL($<node>2)),0);
  1030.          LOCAL_VCB_ROOT=vcb;
  1031.          $<node>$=FICTIVE_NODE;
  1032.          del_local_vcb=1;
  1033.        }
  1034.    }
  1035.   ;
  1036. roll_stmt
  1037.   : TOK_ROLLBACK TOK_WORK
  1038.     {
  1039.      $<node>$=FICTIVE_NODE;
  1040.      dyn_sql_section_id = -1; /* !! */
  1041.      emit_call (TNULL,dyn_sql_section_id,0);
  1042.      del_local_vcb=1;
  1043.     }
  1044.   ;
  1045. select_stmt
  1046.   : TOK_SELECT select_spec selection TOK_INTO target_list tableexpr
  1047.     {
  1048.       register TXTREF S=gen_object(SELECT,@1),s=$<node>3,t;
  1049.       t=gen_up_node(INTO,$<node>5,@4);
  1050.       MASK_TRN(S)  = MASK_TRN($<node>6);
  1051.       DOWN_TRN(S)  = DOWN_TRN($<node>6);
  1052.       ARITY_TRN(S) = ARITY_TRN($<node>6);
  1053.       free_node($<node>6);
  1054.       if($<code>2)SetF_TRN(S,DISTINCT_F);
  1055.       RIGHT_TRN(t)=RIGHT_TRN(DOWN_TRN(S));      /* insert after from */
  1056.       RIGHT_TRN(s)=t;
  1057.       RIGHT_TRN(DOWN_TRN(S))=s;
  1058.       ARITY_TRN(S)+=2;
  1059.       $<node>$=S;
  1060.     }
  1061.   ;
  1062. select_spec
  1063.   : all              { $<code>$=0;}
  1064.   | TOK_DISTINCT     { $<code>$=1;}
  1065.   ;
  1066. update_stmt
  1067.   : TOK_UPDATE host_scan TOK_SET assignment_list where_d
  1068.     {
  1069.       register TXTREF u=
  1070.        join_list(join_list($<node>2,gen_parent(ASSLIST,$<node>4)),$<node>5);
  1071.       $<node>$=gen_up_node(UPDATE,u,@1);
  1072.     }
  1073.   | TOK_UPDATE host_scan TOK_SET assignment_list where_cur
  1074.     {
  1075.       register TXTREF u = TNULL;
  1076.       if ($<node>5)
  1077.         {
  1078.           u=gen_up_node(UPDATE,join_list($<node>2,
  1079.                                          gen_parent(ASSLIST,$<node>4)),@1);
  1080.           UPD_CURS(u)=$<node>5;
  1081.           SetF_TRN($<node>5,CURS_UPD_F);
  1082.         }
  1083.       $<node>$=u;
  1084.     }
  1085.   ;
  1086. assignment_list
  1087.   : assignment                      { $<node>$=$<node>1;}
  1088.   | assignment_list ',' assignment  { $<node>$=join_list($<node>1,$<node>3);}
  1089.   ;
  1090. assignment
  1091.   : TOK_IDENTIFIER '=' assign_tail /* column - IDENTIFIER */
  1092.     {
  1093.       $<node>$=gen_up_node(ASSIGN,
  1094.                   join_list(gen_column(NULL,$<ltrp>1,@1),$<node>3),
  1095.                            @2);
  1096.     }
  1097.   ;
  1098. assign_tail
  1099.   : expr_or_null   { $<node>$=$<node>1;  }
  1100.   ;
  1101. expr_or_null
  1102.   : expr       { $<node>$=$<node>1;  }
  1103.   | TOK_NULL   { $<node>$=gen_object(NULL_VL,@1);  }
  1104.   ;
  1105. /*
  1106.   query expression
  1107. */
  1108. queryexpr
  1109.   : queryterm
  1110.     { $<node>$=$<node>1; }
  1111.   | queryexpr TOK_UNION all queryterm
  1112.     {
  1113.       register TXTREF n=$<node>1;
  1114.       if ( (CODE_TRN(n)==UNION) && (($<code>3==0) || TstF_TRN(n,ALL_F) ))
  1115.         {
  1116.           add_child(n,$<node>4);
  1117.           if($<code>3==0)
  1118.             ClrF_TRN(n,ALL_F);
  1119.         }
  1120.       else
  1121.         {
  1122.           n=gen_up_node(UNION,join_list($<node>1,$<node>4),@2);
  1123.           if($<code>3 > 0)
  1124.             SetF_TRN(n,ALL_F);
  1125.         }
  1126.       $<node>$=n;
  1127.     }
  1128.   ;
  1129. queryterm
  1130.   : queryspec           { $<node>$=$<node>1; }
  1131.   | '(' queryexpr ')'   { $<node>$=$<node>2; }
  1132.   ;
  1133. queryspec
  1134.   : '(' queryspec1 ')'  { $<node>$=$<node>2; }
  1135.   ;
  1136. queryspec1
  1137.   : TOK_SELECT select_spec selection tableexpr 
  1138.     {
  1139.       register TXTREF q=$<node>4,s=$<node>3;
  1140.       set_location(q,@1);
  1141.       CODE_TRN(q)=QUERY;
  1142.       if($<code>2)SetF_TRN(q,DISTINCT_F);
  1143.       RIGHT_TRN(s)=RIGHT_TRN(DOWN_TRN(q));     /* insert after from */
  1144.       RIGHT_TRN(DOWN_TRN(q))=s;
  1145.       ARITY_TRN(q)++;
  1146.       $<node>$=q;
  1147.     }
  1148.   ;
  1149. selection
  1150.   : expr_list
  1151.     {
  1152.       $<node>$=gen_parent(SELECTION,$<node>1);
  1153.     }
  1154.   | '*'
  1155.     {
  1156.       $<node>$=gen_parent(SELECTION,gen_object(STAR,@1));
  1157.     }
  1158.   ;
  1159. expr_list
  1160.   : expr                      { $<node>$=$<node>1;}
  1161.   | expr_list ',' expr        { $<node>$=join_list($<node>1,$<node>3);}
  1162.   ;
  1163. tableexpr
  1164.   : from where_d groupby having
  1165.     {
  1166.       register TXTREF tbl;
  1167.       tbl=gen_parent(TBLEXP,join_list(
  1168.                               join_list(
  1169.                                 join_list($<node>1,$<node>2),
  1170.                                 $<node>3),
  1171.                               $<node>4));
  1172.       if($<node>2)SetF_TRN(tbl,WHERE_F);
  1173.       if($<node>3)SetF_TRN(tbl,GROUP_F);
  1174.       if($<node>4)SetF_TRN(tbl,HAVING_F);
  1175.       if(subquery)SetF_TRN(tbl,SUBQUERY_F);
  1176.       subquery=0;
  1177.       $<node>$=tbl;
  1178.     }
  1179.   ;
  1180. from
  1181.   : TOK_FROM scan_list
  1182.     {
  1183.       $<node>$=gen_up_node(FROM,$<node>2,@1);
  1184.     }
  1185.   ;
  1186. scan_list
  1187.   : scan_desc                 { $<node>$=$<node>1;}
  1188.   | scan_list ',' scan_desc   { $<node>$=join_list($<node>1,$<node>3);}
  1189.   ;
  1190. scan_desc
  1191.   : table_desc TOK_IDENTIFIER /* IDENTIFIER -- scan name */
  1192.     {
  1193.       $<node>$ = gen_scanptr ($<node>1, $<ltrp>2, @2);
  1194.     }
  1195.   | table_desc
  1196.     {
  1197.       $<node>$ = gen_scanptr ($<node>1, (LTRLREF) NULL, tblnm.p);
  1198.     }
  1199.   ;
  1200. where_d
  1201.   :        { $<node>$ = TNULL;    }
  1202.   | where  { $<node>$ = $<node>1;}
  1203.   ;
  1204. where
  1205.   : TOK_WHERE cond
  1206.     {
  1207.       $<node>$=gen_up_node(WHERE,$<node>2,@1);
  1208.     }
  1209.   ;
  1210. where_cur        /* return pointer to cursor */
  1211.   : TOK_WHERE TOK_CURRENT TOK_OF cursor_name   { $<node>$=$<node>4; }
  1212.   ;
  1213. cursor_name
  1214.   : TOK_IDENTIFIER
  1215.     {
  1216.       register TXTREF cursor=find_info(CURSOR,$<ltrp>1);
  1217.       if(!cursor)
  1218.         lperror("Cursor name '%s' not  found ",STRING($<ltrp>1));
  1219.       $<node>$=cursor;
  1220.     }
  1221.   ;
  1222. groupby
  1223.   : { $<node>$ = TNULL;    }
  1224.   | TOK_GROUP TOK_BY column_list
  1225.     {
  1226.       $<node>$ = gen_up_node (GROUP, $<node>3, @1);
  1227.     }
  1228.   ;
  1229. having
  1230.   : { $<node>$ = TNULL;    }
  1231.   | TOK_HAVING cond
  1232.     {
  1233.       $<node>$ = gen_up_node (HAVING, $<node>2, @1);
  1234.     }
  1235.   ;
  1236. /*
  1237.   search condition
  1238. */
  1239. cond
  1240.   : pred
  1241.     { $<node>$=$<node>1; }
  1242.   | '(' cond ')'  %prec BRACETS
  1243.     { $<node>$=$<node>2; }
  1244.   | cond TOK_OR cond  %prec TOK_OR
  1245.     { $<node>$=gen_oper(OR,$<node>1,$<node>3,@2); }
  1246.   | cond TOK_AND cond %prec TOK_AND
  1247.     { $<node>$=gen_oper(AND,$<node>1,$<node>3,@2); }
  1248.   | TOK_NOT cond  %prec TOK_NOT
  1249.     {
  1250.       TXTREF n=gen_node(NOT);
  1251.       set_location(n,@1);
  1252.       FUNC_OBJ(n)=$<node>2;
  1253.       ARITY_TRN(n)=1;
  1254.       $<node>$=n;
  1255.     }
  1256.   | error TOK_OR
  1257.     {
  1258.       $<node>$=TNULL;
  1259.       YYERROK;
  1260.       yyerror("error in condition");
  1261.     }
  1262.   | error TOK_AND
  1263.     {
  1264.       $<node>$=TNULL;
  1265.       YYERROK;
  1266.       yyerror("error in condition");
  1267.     }
  1268.   | '(' error ')' 
  1269.     {
  1270.       $<node>$=TNULL;
  1271.       YYERROK;
  1272.       yyerror("error in condition");
  1273.     }
  1274.   ;
  1275. pred
  1276.   : TOK_EXISTS subquery                             /* existence */ 
  1277.     {
  1278.       $<node>$=gen_up_node(EXISTS,$<node>2,@1);
  1279.     }
  1280.   | column TOK_IS not TOK_NULL   /* column !!!*/   /* null       */ 
  1281.     {
  1282.       $<node>$=gen_up_node(($<code>3?ISNOTNULL:ISNULL),
  1283.                            coltar_column($<node>1),@2);
  1284.     }
  1285.   | expr not TOK_BETWEEN expr TOK_AND expr         /* between */ 
  1286.     {
  1287.       register TXTREF b;
  1288.       b=gen_up_node(BETWEEN,join_list(join_list($<node>1,$<node>4),
  1289.                                       $<node>6),@3);
  1290.       if ($<code>2)
  1291.         b=gen_parent(NOT,b);
  1292.       $<node>$=b;
  1293.     }
  1294.   | expr not TOK_LIKE atom esc                   /* like */ 
  1295.     {
  1296.       register TXTREF l;
  1297.       l=gen_up_node(LIKE,join_list(join_list(coltar_column($<node>1),
  1298.                                              $<node>4),$<node>5),@3);
  1299.       if ( $<code>2)
  1300.         l = gen_parent(NOT,l);
  1301.       $<node>$=l;
  1302.     }
  1303.   | expr not TOK_IN inin                           /* in  */ 
  1304.     {
  1305.       register TXTREF i;
  1306.       i = gen_up_node(IN,join_list($<node>1,$<node>4),@3);
  1307.       if ( $<code>2)
  1308.         i = gen_parent(NOT,i);
  1309.       $<node>$=i;
  1310.     }
  1311.   | expr comp_op compare_to                        /* compare   */
  1312.     {
  1313.       TXTREF c = $<node>3;
  1314.       if (CODE_TRN(c) == NE)  /* quantified subquery */
  1315.         {
  1316.           CODE_TRN(c) = $<code>2;
  1317.           DOWN_TRN(c) = join_list($<node>1,DOWN_TRN(c));
  1318.           $<node>$ = c;
  1319.         }
  1320.       else
  1321.         $<node>$=gen_up_node($<code>2,join_list($<node>1,c),@2);
  1322.     }
  1323.   ;
  1324. compare_to
  1325.   : expr      { $<node>$=$<node>1; }
  1326.   | subquery  { $<node>$=$<node>1; }
  1327.   | allany subquery
  1328.     {
  1329.       register TXTREF c = $<node>2;
  1330.       c=gen_parent(NE,c);
  1331.       SetF_TRN(c,QUANTIF_F);
  1332.       if($<code>1==2) SetF_TRN(c,SOME_F);
  1333.       $<node>$=c;
  1334.     }
  1335.   ;
  1336. comp_op
  1337.   : '='         { $<code>$=EQU; }
  1338.   | TOK_NE      { $<code>$=NE;  }
  1339.   | '<'         { $<code>$=LT;  }
  1340.   | '>'         { $<code>$=GT;  }
  1341.   | TOK_LE      { $<code>$=LE;  }
  1342.   | TOK_GE      { $<code>$=GE;  }
  1343.   ;
  1344. allany
  1345.   : TOK_ALL       { $<code>$=1; }
  1346.   | TOK_ANY       { $<code>$=2; }
  1347.   | TOK_SOME      { $<code>$=2; }
  1348.   ;
  1349. not
  1350.   :             { $<code>$=0; }
  1351.   | TOK_NOT     { $<code>$=1; }
  1352.   ;
  1353. esc
  1354.   :                 { $<node>$ = TNULL; }
  1355.   | TOK_ESCAPE atom { $<node>$ = $<node>2; }
  1356.   ;
  1357. inin
  1358.   : subquery
  1359.     { $<node>$=$<node>1;}
  1360.   | '(' atom_list ')'
  1361.     { $<node>$=gen_parent(VALUES,$<node>2); }
  1362.   | '(' error ')'
  1363.     {
  1364.       $<node>$=TNULL;
  1365.       YYERROK;
  1366.       yyerror("error in IN predicate list" );
  1367.     }
  1368.   ;
  1369. atom_list
  1370.   : atom                      { $<node>$=$<node>1;}
  1371.   | atom_list ',' atom        { $<node>$=join_list($<node>1,$<node>3);}
  1372.   ;
  1373. subquery
  1374.   : '(' TOK_SELECT select_spec result_spec tableexpr ')'
  1375.     {
  1376.       register TXTREF sq=$<node>5,s=$<node>4;
  1377.       set_location(sq,@1);
  1378.       CODE_TRN(sq)=SUBQUERY;
  1379.       if($<code>3)SetF_TRN(sq,DISTINCT_F);
  1380.       RIGHT_TRN(s)=RIGHT_TRN(DOWN_TRN(sq));     /* insert after from */
  1381.       RIGHT_TRN(DOWN_TRN(sq))=s;
  1382.       ARITY_TRN(sq)++;
  1383.       subquery=1;
  1384.       $<node>$=sq;
  1385.     }
  1386.   | '(' TOK_SELECT error ')'
  1387.    { 
  1388.      yyerror("Error in subquery: skipped to ')'");
  1389.      $<node>$ = TNULL; 
  1390.    }  
  1391.   ;
  1392. result_spec
  1393.   : expr
  1394.     {
  1395.       $<node>$=gen_parent(RESULT,$<node>1);
  1396.     }
  1397.   | '*'
  1398.     {
  1399.       $<node>$=gen_parent(RESULT,gen_object(STAR,@1));
  1400.     }
  1401.   ;
  1402. all
  1403.   :            { $<code>$=0; }
  1404.   |TOK_ALL     { $<code>$=1; }
  1405.   ;
  1406. /*
  1407.   expression
  1408. */
  1409. expr
  1410.   : prim          { $<node>$=$<node>1; }
  1411.   | '(' expr ')'  { $<node>$=$<node>2; }
  1412.   | expr '+' expr { $<node>$=gen_oper(ADD,$<node>1,$<node>3,@2); }
  1413.   | expr '-' expr { $<node>$=gen_oper(SUB,$<node>1,$<node>3,@2); }
  1414.   | expr '*' expr { $<node>$=gen_oper(MULT,$<node>1,$<node>3,@2); }
  1415.   | expr '/' expr { $<node>$=gen_oper(DIV,$<node>1,$<node>3,@2); }
  1416.   | sign expr    %prec UNARY
  1417.     {
  1418.       TXTREF n=$<node>1;
  1419.       if(!n)
  1420.         $<node>$=$<node>2;
  1421.       else
  1422.         if(CODE_TRN($<node>2)==UMINUS)
  1423.           {
  1424.             $<node>$=FUNC_OBJ($<node>2);
  1425.             free_node($<node>2);     /* double minus elimination */
  1426.             free_node($<node>1);
  1427.           }
  1428.         else
  1429.           {
  1430.             FUNC_OBJ(n)=$<node>2;
  1431.             ARITY_TRN(n)=1;
  1432.             $<node>$=n;
  1433.           }
  1434.     }
  1435.   ;
  1436. sign
  1437.   : '+' {   $<node>$ = TNULL;           }
  1438.   | '-' {   $<node>$ = gen_object (UMINUS, @1); }
  1439.   ;
  1440. prim
  1441.   : coltar         { $<node>$=$<node>1; }
  1442.   | constant       { $<node>$=$<node>1; }
  1443.   | funcref        { $<node>$=$<node>1; }
  1444.   | TOK_USER
  1445.     {  $<node>$=gen_object(USERNAME,@1); }
  1446.   ;
  1447. atom
  1448.   : target1        { $<node>$=$<node>1; }
  1449.   | constant       { $<node>$=$<node>1; }
  1450.   | sign constant  %prec UNARY
  1451.     {
  1452.       TXTREF n = $<node>1;
  1453.       if ( ! n )
  1454.         $<node>$ = $<node>2;
  1455.       else
  1456.         {
  1457.           char *s;
  1458.           i4_t  l;
  1459.           free_node (n);
  1460.           $<node>$ = n = $<node>2;
  1461.           l = strlen (STRING (CNST_NAME (n))) + 2;
  1462.           s = xmalloc (l);
  1463.           strcpy (s, "-");
  1464.           strcat (s, STRING(CNST_NAME(n)));
  1465.           CNST_NAME (n) = ltr_rec (s);
  1466.           xfree (s);
  1467.         }
  1468.     }
  1469.   | TOK_USER
  1470.     {  $<node>$ = gen_object(USERNAME,@1); }
  1471.   ;
  1472. funcref
  1473.   : TOK_COUNT '(' '*' ')'
  1474.     {
  1475.       $<node>$=gen_func(COUNT,@1, TNULL,0);
  1476.     }
  1477.   | TOK_COUNT '(' TOK_DISTINCT column ')'
  1478.     {
  1479.       $<node>$=gen_func(COUNT,@1,$<node>4,1);
  1480.     }
  1481.   | fname '(' TOK_DISTINCT column ')'
  1482.     {
  1483.       $<node>$=gen_func($<code>1,@1,$<node>4,1);
  1484.     }
  1485.   | fname '(' all expr ')'
  1486.     {
  1487.       $<node>$=gen_func($<code>1,@1,$<node>4,0);
  1488.     }
  1489.   ;
  1490. fname
  1491.   : TOK_AVG { $<code>$=AVG; }
  1492.   | TOK_MAX { $<code>$=MAX; }
  1493.   | TOK_MIN { $<code>$=MIN; }
  1494.   | TOK_SUM { $<code>$=SUM; }
  1495.   ;
  1496. constant
  1497.   : TOK_INTEGER_CONST { $<node>$=$<node>1; }
  1498.   | TOK_REAL_CONST    { $<node>$=$<node>1; }
  1499.   | TOK_NUM_CONST     { $<node>$=$<node>1; }
  1500.   | TOK_STRING_CONST  { $<node>$=$<node>1; }
  1501.   ;
  1502. type
  1503.   : TOK_T_CHAR
  1504.      { $<type>$=pack_type(SQLType_Char,1,0);                        }
  1505.   | TOK_T_SINT
  1506.      { $<type>$=pack_type(SQLType_Short,5,0);                       }
  1507.   | TOK_T_INT
  1508.      { $<type>$=pack_type(SQLType_Int,10,0);                        }
  1509.   | TOK_T_REAL
  1510.      { $<type>$=pack_type(SQLType_Real,0,0);                        }
  1511.   | TOK_T_DOUBLE
  1512.      { $<type>$=pack_type(SQLType_Double,0,0);                      }
  1513.   | TOK_T_DOUBLE TOK_T_PRECISION
  1514.      { $<type>$=pack_type(SQLType_Double,0,0);                      }
  1515.   | TOK_T_FLT  '(' TOK_INTEGER_CONST ')'
  1516.      { $<type>$=pack_type(SQLType_Float,atol(STRING(CNST_NAME($<node>3))),0);  }
  1517.   | TOK_T_FLT  
  1518.      { $<type>$=pack_type(SQLType_Real,0,0);  }
  1519.   | TOK_T_CHAR '(' TOK_INTEGER_CONST ')'
  1520.      { $<type>$=pack_type(SQLType_Char,atol(STRING(CNST_NAME($<node>3))),0);   }
  1521.   | TOK_T_NUM 
  1522.      { $<type>$=pack_type(SQLType_Int,0,0);    }
  1523.   | TOK_T_NUM '(' TOK_INTEGER_CONST ')'
  1524.      { $<type>$=pack_type(SQLType_Num,atol(STRING(CNST_NAME($<node>3))),0);    }
  1525.   | TOK_T_NUM '(' TOK_INTEGER_CONST ',' TOK_INTEGER_CONST ')'
  1526.      { $<type>$=pack_type(SQLType_Num,atol(STRING(CNST_NAME($<node>3))),
  1527.                            atol(STRING(CNST_NAME($<node>5))));
  1528.      }
  1529.   ;
  1530. table_def:  tablename
  1531.      {
  1532.        TXTREF n;
  1533.        if(!tblnm.a)
  1534.          tblnm.a=GL_AUTHOR;
  1535.        n = find_table (ANY_TBL, tblnm.a, tblnm.n);
  1536.        if (n)
  1537.          {
  1538.            yyerror ("Error: Duplicate table name definitionn");
  1539.            $<node>$ = TNULL;
  1540.          }
  1541.        else
  1542.          {
  1543.            n = gen_node (ANY_TBL);
  1544.            /* SetF_TRN(n,CHECKED_F); */
  1545.            /* table hasn't  not already defined yet */
  1546.            TBL_FNAME (n) = tblnm.a;
  1547.            TBL_NAME (n) = tblnm.n;
  1548.            add_info (n);
  1549.            $<node>$ = new_table = n;
  1550.    new_table_col_no = 0;
  1551.          }
  1552.      }
  1553.   ;
  1554. table_desc: tablename
  1555.      {
  1556.        TXTREF n;
  1557.        if (!tblnm.a)
  1558.          tblnm.a=GL_AUTHOR;
  1559.        n = find_table (ANY_TBL, tblnm.a, tblnm.n);
  1560.        if (!n)
  1561.          {
  1562.            n = gen_node (ANY_TBL);
  1563.            TBL_FNAME (n) = tblnm.a;
  1564.            TBL_NAME (n) = tblnm.n;
  1565.            add_info (n);
  1566.          }
  1567.        $<node>$ = n;
  1568.      }
  1569.   ;
  1570. host_scan:  table_desc
  1571.      {
  1572.        $<node>$ = gen_scanptr ($<node>1, (LTRLREF) NULL, tblnm.p);
  1573.      }
  1574.   ;
  1575. tablename      /*++*/
  1576.   : TOK_IDENTIFIER
  1577.     { /*  user_identifier.tablename  or correlation name */
  1578.       tblnm.a  = (LTRLREF) NULL;
  1579.       tblnm.n  = $<ltrp>1;
  1580.       tblnm.p  = @1;
  1581.       $<code>$ = 0;
  1582.     }
  1583.   | TOK_IDENTIFIER '.' TOK_IDENTIFIER
  1584.     { /* authorization.tablename */
  1585.       tblnm.a  = $<ltrp>1;
  1586.       tblnm.n  = $<ltrp>3;
  1587.       tblnm.p  = @1;
  1588.       $<code>$ = 0;
  1589.     }
  1590.   ;
  1591. column_list
  1592.   : column                    { $<node>$ = $<node>1;                     }
  1593.   | column_list ',' column    { $<node>$ = join_list($<node>1,$<node>3); }
  1594.   ;
  1595. column
  1596.   : TOK_IDENTIFIER
  1597.     {  $<node>$=gen_column(NULL,$<ltrp>1,@1);  }
  1598.   | TOK_IDENTIFIER  '.' TOK_IDENTIFIER
  1599.     { /*  user_identifier.tablename  or correlation name */
  1600.       tblnm.a  = (LTRLREF) NULL;
  1601.       tblnm.n  = $<ltrp>1;
  1602.       tblnm.p  = @1;
  1603.       $<node>$ = gen_column (&tblnm, $<ltrp>3, @3);
  1604.     }
  1605.   | TOK_IDENTIFIER '.' TOK_IDENTIFIER  '.' TOK_IDENTIFIER
  1606.     { /* authorization.tablename */
  1607.       tblnm.a  = $<ltrp>1;
  1608.       tblnm.n  = $<ltrp>3;
  1609.       tblnm.p  = @1;
  1610.       $<node>$ = gen_column (&tblnm, $<ltrp>5, @5);
  1611.     }
  1612.   ;
  1613. target_list
  1614.   : target                  { $<node>$=$<node>1;                     }
  1615.   | target_list ',' target  { $<node>$=join_list($<node>1,$<node>3); }
  1616.   ;
  1617. target
  1618.   : target1 
  1619.     {
  1620.       register TXTREF t=OBJ_DESC($<node>1);
  1621.       SetF_TRN(t,OUT_F);
  1622.   if( !TstF_TRN(t,INDICATOR_F) && PAR_INDICATOR(t) != TNULL )
  1623.     SetF_TRN(PAR_INDICATOR(t),OUT_F);
  1624.       $<node>$=$<node>1;
  1625.     }
  1626.   ;
  1627.   
  1628. target1
  1629.   : TOK_IDENTIFIER
  1630.     {  $<node>$=get_parm_node($<ltrp>1,@1,1);  }
  1631.   | TOK_PARAM
  1632.     {  $<node>$=get_parm_node($<ltrp>1,@1,0);  }
  1633.   | TOK_IDENTIFIER TOK_INDICATOR TOK_IDENTIFIER
  1634.     {
  1635.       $<node>$=get_ind(get_param($<ltrp>1,1,@1),get_param($<ltrp>3,1,@3),@2);
  1636.     }
  1637.   | TOK_IDENTIFIER TOK_IDENTIFIER
  1638.     {
  1639.       $<node>$=get_ind(get_param($<ltrp>1,1,@1),get_param($<ltrp>2,1,@2),@2);
  1640.     }
  1641.   | TOK_PARAM TOK_INDICATOR TOK_PARAM
  1642.     {
  1643.       $<node>$=get_ind(get_param($<ltrp>1,0,@1),get_param($<ltrp>3,0,@3),@2);
  1644.     }
  1645.   | TOK_PARAM TOK_PARAM
  1646.     {
  1647.       $<node>$=get_ind(get_param($<ltrp>1,0,@1),get_param($<ltrp>2,0,@2),@2);
  1648.     }
  1649.   ;
  1650. coltar
  1651.   : TOK_IDENTIFIER
  1652.      {
  1653.        TXTREF n;
  1654.        n=find_info(PARAMETER,$<ltrp>1);
  1655.        if(n)
  1656.          $<node>$=get_parm_node($<ltrp>1,@1,1);
  1657.        else
  1658.          $<node>$=gen_column(NULL,$<ltrp>1,@1);
  1659.      }
  1660.   | TOK_IDENTIFIER  '.' TOK_IDENTIFIER
  1661.     { /*  user_identifier.tablename  or correlation name */
  1662.       tblnm.a  = (LTRLREF) NULL;
  1663.       tblnm.n  = $<ltrp>1;
  1664.       tblnm.p  = @1;
  1665.       $<node>$ = gen_column (&tblnm, $<ltrp>3, @3);
  1666.     }
  1667.   | TOK_IDENTIFIER '.' TOK_IDENTIFIER  '.' TOK_IDENTIFIER
  1668.     { /* authorization.tablename */
  1669.       tblnm.a  = $<ltrp>1;
  1670.       tblnm.n  = $<ltrp>3;
  1671.       tblnm.p  = @1;
  1672.       $<node>$ = gen_column (&tblnm, $<ltrp>5, @5);
  1673.     }
  1674.   | TOK_PARAM
  1675.      { $<node>$=get_parm_node($<ltrp>1,@1,0);     }
  1676.   | TOK_IDENTIFIER TOK_INDICATOR TOK_IDENTIFIER
  1677.      {
  1678.        $<node>$=get_ind(get_param($<ltrp>1,1,@1),get_param($<ltrp>3,1,@3),@2);
  1679.      }
  1680.   | TOK_IDENTIFIER TOK_IDENTIFIER
  1681.      {
  1682.        $<node>$=get_ind(get_param($<ltrp>1,1,@1),get_param($<ltrp>2,1,@2),@2);
  1683.      }
  1684.   | TOK_PARAM TOK_INDICATOR TOK_PARAM
  1685.      {
  1686.        $<node>$=get_ind(get_param($<ltrp>1,0,@1),get_param($<ltrp>3,0,@3),@2);
  1687.      }
  1688.   | TOK_PARAM TOK_PARAM
  1689.      {
  1690.        $<node>$=get_ind(get_param($<ltrp>1,0,@1),get_param($<ltrp>2,0,@2),@2);
  1691.      }
  1692.   ;
  1693. /* end of rules */
  1694. %%
  1695. static void
  1696. free_tail(void)
  1697. {
  1698.   if (del_local_vcb)
  1699.     FREE_VCB;
  1700.   LOCAL_VCB_ROOT = TNULL;
  1701.   del_local_vcb = 0;
  1702. }
  1703. static TXTREF holes_tbl = TNULL;
  1704. static TXTREF 
  1705. replace_clm_hole(TXTREF clmptr,i4_t f)
  1706. {
  1707.   register TXTREF ptr,clm;
  1708.   register enum token code=CODE_TRN(clmptr);
  1709.   assert(f==CYCLER_LD);
  1710.   if(code!=COLPTR)return clmptr;
  1711.   ptr=OBJ_DESC(clmptr);
  1712.   if(CODE_TRN(ptr)!=COLUMN_HOLE)return clmptr;
  1713.   clm=find_column(holes_tbl,CHOLE_CNAME(ptr));
  1714.   if(!clm)
  1715.     {
  1716.       if (TstF_TRN(holes_tbl,CHECKED_F))
  1717.         lperror("Incorrect column name '%s' used",STRING(CHOLE_CNAME(ptr)));
  1718.       else
  1719.         {
  1720.           add_column(holes_tbl,CHOLE_CNAME(ptr));
  1721.           clm=find_column(holes_tbl,CHOLE_CNAME(ptr));
  1722.         }
  1723.     }
  1724.   free_node(ptr);
  1725.   OBJ_DESC(clmptr)=clm;
  1726.   return clmptr;
  1727. }
  1728. static TXTREF 
  1729. replace_column_holes(TXTREF rb,VCBREF tbl)
  1730. {
  1731.   holes_tbl = tbl;
  1732.   rb=cycler(rb,replace_clm_hole,CYCLER_LD+CYCLER_LN);
  1733.   holes_tbl = TNULL;
  1734.   return rb;
  1735. }
  1736. static void 
  1737. add_table_column(enum token tbl_code,LTRLREF ltrp,sql_type_t type,TXTREF def,TXTREF constr)
  1738. {
  1739.   register TXTREF col;
  1740.   register i4_t    can_be_null = 1;
  1741.   
  1742.   if(!new_table) return;
  1743.   if(CODE_TRN(new_table)==ANY_TBL)
  1744.     CODE_TRN(new_table)=tbl_code;
  1745.   TASSERT(tbl_code == CODE_TRN(new_table),new_table);
  1746.   col = find_column(new_table,ltrp);
  1747.   if (col)
  1748.     {
  1749.       lperror("Duplicate column '%s' definition in table '%s.%s'",STRING(ltrp),
  1750.               STRING(TBL_FNAME(new_table)),STRING(TBL_NAME(new_table)));
  1751.       if(def)
  1752.         free_tree(def);
  1753.       if(constr)
  1754.         free_tree(constr);
  1755.     }
  1756.   else
  1757.     {
  1758.       add_column(new_table,ltrp);
  1759.       col=find_column(new_table,ltrp);
  1760.       COL_TYPE(col)   = type;
  1761.       COL_DEFAULT(col)= def;
  1762.       COL_NO(col) = new_table_col_no++;
  1763.     }
  1764.   while(constr)
  1765.     {
  1766.       register TXTREF c = constr;
  1767.       i4_t             null_vl = 0;
  1768.       constr = RIGHT_TRN(c);
  1769.       RIGHT_TRN(c) = TNULL;
  1770.       switch(CODE_TRN(c))
  1771. {
  1772. case NULL_VL:
  1773.           free_node(c);
  1774.           null_vl=1;
  1775. case PRIMARY:
  1776. case UNIQUE:
  1777.   can_be_null = 0;
  1778. #define P_(code,subtree) gen_parent(code,subtree)
  1779.           TBL_CONSTR(new_table) = 
  1780.     join_list(P_(CHECK,P_(ISNOTNULL,gen_colptr(col))),
  1781.       TBL_CONSTR(new_table));
  1782. #undef P_
  1783.           if(null_vl)
  1784.             break;
  1785. case INDEX:
  1786.   ARITY_TRN(c) = 1;
  1787.   DOWN_TRN(c)  = gen_colptr(col);
  1788.   IND_INFO(new_table)=join_list(c,IND_INFO(new_table));
  1789.   break;
  1790. case CHECK:
  1791.   TBL_CONSTR(new_table) = 
  1792.     join_list (replace_column_holes(c,new_table),
  1793.        TBL_CONSTR(new_table));
  1794.   break;
  1795. case REFERENCE:
  1796.           TBL_CONSTR(new_table)=
  1797.             join_list(gen_parent(FOREIGN,
  1798.                                  join_list(gen_parent(LOCALLIST,gen_colptr(col)),c)),
  1799.                       TBL_CONSTR(new_table));
  1800.           break;
  1801. default:
  1802.   debug_trn(c);
  1803.   yyfatal("Unexpected column constraints found");
  1804.   break;
  1805. }
  1806.     }
  1807.   
  1808.   if (!def && can_be_null)
  1809.     COL_DEFAULT (col) = gen_node (NULL_VL);
  1810.   
  1811.   if(COL_DEFAULT(col) && CODE_TRN(COL_DEFAULT(col))==NULL_VL)
  1812.     {
  1813.       if (can_be_null)
  1814.         NULL_TYPE(COL_DEFAULT (col)) = COL_TYPE(col);
  1815.       else
  1816.         yyerror("Error: ambiguous column description");
  1817.     }
  1818. #if 0
  1819.   {
  1820.     MASKTYPE x = MASK_TRN(new_table);
  1821.     debug_trn(new_table);
  1822.     MASK_TRN(new_table) = x;
  1823.   }
  1824. #endif
  1825. }
  1826. /*
  1827.  * 'check_not_null' check columns in UNIQUE or PRIMARY key definition
  1828.  * for constraints 'not null'.
  1829.  */
  1830. static void
  1831. check_not_null(TXTREF ind)
  1832. {
  1833.   TXTREF tbl = COL_TBL(OBJ_DESC(DOWN_TRN(ind)));
  1834.   TXTREF constr,cp;
  1835.   for ( cp = DOWN_TRN(ind);cp;cp = RIGHT_TRN(cp)) /* check every column */
  1836.     {
  1837.       TXTREF col = OBJ_DESC(cp);
  1838.       for(constr = TBL_CONSTR(tbl);constr;constr = RIGHT_TRN(constr))
  1839.         {
  1840.           /*
  1841.            * if ( constr = (Check (IsNotNull (ColPtr <col>))))
  1842.            */
  1843.           TXTREF pred = DOWN_TRN(constr);
  1844.           if(CODE_TRN(pred) == NOT)
  1845.             {
  1846.               pred = DOWN_TRN(pred);
  1847.               switch(CODE_TRN(pred))
  1848.                 {
  1849.                 case ISNULL:
  1850.                   CODE_TRN(pred)  = ISNOTNULL;
  1851.                   free_node(DOWN_TRN(constr));
  1852.                   DOWN_TRN(constr) = pred;
  1853.                   break;
  1854.                 default: break; 
  1855.                 }
  1856.             }
  1857.           if(CODE_TRN(pred) != ISNOTNULL)
  1858.             continue;
  1859.           pred = DOWN_TRN(pred);
  1860.           if(CODE_TRN(pred) != COLPTR) /* it quite strange */
  1861.             continue;
  1862.           if(OBJ_DESC(pred) == col) /* if there is a constraint on given column */
  1863.             break;
  1864.         }
  1865.       if (constr) /* something was found */
  1866.         continue;
  1867.       /* if we have not found 'not null' constraints on given column */
  1868.       file_pos = LOCATION_TRN(cp);
  1869.       lperror("Warning: primary key column '%s.%s.%s' not restrictedn"
  1870.               "ttby 'not null' qualifier",
  1871.               STRING(TBL_FNAME(tbl)),STRING(TBL_NAME(tbl)),
  1872.               STRING(COL_NAME(col)));
  1873.       errors--; /* clear error flag - translate message as a warning */
  1874.       if (CODE_TRN(COL_DEFAULT(col))==NULL_VL)
  1875.         {
  1876.           free_node(COL_DEFAULT(col));
  1877.           COL_DEFAULT(col) = TNULL;
  1878.         }
  1879.       col = gen_node(COLPTR);
  1880.       OBJ_DESC(col) = OBJ_DESC(cp);
  1881.       TBL_CONSTR(tbl) = 
  1882.         join_list (gen_parent(CHECK,gen_parent(ISNOTNULL,col)),
  1883.                    TBL_CONSTR(new_table));
  1884.     }
  1885. }
  1886. static void
  1887. emit_module_proc(VCBREF parmlist,LTRLREF procname)
  1888. {
  1889.   if (call.subst==NULL)
  1890.     call.subst = (call_subst_t*)xmalloc (sizeof(call_subst_t));
  1891.   call.subst->proc_name = savestring(STRING(procname));
  1892.   describe_stmt(&(call.subst->interface),parmlist,'I');
  1893.   free_tail();
  1894. }
  1895. static void
  1896. emit_call(TXTREF vcb,i4_t object_id, i4_t method_id)
  1897. {
  1898.   if (call.subst==NULL)
  1899.     call.subst = (call_subst_t*)xmalloc ( sizeof(call_subst_t));
  1900.   call.subst->object = object_id;
  1901.   call.subst->method = method_id;
  1902.   describe_stmt(&(call.subst->in_sql_parm),vcb,'>');
  1903.   describe_stmt(&(call.subst->out_sql_parm),vcb,'<');
  1904.   call.subst->jmp_on_eofscan = savestring(label_nf?label_nf:"");
  1905.   call.subst->jmp_on_error   = savestring(label_er?label_er:"");
  1906. }
  1907. call_t *
  1908. prepare_replacement(void)
  1909. {
  1910.   call_t *c;
  1911.   c = (call_t*)xmalloc ( sizeof(call_t));
  1912.   c->subst = call.subst;
  1913.   if(c->subst)  /* preserve NULL string reference */
  1914.     {
  1915.       if (!call.subst->proc_name)
  1916.         call.subst->proc_name      =  savestring("");
  1917.       if (!call.subst->jmp_on_eofscan)
  1918.         call.subst->jmp_on_eofscan =  savestring("");
  1919.       if (!call.subst->jmp_on_error)
  1920.         call.subst->jmp_on_error   =  savestring("");
  1921.     }
  1922.   return c;
  1923. }
  1924. i4_t 
  1925. sql_parse(void)
  1926. {
  1927.   i4_t rc;
  1928.   yydebug=parse_debug;
  1929.   parse_mode=Esql;
  1930.   dyn_sql_section_id = 0;
  1931.   bzero(&call,sizeof(call));
  1932.   rc = yyparse();
  1933.   dyn_sql_stmt_name = NULL;
  1934.   return rc;
  1935. }