BadgerDB
/afs/cs.wisc.edu/u/n/w/nwilliam/private/workspace/Quut/src/parser/SqlInterp.cpp
00001 //
00002 // Author: Jignesh M. Patel
00003 //         EECS Department, University of Michigan
00004 // Date:  August-October 2001
00005 //
00006 //
00007 
00008 
00015 #include <stdio.h>
00016 #include <assert.h>
00017 
00018 #include <sstream>
00019 #include <cstdlib>
00020 #include <string>
00021 
00022 #include "SqlParser.h"
00023 #include "SqlInterp.h"
00024 #include "catalog.h"
00025 #include "query.h"
00026 #include "updates.h"
00027 #include "utility.h"
00028 #include "exceptions/relation_not_found_exception.h"
00029 
00030 #define E_OK      0
00031 #define E_INCOMPATIBLE    -1
00032 #define E_TOOMANYATTRS    -2
00033 #define E_NOLENGTH    -3
00034 #define E_INVINTSIZE    -4
00035 #define E_INVFLOATSIZE    -5
00036 #define E_INVFORMATSTRING -6
00037 #define E_INVSTRLEN   -7
00038 #define E_DUPLICATEATTR   -8
00039 #define E_TOOLONG   -9
00040 #define E_STRINGTOOLONG   -10
00041 #define E_CORRUPTSQL    -11
00042 #define E_LITERALTYPE   -12
00043 
00044 
00045 #define ERRFP     stderr  // error message go here
00046 #define MAXATTRS    40      // max. number of attrs in a relation
00047 
00048 
00049 
00050 //
00051 // prefab arrays of useful types
00052 //
00053 
00054 static REL_ATTR qual_attrs[MAXATTRS + 1];
00055 static ATTR_DESCR attr_descrs[MAXATTRS + 1];
00056 static ATTR_VAL ins_attrs[MAXATTRS + 1];
00057 static char *names[MAXATTRS + 1];
00058 
00059 static int mk_attrnames(PxxList *list, char *attrnames[], char *relname);
00060 static int mk_qual_attrs(PxxList *list, REL_ATTR qual_attrs[],
00061                          char *relname1, char *relname2);
00062 static int mk_attr_descrs(PxxList *list, ATTR_DESCR attr_descrs[]);
00063 static int mk_ins_attrs(PxxPnode *list, ATTR_VAL ins_attrs[]);
00064 static void print_error(const char *errmsg, int errval);
00065 /*
00066 static int parse_format_string(char *format_string, int *type, int *len);
00067 static void *value_of(PxxPnode *n);
00068 static int  type_of(PxxPnode *n);
00069 static int  length_of(PxxPnode *n);
00070 static void echo_query(PxxPnode *n);
00071 static void print_qual(PxxPnode *n);
00072 static void print_attrnames(PxxPnode *n);
00073 static void print_attrdescrs(PxxPnode *n);
00074 static void print_attrvals(PxxPnode *n);
00075 static void print_primattr(PxxPnode *n);
00076 static void print_qualattr(PxxPnode *n);
00077 static void print_op(int op);
00078 static void print_val(NODE *n);
00079 */
00080 
00081 static int nattrs;
00082 static string resultName;
00083 
00084 static attrInfo attrList[MAXATTRS];
00085 static attrInfo attr1;
00086 static attrInfo attr2;
00087 
00088 
00089 extern "C" int isatty(int fd);          // returns 1 if fd is a tty device
00090 
00091 //
00092 // Evaluate the parse tree
00093 //
00094 
00095 void PxxInterp::eval(PxxPnode *ptree)
00096 {
00097    // cout << *ptree << endl;
00098    
00099    switch(ptree->MyType()) 
00100    {
00101    case PxxPnode::Create:
00102       createTable(ptree);
00103       break;
00104    case PxxPnode::Insert:
00105       insertIntoTable(ptree);
00106       break;
00107    case PxxPnode::Drop:
00108       deleteTable((PxxDrop*)ptree);
00109       break;
00110    case PxxPnode::Query:
00111       processQuery(ptree);
00112       break;
00113    case PxxPnode::CreateIndex:
00114       createIndex((PxxCreateIndex*)ptree);
00115       break;
00116    case PxxPnode::DropIndex:
00117       deleteIndex((PxxDropIndex*)ptree);
00118       break;
00119    case PxxPnode::Delete:
00120       deleteTable((PxxDrop*)ptree);
00121       break; 
00122    default:
00123       assert(!"Invalid node type");
00124    }
00125 }
00126 
00127 //
00128 // quit the system
00129 //
00130 void PxxInterp::quit(void)
00131 {
00132    Utilities::Quit();
00133    exit(1);
00134 }
00135 
00140 void PxxInterp::createTable(PxxPnode *ptree)
00141 {   
00142    // make a list of ATTR_DESCRS suitable for sending to Create
00143    nattrs = mk_attr_descrs(((PxxCreate*)ptree)->AttrList(), attr_descrs);
00144    if (nattrs < 0) 
00145    {
00146       print_error("Corrupt attribute list", E_CORRUPTSQL);
00147       return;
00148    }
00149    
00150    for(int acnt = 0; acnt < nattrs; acnt++) {
00151       strcpy(attrList[acnt].relName, ((PxxCreate*)ptree) -> RelName());
00152       strcpy(attrList[acnt].attrName, attr_descrs[acnt].attrName);
00153       attrList[acnt].attrType = attr_descrs[acnt].attrType;
00154       attrList[acnt].attrLen = attr_descrs[acnt].attrLen;
00155       attrList[acnt].attrValue = NULL;
00156    }
00157    
00158    // make the call to Create
00159    relCat->createRel(((PxxCreate*)ptree)->RelName(), nattrs, attrList);
00160    
00161    return;
00162 }
00163 
00167 void PxxInterp::deleteTable(PxxDrop *ptree)
00168 {
00169    // Make a call to Drop.
00170    relCat->destroyRel(ptree->RelName());
00171 }
00172 
00176 void PxxInterp::createIndex(PxxCreateIndex *ptree)
00177 {
00178    // Call the catalog create index
00179    relCat->addIndex(ptree->RelName(), ptree->AttrName());
00180 }
00181 
00185 void PxxInterp::deleteIndex(PxxDropIndex *ptree)
00186 {
00187    relCat->dropIndex(ptree->RelName(), ptree->AttrName());
00188 }
00189 
00194 void PxxInterp::insertIntoTable(PxxPnode *ptree)
00195 {
00196    if(((PxxInsert*)ptree)->ValList() != NULL)
00197    { 
00198       // make attribute and value list to be passed to Updates::Insert
00199       nattrs = mk_ins_attrs(ptree, ins_attrs);
00200       if (nattrs < 0) 
00201       {
00202          print_error("Invalid attribute list", E_CORRUPTSQL);
00203          return;
00204       }
00205       
00206       PxxInsert* pinsert = (PxxInsert*)ptree;
00207       
00208       // make the call to Updates::Insert
00209       int acnt;
00210       for(acnt = 0; acnt < nattrs; acnt++) 
00211       {
00212          strcpy(attrList[acnt].relName, pinsert->RelName());
00213          
00214          strcpy(attrList[acnt].attrName, ins_attrs[acnt].attrName);
00215          attrList[acnt].attrType = (Datatype)ins_attrs[acnt].valType;
00216          attrList[acnt].attrLen = -1;
00217          attrList[acnt].attrValue = ins_attrs[acnt].value;
00218       }
00219       
00220       Updates::Insert(pinsert->RelName(),nattrs,attrList);
00221       
00222       // for (acnt = 0; acnt < nattrs; acnt++)
00223       //  delete [] (char*)attrList[acnt].attrValue; // Winter 00
00224       
00225       return;
00226    }   
00227    else
00228    {
00229       /* Doing a load from a file */
00230       Utilities::Load(((PxxInsert*)ptree)->RelName(), ((PxxInsert*)ptree)->FileName());
00231    }
00232 }
00233 
00239 void PxxInterp::processQuery(PxxPnode *ptree)
00240 {
00241    PxxQuery* pquery = (PxxQuery*)ptree;
00242    PxxList* projnames = pquery->Projs();
00243    PxxList  starList; 
00244    PxxList* fromnames = pquery->Froms();
00245    // PxxList* fromlist = fromnames; 
00246    PxxPredTree* predicates = pquery->Preds();
00247    PxxPredicate* singlepred = 0;
00248    PxxLiteral* literal = 0; 
00249    //unsigned int usingtemp = 0; //This is a flag to let us know when we are reading into a temp
00250    int numberoftables;  
00251    int attrCnt;
00252    
00253    // First, check to see how many tables we are reading from.
00254    // If it is more than one, then the query is a join query
00255    // Check if the table definition exists in the catalog. 
00256    ListNode* table = fromnames->Init();  
00257    for(numberoftables = 0; table != NULL; table = table->Next())
00258    {
00259       PxxRelName* relname = (PxxRelName*)(table->Data()); 
00260       RelDesc relDesc;
00261 
00262       relCat->getInfo(relname->RelName(), relDesc);
00263 
00264       // Add attrnames to the starlist.
00265       AttrDesc* attrDescs;
00266       int numAttrs;
00267 
00268       attrCat->getRelInfo(relname->RelName(), numAttrs, attrDescs);
00269 
00270       // Add all the attributes of this relations to the starList. 
00271       for (int j=0; j<numAttrs; j++)
00272       {
00273          PxxAttrName *aname = new PxxAttrName(attrDescs[j].attrName, 
00274                                               attrDescs[j].relName,
00275                                               true);
00276          starList.Add(aname);
00277       }
00278 
00279       delete [] attrDescs;
00280 
00281       numberoftables++;
00282    } 
00283    
00284    // process * ops in the projection list
00285    if (projnames->Cardinality() == 1 &&  
00286        ((PxxAttrName*)(projnames->First()->Data()))->Star())
00287    {
00288       projnames = &starList; 
00289    }
00290 
00291    // Check to see if an "INTO" was specified, else just write into a default
00292    PxxRelName insert_relname = pquery->RelName();
00293    
00294    RelDesc relDesc;
00295    if(insert_relname.RelName() == NULL)
00296    {
00297       // If we are using a temp relation then the number of 
00298       // attributes will just be the number of projected ones 
00299       //usingtemp = 1;
00300       resultName = "TMP_BDB";
00301       unsigned i;
00302       attrCnt = projnames->Cardinality();
00303       
00304       try
00305       {
00306         relCat->getInfo(resultName, relDesc);
00307         std::cerr << "TMP_RES_EXISTS : Database corrupted!" << std::endl;
00308         return;
00309       }
00310       catch(RelationNotFoundException &e)
00311       {
00312       }
00313 
00314       // Create the temp result relation
00315       attrInfo *createAttrInfo = new attrInfo[attrCnt];
00316            
00317       ListNode *projdata = projnames->Init();
00318       PxxAttrName* projattr;
00319       
00320       // for each element of the list...
00321       for(i = 0; projdata != NULL && i < MAXATTRS; ++i, projdata = projdata->Next()) 
00322       {     
00323          projattr = (PxxAttrName*)(projdata->Data());
00324          
00325          // Step through each projection attribute.
00326          AttrDesc attrDesc;
00327          attrCat->getInfo(projattr->RelName(), projattr->AttrName(), attrDesc); 
00328          
00329          strcpy(createAttrInfo[i].relName, resultName.c_str());
00330          
00331          // Create a unique attribute name
00332          ostringstream newAttrName;
00333          newAttrName << projattr->AttrName() << '.' << i << endl;
00334          strcpy(createAttrInfo[i].attrName, newAttrName.str().c_str());
00335  
00336          createAttrInfo[i].attrType = attrDesc.attrType;
00337          createAttrInfo[i].attrLen = attrDesc.attrLen;
00338       }
00339       
00340       if (i != projnames->Cardinality())
00341       {
00342          print_error("Corrupt SELECT clause", E_CORRUPTSQL);
00343          return;
00344       }
00345 
00346       // Create the temp relation. 
00347       relCat->createRel(resultName, attrCnt, createAttrInfo);
00348       delete [] createAttrInfo;
00349    } 
00350    else
00351    { 
00352       resultName = insert_relname.RelName();
00353       relCat->getInfo(resultName, relDesc);
00354       // if (status != OK && status != RELNOTFOUND)
00355 
00356       AttrDesc* resAttrDesc;
00357       attrCat->getRelInfo(resultName, attrCnt, resAttrDesc); 
00358 
00359       if (attrCnt != relDesc.attrCnt)
00360       {
00361          print_error("Incompatible projection list", E_CORRUPTSQL);
00362          return; 
00363       }
00364 
00365       // Type check the projection list and the target relation schema
00366       ListNode *temp = projnames->Init();
00367       PxxAttrName *attr;
00368 
00369       int iter;
00370       AttrDesc attrDesc;
00371       // for each qualified attribute in the list...
00372       for(iter = 0; temp != NULL; iter++, temp = temp->Next()) 
00373       {
00374          attr = (PxxAttrName*)(temp->Data());
00375          char* aName = attr->AttrName();
00376          char* rName = attr->RelName();
00377 
00378          attrCat->getInfo(rName, aName, attrDesc);
00379 
00380          if (resAttrDesc[iter].attrType != attrDesc.attrType || resAttrDesc[iter].attrLen  != attrDesc.attrLen)
00381          {
00382              print_error("Corrupt projection list", E_CORRUPTSQL);
00383              delete [] resAttrDesc;
00384              return; 
00385          }
00386       }
00387 
00388       if (iter != relDesc.attrCnt)
00389       {
00390          print_error("Incompatible projection list", E_CORRUPTSQL);
00391          delete [] resAttrDesc;
00392          return; 
00393       }
00394 
00395       delete [] resAttrDesc;
00396    }
00397    
00398    // See if we are doing a join or calling select
00399    if(numberoftables == 1)
00400    {
00401       // Now take care of the projected names and
00402       // make a list of attribute names suitable for passing to select
00403       char *rName = 0;
00404       nattrs = mk_attrnames(projnames, names, rName);
00405       if (nattrs < 0) 
00406       {
00407          print_error("Select Clause", E_CORRUPTSQL);
00408          return; 
00409       }
00410       
00411       for(int acnt = 0; acnt < nattrs; acnt++) 
00412       {
00413          strcpy(attrList[acnt].relName, names[nattrs]);
00414          strcpy(attrList[acnt].attrName, names[acnt]);
00415          attrList[acnt].attrType = -1;
00416          attrList[acnt].attrLen = -1;
00417          attrList[acnt].attrValue = NULL;
00418       }
00419       
00420       if(predicates != NULL)
00421       {
00422          // cout << "Predicate Node Type: " << predicates->MyType() << endl;
00423          if (predicates->MyType() == PxxPnode::Predicate)
00424          {
00425             singlepred = (PxxPredicate*) predicates;
00426             // cout << *singlepred << endl;
00427             // At this point single pred is the predicate to evaluate. Assume 
00428             // that a query never has more than one predicate ... 
00429             
00430             strcpy(attr1.relName, (*singlepred)[0].AttrName()->RelName());
00431             strcpy(attr1.attrName, (*singlepred)[0].AttrName()->AttrName());
00432             attr1.attrLen = -1; 
00433             literal = ((*singlepred)[1]).Lit(); 
00434             attr1.attrType = literal->Type();
00435             switch(attr1.attrType)
00436             {
00437             case PxxAttrType::STRING:
00438                attr1.attrValue = (void*)(literal->Char());
00439                break; 
00440             case PxxAttrType::INTEGER:
00441                attr1.attrValue = (void*)(literal->Int());
00442                break; 
00443             case PxxAttrType::DOUBLE: 
00444                attr1.attrValue = (void*)(literal->Double());
00445                break;
00446             }
00447          } 
00448          else
00449          {
00450             assert (!"multiple predicates not supported");
00451          }
00452          
00453       }
00454       
00455       // make different calls to Operators::Select depending upon whether 
00456       // there is a predicate or not
00457       if(predicates == NULL)
00458       {
00459          Operators::Select(resultName, nattrs, attrList, NULL, NOTSET, NULL);
00460       }
00461       else
00462       {
00463          void* filter = 0;
00464          switch(attr1.attrType)
00465          { 
00466          case PxxAttrType::STRING:
00467             filter = literal->Char();
00468             break; 
00469          case PxxAttrType::INTEGER:
00470             filter = literal->Int();
00471             break; 
00472          case PxxAttrType::DOUBLE: 
00473             filter = literal->Double();
00474             break; 
00475          }
00476          // cerr << "Calling select with a predicate" << endl;
00477          Operator selectop = singlepred->Oper();
00478          Operators::Select(resultName, nattrs,
00479             attrList, &attr1,
00480             selectop,
00481             filter);
00482       }
00483   }
00484   
00485   // JOIN Query: If we are joining then don't actually select, just call join
00486   else 
00487   {
00488      PxxPredicate* singlepred = (PxxPredicate*) predicates;
00489      PxxAttrName* first_attr = (*singlepred)[0].AttrName();
00490      PxxAttrName* second_attr = (*singlepred)[1].AttrName();   
00491      
00492      // make an attribute list suitable for passing to join
00493      nattrs = mk_qual_attrs(projnames,
00494                             qual_attrs,
00495                             first_attr->RelName(),
00496                             second_attr->RelName());
00497      if (nattrs < 0) 
00498      {
00499         print_error("Invalid attribute list", E_CORRUPTSQL);
00500      }
00501      
00502      // set up the joined attributes to be passed to Join
00503      qual_attrs[nattrs].relName = first_attr->RelName();
00504      qual_attrs[nattrs].attrName = first_attr->AttrName();
00505      qual_attrs[nattrs + 1].relName = second_attr->RelName(); 
00506      qual_attrs[nattrs + 1].attrName = second_attr->AttrName();
00507      
00508      for(int acnt = 0; acnt < nattrs; acnt++) 
00509      {
00510         strcpy(attrList[acnt].relName, qual_attrs[acnt].relName);
00511         strcpy(attrList[acnt].attrName, qual_attrs[acnt].attrName);
00512         attrList[acnt].attrType = -1;
00513         attrList[acnt].attrLen = -1;
00514         attrList[acnt].attrValue = NULL;
00515      }
00516      
00517      strcpy(attr1.relName, qual_attrs[nattrs].relName);
00518      strcpy(attr1.attrName, qual_attrs[nattrs].attrName);
00519      attr1.attrType = -1;
00520      attr1.attrLen = -1;
00521      attr1.attrValue = NULL;
00522      
00523      strcpy(attr2.relName, qual_attrs[nattrs+1].relName);
00524      strcpy(attr2.attrName, qual_attrs[nattrs+1].attrName);
00525      attr2.attrType = -1;
00526      attr2.attrLen = -1;
00527      attr2.attrValue = NULL;
00528           
00529      // make the call to Operators::Join
00530      
00531      Operators::Join(resultName, nattrs, attrList, &attr1, (Operator)(singlepred->Oper()), &attr2);
00532   }
00533   
00534   if (resultName == string( "TMP_BDB"))
00535   {
00536      // Print the contents of the result relation and destroy it
00537      Utilities::Print(resultName);
00538      
00539      relCat->destroyRel(resultName);
00540   }
00541   
00542   
00543   return; 
00544 }
00545 
00546 
00547 static int mk_attr_descrs(PxxList *list, ATTR_DESCR attr_descrs[])
00548 {
00549    int i;
00550    // int type, len;
00551    ListNode *attrlist = list->Init();
00552    PxxAttrType *attr;
00553    // int errval;
00554    
00555    // for each element of the list...
00556    for(i = 0; 
00557        attrlist != NULL && i < MAXATTRS; 
00558        ++i, attrlist = attrlist->Next())
00559    {
00560       attr = (PxxAttrType*)(attrlist->Data());
00561       
00562       // add it to the list
00563       attr_descrs[i].attrName = attr->AttrName();
00564       attr_descrs[i].attrType = attr->Type();
00565       switch(attr->Type()){
00566          
00567       case PxxAttrType::STRING:
00568          attr_descrs[i].attrLen = attr->Param1();
00569          // cout << "Length is " << attr->Param1() << endl;
00570          break; 
00571       case PxxAttrType::INTEGER:
00572          attr_descrs[i].attrLen = sizeof(int);
00573          break; 
00574       case PxxAttrType::DOUBLE: 
00575          attr_descrs[i].attrLen = sizeof(double);
00576          break;
00577       }
00578    } 
00579    // if the list is too long, then error
00580    if (i == MAXATTRS)
00581       return E_TOOMANYATTRS;
00582    
00583    return i;
00584 }
00585 
00586 //
00587 // mk_ins_attrs: converts a list of <attribute, value> pairs to an array
00588 // of ATTR_VAL's so it can be sent to Updates::Insert.
00589 //
00590 // Returns:
00591 //  length of the list on success ( >= 0 )
00592 //  error code otherwise ( < 0 )
00593 //
00594 
00595 static int mk_ins_attrs(PxxPnode *list, ATTR_VAL ins_attrs[])
00596 {
00597    int i, type, len;
00598    PxxInsert* insertlist = (PxxInsert*)list; 
00599    
00600    ListNode *attrlist = insertlist->OptList()->Init();
00601    ListNode *valuelist = insertlist->ValList()->Init(); 
00602    PxxAttrName* attr;
00603    PxxLiteral* literal; 
00604    
00605    // add the attributes to the list
00606    for(i = 0; 
00607    attrlist != NULL && i < MAXATTRS; 
00608    ++i, attrlist = attrlist->Next(), valuelist = valuelist->Next())
00609    {
00610       attr = (PxxAttrName*)(attrlist->Data());
00611       literal = (PxxLiteral*)(valuelist->Data());    
00612       
00613       AttrDesc attrDesc;
00614       
00615       attrCat->getInfo(insertlist->RelName(), attr->AttrName(), attrDesc);
00616       
00617       // make sure string attributes aren't too long
00618       type = attrDesc.attrType;
00619       len = attrDesc.attrLen;
00620       
00621       if (type != literal->LiteralType())
00622       {
00623          print_error("Value List Corrupt ", E_LITERALTYPE);
00624          return -1;
00625       }
00626 
00627       switch(type)
00628       {
00629          
00630       case PxxAttrType::STRING:
00631          ins_attrs[i].value = (void*)(literal->Char());
00632          break; 
00633       case PxxAttrType::INTEGER:
00634          ins_attrs[i].value = (void*)(literal->Int());
00635          break; 
00636       case PxxAttrType::DOUBLE: 
00637          ins_attrs[i].value = (void*)(literal->Double());
00638          break;
00639       }
00640       
00641       if (type == PxxAttrType::STRING){
00642          if(len > MAXSTRINGLEN){ 
00643             
00644             return E_STRINGTOOLONG;
00645          }
00646       } 
00647       ins_attrs[i].attrName = attr->AttrName();
00648       ins_attrs[i].valType = type;
00649       ins_attrs[i].valLength = len;
00650    }
00651    
00652    if (attrlist) return E_TOOMANYATTRS;
00653    
00654    return i;
00655 }
00656 
00657 //
00658 // mk_attrnames: converts a list of qualified attributes (<relation,
00659 // attribute> pairs) into an array of char pointers so it can be
00660 // sent to the appropriate Utilities or Operators function.
00661 //
00662 // All of the attributes should come from relation relname.  If relname
00663 // is NULL, then it checks that all attributes come from the same
00664 // relation.
00665 //
00666 // The first element of the array after the last attribute name is
00667 // set to the name of the relation.
00668 // 
00669 // Returns:
00670 //  the length of the list on success ( >= 0 )
00671 //  error code otherwise ( < 0 )
00672 //
00673 // (Thus, the return code is both the number of attributes in the array,
00674 // and the index of the relatin name in the array).
00675 //
00676 
00677 static int mk_attrnames(PxxList *list, char *attrnames[], char *relname)
00678 {
00679    int i;
00680    ListNode *temp = list->Init();
00681    PxxAttrName *attr;
00682    
00683    // for each qualified attribute in the list...
00684    for(i = 0; temp != NULL && i < MAXATTRS; ++i, temp = temp->Next()) 
00685    {
00686       
00687       attr = (PxxAttrName*)(temp->Data());
00688       
00689       // if relname is NULL, then remember this relname
00690       if (relname == NULL)
00691          relname = attr->RelName();
00692       
00693       // otherwise, see if the relname matches the remembered relname
00694       else if (strcmp(relname, attr->RelName()))
00695          return E_INCOMPATIBLE;
00696       
00697       // add attribute name to the list
00698       attrnames[i] = attr->AttrName();
00699    }
00700    
00701    // if the list is too long then error
00702    if (i == MAXATTRS)
00703       return E_TOOMANYATTRS;
00704    
00705    // put the relation name in the last position in the array
00706    attrnames[i] = relname;
00707    
00708    return i;
00709 }
00710 
00711 
00712 //
00713 // mk_qual_attrs: converts a list of qualified attributes (<relation,
00714 // attribute> pairs) into an array of REL_ATTRS so it can be sent to
00715 // Operators::Join.
00716 //
00717 // All of the attributes must come from either relname1 or relname2.
00718 //
00719 // Returns:
00720 //  the lengh of the list on success ( >= 0 )
00721 //  error code otherwise
00722 //
00723 
00724 static int mk_qual_attrs(PxxList *list, REL_ATTR qual_attrs[],
00725                          char *relname1, char *relname2)
00726 {
00727    int i;
00728    ListNode *temp = list->Init();
00729    PxxAttrName* attr;
00730 
00731    // for each element of the list...
00732    for(i = 0; temp != NULL && i < MAXATTRS; ++i, temp = temp->Next()) 
00733    {     
00734       attr = (PxxAttrName*)(temp->Data());
00735 
00736       // if relname != relname 1...
00737       if (strcmp(attr->RelName(), relname1)) 
00738       {       
00739          // and relname != relname 2, then error
00740          if (strcmp(attr->RelName(), relname2))
00741             return E_INCOMPATIBLE;
00742       }
00743       
00744       // add it to the list
00745       qual_attrs[i].relName = attr->RelName();
00746       qual_attrs[i].attrName = attr->AttrName();
00747    }
00748    
00749    // If the list is too long then error
00750    if (i == MAXATTRS)
00751       return E_TOOMANYATTRS;
00752    
00753    return i;
00754 }
00755 
00756 static void print_error(const char *errmsg, int errval)
00757 {
00758    if (errmsg != NULL)
00759       fprintf(stderr, "%s: ", errmsg);
00760    switch(errval) {
00761    case E_OK:
00762       fprintf(ERRFP, "no error\n");
00763       break;
00764    case E_INCOMPATIBLE:
00765       fprintf(ERRFP, "attributes must be from selected relation(s)\n");
00766       break;
00767    case E_TOOMANYATTRS:
00768       fprintf(ERRFP, "too many attributes\n");
00769       break;
00770    case E_NOLENGTH:
00771       fprintf(ERRFP, "length must be specified for STRING attribute\n");
00772       break;
00773    case E_INVINTSIZE:
00774       fprintf(ERRFP, "invalid size for INTEGER attribute (should be %d)\n",
00775          sizeof(int));
00776       break;
00777    case E_INVFLOATSIZE:
00778       fprintf(ERRFP, "invalid size for FLOAT attribute (should be %d)\n",
00779          sizeof(float));
00780       break;
00781    case E_INVFORMATSTRING:
00782       fprintf(ERRFP, "invalid format string\n");
00783       break;
00784    case E_INVSTRLEN:
00785       fprintf(ERRFP, "invalid length for string attribute\n");
00786       break;
00787    case E_DUPLICATEATTR:
00788       fprintf(ERRFP, "duplicated attribute name\n");
00789       break;
00790    case E_TOOLONG:
00791       fprintf(stderr, "relation name or attribute name too long\n");
00792       break;
00793    case E_STRINGTOOLONG:
00794       fprintf(stderr, "string attribute too long\n");
00795       break;
00796    case E_CORRUPTSQL:
00797       fprintf(stderr, "Invalid SQL Statement\n");
00798       break;
00799    case E_LITERALTYPE:
00800       fprintf(stderr, "Data Type Mistmatch\n");
00801       break;
00802    default:
00803       fprintf(ERRFP, "unrecognized errval: %d\n", errval);
00804    }
00805 }
00806 
 All Classes Namespaces Functions Variables Typedefs Enumerations Friends