1 /* ------------------------------------------------
2 Copyright 2014 AT&T Intellectual Property
3 Licensed under the Apache License, Version 2.0 (the "License");
4 you may not use this file except in compliance with the License.
5 You may obtain a copy of the License at
7 http://www.apache.org/licenses/LICENSE-2.0
9 Unless required by applicable law or agreed to in writing, software
10 distributed under the License is distributed on an "AS IS" BASIS,
11 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 See the License for the specific language governing permissions and
13 limitations under the License.
14 ------------------------------------------- */
18 #include "parse_schema.h"
19 #include "type_objects.h"
29 table_def::table_def(const char *name, param_list *oprop, field_entry_list *fel,
30 subqueryspec_list *ql, param_list *selp){
32 fields = fel->get_list();
33 schema_type = OPERATOR_VIEW_SCHEMA;
34 qspec_list = ql->spec_list;
36 if(oprop == NULL) op_properties = new param_list();
37 else op_properties = oprop;
38 if(selp == NULL) selpush = new param_list();
40 base_tables = new param_list();
43 table_def *table_def::make_shallow_copy(string n){
44 table_def *ret = new table_def();
47 ret->schema_type = schema_type;
48 ret->base_tables = base_tables;
49 ret->op_properties = op_properties;
50 ret->qspec_list = qspec_list;
51 ret->selpush = selpush;
56 void table_def::mangle_subq_names(std::string mngl){
58 for(i=0;i<qspec_list.size();++i){
59 subquery_spec *s = qspec_list[i]->duplicate();
67 bool table_def::contains_field(string f){
70 for(i=0;i<fields.size();i++){
71 if(fields[i]->get_name() == f){
79 int table_def::get_field_idx(std::string f){
81 for(i=0;i<fields.size();i++){
82 if(fields[i]->get_name() == f){
90 string table_def::get_type_name(std::string f){
92 for(i=0;i<fields.size();i++){
93 if(fields[i]->get_name() == f){
94 return(fields[i]->get_type());
97 return("INTERNAL ERROR undefined field " + f);
100 param_list *table_def::get_modifier_list(std::string f){
102 for(i=0;i<fields.size();i++){
103 if(fields[i]->get_name() == f){
104 return(fields[i]->get_modifier_list());
107 fprintf(stderr,"INTERNAL ERROR, no field %s in table %s, call is get_modifier_list.\n",
108 f.c_str(), table_name.c_str() );
114 string table_def::get_fcn(std::string f){
116 for(i=0;i<fields.size();i++){
117 if(fields[i]->get_name() == f){
118 return(fields[i]->get_fcn());
121 return("INTERNAL ERROR undefined field " + f);
126 string table_def::get_field_basetable(std::string f){
128 for(i=0;i<fields.size();i++){
129 if(fields[i]->get_name() == f){
130 return(fields[i]->get_basetable());
133 return("INTERNAL ERROR undefined field " + f);
137 int table_def::verify_no_duplicates(std::string &err){
140 for(f1=0;f1<fields.size()-1;f1++){
141 string f1_name = fields[f1]->get_name();
142 for(f2=f1+1;f2<fields.size();f2++){
143 if(f1_name == fields[f2]->get_name()){
144 err.append("Error, table ");
145 err.append(table_name);
146 err.append(" has a duplicate field :");
156 int table_def::verify_access_fcns(std::string &err){
159 for(f=0;f<fields.size();++f){
160 if(fields[f]->get_fcn() == ""){
161 err += "Error, PROTOCOL field "+table_name+"."+fields[f]->get_name()+" has an empty access function.\n";
169 int table_def::add_field(field_entry *fe){
170 string fe_name = fe->get_name();
173 for(f=0;f<fields.size();f++){
174 if(fe_name == fields[f]->get_name()){
178 fields.push_back(fe);
183 vector<string> table_list::get_table_names(){
184 vector<string> retval;
186 for(i=0;i<tbl_list.size();i++){
187 retval.push_back(tbl_list[i]->get_tbl_name());
193 int table_list::find_tbl(string t){
195 for(i=0;i<tbl_list.size();i++)
196 if(tbl_list[i]->get_tbl_name() == t)
198 // fprintf(stderr,"INTERNAL ERROR: Could not find table %s in table_list::find_tbl\n",t.c_str());
202 vector<field_entry *> table_list::get_fields(string t){
203 int pos = find_tbl(t);
205 vector<field_entry *> r;
208 return(tbl_list[pos]->get_fields());
211 field_entry *table_list::get_field(string t, int i){
212 int pos = find_tbl(t);
216 return(tbl_list[pos]->get_field(i));
219 int table_list::get_field_idx(string t, string f){
220 int pos = find_tbl(t);
224 return(tbl_list[pos]->get_field_idx(f));
228 vector<int> table_list::get_tblref_of_field(string f){
232 for(i=0;i<tbl_list.size();i++){
233 if( tbl_list[i]->contains_field(f) ){
240 // TODO: this seems to duplicate find_tbl
241 int table_list::get_table_ref(string t){
243 for(i=0;i<tbl_list.size();i++){
244 if(tbl_list[i]->get_tbl_name() == t ){
252 // Use to unroll hierarchically defined
253 // tables. Used for source tables.
254 // Also, do some sanity checking, better
255 // to find the errors now when its easy to report
256 // than later when its obscure.
258 // Also, process the unpacking functions.
259 // and verify that all field unpacking functions
260 // are listed in the schema.
261 int table_list::unroll_tables(string &err){
262 int f, tref, p, t, ret=0, retval=0;
264 // First, verify there are no repeat field names in any
266 set<string> found_names;
267 set<string> dup_names;
268 for(t=0;t<tbl_list.size();t++){
269 if(found_names.find(tbl_list[t]->get_tbl_name()) != found_names.end()){
270 dup_names.insert(tbl_list[t]->get_tbl_name());
272 found_names.insert(tbl_list[t]->get_tbl_name());
275 if(dup_names.size()>0){
276 fprintf(stderr, "Error, the schema has duplicate names:");
277 for(auto dit=dup_names.begin();dit!=dup_names.end(); ++dit)
278 fprintf(stderr, " %s",(*dit).c_str());
279 fprintf(stderr, "\n");
284 // extrack unpack functions
285 for(t=0;t<tbl_list.size();t++){
286 if(tbl_list[t]->get_schema_type() == UNPACK_FCNS_SCHEMA){
287 for(f=0;f<tbl_list[t]->ufcn_list.size();f++){
288 ufcn_fcn[ tbl_list[t]->ufcn_list[f]->name ] = tbl_list[t]->ufcn_list[f]->fcn;
289 ufcn_cost[ tbl_list[t]->ufcn_list[f]->name ] = tbl_list[t]->ufcn_list[f]->cost;
295 for(t=0;t<tbl_list.size();t++){
296 if(tbl_list[t]->get_schema_type() != UNPACK_FCNS_SCHEMA){
297 // No duplicate field names
298 ret = tbl_list[t]->verify_no_duplicates(err);
299 if(ret) retval = ret;
301 // every field has an access function
302 if(tbl_list[t]->get_schema_type() == PROTOCOL_SCHEMA){
303 ret = tbl_list[t]->verify_access_fcns(err);
304 if(ret) retval = ret;
307 // Every type can be parsed
308 vector<field_entry *> flds = tbl_list[t]->get_fields();
309 for(f=0;f<flds.size();++f){
310 data_type dt(flds[f]->get_type());
311 if(dt.get_type() == undefined_t){
312 err += "ERROR, field "+flds[f]->get_name()+" of table "+tbl_list[t]->get_tbl_name()+" has unrecognized type "+flds[f]->get_type()+"\n";
315 if(dt.get_type() == fstring_t){
316 err += "ERROR, field "+flds[f]->get_name()+" of table "+tbl_list[t]->get_tbl_name()+" has unsupported type "+flds[f]->get_type()+"\n";
321 // Ensure that the unpack functions, if any, exist.
322 for(f=0;f<flds.size();++f){
323 set<string> ufcns = flds[f]->get_unpack_fcns();
324 set<string>::iterator ssi;
325 for(ssi=ufcns.begin();ssi!=ufcns.end();ssi++){
326 if(ufcn_fcn.count((*ssi))==0){
327 err += "ERROR, field "+flds[f]->get_name()+" of table "+tbl_list[t]->get_tbl_name()+" has unrecognized unpacking function "+(*ssi)+"\n";
333 // annote the original source of the field -- for prefilter
334 string tbl_name = tbl_list[t]->get_tbl_name();
335 vector<field_entry *> fev = tbl_list[t]->get_fields();
336 for(f=0;f<fev.size();++f)
337 fev[f]->set_basetable(tbl_name);
341 if(retval) return(retval);
343 // Next, build a predecessors graph.
344 // Verify that all referenced tables exist.
346 vector< vector<int> > predecessors; // list of tables inherited from.
347 vector<int> n_pred; // number of (remaining) predecessors.
348 // -1 indicates a processed table.
350 for(t=0;t<tbl_list.size();t++){
351 if(tbl_list[t]->get_schema_type() != UNPACK_FCNS_SCHEMA){
352 vector<string> pred_tbls = tbl_list[t]->get_pred_tbls();
353 vector<int> pred_ref;
354 for(p=0;p<pred_tbls.size();p++){
355 tref = this->get_table_ref(pred_tbls[p]);
357 err.append("Error: table ");
358 err.append(tbl_list[t]->get_tbl_name());
359 err.append(" referenced non-existent table ");
360 err.append(pred_tbls[p]);
364 pred_ref.push_back(tref);
367 predecessors.push_back(pred_ref);
368 n_pred.push_back(pred_ref.size());
371 predecessors.push_back(tmp_iv);
377 int n_remaining = predecessors.size();
378 int n_total = n_remaining;
380 // Run through the DAG and pull off one root at a time (n_pred == 0).
381 // there might be a cycle, so iterate until n_remaining == 0.
383 while(n_remaining > 0){
387 for(root=0;root < n_total;root++){
388 if(n_pred[root] == 0)
391 if(root == n_total){ // didn't find a root.
392 err.append("Error : cycle in inheritance among the following tables:");
394 for(r=0;r<n_total;r++){
397 err.append(tbl_list[r]->get_tbl_name());
403 // I'd adding fields from the root table to the
404 vector<field_entry *> pred_fields = tbl_list[root]->get_fields();
407 // Scan for all successors of the root.
409 for(s=0;s<n_total;s++){
410 if(find((predecessors[s]).begin(), (predecessors[s]).end(), root) !=
411 (predecessors[s]).end() ){
413 // s is a successor : add the fields from the root.
414 for(f=0;f<pred_fields.size();f++){
415 retval = tbl_list[s]->add_field(pred_fields[f]);
417 err.append("Warning: field ");
418 err.append(pred_fields[f]->get_name());
419 err.append(" already exists in table ");
420 err.append(tbl_list[s]->get_tbl_name());
421 err.append(" (inheriting from table ");
422 err.append(tbl_list[root]->get_tbl_name());
426 // and insert schema_ids
427 set<int> s_schema_ids = tbl_list[root]->get_all_schema_ids();
428 for(auto sit=s_schema_ids.begin(); sit!=s_schema_ids.end(); ++sit){
429 tbl_list[s]->add_to_all_schema_ids((*sit));
432 // s has one less predecessor.
437 // Indicate that the root has been processed.
447 int table_list::add_table(table_def *td){
448 int tref = get_table_ref(td->get_tbl_name());
449 if(tref >= 0) return(tref);
450 tbl_list.push_back(td);
451 return(tbl_list.size() - 1);
456 //////////////////////////////////////////////////////
457 ////////// Serialize functions.
458 ////////// The deserialize fcn is the parser.
461 string param_list::to_string(){
463 map<string, string>::iterator mssi;
464 bool first_exec=true;
465 for(mssi=pmap.begin();mssi!=pmap.end();++mssi){
466 if(first_exec){ first_exec=false; }
468 retval += (*mssi).first + " ";
469 retval += (*mssi).second;
474 string field_entry::to_string(){
475 string retval = type + " " + name + " " + function;
476 if(mod_list->size() > 0){
477 retval += " ( " + mod_list->to_string() + " ) ";
486 string table_def::to_string(){
490 case PROTOCOL_SCHEMA:
496 case OPERATOR_VIEW_SCHEMA:
497 retval += "OPERATOR_VIEW ";
500 retval = "ERROR UNKNOWN TABLE TYPE ";
504 retval += table_name + " ";
506 if(base_tables->size() > 0){
507 retval += "( "+base_tables->to_string() + " ) ";
512 if(schema_type == OPERATOR_VIEW_SCHEMA){
513 retval += "\tOPERATOR ("+op_properties->to_string()+")\n";
514 retval += "\tFIELDS{\n";
518 for(f=0;f<fields.size();f++){
519 retval += "\t" + fields[f]->to_string() + ";\n";
522 if(schema_type == OPERATOR_VIEW_SCHEMA){
523 retval += "\tSUBQUERIES{\n";
524 for(q=0;q<qspec_list.size();++q){
525 if(q>0) retval += ";\n";
526 retval += qspec_list[q]->to_string();
529 retval += "\tSELECTION_PUSHDOWN ("+selpush->to_string()+")\n";
539 string table_list::to_string(){
542 for(t=0;t<tbl_list.size();t++){
543 retval += tbl_list[t]->to_string();