Added quantiling UDAFs
[com/gs-lite.git] / src / ftacmp / parse_fta.h
1 /* ------------------------------------------------\r
2 Copyright 2014 AT&T Intellectual Property\r
3    Licensed under the Apache License, Version 2.0 (the "License");\r
4    you may not use this file except in compliance with the License.\r
5    You may obtain a copy of the License at\r
6 \r
7      http://www.apache.org/licenses/LICENSE-2.0\r
8 \r
9    Unless required by applicable law or agreed to in writing, software\r
10    distributed under the License is distributed on an "AS IS" BASIS,\r
11    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
12    See the License for the specific language governing permissions and\r
13    limitations under the License.\r
14  ------------------------------------------- */\r
15 #ifndef _FTA_PARSE_H_INCLUDED__\r
16 #define _FTA_PARSE_H_INCLUDED__\r
17 \r
18 #include<stdio.h>\r
19 #include<ctype.h>\r
20 \r
21         int yyparse();\r
22         void yyerror(char *s);\r
23         int yylex();\r
24 extern int flex_fta_lineno, flex_fta_ch;\r
25 \r
26 /*              Interface to FTA Parser         */\r
27 void FtaParser_setfileinput(FILE *f);\r
28 void FtaParser_setstringinput(char *s);\r
29 \r
30 \r
31 /*              Get type defines.       */\r
32 #include"type_objects.h"\r
33 #include"literal_types.h"\r
34 #include"type_indicators.h"\r
35 \r
36 #include <string>\r
37 #include <vector>\r
38 #include <map>\r
39 #include <math.h>\r
40 #include <string>\r
41 #include <stdio.h>\r
42 #include <stdlib.h>\r
43 \r
44 \r
45 //              colref_t::is_equivalent needs to understand the schema\r
46 #include"parse_schema.h"\r
47 class colref_t;\r
48 \r
49 \r
50 \r
51 class var_pair_t{\r
52 public:\r
53   std::string name;\r
54   std::string val;\r
55 \r
56   var_pair_t(char *n, char *v){\r
57         name=n; val=v;\r
58 //printf("NEW var_pair_t(%s, %s)\n",n,v);\r
59         };\r
60 \r
61   var_pair_t(const std::string n, const std::string v){\r
62         name=n; val=v;\r
63         };\r
64 };\r
65 \r
66 typedef std::map< std::string, std::string > ss_map;\r
67 \r
68 class var_defs_t{\r
69 private:\r
70         std::vector<var_pair_t *> namevec;\r
71 \r
72 public:\r
73         var_defs_t(var_pair_t *vp){\r
74                 namevec.push_back(vp);\r
75         };\r
76 \r
77         var_defs_t *add_var_pair(var_pair_t *vp){\r
78                 namevec.push_back(vp);\r
79                 return(this);\r
80         };\r
81 \r
82         std::vector<var_pair_t *> get_nvec(){return namevec;};\r
83 \r
84         int size(){return namevec.size();};\r
85 \r
86         int find_name(std::string n){\r
87                 int i;\r
88                 for(i=0;i<namevec.size();i++){\r
89                         if(namevec[i]->name == n)\r
90                                 return i;\r
91                 }\r
92                 return -1;\r
93         }\r
94         std::string get_name(int i){\r
95                 if(i>=0 && i<namevec.size()){\r
96                         return(namevec[i]->name);\r
97                 }else{\r
98                         return("");\r
99                 }\r
100         }\r
101 \r
102         std::string get_def(int i){\r
103                 if(i>=0 && i<namevec.size()){\r
104                         return(namevec[i]->val);\r
105                 }else{\r
106                         return("");\r
107                 }\r
108         }\r
109 \r
110         std::string dump(){\r
111                 int i;\r
112                 std::string ret;\r
113                 for(i=0;i<namevec.size();++i){\r
114                         ret += "\t"+namevec[i]->name+" = "+namevec[i]->val+"\n";\r
115                 }\r
116                 return ret;\r
117         }\r
118 \r
119 };\r
120 \r
121 \r
122 \r
123 \r
124 //              literal type constants are defined in literal_types.h\r
125 //              (must share this info with type_objects.h)\r
126 \r
127 //              Represents a literal, as expected\r
128 //              NOTE: this class contains some code generation methods.\r
129 \r
130 class literal_t{\r
131 private:\r
132 \r
133 public:\r
134         std::string lstring;            /* literal value */\r
135         short int ltype;                        /* literal type */\r
136         int lineno, charno;\r
137 \r
138         int complex_literal_id; // if this literal has a complex constructor,\r
139                                                         // there is a function which constructs it)\r
140                                                         //set to the idx in the complex literal\r
141                                                         // table.  (Must store this here (instead of in SE)\r
142                                                         // because of bare literals in the IN predicate).\r
143 \r
144 \r
145         literal_t(std::string v){\r
146                 lstring = v;\r
147                 ltype = LITERAL_STRING;\r
148                 complex_literal_id = -1;\r
149                 lineno = flex_fta_lineno; charno = flex_fta_ch;\r
150         }\r
151         static literal_t *make_define_literal(const char *s, var_defs_t *d){\r
152                 int i;\r
153                 i=d->find_name(s);\r
154                 if(i<0){\r
155                         fprintf(stderr,"ERROR at line %d, char %d; DEFINE'd literal %s referenced but not in DEFINE block.\n",flex_fta_lineno, flex_fta_ch, s);\r
156                         exit(1);\r
157                 }\r
158                 return new literal_t(d->get_def(i));\r
159         }\r
160 \r
161         literal_t(const char *lit, int t){lstring = lit; ltype = t;\r
162                 lineno = flex_fta_lineno; charno = flex_fta_ch;\r
163                 complex_literal_id = -1;\r
164 \r
165 //              For some datatypes we need to modify literal so make a copy of the string\r
166                 char v[100];\r
167                 strcpy(v, lit);\r
168 \r
169 //                      Remove UL, ULL suffix from INT constants.\r
170                 if(ltype == LITERAL_INT || ltype == LITERAL_LONGINT){\r
171                         int i;\r
172                         int len=strlen(v);\r
173                         for(i=0;i<len;++i){\r
174                                 if(v[i] == 'U') v[i] = '\0';\r
175                         }\r
176                         lstring = v;\r
177                 }\r
178 \r
179 //                      HEX and LONGHEX must be converted to uint (long long uint)\r
180                 if(ltype == LITERAL_HEX){\r
181                         char *c,ltmpstr[100];\r
182                         unsigned long tmp_l;\r
183                         for(c=v; (*c)!='\0';++c){\r
184                                 if(! ( ((*c) >= '0' && (*c) <= '9') || (tolower(*c) >= 'a' && tolower(*c) <= 'f') ) ){\r
185                                         fprintf(stderr,"Syntax Error, line=%d, character=%d.  The literal %s is not a HEX constant.\n",\r
186                                                 lineno, charno, v);\r
187                                         exit(1);\r
188                                 }\r
189                         }\r
190                         sscanf(v,"%lx",&tmp_l);\r
191                         sprintf(ltmpstr,"%lu",tmp_l);\r
192                         lstring = ltmpstr;\r
193                         ltype = LITERAL_INT;\r
194                 }\r
195                 if(ltype == LITERAL_LONGHEX){\r
196                         char *c,ltmpstr[100];\r
197                         unsigned long long tmp_ll;\r
198                         for(c=v; (*c)!='\0';++c){\r
199                                 if(! ( ((*c) >= '0' && (*c) <= '9') || (tolower(*c) >= 'a' && tolower(*c) <= 'f') ) ){\r
200                                         fprintf(stderr,"Syntax Error, line=%d, character=%d.  The literal %s is not a LHEX constant.\n",\r
201                                                 lineno, charno, v);\r
202                                         exit(1);\r
203                                 }\r
204                         }\r
205                         sscanf(v,"%llx",&tmp_ll);\r
206                         sprintf(ltmpstr,"%llu",tmp_ll);\r
207                         lstring = ltmpstr;\r
208                         ltype = LITERAL_LONGINT;\r
209                 }\r
210 //                      Convert IP to uint\r
211                 if(ltype == LITERAL_IP){\r
212                         char ltmpstr[100];\r
213                         unsigned int o1,o2,o3,o4,tmp_l;\r
214                         if(sscanf(v,"%u.%u.%u.%u",&o1,&o2,&o3,&o4) != 4){\r
215                                         fprintf(stderr,"Syntax Error, line=%d, character=%d.  The literal %s is not an IP constant.\n",\r
216                                                 lineno, charno, v);\r
217                                         exit(1);\r
218                         }\r
219                         if( (o1>255) || (o2>255) || (o3>255) || (o4>255) ){\r
220                                         fprintf(stderr,"Syntax Error, line=%d, character=%d.  The literal %s is not an IP constant.\n",\r
221                                                 lineno, charno, v);\r
222                                         exit(1);\r
223                         }\r
224                         tmp_l = (o1<<24)+(o2<<16)+(o3<<8)+o4;\r
225                         sprintf(ltmpstr,"%u",tmp_l);\r
226                         lstring = ltmpstr;\r
227                         ltype = LITERAL_IP;\r
228                 }\r
229         };\r
230 \r
231 //                      used to create literals with a default or initial value.\r
232         literal_t(int type_indicator){\r
233                 lineno=-1; charno=-1;\r
234                 complex_literal_id = -1;\r
235 \r
236                 switch(type_indicator){\r
237                 case UINT_TYPE:\r
238                 case INT_TYPE:\r
239                 case USHORT_TYPE:\r
240                         ltype = LITERAL_INT;\r
241                         lstring = "0";\r
242                         break;\r
243                 case ULLONG_TYPE:\r
244                 case LLONG_TYPE:\r
245                         ltype = LITERAL_LONGINT;\r
246                         lstring = "0";\r
247                         break;\r
248                 case FLOAT_TYPE:\r
249                         ltype = LITERAL_FLOAT;\r
250                         lstring = "0.0";\r
251                         break;\r
252                 case BOOL_TYPE:\r
253                         ltype = LITERAL_BOOL;\r
254                         lstring = "FALSE";\r
255                         break;\r
256                 case VSTR_TYPE:\r
257                         ltype = LITERAL_STRING;\r
258                         lstring = ""; complex_literal_id = 0; // unregistred complex lit\r
259                         break;\r
260                 case TIMEVAL_TYPE:\r
261                         ltype = LITERAL_TIMEVAL;\r
262                         lstring = "0.0";\r
263                         break;\r
264                 case IPV6_TYPE:\r
265                         ltype = LITERAL_IPV6;\r
266                         lstring = "0000:0000:0000:0000:0000:0000:0000:0000";\r
267                         complex_literal_id = 0; // unregistered complex literal\r
268                         break;\r
269                 case IP_TYPE:\r
270                         ltype = LITERAL_IP;\r
271                         lstring = "0";\r
272                         break;\r
273                 default:\r
274                         ltype = LITERAL_UDEF;\r
275                         lstring=" INTERNAL ERROR, UNKNOWN TYPE INDICATOR IN literal_t::literal_t(int) ";\r
276                 }\r
277         };\r
278 \r
279         std::string to_string(){return lstring;};\r
280 \r
281         int get_type(){return ltype;    };\r
282         int get_lineno(){return lineno; };\r
283         int get_charno(){return charno; };\r
284 \r
285         bool is_equivalent(literal_t *l2){\r
286                 if(ltype != l2->ltype)\r
287                         return(false);\r
288                 if(lstring != l2->lstring)\r
289                         return(false);\r
290 \r
291                 return(true);\r
292         };\r
293 \r
294 //                      Internal function to unescape control characters.\r
295         static std::string gsqlstr_to_cstr(std::string s){\r
296                 std::string retval;\r
297                 unsigned char c, prev_c='\0';\r
298                 int i;\r
299 \r
300                 for(i=0;i<s.size();++i){\r
301                         c = s[i];\r
302                         if(c=='\''){            // || c=='\\'\r
303                                 if(prev_c==c){\r
304                                         retval += c;\r
305                                         prev_c = '\0';\r
306                                 }else{\r
307                                         prev_c=c;\r
308                                 }\r
309                                 continue;\r
310                         }\r
311 \r
312                         retval += c;\r
313                         prev_c = c;\r
314                 }\r
315 \r
316                 return retval;\r
317         }\r
318 \r
319 \r
320 \r
321         std::string to_hfta_C_code(std::string param){\r
322                 std::string retval;\r
323                 double tmp_f;\r
324                 int secs, millisecs;\r
325                 char tmpstr[100];\r
326 \r
327                 switch(ltype){\r
328                 case LITERAL_STRING:\r
329                         retval.append(this->hfta_constructor_name() );\r
330                         retval.append("("+param+",\"");\r
331                         retval.append(gsqlstr_to_cstr(lstring));\r
332                         retval.append("\")");\r
333                         return(retval);\r
334                 case LITERAL_INT:\r
335                 case LITERAL_IP:\r
336                         return("((gs_uint32_t)"+lstring+")");\r
337                 case LITERAL_LONGINT:\r
338                         return("((gs_uint64_t)"+lstring+")");\r
339                 case LITERAL_FLOAT:\r
340                         return(lstring);\r
341 //              case LITERAL_HEX:\r
342 //                      return("0x"+lstring);\r
343                 case LITERAL_BOOL:\r
344                         if(lstring == "TRUE"){\r
345                                 return("1");\r
346                         }else{\r
347                                 return("0");\r
348                         }\r
349                 case LITERAL_TIMEVAL:\r
350                         retval.append(this->hfta_constructor_name() );\r
351                         tmp_f = atof(lstring.c_str());\r
352                         secs = (int)floor(tmp_f);\r
353                         millisecs = (int) rint((tmp_f - secs)*1000);\r
354                         sprintf(tmpstr,"(%d, %d)",secs,millisecs);\r
355                         retval.append(tmpstr);\r
356                         return(retval);\r
357                 case LITERAL_IPV6:\r
358                         retval = this->hfta_constructor_name();\r
359                         retval += "("+param+",\""+lstring+"\")";\r
360                         return retval;\r
361                 }\r
362 \r
363                 return("ERROR UNKNOWN LITERAL");\r
364         };\r
365 \r
366 \r
367 ///                     for LFTA code generation\r
368         std::string to_C_code(std::string param){\r
369                 std::string retval;\r
370                 double tmp_f;\r
371                 int secs, millisecs;\r
372                 char tmpstr[100];\r
373 \r
374                 switch(ltype){\r
375                 case LITERAL_STRING:\r
376                         retval = this->constructor_name()+"("+param+",\""+gsqlstr_to_cstr(lstring)+"\")";\r
377                         return(retval);\r
378                 case LITERAL_INT:\r
379                 case LITERAL_IP:\r
380                         return("((gs_uint32_t)"+lstring+")");\r
381                 case LITERAL_LONGINT:\r
382                         return("((gs_uint64_t)"+lstring+")");\r
383                 case LITERAL_FLOAT:\r
384                         return(lstring);\r
385 //              case LITERAL_HEX:\r
386 //                      return("0x"+lstring);\r
387                 case LITERAL_BOOL:\r
388                         if(lstring == "TRUE"){\r
389                                 return("1");\r
390                         }else{\r
391                                 return("0");\r
392                         }\r
393                 case LITERAL_IPV6:\r
394                         retval = this->constructor_name()+"("+param+",\""+lstring+"\")";\r
395                         return(retval);\r
396                 case LITERAL_TIMEVAL:\r
397                         retval.append(this->constructor_name() );\r
398                         tmp_f = atof(lstring.c_str());\r
399                         secs = (int)floor(tmp_f);\r
400                         millisecs = (int) rint((tmp_f - secs)*1000);\r
401                         sprintf(tmpstr,"(%d, %d)",secs,millisecs);\r
402                         retval.append(tmpstr);\r
403                         return(retval);\r
404                 }\r
405 \r
406                 return("ERROR UNKNOWN LITERAL");\r
407         };\r
408 \r
409 \r
410         std::string to_query_string(){\r
411                 std::string retval;\r
412 \r
413                 switch(ltype){\r
414                 case LITERAL_IP:\r
415                 {\r
416                         unsigned int v;\r
417                         sscanf(lstring.c_str(),"%u",&v);\r
418                         int d1 = v & 0xff;\r
419                         int d2 = (v & 0xff00) >> 8;\r
420                         int d3 = (v & 0xff0000) >> 16;\r
421                         int d4 = (v & 0xff000000) >> 24;\r
422                         char ret[200];\r
423                         sprintf(ret,"IP_VAL'%u.%u.%u.%u'",d4,d3,d2,d1);\r
424                         return ret;\r
425                 }\r
426                 case LITERAL_STRING:\r
427                         retval = "'"+lstring+"'";\r
428                         return(retval);\r
429                 case LITERAL_INT:\r
430                 case LITERAL_FLOAT:\r
431                 case LITERAL_TIMEVAL:\r
432                 case LITERAL_IPV6:\r
433                 case LITERAL_BOOL:\r
434                         return(lstring);\r
435                 case LITERAL_LONGINT:\r
436                         return(lstring+"ULL");\r
437                 }\r
438 \r
439                 return("ERROR UNKNOWN LITERAL in literal_t::to_query_string");\r
440         };\r
441 \r
442 //              TODO : Use definition files instead of hardwiring these.\r
443 \r
444 //              constructor in LFTA code\r
445         std::string constructor_name(){\r
446 \r
447                 switch(ltype){\r
448                 case LITERAL_TIMEVAL:\r
449                         return("Timeval_Constructor");\r
450                 case LITERAL_IPV6:\r
451                         return("Ipv6_Constructor");\r
452                 case LITERAL_STRING:\r
453                         return("str_constructor");\r
454                 case LITERAL_INT:\r
455                 case LITERAL_IP:\r
456                 case LITERAL_LONGINT:\r
457                 case LITERAL_BOOL:\r
458                 case LITERAL_FLOAT:\r
459                         return("");\r
460                 }\r
461                 return("ERROR UNKNOWN LITERAL");\r
462         };\r
463 \r
464         std::string hfta_constructor_name(){\r
465 \r
466                 switch(ltype){\r
467                 case LITERAL_TIMEVAL:\r
468                         return("HFTA_Timeval_Constructor");\r
469                 case LITERAL_IPV6:\r
470                         return("HFTA_Ipv6_Constructor");\r
471                 case LITERAL_STRING:\r
472                         return("Vstring_Constructor");\r
473                 case LITERAL_INT:\r
474                 case LITERAL_IP:\r
475                 case LITERAL_LONGINT:\r
476                 case LITERAL_BOOL:\r
477                 case LITERAL_FLOAT:\r
478                         return("");\r
479                 }\r
480                 return("ERROR UNKNOWN LITERAL");\r
481         };\r
482 \r
483         std::string hfta_empty_literal_name(){\r
484 \r
485                 switch(ltype){\r
486                 case LITERAL_TIMEVAL:\r
487                         return("EmptyTimeval");\r
488                 case LITERAL_IPV6:\r
489                         return("EmptyIp6");\r
490                 case LITERAL_STRING:\r
491                         return("EmptyString");\r
492                 }\r
493                 return("ERROR_NOT_A_COMPLEX_LITERAL");\r
494         };\r
495 \r
496 \r
497         void set_cpx_lit_ref(int g){complex_literal_id = g;     };\r
498         int get_cpx_lit_ref(){return (complex_literal_id );     };\r
499         bool is_cpx_lit(){return(complex_literal_id  >= 0);     };\r
500 \r
501 };\r
502 \r
503 \r
504 /*\r
505                 A (null terminated) list of literals.\r
506                 Used for the IN clause\r
507 */\r
508 \r
509 class literal_list_t{\r
510 private:\r
511 \r
512 public:\r
513         std::vector<literal_t *> lit_list;\r
514         int lineno, charno;\r
515 \r
516         literal_list_t(literal_t *l){\r
517                 lit_list.push_back(l);\r
518                 lineno = flex_fta_lineno; charno = flex_fta_ch;\r
519         };\r
520 \r
521         literal_list_t(std::vector<literal_t *> lvec){\r
522                 lineno = charno = 0;\r
523                 lit_list = lvec;\r
524         };\r
525 \r
526         literal_list_t *append_literal(literal_t *l){\r
527                 lit_list.push_back(l);\r
528                 return(this);\r
529         };\r
530 \r
531         std::string to_string(){\r
532                 int i;\r
533                 std::string retval;\r
534                 for(i=0;i<lit_list.size();i++){\r
535                         if(i>0) retval.append(", ");\r
536                         retval.append(lit_list[i]->to_query_string());\r
537                 }\r
538             return(retval);\r
539         };\r
540 \r
541         std::vector<literal_t *> get_literal_vector(){return(lit_list);};\r
542 \r
543 };\r
544 \r
545 \r
546 class string_t{\r
547 public:\r
548         std::string val;\r
549         string_t(char *s){\r
550                 val = s;\r
551         }\r
552         string_t *append(char *s){\r
553                 val += s;\r
554                 return this;\r
555         }\r
556         string_t *append(char *sep, char *s){\r
557                 val += sep;\r
558                 val += s;\r
559                 return this;\r
560         }\r
561         const char *c_str(){\r
562                 return val.c_str();\r
563         }\r
564 };\r
565 \r
566 //              A tablevar is a data source in a GSQL query.\r
567 //              Every column ref must be bound to a tablevar,\r
568 //              either explicitly or via imputation.\r
569 \r
570 \r
571 class tablevar_t{\r
572 public:\r
573 //              A tablevar is a variable which binds to a named data source.\r
574 //              the variable name might be explicit in the query, or it might be\r
575 //              implicit in which case the variable name is imputed.  In either case\r
576 //              the variable name is set via the set_range_var method.\r
577 //\r
578 //              The data source is the name of either a STREAM or a PROTOCOL.\r
579 //              All STREAMS are unique, but a PROTOCOL must be bound to an\r
580 //              interface.  If the interface is not given, it is imputed to be\r
581 //              the default interface.\r
582 \r
583         std::string machine;\r
584         std::string interface;\r
585         std::string schema_name;\r
586         std::string variable_name;\r
587         std::string udop_alias;         // record UDOP ID for of UDOP\r
588                                                                 // for use by cluster manager\r
589 \r
590         int schema_ref;         // index of the table in the schema (table_list)\r
591         int opview_idx;         // index in list of operator views (if any)\r
592         bool iface_is_query;    // true if iface resolves to query\r
593                                                         // instead of specific interface.\r
594 \r
595         int properties;         // inner (0) or outer (1) join;\r
596                                                 // labeled using FROM clause,\r
597                                                 // determines join algorithm.\r
598 \r
599         int lineno, charno;\r
600 \r
601         tablevar_t(){ opview_idx = -1; schema_ref=-1; iface_is_query = false;\r
602                                 lineno=-1; charno=-1;};\r
603         tablevar_t(const char *t){schema_name=t;  interface="";\r
604                 opview_idx = -1; schema_ref = -1;\r
605                 variable_name=""; properties = 0;\r
606                 iface_is_query = false;\r
607                 lineno = flex_fta_lineno; charno = flex_fta_ch;};\r
608 \r
609         tablevar_t(const char *i, const char *s, int iq){interface=i; schema_name=s;\r
610                 opview_idx = -1; schema_ref = -1;\r
611                 variable_name=""; properties = 0;\r
612                 if(iq) iface_is_query = true; else iface_is_query = false;\r
613                 lineno = flex_fta_lineno; charno = flex_fta_ch;};\r
614 \r
615         tablevar_t(const char *m, const char *i, const char *s){\r
616                 machine = m; interface=i; schema_name=s;\r
617                 opview_idx = -1; schema_ref = -1;\r
618                 variable_name=""; properties = 0;\r
619                 iface_is_query = false;\r
620                 lineno = flex_fta_lineno; charno = flex_fta_ch;};\r
621 \r
622         tablevar_t *duplicate(){\r
623                 tablevar_t *ret = new tablevar_t();\r
624                 ret->lineno = lineno; ret->charno = charno;\r
625                 ret->schema_ref = schema_ref;\r
626                 ret->opview_idx = opview_idx;\r
627                 ret->machine = machine;\r
628                 ret->interface = interface;\r
629                 ret->schema_name = schema_name;\r
630                 ret->variable_name = variable_name;\r
631                 ret->properties = properties;\r
632                 ret->iface_is_query = iface_is_query;\r
633                 return(ret);\r
634         };\r
635 \r
636         tablevar_t *set_range_var(const char *r){\r
637                 variable_name = r;\r
638                 return(this);\r
639         };\r
640         tablevar_t *set_range_var(std::string r){\r
641                 variable_name = r;\r
642                 return(this);\r
643         };\r
644 \r
645         void set_schema(std::string s){schema_name = s;};\r
646         void set_interface(std::string i){interface=i;};\r
647         void set_machine(std::string m){machine = m;};\r
648         void set_udop_alias(std::string u){udop_alias = u;};\r
649 \r
650         void set_schema_ref(int r){schema_ref = r;};\r
651         int get_schema_ref(){return schema_ref;};\r
652 \r
653         void set_opview_idx(int i){opview_idx = i;};\r
654         int get_opview_idx(){return opview_idx;};\r
655 \r
656         void set_property(int p){properties = p;};\r
657         int get_property(){return properties;};\r
658 \r
659         bool get_ifq(){return iface_is_query;};\r
660     void set_ifq(bool b){iface_is_query = b;};\r
661 \r
662         std::string to_string(){\r
663                 std::string retval;\r
664 \r
665                 if(machine != "" && !iface_is_query)\r
666                         retval += "'"+machine+"'.";\r
667                 if(interface != ""){\r
668                         if(iface_is_query){\r
669                          retval += '['+interface+"].";\r
670                         }else{\r
671                          retval += interface+".";\r
672                         }\r
673                 }\r
674                 retval += schema_name;\r
675                 if(variable_name != "") retval+=" "+variable_name;\r
676 \r
677                 return(retval);\r
678         };\r
679 \r
680         std::string get_schema_name(){return schema_name;};\r
681         void set_schema_name(std::string n){schema_name=n;};\r
682         std::string get_var_name(){return variable_name;};\r
683         std::string get_interface(){return interface;};\r
684         std::string get_machine(){return machine;};\r
685         std::string get_udop_alias(){return udop_alias;};\r
686 \r
687         int get_lineno(){return(lineno);        };\r
688         int get_charno(){return(charno);        };\r
689 \r
690 };\r
691 \r
692 #define INNER_JOIN_PROPERTY 0\r
693 #define LEFT_OUTER_JOIN_PROPERTY 1\r
694 #define RIGHT_OUTER_JOIN_PROPERTY 2\r
695 #define OUTER_JOIN_PROPERTY 3\r
696 #define FILTER_JOIN_PROPERTY 4\r
697 \r
698 //              tablevar_list_t is the list of tablevars in a FROM clause\r
699 \r
700 struct tablevar_list_t{\r
701 public:\r
702         std::vector<tablevar_t *> tlist;\r
703         int properties;\r
704         int lineno, charno;\r
705 //              For filter join\r
706         colref_t *temporal_var;\r
707         unsigned int temporal_range;\r
708 \r
709         tablevar_list_t(){properties = -1; temporal_var = NULL;}\r
710         tablevar_list_t(tablevar_t *t){tlist.push_back(t); properties=-1; temporal_var = NULL;\r
711                 lineno = flex_fta_lineno; charno = flex_fta_ch;};\r
712         tablevar_list_t(std::vector<tablevar_t *> t){tlist = t; properties=-1; temporal_var = NULL;\r
713                 lineno = 0; charno = 0;};\r
714 \r
715         tablevar_list_t *duplicate(){\r
716                 tablevar_list_t *ret = new tablevar_list_t();\r
717                 ret->lineno = lineno; ret->charno = charno;\r
718                 ret->properties = properties;\r
719                 ret->temporal_var = temporal_var;\r
720                 ret->temporal_range = temporal_range;\r
721                 int i;\r
722                 for(i=0;i<tlist.size();++i){\r
723                         ret->append_table(tlist[i]->duplicate());\r
724                 }\r
725                 return(ret);\r
726         }\r
727 \r
728 \r
729 \r
730         tablevar_list_t *append_table(tablevar_t *t){\r
731                 tlist.push_back(t);\r
732                 return(this);\r
733         };\r
734 \r
735         std::string to_string(){\r
736                 int i;\r
737                 std::string retval;\r
738 \r
739                 for(i=0;i<tlist.size();i++){\r
740                         if(i>0) retval.append(", ");\r
741                         retval.append(tlist[i]->to_string());\r
742                 }\r
743                 return(retval);\r
744         };\r
745 \r
746         std::vector<tablevar_t *> get_table_list(){return(tlist);       };\r
747 \r
748         std::vector<std::string> get_table_names(){\r
749                 std::vector<std::string> ret;\r
750                 int t;\r
751                 for(t=0;t<tlist.size();++t){\r
752                         std::string tbl_name = tlist[t]->get_schema_name();\r
753                         ret.push_back(tbl_name);\r
754                 }\r
755                 return(ret);\r
756         }\r
757 \r
758         std::vector<std::string> get_src_tbls(table_list *Schema){\r
759                 std::vector<std::string> ret;\r
760                 int t, sq;\r
761                 for(t=0;t<tlist.size();++t){\r
762                         std::string tbl_name = tlist[t]->get_schema_name();\r
763                         int sid = Schema->find_tbl(tbl_name);\r
764                         if(sid < 0){ ret.push_back(tbl_name);\r
765                         }else\r
766                         if(Schema->get_schema_type(sid) != OPERATOR_VIEW_SCHEMA){\r
767                                 ret.push_back(tbl_name);\r
768                         }else{\r
769                                 std::vector<subquery_spec *> sqspec = Schema->get_subqueryspecs(sid);\r
770                                 for(sq=0;sq<sqspec.size();++sq){\r
771                                         ret.push_back(sqspec[sq]->name);\r
772                                 }\r
773                         }\r
774                 }\r
775                 return(ret);\r
776         };\r
777 \r
778         int size(){\r
779                 return tlist.size();\r
780         };\r
781 \r
782 //              Some accessor functions.\r
783 \r
784         std::vector<std::string> get_schema_names(){\r
785                 int i;\r
786                 std::vector<std::string > retval;\r
787                 for(i=0;i<tlist.size();i++){\r
788                         retval.push_back(tlist[i]->get_schema_name());\r
789                 }\r
790                 return(retval);\r
791         }\r
792 \r
793         std::vector<int> get_schema_refs(){\r
794                 int i;\r
795                 std::vector<int> retval;\r
796                 for(i=0;i<tlist.size();i++){\r
797                         retval.push_back(tlist[i]->get_schema_ref());\r
798                 }\r
799                 return(retval);\r
800         }\r
801 \r
802 \r
803         int get_schema_ref(int i){\r
804                 if(i<0 || i>=tlist.size()) return(-1);\r
805                 return tlist[i]->get_schema_ref();\r
806         };\r
807 \r
808         std::string get_tablevar_name(int i){\r
809                 if(i<0 || i>=tlist.size()) return("");\r
810                 return tlist[i]->get_var_name();\r
811         };\r
812 \r
813         void set_properties(int p){properties = p;};\r
814         int get_properties(){return properties;};\r
815 \r
816         void set_colref(colref_t *c){temporal_var = c;};\r
817         void set_temporal_range(unsigned int t){temporal_range = t;};\r
818         void set_temporal_range(const char *t){temporal_range= atoi(t);};\r
819         colref_t *get_colref(){return temporal_var;};\r
820         unsigned int get_temporal_range(){return temporal_range;};\r
821 \r
822 };\r
823 \r
824 //                      A reference to an interface parameter.\r
825 //                      (I need to be able to record the source\r
826 //                       tablevar, else this would be a lot simpler).\r
827 class ifpref_t{\r
828 public:\r
829         std::string tablevar;\r
830         std::string pname;\r
831         int tablevar_ref;\r
832         int lineno, charno;\r
833 \r
834         ifpref_t(const char *p){\r
835                 tablevar="";\r
836                 pname = p;\r
837                 tablevar_ref = -1;\r
838                 lineno = flex_fta_lineno; charno = flex_fta_ch;\r
839         };\r
840 \r
841         ifpref_t(const char *t, const char *p){\r
842                 tablevar=t;\r
843                 pname = p;\r
844                 tablevar_ref = -1;\r
845                 lineno = flex_fta_lineno; charno = flex_fta_ch;\r
846         };\r
847 \r
848         void set_tablevar_ref(int i){tablevar_ref = i;};\r
849         int get_tablevar_ref(){return tablevar_ref;};\r
850         std::string get_tablevar(){return tablevar;}\r
851         void set_tablevar(std::string t){tablevar = t;};\r
852         std::string get_pname(){return pname;}\r
853         std::string to_string(){\r
854                 std::string ret;\r
855                 if(tablevar != "")\r
856                         ret += tablevar + ".";\r
857                 ret += "@"+pname;\r
858                 return ret;\r
859         };\r
860         bool is_equivalent(ifpref_t *i){\r
861                 return (tablevar_ref == i->tablevar_ref) && (pname == i->pname);\r
862         };\r
863 };\r
864 \r
865 \r
866 \r
867 \r
868 //                      A representation of a reference to a field of a\r
869 //                      stream (or table).  This reference must be bound\r
870 //                      to a particular schema (schema_ref) and to a\r
871 //                      particular table variable in the FROM clause (tablevar_ref)\r
872 //                      If the column reference was generated by the parser,\r
873 //                      it will contain some binding text wich might need\r
874 //                      interpretation to do the actual binding.\r
875 class colref_t{\r
876 public:\r
877         std::string interface;          // specified interface, if any.\r
878         std::string table_name;         // specified table name or range var, if any.\r
879         std::string field;                      // field name\r
880         bool default_table;                     // true iff. no table or range var given.\r
881         int schema_ref;                         // ID of the source schema.\r
882         int tablevar_ref;                       // ID of the tablevar (in FROM clause).\r
883         int lineno, charno;\r
884 \r
885         colref_t(const char *f){\r
886                 field = f; default_table = true;\r
887                 schema_ref = -1; tablevar_ref = -1;\r
888                 lineno = flex_fta_lineno; charno = flex_fta_ch;\r
889         };\r
890 \r
891         colref_t(const char *t, const char *f){\r
892                 table_name = t; field=f; default_table = false;\r
893                 schema_ref = -1; tablevar_ref = -1;\r
894                 lineno = flex_fta_lineno; charno = flex_fta_ch;\r
895         };\r
896 \r
897         colref_t(const char *i, const char *t, const char *f){\r
898                 interface=i;\r
899                 table_name = t; field=f; default_table = false;\r
900                 schema_ref = -1; tablevar_ref = -1;\r
901                 lineno = flex_fta_lineno; charno = flex_fta_ch;\r
902         };\r
903 \r
904         colref_t *duplicate(){\r
905                 colref_t *retval = new colref_t(interface.c_str(), table_name.c_str(), field.c_str());\r
906                 retval->schema_ref = schema_ref;\r
907                 retval->tablevar_ref = tablevar_ref;\r
908                 retval->lineno = lineno;\r
909                 retval->charno = charno;\r
910                 retval->default_table = default_table;\r
911                 return(retval);\r
912         }\r
913 \r
914         std::string to_string(){\r
915                 if(default_table){\r
916                         return field;\r
917                 }else{\r
918                         if(interface != "") return(interface+"."+table_name+"."+field);\r
919                         return(table_name + "." + field);\r
920                 }\r
921         };\r
922 \r
923         std::string to_query_string(){\r
924                 if(default_table){\r
925                         return field;\r
926                 }else{\r
927                         if(interface != "") return(interface+"."+table_name+"."+field);\r
928                         if(table_name != "") return(table_name + "." + field);\r
929                         return(field);\r
930                 }\r
931         };\r
932 \r
933         int get_lineno(){return lineno; };\r
934         int get_charno(){return charno; };\r
935 \r
936         bool uses_default_table(){return default_table; };\r
937 \r
938         std::string get_field(){return(field);  };\r
939         void set_field(std::string f){field=f;};\r
940         std::string get_table_name(){return(table_name);};\r
941         std::string get_interface(){return(interface);};\r
942         void set_table_name(std::string t){table_name = t; default_table=false;};\r
943         void set_interface(std::string i){interface=i;};\r
944 \r
945         int get_schema_ref(){return schema_ref;}\r
946         void set_schema_ref(int s){schema_ref = s;};\r
947         int get_tablevar_ref(){return tablevar_ref;}\r
948         void set_tablevar_ref(int s){tablevar_ref = s;};\r
949 \r
950 //                      Should equivalence be based on tablevar_ref or schema_ref?\r
951         bool is_equivalent(colref_t *c2){\r
952                 if(schema_ref == c2->schema_ref){\r
953                         return(field == c2->field);\r
954                 }\r
955                 return(false);\r
956         };\r
957 \r
958         bool is_equivalent_base(colref_t *c2, table_list *Schema){\r
959                 if(Schema->get_basetbl_name(schema_ref,field) ==\r
960                    Schema->get_basetbl_name(c2->schema_ref,c2->field)){\r
961                         return(field == c2->field);\r
962                 }\r
963                 return(false);\r
964         };\r
965 };\r
966 \r
967 class colref_list_t{\r
968 public:\r
969         std::vector<colref_t *> clist;\r
970 \r
971 //      colref_list_t(){};\r
972 \r
973         colref_list_t(colref_t *c){\r
974                 clist.push_back(c);\r
975         }\r
976 \r
977         colref_list_t *append(colref_t *c){\r
978                 clist.push_back(c);\r
979                 return this;\r
980         }\r
981 \r
982         std::vector<colref_t *> get_clist(){\r
983                 return clist;\r
984         }\r
985 };\r
986 \r
987 \r
988 \r
989 \r
990 \r
991 \r
992 /*\r
993                 A tree containing a scalar expression.\r
994                         Used for\r
995                                 atom : a parameter or a literal\r
996                                 scalar_exp (see the scalar_exp: rule in emf.l for details)\r
997                                 function_ref (a function that has a value, e.g. an aggregate\r
998                                                                 function).\r
999                 operator_type defines the contents of the node.  If its a non-terminal,\r
1000                 then op has a meaning and defines the operation.  See the list of\r
1001                 #define'd constants following the structure definition.\r
1002 \r
1003 \r
1004 */\r
1005 \r
1006 #define SE_LITERAL 1\r
1007 #define SE_PARAM 2\r
1008 #define SE_COLREF 3\r
1009 #define SE_UNARY_OP 4\r
1010 #define SE_BINARY_OP 5\r
1011 #define SE_AGGR_STAR 6\r
1012 #define SE_AGGR_SE 7\r
1013 #define SE_FUNC 8\r
1014 #define SE_IFACE_PARAM 9\r
1015 \r
1016 \r
1017 class scalarexp_t{\r
1018 public:\r
1019         int operator_type;\r
1020         std::string op;\r
1021         union{\r
1022                 scalarexp_t *scalarp;\r
1023                 literal_t *litp;\r
1024                 colref_t *colref;\r
1025                 ifpref_t *ifp;\r
1026         } lhs;\r
1027         union{\r
1028                 scalarexp_t *scalarp;\r
1029         } rhs;\r
1030         std::vector<scalarexp_t *> param_list;\r
1031 \r
1032 //              SE node decorations -- results of query analysis.\r
1033         data_type *dt;\r
1034         int gb_ref;                             // set to the gb attr tbl ref, else -1\r
1035         int aggr_id;                    // set to the aggr tbl ref, else -1\r
1036         int fcn_id;                             // external function table ref, else -1\r
1037         int partial_ref;                // partial fcn table ref, else -1\r
1038         int fcn_cache_ref;              // function cache ref, else -1\r
1039         int handle_ref;                 // Entry in pass-by-handle parameter table, else -1.\r
1040                                                         // (might be a literal or a query param).\r
1041         bool is_superagg;               // true if is aggregate and associated with supergroup.\r
1042         std::string storage_state;      // storage state of stateful fcn,\r
1043                                                                 // empty o'wise.\r
1044 \r
1045         int lineno, charno;\r
1046 \r
1047         void default_init(){\r
1048                 operator_type = 0;\r
1049                 gb_ref = -1; aggr_id = -1;      fcn_id = -1;\r
1050                 partial_ref = -1; fcn_cache_ref=-1;\r
1051                 handle_ref = -1;\r
1052                 dt = NULL; lineno = flex_fta_lineno; charno = flex_fta_ch;\r
1053                 is_superagg = false;\r
1054                 };\r
1055 \r
1056         scalarexp_t(){\r
1057                 default_init();};\r
1058 \r
1059         scalarexp_t(colref_t *c){\r
1060                 default_init();\r
1061                 operator_type = SE_COLREF;\r
1062                 lhs.colref = c;\r
1063         };\r
1064 \r
1065         scalarexp_t(literal_t *l){\r
1066                 default_init();\r
1067                 operator_type = SE_LITERAL;\r
1068                 lhs.litp = l;\r
1069         };\r
1070 \r
1071         void convert_to_literal(literal_t *l){\r
1072 //              default_init();\r
1073                 if(operator_type != SE_IFACE_PARAM){\r
1074                         fprintf(stderr,"INTERNAL ERROR in literal_t::convert_to_literal, operator type isn't SE_IFACE_PARAM.\n");\r
1075                         exit(1);\r
1076                 }\r
1077                 operator_type = SE_LITERAL;\r
1078                 lhs.litp = l;\r
1079         }\r
1080 \r
1081         scalarexp_t(const char *o, scalarexp_t *operand){\r
1082                 default_init();\r
1083                 operator_type = SE_UNARY_OP;\r
1084                 op = o;\r
1085                 lhs.scalarp = operand;\r
1086         };\r
1087 \r
1088         scalarexp_t(const char *o, scalarexp_t *l_op, scalarexp_t *r_op){\r
1089                 default_init();\r
1090                 operator_type = SE_BINARY_OP;\r
1091                 op = o;\r
1092                 lhs.scalarp = l_op;\r
1093                 rhs.scalarp = r_op;\r
1094         };\r
1095 \r
1096         scalarexp_t(const char *o, std::vector<scalarexp_t *> op_list){\r
1097                 default_init();\r
1098                 operator_type = SE_FUNC;\r
1099                 op = o;\r
1100                 param_list = op_list;\r
1101         };\r
1102 \r
1103         static scalarexp_t *make_paramless_fcn(const char *o){\r
1104                 scalarexp_t *ret = new scalarexp_t();\r
1105                 ret->operator_type = SE_FUNC;\r
1106                 ret->op = o;\r
1107                 return(ret);\r
1108         };\r
1109 \r
1110         static scalarexp_t *make_star_aggr(const char *ag){\r
1111                 scalarexp_t *ret = new scalarexp_t();\r
1112                 ret->operator_type = SE_AGGR_STAR;\r
1113                 ret->op = ag;\r
1114                 return(ret);\r
1115         };\r
1116 \r
1117         static scalarexp_t *make_se_aggr(const char *ag, scalarexp_t *l_op){\r
1118                 scalarexp_t *ret = new scalarexp_t();\r
1119                 ret->operator_type = SE_AGGR_SE;\r
1120                 ret->op = ag;\r
1121                 ret->lhs.scalarp = l_op;\r
1122                 return(ret);\r
1123         };\r
1124 \r
1125         static scalarexp_t *make_param_reference(const char *param){\r
1126                 scalarexp_t *ret = new scalarexp_t();\r
1127                 ret->operator_type = SE_PARAM;\r
1128                 ret->op = param;\r
1129                 return(ret);\r
1130         };\r
1131 \r
1132         static scalarexp_t *make_iface_param_reference(ifpref_t *i){\r
1133                 scalarexp_t *ret = new scalarexp_t();\r
1134                 ret->operator_type = SE_IFACE_PARAM;\r
1135                 ret->lhs.ifp = i;\r
1136                 return(ret);\r
1137         };\r
1138 \r
1139 \r
1140         std::string to_string(){\r
1141                 if(operator_type == SE_COLREF){\r
1142                         return lhs.colref->to_string();\r
1143                 }\r
1144                 if(operator_type == SE_LITERAL){\r
1145                         return lhs.litp->to_string();\r
1146                 }\r
1147                 if(operator_type == SE_UNARY_OP){\r
1148                         return op + " (" + lhs.scalarp->to_string() + ")";\r
1149                 }\r
1150                 if(operator_type == SE_BINARY_OP){\r
1151                         return "(" + lhs.scalarp->to_string() + " " + op + " " + rhs.scalarp->to_string() + ")";\r
1152                 }\r
1153                 return("");\r
1154         };\r
1155 \r
1156         scalarexp_t *get_left_se(){return lhs.scalarp;  };\r
1157         scalarexp_t *get_right_se(){return rhs.scalarp; };\r
1158         int get_operator_type(){return operator_type;   };\r
1159         std::string & get_op(){return op;       };\r
1160         std::string & get_param_name(){return op;       };\r
1161 //      std::string & get_iface_param_name(){return op; };\r
1162         colref_t *get_colref(){return lhs.colref;       };\r
1163         ifpref_t *get_ifpref(){return lhs.ifp;  };\r
1164         literal_t *get_literal(){return lhs.litp;       };\r
1165 \r
1166         int get_lineno(){return lineno; };\r
1167         int get_charno(){return charno; };\r
1168 \r
1169         void set_data_type(data_type *d){dt=d;  };\r
1170         data_type *get_data_type(){return dt;   };\r
1171         void reset_temporal(){if(dt!=NULL) dt->reset_temporal();}\r
1172 \r
1173         void set_gb_ref(int g){gb_ref = g;      };\r
1174         int get_gb_ref(){return (gb_ref);       };\r
1175         bool is_gb(){return(gb_ref >= 0);       };\r
1176 \r
1177         void set_aggr_id(int a){aggr_id = a;};\r
1178         int get_aggr_ref(){return(aggr_id);     };\r
1179 \r
1180         void set_storage_state(std::string s){storage_state = s;};\r
1181         std::string get_storage_state(){return storage_state;};\r
1182 \r
1183         std::vector<scalarexp_t *> get_operands(){return param_list;};\r
1184         void set_fcn_id(int f){fcn_id = f;      };\r
1185         int get_fcn_id(){return fcn_id; };\r
1186 \r
1187         void set_partial_ref(int p){partial_ref = p;    };\r
1188         int get_partial_ref(){return partial_ref;       };\r
1189         bool is_partial(){return partial_ref >= 0;      };\r
1190 \r
1191         void set_fcncache_ref(int p){fcn_cache_ref = p; };\r
1192         int get_fcncache_ref(){return fcn_cache_ref;    };\r
1193         bool is_fcncached(){return fcn_cache_ref >= 0;  };\r
1194 \r
1195         void set_handle_ref(int tf){handle_ref = tf;    };\r
1196         int get_handle_ref(){return handle_ref; };\r
1197         bool is_handle_ref(){return handle_ref>=0;      };\r
1198 \r
1199         void set_superaggr(bool b){is_superagg=b;};\r
1200         bool is_superaggr(){return is_superagg;};\r
1201 \r
1202         void use_decorations_of(scalarexp_t *se){\r
1203                 if(se->get_data_type() != NULL)\r
1204                         dt = se->get_data_type()->duplicate();\r
1205                 gb_ref = se->gb_ref;\r
1206                 aggr_id = se->aggr_id;\r
1207                 fcn_id = se->fcn_id;\r
1208                 partial_ref = se->partial_ref;\r
1209                 handle_ref = se->handle_ref;\r
1210                 lineno = se->lineno;\r
1211                 charno = se->charno;\r
1212                 is_superagg = se->is_superagg;\r
1213         };\r
1214 };\r
1215 \r
1216 \r
1217 /*\r
1218                 A (null terminated) list of scalar expressions.\r
1219                 Used for\r
1220                         selection, scalar_exp_commalist\r
1221 */\r
1222 \r
1223 class se_list_t{\r
1224 public:\r
1225         std::vector<scalarexp_t *> se_list;\r
1226         int lineno, charno;\r
1227 \r
1228         se_list_t(scalarexp_t *s){se_list.push_back(s);\r
1229                 lineno = flex_fta_lineno; charno = flex_fta_ch;};\r
1230 \r
1231         se_list_t *append(scalarexp_t *s){\r
1232                         se_list.push_back(s);\r
1233                         return(this);\r
1234         };\r
1235 \r
1236         std::string to_string(){\r
1237                 int i;\r
1238                 std::string retval;\r
1239                 for(i=0;i<se_list.size();i++){\r
1240                         if(i>0) retval.append(", ");\r
1241                         retval.append(se_list[i]->to_string());\r
1242                 }\r
1243                 return(retval);\r
1244         };\r
1245 \r
1246         std::vector<scalarexp_t *> get_se_list(){return se_list;        };\r
1247 \r
1248 \r
1249 };\r
1250 \r
1251 /*\r
1252                 select_commalist : collect some additional info about\r
1253                 the selected things -- mostly the name.\r
1254 */\r
1255 \r
1256 struct select_element{\r
1257         scalarexp_t *se;\r
1258         std::string name;\r
1259 \r
1260         select_element(){se=NULL; name="";};\r
1261         select_element(scalarexp_t *s){se=s; name="";};\r
1262         select_element(scalarexp_t *s, std::string n){se=s; name=n;};\r
1263 };\r
1264 \r
1265 class select_list_t{\r
1266 public:\r
1267         std::vector<select_element *> select_list;\r
1268         int lineno, charno;\r
1269 \r
1270         select_list_t(){lineno = -1; charno = -1;};\r
1271         select_list_t(scalarexp_t *s){select_list.push_back(new select_element(s));\r
1272                 lineno = flex_fta_lineno; charno = flex_fta_ch;};\r
1273         select_list_t(scalarexp_t *s, std::string n){\r
1274                 select_list.push_back(new select_element(s,n));\r
1275                 lineno = flex_fta_lineno; charno = flex_fta_ch;\r
1276         };\r
1277         select_list_t *append(scalarexp_t *s){\r
1278                         select_list.push_back(new select_element(s));\r
1279                         return(this);\r
1280         };\r
1281         select_list_t *append(scalarexp_t *s, std::string n){\r
1282                         select_list.push_back(new select_element(s,n));\r
1283                         return(this);\r
1284         };\r
1285 \r
1286         std::string to_string(){\r
1287                 int i;\r
1288                 std::string retval;\r
1289                 for(i=0;i<select_list.size();i++){\r
1290                         if(i>0) retval.append(", ");\r
1291                         retval.append(select_list[i]->se->to_string());\r
1292                         if(select_list[i]->name != "")\r
1293                                 retval += " AS " + select_list[i]->name;\r
1294 \r
1295                 }\r
1296                 return(retval);\r
1297         };\r
1298 \r
1299         std::vector<select_element *> get_select_list(){return select_list;     };\r
1300         std::vector<scalarexp_t *> get_select_se_list(){\r
1301                 std::vector<scalarexp_t *> ret;\r
1302                 int i;\r
1303                 for(i=0; i<select_list.size();++i) ret.push_back(select_list[i]->se);\r
1304                 return ret;\r
1305         };\r
1306 };\r
1307 \r
1308 \r
1309 \r
1310 #define GB_COLREF 1\r
1311 #define GB_COMPUTED 2\r
1312 \r
1313 class gb_t{\r
1314 public:\r
1315         std::string name;\r
1316         std::string table;\r
1317         std::string interface;\r
1318         scalarexp_t *def;\r
1319         int type;\r
1320         int lineno, charno;\r
1321 \r
1322         gb_t(const char *field_name){\r
1323                 interface="";\r
1324                 name = field_name; table=""; def=NULL; type=GB_COLREF;\r
1325                 lineno = flex_fta_lineno; charno = flex_fta_ch;\r
1326         };\r
1327 \r
1328         gb_t(const char *table_name, const char *field_name){\r
1329                 interface="";\r
1330                 name = field_name; table=""; def=NULL; type=GB_COLREF;\r
1331                 lineno = flex_fta_lineno; charno = flex_fta_ch;\r
1332         };\r
1333 \r
1334         gb_t(const char *iface, const char *table_name, const char *field_name){\r
1335                 interface=iface;\r
1336                 name = field_name; table=""; def=NULL; type=GB_COLREF;\r
1337                 lineno = flex_fta_lineno; charno = flex_fta_ch;\r
1338         };\r
1339 \r
1340         gb_t( scalarexp_t *s, const char *gname){\r
1341                 name = gname; table = ""; def = s; type = GB_COMPUTED;\r
1342                 lineno = flex_fta_lineno; charno = flex_fta_ch;\r
1343         };\r
1344 \r
1345         std::string to_string(){\r
1346                 std::string retval;\r
1347                 if(type == GB_COLREF){\r
1348                         if(table != ""){\r
1349                                 retval = table;\r
1350                                 retval.append(".");\r
1351                         }\r
1352                         retval.append(name);\r
1353                 }\r
1354                 if(type == GB_COMPUTED){\r
1355                         retval = "(scalarexp) AS ";\r
1356                         retval.append(name);\r
1357                 }\r
1358                 return(retval);\r
1359         };\r
1360 \r
1361         gb_t *duplicate();\r
1362 \r
1363 };\r
1364 \r
1365 /*\r
1366                 A (null terminated) list of group by attributes\r
1367 */\r
1368 \r
1369 class gb_list_t{\r
1370 public:\r
1371         std::vector<gb_t *> gb_list;\r
1372         int lineno, charno;\r
1373 \r
1374         gb_list_t(gb_t *g){gb_list.push_back(g);\r
1375                 lineno = flex_fta_lineno; charno = flex_fta_ch;};\r
1376 \r
1377         gb_list_t *append(gb_t *s){\r
1378                         gb_list.push_back(s);\r
1379                         return(this);\r
1380         };\r
1381         gb_list_t(int l, int c) : lineno(l), charno(c){ }\r
1382 \r
1383         std::string to_string(){\r
1384                 int i;\r
1385                 std::string retval;\r
1386                 for(i=0;i<gb_list.size();i++){\r
1387                         if(i>0) retval.append(", ");\r
1388                         retval.append(gb_list[i]->to_string());\r
1389                 }\r
1390                 return(retval);\r
1391         };\r
1392 \r
1393         std::vector<gb_t *> get_gb_list(){return gb_list;       };\r
1394 \r
1395         gb_list_t *duplicate(){\r
1396                 gb_list_t *ret = new gb_list_t(lineno, charno);\r
1397                 int i;\r
1398                 for(i=0;i<gb_list.size();++i){\r
1399                         ret->append(gb_list[i]->duplicate());\r
1400                 }\r
1401 \r
1402                 return ret;\r
1403         }\r
1404 \r
1405 \r
1406 };\r
1407 \r
1408 class list_of_gb_list_t{\r
1409 public:\r
1410         std::vector<gb_list_t *> gb_lists;\r
1411 \r
1412         list_of_gb_list_t(gb_list_t *gl){\r
1413                 gb_lists.push_back(gl);\r
1414         }\r
1415 \r
1416         list_of_gb_list_t *append(gb_list_t *gl){\r
1417                 gb_lists.push_back(gl);\r
1418                 return this;\r
1419         }\r
1420 };\r
1421 \r
1422 \r
1423 enum extended_gb_type {no_egb_type, gb_egb_type, rollup_egb_type,\r
1424                         cube_egb_type, gsets_egb_type};\r
1425 class extended_gb_t{\r
1426 public:\r
1427 \r
1428         extended_gb_type type;\r
1429         gb_t *gb;\r
1430         std::vector<gb_list_t *> gb_lists;\r
1431 \r
1432         extended_gb_t(){\r
1433                 gb = NULL;\r
1434                 type = no_egb_type;\r
1435         }\r
1436 \r
1437         ~extended_gb_t(){\r
1438         }\r
1439 \r
1440         static extended_gb_t *create_from_gb(gb_t *g){\r
1441                 extended_gb_t *ret  = new extended_gb_t();\r
1442                 ret->type = gb_egb_type;\r
1443                 ret->gb = g;\r
1444                 return ret;\r
1445         }\r
1446 \r
1447         static extended_gb_t *extended_create_from_rollup(gb_list_t *gl){\r
1448                 extended_gb_t *ret  = new extended_gb_t();\r
1449                 ret->type = rollup_egb_type;\r
1450                 ret->gb_lists.push_back(gl);\r
1451                 return ret;\r
1452         }\r
1453 \r
1454         static extended_gb_t *extended_create_from_cube(gb_list_t *gl){\r
1455                 extended_gb_t *ret  = new extended_gb_t();\r
1456                 ret->type = cube_egb_type;\r
1457                 ret->gb_lists.push_back(gl);\r
1458                 return ret;\r
1459         }\r
1460 \r
1461         static extended_gb_t *extended_create_from_gsets(list_of_gb_list_t *lgl){\r
1462                 extended_gb_t *ret  = new extended_gb_t();\r
1463                 ret->type = gsets_egb_type;\r
1464                 ret->gb_lists = lgl->gb_lists;\r
1465                 return ret;\r
1466         }\r
1467 \r
1468         extended_gb_t *duplicate(){\r
1469                 extended_gb_t *ret = new extended_gb_t();\r
1470                 ret->type = type;\r
1471                 if(gb != NULL)\r
1472                         ret->gb = gb->duplicate();\r
1473                 int i;\r
1474                 for(i=0;i<gb_lists.size();++i){\r
1475                         ret->gb_lists.push_back(gb_lists[i]->duplicate());\r
1476                 }\r
1477                 return ret;\r
1478         }\r
1479 \r
1480 \r
1481         std::string to_string(){\r
1482                 std::string ret;\r
1483                 int i;\r
1484 \r
1485                 switch(type){\r
1486                 case no_egb_type:\r
1487                         return "Error, undefined extended gb type.";\r
1488                 case gb_egb_type:\r
1489                         return gb->to_string();\r
1490                 case rollup_egb_type:\r
1491                         return "ROLLUP("+gb_lists[0]->to_string()+")";\r
1492                 case cube_egb_type:\r
1493                         return "CUBE("+gb_lists[0]->to_string()+")";\r
1494                 case gsets_egb_type:\r
1495                         ret = "GROUPING_SETS(";\r
1496                         for(i=0;i<gb_lists.size();++i){\r
1497                                 if(i>0) ret+=", ";\r
1498                                 ret += "(" +gb_lists[i]->to_string()+")";\r
1499                         }\r
1500                         ret += ")";\r
1501                         return ret;\r
1502                 default:\r
1503                         break;\r
1504                 }\r
1505                 return "Error, unknown extended gb type.";\r
1506         }\r
1507 \r
1508 };\r
1509 \r
1510 class extended_gb_list_t{\r
1511 public:\r
1512         std::vector<extended_gb_t *> gb_list;\r
1513         int lineno, charno;\r
1514 \r
1515         extended_gb_list_t(extended_gb_t *g){gb_list.push_back(g);\r
1516                 lineno = flex_fta_lineno; charno = flex_fta_ch;};\r
1517 \r
1518         extended_gb_list_t *append(extended_gb_t *s){\r
1519                         gb_list.push_back(s);\r
1520                         return(this);\r
1521         };\r
1522 \r
1523         std::string to_string(){\r
1524                 int i;\r
1525                 std::string retval;\r
1526                 for(i=0;i<gb_list.size();i++){\r
1527                         if(i>0) retval.append(", ");\r
1528                         retval.append(gb_list[i]->to_string());\r
1529                 }\r
1530                 return(retval);\r
1531         };\r
1532 \r
1533         std::vector<extended_gb_t *> get_gb_list(){return gb_list;      };\r
1534 };\r
1535 \r
1536 \r
1537 \r
1538 /*\r
1539                 A predicate tree.  Structure is similar to\r
1540                 a scalar expression tree but the type is always boolean.\r
1541                 Used by\r
1542                         opt_where_clause, where_clause, opt_having_clause,\r
1543                         search_condition, predicate, comparison_predicate, repl_predicate\r
1544 */\r
1545 \r
1546 #define PRED_COMPARE 1\r
1547 #define PRED_UNARY_OP 2\r
1548 #define PRED_BINARY_OP 3\r
1549 #define PRED_FUNC 4\r
1550 #define PRED_IN 5\r
1551 \r
1552 class  predicate_t{\r
1553 public:\r
1554         int operator_type;\r
1555         std::string op;\r
1556         union {\r
1557                 predicate_t *predp;\r
1558                 scalarexp_t *sexp;\r
1559         }lhs;\r
1560         union {\r
1561                 predicate_t *predp;\r
1562                 scalarexp_t *sexp;\r
1563                 literal_list_t *ll;\r
1564         }rhs;\r
1565         std::vector<scalarexp_t *> param_list;  /// pred fcn params\r
1566         int fcn_id;                                                             /// external pred fcn id\r
1567         int combinable_ref;\r
1568         bool is_sampling_fcn;\r
1569         int lineno, charno;\r
1570 \r
1571         predicate_t(scalarexp_t *s, literal_list_t *litl){\r
1572                 operator_type = PRED_IN;\r
1573                 op = "in";\r
1574                 lhs.sexp = s;\r
1575                 rhs.ll = litl;\r
1576                 fcn_id = -1;\r
1577                 combinable_ref = -1;\r
1578                 lineno = flex_fta_lineno; charno = flex_fta_ch;\r
1579         };\r
1580 \r
1581         predicate_t(scalarexp_t *s, std::vector<literal_t *> litv){\r
1582                 operator_type = PRED_IN;\r
1583                 op = "in";\r
1584                 lhs.sexp = s;\r
1585                 rhs.ll = new literal_list_t(litv);\r
1586                 fcn_id = -1;\r
1587                 combinable_ref = -1;\r
1588                 lineno = flex_fta_lineno; charno = flex_fta_ch;\r
1589         };\r
1590 \r
1591 \r
1592         predicate_t(scalarexp_t *l_op, const char *o, scalarexp_t *r_op){\r
1593                 operator_type = PRED_COMPARE;\r
1594                 op = o;\r
1595                 lhs.sexp = l_op;\r
1596                 rhs.sexp = r_op;\r
1597                 fcn_id = -1;\r
1598                 combinable_ref = -1;\r
1599                 lineno = flex_fta_lineno; charno = flex_fta_ch;\r
1600         };\r
1601 \r
1602         predicate_t(const char *o, predicate_t *p){\r
1603                 operator_type = PRED_UNARY_OP;\r
1604                 op = o;\r
1605                 lhs.predp = p;\r
1606                 fcn_id = -1;\r
1607                 combinable_ref = -1;\r
1608                 lineno = flex_fta_lineno; charno = flex_fta_ch;\r
1609         };\r
1610 \r
1611         predicate_t(const char *o, predicate_t *l_p, predicate_t *r_p){\r
1612                 operator_type = PRED_BINARY_OP;\r
1613                 op = o;\r
1614                 lhs.predp = l_p;\r
1615                 rhs.predp = r_p;\r
1616                 fcn_id = -1;\r
1617                 combinable_ref = -1;\r
1618                 lineno = flex_fta_lineno; charno = flex_fta_ch;\r
1619         };\r
1620 \r
1621         predicate_t(const char *o, std::vector<scalarexp_t *> op_list){\r
1622                 operator_type = PRED_FUNC;\r
1623                 op = o;\r
1624                 param_list = op_list;\r
1625                 fcn_id = -1;\r
1626                 combinable_ref = -1;\r
1627                 lineno = flex_fta_lineno; charno = flex_fta_ch;\r
1628         };\r
1629 \r
1630         predicate_t(const char *o){\r
1631                 op = o;\r
1632                 fcn_id = -1;\r
1633                 combinable_ref = -1;\r
1634                 lineno = flex_fta_lineno; charno = flex_fta_ch;\r
1635         };\r
1636 \r
1637 \r
1638         static predicate_t *make_paramless_fcn_predicate(const char *o){\r
1639                 predicate_t *ret = new predicate_t(o);\r
1640                 ret->operator_type = PRED_FUNC;\r
1641                 ret->fcn_id = -1;\r
1642                 ret->combinable_ref = -1;\r
1643                 return(ret);\r
1644         };\r
1645 \r
1646         std::string to_string(){\r
1647                 if(operator_type == PRED_IN){\r
1648                         return( lhs.sexp->to_string() + " " + op + " [ " + rhs.ll->to_string() +" ]");\r
1649                 }\r
1650                 if(operator_type == PRED_COMPARE){\r
1651                         return( lhs.sexp->to_string() + " " + op + " " + rhs.sexp->to_string() );\r
1652                 }\r
1653                 if(operator_type == PRED_UNARY_OP){\r
1654                         return( op + " (" + lhs.predp->to_string() + ")" );\r
1655                 }\r
1656                 if(operator_type == PRED_BINARY_OP){\r
1657                         return( "(" + lhs.predp->to_string() + " " + op + " " + rhs.predp->to_string() + ")" );\r
1658                 }\r
1659                 if(operator_type == PRED_FUNC){\r
1660                         std::string ret = op + "[ ";\r
1661                         int i;\r
1662                         for(i=0;i<param_list.size();++i){\r
1663                                 if(i>0) ret += ", ";\r
1664                                 ret += param_list[i]->to_string();\r
1665                         }\r
1666                         ret += "] ";\r
1667                         return(ret);\r
1668                 }\r
1669                 return("");\r
1670         };\r
1671 \r
1672         std::vector<scalarexp_t *> get_op_list(){return param_list;     };\r
1673         int get_operator_type(){return operator_type;   };\r
1674         std::string get_op(){return op; };\r
1675         int get_lineno(){return lineno; };\r
1676         int get_charno(){return charno; };\r
1677         int get_combinable_ref(){return combinable_ref;}\r
1678         void set_combinable_ref(int f){combinable_ref = f;};\r
1679         predicate_t *get_left_pr(){return(lhs.predp);   };\r
1680         predicate_t *get_right_pr(){return(rhs.predp);  };\r
1681         scalarexp_t *get_left_se(){return(lhs.sexp);    };\r
1682         scalarexp_t *get_right_se(){return(rhs.sexp);   };\r
1683         std::vector<literal_t *> get_lit_vec(){return(rhs.ll->get_literal_vector());            };\r
1684 \r
1685         void swap_scalar_operands(){\r
1686                 if(operator_type != PRED_COMPARE){\r
1687                         fprintf(stderr,"INTERNAL ERROR: swap_scalar_operands called on predicate of type %d\n",operator_type);\r
1688                         exit(1);\r
1689                 }\r
1690                 scalarexp_t *tmp;\r
1691                 tmp = lhs.sexp; lhs.sexp = rhs.sexp; rhs.sexp = tmp;\r
1692                 if(op == ">"){op = "<"; return;}\r
1693                 if(op == ">="){op = "<="; return;}\r
1694                 if(op == "<"){op = ">"; return;}\r
1695                 if(op == "<="){op = ">="; return;}\r
1696         };\r
1697         void set_fcn_id(int i){fcn_id = i;};\r
1698         int get_fcn_id(){return fcn_id;};\r
1699 \r
1700 \r
1701 };\r
1702 \r
1703 \r
1704 /*\r
1705                 A structure that holds the components of a query.\r
1706                 This is the root type.\r
1707                 Used by manipulative_statement, select_statement, table_exp\r
1708 */\r
1709 \r
1710 #define SELECT_QUERY 1\r
1711 #define MERGE_QUERY 2\r
1712 \r
1713 class table_exp_t{\r
1714 public:\r
1715   int query_type;                                       // roughly, the type of the query.\r
1716   ss_map nmap;                                          //      DEFINE block\r
1717   std::vector<var_pair_t *> query_params;       // PARAM block (uninterpreted)\r
1718   select_list_t *sl;                                    // SELECT\r
1719   tablevar_list_t *fm;                                  // FROM\r
1720   predicate_t *wh;                                      // WHERE\r
1721   predicate_t *hv;                                      // HAVING\r
1722   predicate_t *cleaning_when;           // CLEANING WHEN\r
1723   predicate_t *cleaning_by;                     // CLEANING BY\r
1724   predicate_t *closing_when;            // CLOSING WHEN\r
1725   std::vector<extended_gb_t *> gb;                      // GROUP BY\r
1726   std::vector<colref_t *> mergevars;            // merge colrefs.\r
1727   std::vector<colref_t *> supergb;      // supergroup.\r
1728   scalarexp_t *slack;                           // merge slack\r
1729   bool exernal_visible;                         // true iff. it can be subscribed to.\r
1730   int lineno, charno;\r
1731 \r
1732 \r
1733   table_exp_t(tablevar_list_t *f, predicate_t *p, extended_gb_list_t *g, colref_list_t *sg, predicate_t *h, predicate_t *cw, predicate_t *cb, predicate_t *closew)\r
1734                 {fm = f; wh = p; hv = h;\r
1735                 cleaning_when = cw; cleaning_by = cb;\r
1736                 closing_when = closew;\r
1737                 if(g != NULL)\r
1738                         gb = g->gb_list;\r
1739                 if(sg != NULL)\r
1740                         supergb = sg->get_clist();\r
1741                 slack = NULL;\r
1742                 query_type = SELECT_QUERY;\r
1743                 exernal_visible = true;\r
1744                 lineno = flex_fta_lineno; charno = flex_fta_ch;\r
1745         };\r
1746 \r
1747   table_exp_t(colref_list_t *mv, tablevar_list_t *f)\r
1748                 {fm = f; mergevars=mv->get_clist();\r
1749                  slack = NULL;\r
1750                 query_type = MERGE_QUERY;\r
1751                 exernal_visible = true;\r
1752                 lineno = flex_fta_lineno; charno = flex_fta_ch;\r
1753         };\r
1754 \r
1755   table_exp_t(colref_list_t *mv, scalarexp_t *sl, tablevar_list_t *f)\r
1756                 {fm = f; mergevars=mv->get_clist();\r
1757                  slack = sl;\r
1758                 query_type = MERGE_QUERY;\r
1759                 exernal_visible = true;\r
1760                 lineno = flex_fta_lineno; charno = flex_fta_ch;\r
1761         };\r
1762 \r
1763 //                      Figure out the temporal merge field at analyze_fta time.\r
1764         static table_exp_t *make_deferred_merge(std::vector<std::string> src_tbls){\r
1765                 table_exp_t *ret = new table_exp_t();\r
1766                 ret->query_type = MERGE_QUERY;\r
1767                 ret->fm = new tablevar_list_t();\r
1768                 int t;\r
1769                 for(t=0;t<src_tbls.size();++t){\r
1770                         ret->fm->append_table(new tablevar_t(src_tbls[t].c_str()));\r
1771                 }\r
1772                 ret->lineno = 0; ret->charno = 0;\r
1773                 return ret;\r
1774         }\r
1775 \r
1776         table_exp_t(){\r
1777                 fm = NULL; sl = NULL; wh=NULL; hv=NULL;\r
1778                 slack = NULL;\r
1779                 cleaning_when=NULL; cleaning_by = NULL;\r
1780                 closing_when = NULL;\r
1781                 exernal_visible = true;\r
1782         };\r
1783 \r
1784   table_exp_t *add_selection(select_list_t *s){\r
1785           sl = s;\r
1786           return(this);\r
1787         };\r
1788 \r
1789         void add_nmap(var_defs_t *vd){\r
1790                 int n;\r
1791                 if(vd != NULL){\r
1792                         for(n=0;n<vd->size();++n){\r
1793                                 nmap[vd->get_name(n)] = vd->get_def(n);\r
1794 //printf("Adding (%s, %s) to name map.\n",vd->get_name(n).c_str(), vd->get_def(n).c_str());\r
1795                         }\r
1796                 }\r
1797         };\r
1798 \r
1799         void add_param_list(var_defs_t *vd){\r
1800                 int n;\r
1801                 if(vd != NULL){\r
1802                         query_params = vd->get_nvec();\r
1803                 }\r
1804         };\r
1805 \r
1806 \r
1807         std::string to_string(){\r
1808                 std::string retval;\r
1809                 if(sl != NULL){\r
1810                         retval.append("Select " + sl->to_string() + "\n");\r
1811                 }\r
1812                 if(fm != NULL){\r
1813                         retval.append("From " + fm->to_string() + "\n");\r
1814                 }\r
1815                 if(wh != NULL){\r
1816                         retval.append("Where "+ wh->to_string() + "\n");\r
1817                 }\r
1818                 if(hv != NULL){\r
1819                         retval.append("Having "+hv->to_string() + "\n");\r
1820                 }\r
1821                 return(retval);\r
1822                 };\r
1823 \r
1824         tablevar_list_t *get_from(){return fm;  };\r
1825         select_list_t *get_select(){return sl;  };\r
1826         std::vector<select_element *> get_sl_vec(){return sl->get_select_list();        };\r
1827         predicate_t *get_where(){return wh;     };\r
1828         predicate_t *get_having(){return hv;    };\r
1829         predicate_t *get_cleaning_by(){return cleaning_by;      };\r
1830         predicate_t *get_cleaning_when(){return cleaning_when;  };\r
1831         predicate_t *get_closing_when(){return closing_when;    };\r
1832         std::vector<extended_gb_t *> get_groupby(){return(gb);  };\r
1833     std::vector<colref_t *> get_supergb(){return supergb;};\r
1834 \r
1835         ss_map get_name_map(){return nmap;};\r
1836 \r
1837         bool name_exists(std::string nm){\r
1838                 return(nmap.count(nm) > 0);\r
1839         };\r
1840 \r
1841         std::string get_val_of_name(std::string nm){\r
1842                 if(nmap.count(nm) == 0) return("");\r
1843                 else return nmap[nm];\r
1844         };\r
1845 \r
1846         void set_val_of_name(const std::string n, const std::string v){\r
1847                 nmap[n]=v;\r
1848         }\r
1849 \r
1850         void set_visible(bool v){exernal_visible=v;};\r
1851         bool get_visible(){return exernal_visible;};\r
1852 };\r
1853 \r
1854 struct query_list_t{\r
1855         std::vector<table_exp_t *> qlist;\r
1856 \r
1857         query_list_t(table_exp_t *t){\r
1858                 qlist.push_back(t);\r
1859         };\r
1860         query_list_t *append(table_exp_t *t){\r
1861                 qlist.push_back(t);\r
1862                 return(this);\r
1863         };\r
1864 };\r
1865 \r
1866 \r
1867 #define TABLE_PARSE 1\r
1868 #define QUERY_PARSE 2\r
1869 #define STREAM_PARSE 3\r
1870 \r
1871 struct fta_parse_t{\r
1872         query_list_t *parse_tree_list;\r
1873         table_exp_t *fta_parse_tree;\r
1874         table_list *tables;\r
1875         int parse_type;\r
1876 };\r
1877 \r
1878 \r
1879 \r
1880 \r
1881 \r
1882         extern table_exp_t *fta_parse_tree;\r
1883 \r
1884 \r
1885 \r
1886 \r
1887 \r
1888 #endif\r
1889 \r