X-Git-Url: https://gerrit.o-ran-sc.org/r/gitweb?a=blobdiff_plain;f=src%2Fftacmp%2Fparse_schema.cc;h=4d2f38f11ca9b58dba3e01e104b1628e7e909592;hb=8b04ba410b46bc4853dfda7095d2a2229b609003;hp=d22bdb4b5c64684cda40dedc4346f92d8cf0d8a1;hpb=07495effe193ca3f73c3bf0ce417068f9ac9dcdd;p=com%2Fgs-lite.git diff --git a/src/ftacmp/parse_schema.cc b/src/ftacmp/parse_schema.cc index d22bdb4..4d2f38f 100644 --- a/src/ftacmp/parse_schema.cc +++ b/src/ftacmp/parse_schema.cc @@ -1,524 +1,550 @@ -/* ------------------------------------------------ -Copyright 2014 AT&T Intellectual Property - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - ------------------------------------------- */ - -#include -#include"parse_fta.h" -#include "parse_schema.h" -#include "type_objects.h" -#include -#include -// #include -#include - -using namespace std; - -table_list *Schema; - -table_def::table_def(const char *name, param_list *oprop, field_entry_list *fel, - subqueryspec_list *ql, param_list *selp){ - table_name =name; - fields = fel->get_list(); - schema_type = OPERATOR_VIEW_SCHEMA; - qspec_list = ql->spec_list; - - if(oprop == NULL) op_properties = new param_list(); - else op_properties = oprop; - if(selp == NULL) selpush = new param_list(); - else selpush = selp; - base_tables = new param_list(); -}; - -table_def *table_def::make_shallow_copy(string n){ - table_def *ret = new table_def(); - ret->table_name = n; - ret->fields = fields; - ret->schema_type = schema_type; - ret->base_tables = base_tables; - ret->op_properties = op_properties; - ret->qspec_list = qspec_list; - ret->selpush = selpush; - - return ret; -} - -void table_def::mangle_subq_names(std::string mngl){ - int i; - for(i=0;iduplicate(); - s->name += mngl; - qspec_list[i] = s; - } -} - - - -bool table_def::contains_field(string f){ - int i; - - for(i=0;iget_name() == f){ - return(true); - } - } - return(false); - -} - -int table_def::get_field_idx(std::string f){ - int i; - for(i=0;iget_name() == f){ - return(i); - } - } - return(-1); -} - - -string table_def::get_type_name(std::string f){ - int i; - for(i=0;iget_name() == f){ - return(fields[i]->get_type()); - } - } - return("INTERNAL ERROR undefined field " + f); -} - -param_list *table_def::get_modifier_list(std::string f){ - int i; - for(i=0;iget_name() == f){ - return(fields[i]->get_modifier_list()); - } - } - fprintf(stderr,"INTERNAL ERROR, no field %s in table %s, call is get_modifier_list.\n", - f.c_str(), table_name.c_str() ); - exit(1); - return(NULL); -} - - -string table_def::get_fcn(std::string f){ - int i; - for(i=0;iget_name() == f){ - return(fields[i]->get_fcn()); - } - } - return("INTERNAL ERROR undefined field " + f); - -} - - -string table_def::get_field_basetable(std::string f){ - int i; - for(i=0;iget_name() == f){ - return(fields[i]->get_basetable()); - } - } - return("INTERNAL ERROR undefined field " + f); - -} - -int table_def::verify_no_duplicates(std::string &err){ - - int f1, f2; - for(f1=0;f1get_name(); - for(f2=f1+1;f2get_name()){ - err.append("Error, table "); - err.append(table_name); - err.append(" has a duplicate field :"); - err.append(f1_name); - err.append("\n"); - return(1); - } - } - } - return(0); -} - -int table_def::verify_access_fcns(std::string &err){ - int retval = 0, f; - - for(f=0;fget_fcn() == ""){ - err += "Error, PROTOCOL field "+table_name+"."+fields[f]->get_name()+" has an empty access function.\n"; - retval = 1; - } - } - - return(retval); -} - -int table_def::add_field(field_entry *fe){ - string fe_name = fe->get_name(); - int f; - - for(f=0;fget_name()){ - return(-1); - } - } - fields.push_back(fe); - return(0); -} - - -vector table_list::get_table_names(){ - vector retval; - int i; - for(i=0;iget_tbl_name()); - } - return(retval); -} - - -int table_list::find_tbl(string t){ - int i; - for(i=0;iget_tbl_name() == t) - return(i); -// fprintf(stderr,"INTERNAL ERROR: Could not find table %s in table_list::find_tbl\n",t.c_str()); - return(-1); -} - -vector table_list::get_fields(string t){ - int pos = find_tbl(t); - if(pos<0){ - vector r; - return(r); - } - return(tbl_list[pos]->get_fields()); -} - -field_entry *table_list::get_field(string t, int i){ - int pos = find_tbl(t); - if(pos<0){ - return(NULL); - } - return(tbl_list[pos]->get_field(i)); -} - -int table_list::get_field_idx(string t, string f){ - int pos = find_tbl(t); - if(pos<0){ - return(-1); - } - return(tbl_list[pos]->get_field_idx(f)); -} - - -vector table_list::get_tblref_of_field(string f){ - int i; - vector retval; - - for(i=0;icontains_field(f) ){ - retval.push_back(i); - } - } - return(retval); -} - -// TODO: this seems to duplicate find_tbl -int table_list::get_table_ref(string t){ - int i; - for(i=0;iget_tbl_name() == t ){ - return(i); - } - } - return(-1); -} - - -// Use to unroll hierarchically defined -// tables. Used for source tables. -// Also, do some sanity checking, better -// to find the errors now when its easy to report -// than later when its obscure. -// -// Also, process the unpacking functions. -// and verify that all field unpacking functions -// are listed in the schema. -int table_list::unroll_tables(string &err){ -// First, verify there are no repeat field names in any -// of the tables. - - int f, tref, p, t, ret, retval; - - for(t=0;tget_schema_type() == UNPACK_FCNS_SCHEMA){ - for(f=0;fufcn_list.size();f++){ - ufcn_fcn[ tbl_list[t]->ufcn_list[f]->name ] = tbl_list[t]->ufcn_list[f]->fcn; - ufcn_cost[ tbl_list[t]->ufcn_list[f]->name ] = tbl_list[t]->ufcn_list[f]->cost; - - } - } - } - - for(t=0;tget_schema_type() != UNPACK_FCNS_SCHEMA){ -// No duplicate field names - ret = tbl_list[t]->verify_no_duplicates(err); - if(ret) retval = ret; - -// every field has an access function - if(tbl_list[t]->get_schema_type() == PROTOCOL_SCHEMA){ - retval = tbl_list[t]->verify_access_fcns(err); - if(ret) retval = ret; - } - -// Every type can be parsed - vector flds = tbl_list[t]->get_fields(); - for(f=0;fget_type()); - if(dt.get_type() == undefined_t){ - err += "ERROR, field "+flds[f]->get_name()+" of table "+tbl_list[t]->get_tbl_name()+" has unrecognized type "+flds[f]->get_type()+"\n"; - retval = 1; - } - if(dt.get_type() == fstring_t){ - err += "ERROR, field "+flds[f]->get_name()+" of table "+tbl_list[t]->get_tbl_name()+" has unsupported type "+flds[f]->get_type()+"\n"; - retval = 1; - } - } - -// Ensure that the unpack functions, if any, exist. - for(f=0;f ufcns = flds[f]->get_unpack_fcns(); - set::iterator ssi; - for(ssi=ufcns.begin();ssi!=ufcns.end();ssi++){ - if(ufcn_fcn.count((*ssi))==0){ - err += "ERROR, field "+flds[f]->get_name()+" of table "+tbl_list[t]->get_tbl_name()+" has unrecognized unpacking function "+(*ssi)+"\n"; - retval = 1; - } - } - } - -// annote the original source of the field -- for prefilter - string tbl_name = tbl_list[t]->get_tbl_name(); - vector fev = tbl_list[t]->get_fields(); - for(f=0;fset_basetable(tbl_name); - } - } - - if(retval) return(retval); - -// Next, build a predecessors graph. -// Verify that all referenced tables exist. - - vector< vector > predecessors; // list of tables inherited from. - vector n_pred; // number of (remaining) predecessors. - // -1 indicates a processed table. - - for(t=0;tget_schema_type() != UNPACK_FCNS_SCHEMA){ - vector pred_tbls = tbl_list[t]->get_pred_tbls(); - vector pred_ref; - for(p=0;pget_table_ref(pred_tbls[p]); - if(tref < 0){ - err.append("Error: table "); - err.append(tbl_list[t]->get_tbl_name()); - err.append(" referenced non-existent table "); - err.append(pred_tbls[p]); - err.append("\n"); - return(2); - }else{ - pred_ref.push_back(tref); - } - } - predecessors.push_back(pred_ref); - n_pred.push_back(pred_ref.size()); - }else{ - vector tmp_iv; - predecessors.push_back(tmp_iv); - n_pred.push_back(0); - } - } - - - int n_remaining = predecessors.size(); - int n_total = n_remaining; - -// Run through the DAG and pull off one root at a time (n_pred == 0). -// there might be a cycle, so iterate until n_remaining == 0. - - while(n_remaining > 0){ - -// Find a root - int root; - for(root=0;root < n_total;root++){ - if(n_pred[root] == 0) - break; - } - if(root == n_total){ // didn't find a root. - err.append("Error : cycle in inheritance among the following tables:"); - int r; - for(r=0;r 0){ - err.append(" "); - err.append(tbl_list[r]->get_tbl_name()); - } - } - return(3); - } - -// I'd adding fields from the root table to the - vector pred_fields = tbl_list[root]->get_fields(); - - -// Scan for all successors of the root. - int s, f; - for(s=0;sadd_field(pred_fields[f]); - if(retval < 0){ - err.append("Warning: field "); - err.append(pred_fields[f]->get_name()); - err.append(" already exists in table "); - err.append(tbl_list[s]->get_tbl_name()); - err.append(" (inheriting from table "); - err.append(tbl_list[root]->get_tbl_name()); - err.append(").\n"); - } - } - -// s has one less predecessor. - n_pred[s]--; - } - } - -// Indicate that the root has been processed. - n_pred[root] = -1; - n_remaining--; - } - - -// Done! - return(0); -} - -int table_list::add_table(table_def *td){ - int tref = get_table_ref(td->get_tbl_name()); - if(tref >= 0) return(tref); - tbl_list.push_back(td); - return(tbl_list.size() - 1); -} - - - -////////////////////////////////////////////////////// -////////// Serialize functions. -////////// The deserialize fcn is the parser. - - -string param_list::to_string(){ - string retval; - map::iterator mssi; - bool first_exec=true; - for(mssi=pmap.begin();mssi!=pmap.end();++mssi){ - if(first_exec){ first_exec=false; } - else{ retval+=","; } - retval += (*mssi).first + " "; - retval += (*mssi).second; - } - return(retval); -} - -string field_entry::to_string(){ - string retval = type + " " + name + " " + function; - if(mod_list->size() > 0){ - retval += " ( " + mod_list->to_string() + " ) "; - } - - return(retval); -} - - - - -string table_def::to_string(){ - int q; - string retval; - switch(schema_type){ - case PROTOCOL_SCHEMA: - retval = "TABLE "; - break; - case STREAM_SCHEMA: - retval = "STREAM "; - break; - case OPERATOR_VIEW_SCHEMA: - retval += "OPERATOR_VIEW "; - break; - default: - retval = "ERROR UNKNOWN TABLE TYPE "; - break; - } - - retval += table_name + " "; - - if(base_tables->size() > 0){ - retval += "( "+base_tables->to_string() + " ) "; - } - - retval += "{\n"; - - if(schema_type == OPERATOR_VIEW_SCHEMA){ - retval += "\tOPERATOR ("+op_properties->to_string()+")\n"; - retval += "\tFIELDS{\n"; - } - - int f; - for(f=0;fto_string() + ";\n"; - } - - if(schema_type == OPERATOR_VIEW_SCHEMA){ - retval += "\tSUBQUERIES{\n"; - for(q=0;q0) retval += ";\n"; - retval += qspec_list[q]->to_string(); - } - retval += "\t}\n"; - retval += "\tSELECTION_PUSHDOWN ("+selpush->to_string()+")\n"; - } - - - - retval += "}\n"; - - return(retval); -} - -string table_list::to_string(){ - string retval; - int t; - for(t=0;tto_string(); - retval += "\n"; - } - return(retval); -} +/* ------------------------------------------------ +Copyright 2014 AT&T Intellectual Property + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + ------------------------------------------- */ + +#include +#include"parse_fta.h" +#include "parse_schema.h" +#include "type_objects.h" +#include +#include +// #include +#include + +using namespace std; + +table_list *Schema; + +table_def::table_def(const char *name, param_list *oprop, field_entry_list *fel, + subqueryspec_list *ql, param_list *selp){ + table_name =name; + fields = fel->get_list(); + schema_type = OPERATOR_VIEW_SCHEMA; + qspec_list = ql->spec_list; + + if(oprop == NULL) op_properties = new param_list(); + else op_properties = oprop; + if(selp == NULL) selpush = new param_list(); + else selpush = selp; + base_tables = new param_list(); +}; + +table_def *table_def::make_shallow_copy(string n){ + table_def *ret = new table_def(); + ret->table_name = n; + ret->fields = fields; + ret->schema_type = schema_type; + ret->base_tables = base_tables; + ret->op_properties = op_properties; + ret->qspec_list = qspec_list; + ret->selpush = selpush; + + return ret; +} + +void table_def::mangle_subq_names(std::string mngl){ + int i; + for(i=0;iduplicate(); + s->name += mngl; + qspec_list[i] = s; + } +} + + + +bool table_def::contains_field(string f){ + int i; + + for(i=0;iget_name() == f){ + return(true); + } + } + return(false); + +} + +int table_def::get_field_idx(std::string f){ + int i; + for(i=0;iget_name() == f){ + return(i); + } + } + return(-1); +} + + +string table_def::get_type_name(std::string f){ + int i; + for(i=0;iget_name() == f){ + return(fields[i]->get_type()); + } + } + return("INTERNAL ERROR undefined field " + f); +} + +param_list *table_def::get_modifier_list(std::string f){ + int i; + for(i=0;iget_name() == f){ + return(fields[i]->get_modifier_list()); + } + } + fprintf(stderr,"INTERNAL ERROR, no field %s in table %s, call is get_modifier_list.\n", + f.c_str(), table_name.c_str() ); + exit(1); + return(NULL); +} + + +string table_def::get_fcn(std::string f){ + int i; + for(i=0;iget_name() == f){ + return(fields[i]->get_fcn()); + } + } + return("INTERNAL ERROR undefined field " + f); + +} + + +string table_def::get_field_basetable(std::string f){ + int i; + for(i=0;iget_name() == f){ + return(fields[i]->get_basetable()); + } + } + return("INTERNAL ERROR undefined field " + f); + +} + +int table_def::verify_no_duplicates(std::string &err){ + + int f1, f2; + for(f1=0;f1get_name(); + for(f2=f1+1;f2get_name()){ + err.append("Error, table "); + err.append(table_name); + err.append(" has a duplicate field :"); + err.append(f1_name); + err.append("\n"); + return(1); + } + } + } + return(0); +} + +int table_def::verify_access_fcns(std::string &err){ + int retval = 0, f; + + for(f=0;fget_fcn() == ""){ + err += "Error, PROTOCOL field "+table_name+"."+fields[f]->get_name()+" has an empty access function.\n"; + retval = 1; + } + } + + return(retval); +} + +int table_def::add_field(field_entry *fe){ + string fe_name = fe->get_name(); + int f; + + for(f=0;fget_name()){ + return(-1); + } + } + fields.push_back(fe); + return(0); +} + + +vector table_list::get_table_names(){ + vector retval; + int i; + for(i=0;iget_tbl_name()); + } + return(retval); +} + + +int table_list::find_tbl(string t){ + int i; + for(i=0;iget_tbl_name() == t) + return(i); +// fprintf(stderr,"INTERNAL ERROR: Could not find table %s in table_list::find_tbl\n",t.c_str()); + return(-1); +} + +vector table_list::get_fields(string t){ + int pos = find_tbl(t); + if(pos<0){ + vector r; + return(r); + } + return(tbl_list[pos]->get_fields()); +} + +field_entry *table_list::get_field(string t, int i){ + int pos = find_tbl(t); + if(pos<0){ + return(NULL); + } + return(tbl_list[pos]->get_field(i)); +} + +int table_list::get_field_idx(string t, string f){ + int pos = find_tbl(t); + if(pos<0){ + return(-1); + } + return(tbl_list[pos]->get_field_idx(f)); +} + + +vector table_list::get_tblref_of_field(string f){ + int i; + vector retval; + + for(i=0;icontains_field(f) ){ + retval.push_back(i); + } + } + return(retval); +} + +// TODO: this seems to duplicate find_tbl +int table_list::get_table_ref(string t){ + int i; + for(i=0;iget_tbl_name() == t ){ + return(i); + } + } + return(-1); +} + + +// Use to unroll hierarchically defined +// tables. Used for source tables. +// Also, do some sanity checking, better +// to find the errors now when its easy to report +// than later when its obscure. +// +// Also, process the unpacking functions. +// and verify that all field unpacking functions +// are listed in the schema. +int table_list::unroll_tables(string &err){ + int f, tref, p, t, ret=0, retval=0; + +// First, verify there are no repeat field names in any +// of the tables. + set found_names; + set dup_names; + for(t=0;tget_tbl_name()) != found_names.end()){ + dup_names.insert(tbl_list[t]->get_tbl_name()); + }else{ + found_names.insert(tbl_list[t]->get_tbl_name()); + } + } + if(dup_names.size()>0){ + fprintf(stderr, "Error, the schema has duplicate names:"); + for(auto dit=dup_names.begin();dit!=dup_names.end(); ++dit) + fprintf(stderr, " %s",(*dit).c_str()); + fprintf(stderr, "\n"); + retval = 1; + } + + +// extrack unpack functions + for(t=0;tget_schema_type() == UNPACK_FCNS_SCHEMA){ + for(f=0;fufcn_list.size();f++){ + ufcn_fcn[ tbl_list[t]->ufcn_list[f]->name ] = tbl_list[t]->ufcn_list[f]->fcn; + ufcn_cost[ tbl_list[t]->ufcn_list[f]->name ] = tbl_list[t]->ufcn_list[f]->cost; + + } + } + } + + for(t=0;tget_schema_type() != UNPACK_FCNS_SCHEMA){ +// No duplicate field names + ret = tbl_list[t]->verify_no_duplicates(err); + if(ret) retval = ret; + +// every field has an access function + if(tbl_list[t]->get_schema_type() == PROTOCOL_SCHEMA){ + ret = tbl_list[t]->verify_access_fcns(err); + if(ret) retval = ret; + } + +// Every type can be parsed + vector flds = tbl_list[t]->get_fields(); + for(f=0;fget_type()); + if(dt.get_type() == undefined_t){ + err += "ERROR, field "+flds[f]->get_name()+" of table "+tbl_list[t]->get_tbl_name()+" has unrecognized type "+flds[f]->get_type()+"\n"; + retval = 1; + } + if(dt.get_type() == fstring_t){ + err += "ERROR, field "+flds[f]->get_name()+" of table "+tbl_list[t]->get_tbl_name()+" has unsupported type "+flds[f]->get_type()+"\n"; + retval = 1; + } + } + +// Ensure that the unpack functions, if any, exist. + for(f=0;f ufcns = flds[f]->get_unpack_fcns(); + set::iterator ssi; + for(ssi=ufcns.begin();ssi!=ufcns.end();ssi++){ + if(ufcn_fcn.count((*ssi))==0){ + err += "ERROR, field "+flds[f]->get_name()+" of table "+tbl_list[t]->get_tbl_name()+" has unrecognized unpacking function "+(*ssi)+"\n"; + retval = 1; + } + } + } + +// annote the original source of the field -- for prefilter + string tbl_name = tbl_list[t]->get_tbl_name(); + vector fev = tbl_list[t]->get_fields(); + for(f=0;fset_basetable(tbl_name); + } + } + + if(retval) return(retval); + +// Next, build a predecessors graph. +// Verify that all referenced tables exist. + + vector< vector > predecessors; // list of tables inherited from. + vector n_pred; // number of (remaining) predecessors. + // -1 indicates a processed table. + + for(t=0;tget_schema_type() != UNPACK_FCNS_SCHEMA){ + vector pred_tbls = tbl_list[t]->get_pred_tbls(); + vector pred_ref; + for(p=0;pget_table_ref(pred_tbls[p]); + if(tref < 0){ + err.append("Error: table "); + err.append(tbl_list[t]->get_tbl_name()); + err.append(" referenced non-existent table "); + err.append(pred_tbls[p]); + err.append("\n"); + return(2); + }else{ + pred_ref.push_back(tref); + } + } + predecessors.push_back(pred_ref); + n_pred.push_back(pred_ref.size()); + }else{ + vector tmp_iv; + predecessors.push_back(tmp_iv); + n_pred.push_back(0); + } + } + + + int n_remaining = predecessors.size(); + int n_total = n_remaining; + +// Run through the DAG and pull off one root at a time (n_pred == 0). +// there might be a cycle, so iterate until n_remaining == 0. + + while(n_remaining > 0){ + +// Find a root + int root; + for(root=0;root < n_total;root++){ + if(n_pred[root] == 0) + break; + } + if(root == n_total){ // didn't find a root. + err.append("Error : cycle in inheritance among the following tables:"); + int r; + for(r=0;r 0){ + err.append(" "); + err.append(tbl_list[r]->get_tbl_name()); + } + } + return(3); + } + +// I'd adding fields from the root table to the + vector pred_fields = tbl_list[root]->get_fields(); + + +// Scan for all successors of the root. + int s, f; + for(s=0;sadd_field(pred_fields[f]); + if(retval < 0){ + err.append("Warning: field "); + err.append(pred_fields[f]->get_name()); + err.append(" already exists in table "); + err.append(tbl_list[s]->get_tbl_name()); + err.append(" (inheriting from table "); + err.append(tbl_list[root]->get_tbl_name()); + err.append(").\n"); + } + } +// and insert schema_ids + set s_schema_ids = tbl_list[root]->get_all_schema_ids(); + for(auto sit=s_schema_ids.begin(); sit!=s_schema_ids.end(); ++sit){ + tbl_list[s]->add_to_all_schema_ids((*sit)); + } + +// s has one less predecessor. + n_pred[s]--; + } + } + +// Indicate that the root has been processed. + n_pred[root] = -1; + n_remaining--; + } + + +// Done! + return(0); +} + +int table_list::add_table(table_def *td){ + int tref = get_table_ref(td->get_tbl_name()); + if(tref >= 0) return(tref); + tbl_list.push_back(td); + return(tbl_list.size() - 1); +} + + + +////////////////////////////////////////////////////// +////////// Serialize functions. +////////// The deserialize fcn is the parser. + + +string param_list::to_string(){ + string retval; + map::iterator mssi; + bool first_exec=true; + for(mssi=pmap.begin();mssi!=pmap.end();++mssi){ + if(first_exec){ first_exec=false; } + else{ retval+=","; } + retval += (*mssi).first + " "; + retval += (*mssi).second; + } + return(retval); +} + +string field_entry::to_string(){ + string retval = type + " " + name + " " + function; + if(mod_list->size() > 0){ + retval += " ( " + mod_list->to_string() + " ) "; + } + + return(retval); +} + + + + +string table_def::to_string(){ + int q; + string retval; + switch(schema_type){ + case PROTOCOL_SCHEMA: + retval = "TABLE "; + break; + case STREAM_SCHEMA: + retval = "STREAM "; + break; + case OPERATOR_VIEW_SCHEMA: + retval += "OPERATOR_VIEW "; + break; + case WATCHLIST_SCHEMA: + retval += "WATCHLIST "; + break; + default: + retval = "ERROR UNKNOWN TABLE TYPE ("+std::to_string(schema_type)+")"; + break; + } + + retval += table_name + " "; + + if(base_tables->size() > 0){ + retval += "( "+base_tables->to_string() + " ) "; + } + + retval += "{\n"; + + if(schema_type == OPERATOR_VIEW_SCHEMA){ + retval += "\tOPERATOR ("+op_properties->to_string()+")\n"; + retval += "\tFIELDS{\n"; + } + + int f; + for(f=0;fto_string() + ";\n"; + } + + if(schema_type == OPERATOR_VIEW_SCHEMA){ + retval += "\tSUBQUERIES{\n"; + for(q=0;q0) retval += ";\n"; + retval += qspec_list[q]->to_string(); + } + retval += "\t}\n"; + retval += "\tSELECTION_PUSHDOWN ("+selpush->to_string()+")\n"; + } + + + + retval += "}\n"; + + return(retval); +} + +string table_list::to_string(){ + string retval; + int t; + for(t=0;tto_string(); + retval += "\n"; + } + return(retval); +}