Main Page   Namespace List   Class Hierarchy   Compound List   File List   Namespace Members   Compound Members  

SQLPredicateTree.cpp

00001                               /* SQLPredicateTree.cpp */
00002 
00003 /*
00004  *  Implementation of SQLPredicateTree.h
00005  */
00006 #include "SQLPredicateTree.h"
00007 
00008 using namespace LcgInfo;
00009 using namespace std;
00010    
00011 
00012 /**************************  METHODS FOR CLASS SQLPredicateTree ***************************/
00013 
00014 string const SQLPredicateTree::CHARS_TO_ESCAPE_IN_SQL_LITERALS = "\t ><=!()";
00015 
00016 /***** Public functions *****/
00017 
00018 SQLPredicateTree::SQLPredicateTree()
00019 :PredicateTree(){
00020 }
00021 
00022 SQLPredicateTree::~SQLPredicateTree(){
00023 }
00024 
00025 void SQLPredicateTree::insertPredicate(string const & pPred){
00026    int level=0;  //indicates the level of depth of the parenthesis
00027    short int lastPosLeft, firstPosRight;  //to be returned by processLevel0()
00028    short int offset=0; //to calculate sub-preds lengths
00029    string::size_type pos=0, aux; //to look for parenthesis
00030    string predicate, subPredicate;
00031 
00032    predicate=pPred;  //copy the parameter passed
00033    escapeLiterals(predicate,CHARS_TO_ESCAPE_IN_SQL_LITERALS); //so special chars are not interpreted
00034    delSurroundingChars(predicate);  //delete blanks and tabs
00035    aux=predicate.length(); //end of subPredicate being considered (by now, all of it);
00036 
00037    // find level 0 sub-strings and then process them looking for boolean operators
00038          pos=predicate.find_first_of("()",0);  //look for the first parenthesis
00039          while(pos!=string::npos){ 
00040             if(predicate.at(pos)=='(') {level++; if((level==1)&&(pos>0)) {aux=pos; break;}}
00041             if(predicate.at(pos)==')') {level--; if((level==0)&&(pos<aux-1)) offset=pos+1;}
00042             pos=predicate.find_first_of("()",pos+1);  //look for new parenthesis
00043          }
00044 
00045    // Check if the whole predicate is between parenthesis (given that no level 0 was found)
00046    while((predicate.at(0)=='(') && (predicate.at(aux-1)==')'))
00047       predicate=predicate.substr(1,aux-=2);  //remove them
00048    
00049    processLevel0(predicate.substr(offset,aux-offset),lastPosLeft,firstPosRight);//process level0
00050 
00051    if(lastPosLeft!=-10){
00052       setLeft(create());
00053       aux=lastPosLeft+offset+1; //let's reuse this variable as end of left sub-predicate
00054       subPredicate=predicate.substr(0,aux);
00055       left()->insertPredicate(subPredicate);
00056    }
00057    if(firstPosRight!=-10){
00058       setRight(create());      
00059       aux=firstPosRight+offset; //reuse it again as beggining of right sub-predicate
00060       subPredicate=predicate.substr(aux,predicate.length()-aux);
00061       right()->insertPredicate(subPredicate);
00062    }
00063 }// end of insertPredicate 
00064 
00065 
00066 /***** Private functions *****/
00067 
00068 void SQLPredicateTree::processLevel0(string const & pPred, short int& pLastPosLeft,
00069                              short int& pFirstPosRight){
00070    // The first boolean op. in level 0 (or 1 if all is in between parentheses) is root
00071    // If none is found, then look for a comparison operator as root node
00072    // Otherwise, it must be a leaf node
00073 
00074   vector<string> tokens;
00075   vector<short int> indices;
00076 
00077   vector<string>::iterator i;
00078   vector<short int>::iterator j; //for loops
00079    
00080   tokenizeStrWithIndices(pPred, tokens, indices); //tokenize the predicate
00081 
00082   //first, look for booleans
00083   for(i=tokens.begin(), j=indices.begin(); i!=tokens.end(); i++, j++)
00084      if(isBooleanOp(*i)){
00085         setType(BOOLEAN);
00086         setValue(*i);
00087         if(nocaseCompare(*i,"NOT"))
00088            pLastPosLeft=-10;  // with "NOT", there is no left child
00089         else
00090            pLastPosLeft=(*j)-1; //before the beggining of current token
00091         pFirstPosRight=(*j)+(*i).length();  //beginning of next token
00092 
00093         if(pFirstPosRight > (indices.back() + (int) tokens.back().size())){
00094            string msg="Parsing error. Missing expression after NOT operator.";
00095            msg+="\nPartial predicate: "+pPred;
00096            throw QueryTranslationException(msg,__FILE__,__LINE__);
00097         }
00098         return;
00099      }
00100         
00101   //if no boolean was found, look for the first comparison operator
00102   string::size_type pointer;  
00103   pointer=pPred.find_first_of("=><");
00104   if(pointer!=string::npos){
00105     setType(COMPARISON);
00106     if(pointer>0) pLastPosLeft=pointer-1;
00107     else{
00108        string msg="Parsing error. Missing expression before comparison operator.";
00109        msg+="\nPartial predicate: "+pPred;
00110        throw QueryTranslationException(msg,__FILE__,__LINE__);
00111     }
00112 
00113     // Now see if the operator is composed of one or two chars
00114     if(pPred.find_first_not_of("=>",pointer+1)==pointer+1){  //true for one char operator
00115        setValue(pPred.substr(pointer,1));
00116        if((pointer+1)<pPred.length()) pFirstPosRight=pointer+1;
00117        else{
00118           string msg="Parsing error. Missing expression after comparison operator.";
00119           msg+="\nPartial predicate: "+pPred;
00120           throw QueryTranslationException(msg,__FILE__,__LINE__);
00121        }
00122     }
00123     else{ //two char operator
00124        setValue(pPred.substr(pointer,2));
00125        if((pointer+2)<pPred.length())  pFirstPosRight=pointer+2;
00126        else{
00127           string msg="Parsing error. Missing expression after comparison operator.";
00128           msg+="\nPartial predicate: "+pPred;
00129           throw QueryTranslationException(msg,__FILE__,__LINE__);
00130        }
00131     }
00132     return;      
00133   }
00134 
00135   //still one more comparison operator: "LIKE"
00136   for(i=tokens.begin(), j=indices.begin(); i!=tokens.end(); i++, j++)
00137      if(nocaseCompare(*i,"LIKE")){
00138         setType(COMPARISON);
00139         setValue(*i);
00140         if(j!=indices.begin()) pLastPosLeft=*(j)-1; //before the beggining of current token
00141         if((j+1)!=indices.end()) pFirstPosRight=*(j)+(*i).length();  //beginning of next token
00142         return;
00143      }
00144 
00145   //if there is no operator, then it is a leaf node
00146   setType(LEAF);             //set type and value 
00147   unescapeLiterals(tokens.at(0),CHARS_TO_ESCAPE_IN_SQL_LITERALS); //undo previous escapes 
00148   setValue(tokens.at(0));
00149   pLastPosLeft=-10;
00150   pFirstPosRight=-10;
00151     
00152 }//end of processLevel0
00153 
00154 string SQLPredicateTree::getCHARS_TO_TOKENIZE_PREDICATES(){
00155    return "\t ><=!()";
00156 }

Generated on Tue Oct 5 14:42:45 2004 for LCG Information System Interface by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002