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

SQLQueryTranslator.cpp

00001                               /* SQLQueryTranslator.cpp */
00002 
00003 /*
00004  *  Implementation of SQLQueryTranslator.h
00005  */
00006 #include "SQLQueryTranslator.h"
00007 
00008 using namespace LcgInfo;
00009 using namespace std;
00010 
00011 /******************  METHODS FOR CLASS SQLQueryTranslator  ********************/
00012 
00013 std::string const SQLQueryTranslator::CHARS_TO_DIVIDE_SQL_WORDS = "\t ,";
00014 std::string const SQLQueryTranslator::CHARS_POSSIBLY_ESCAPED="%";
00015 
00016 SQLQueryTranslator::SQLQueryTranslator()
00017 : QueryTranslator(){
00018 }
00019 
00020 SQLQueryTranslator::SQLQueryTranslator(string const & pMapFile)
00021 : QueryTranslator(pMapFile){
00022 }
00023 
00024 SQLQueryTranslator::SQLQueryTranslator(LcgConfigBuffer::ConfigBuffer & pMap)
00025 : QueryTranslator(pMap){
00026 }
00027 
00028 SQLQueryTranslator::~SQLQueryTranslator(){
00029 }
00030 
00031 void SQLQueryTranslator::translateSemantic(string const & pQueryCanonical,
00032       SQLPredicateTree & pPred, vector<string> & pRowsToReturn, set<string> & pNewTableList){
00033 
00034    string orgQuery=pQueryCanonical;
00035    string currentToken;
00036    string translated="";
00037    string::size_type tokenPointer=0;
00038 
00039    vector<string> queryTokens;
00040    vector<short int> queryIndices;
00041    vector<string> fromList;  // the old list of tables
00042 
00043    pNewTableList.clear();
00044    pRowsToReturn.clear();
00045    pPred.clear();
00046     
00047    //First, check that there are no unmatched "\"
00048    string::size_type pos = orgQuery.find("\\", 0);
00049    while (pos != string::npos){
00050       int count=0; 
00051       for(int i=pos; orgQuery.at(i)=='\\'; i++, count++); //count escape chars
00052       if(count%2 !=0 ){                   //if the count is not even, check what is being escaped
00053          if(CHARS_POSSIBLY_ESCAPED.find(orgQuery.at(pos+1),0)==string::npos){
00054             string msg="Parsing error. Malformed query: unmatched \"\\\".";
00055             msg+="\nQuery: " + orgQuery;
00056             throw QueryTranslationException(msg,__FILE__,__LINE__);
00057          }         
00058       }         
00059       pos = orgQuery.find_first_of('\\', pos+count+1);   // go for next one 
00060    }
00061 
00062    escapeLiterals(orgQuery, CHARS_TO_DIVIDE_SQL_WORDS); //to avoid split of multi-word literals
00063    tokenizeStrWithIndices(orgQuery, queryTokens, queryIndices, CHARS_TO_DIVIDE_SQL_WORDS);
00064    currentToken=queryTokens[tokenPointer];
00065 
00066    //SELECT
00067    if(nocaseCompare(currentToken,"SELECT")){
00068  
00069       // store rows to return
00070       currentToken=queryTokens[++tokenPointer];
00071       while(!nocaseCompare(currentToken,"FROM")){
00072          pRowsToReturn.push_back(currentToken);
00073          currentToken=queryTokens[++tokenPointer];
00074       }
00075   
00076       // store the tables for the FROM list
00077       currentToken=queryTokens[++tokenPointer];
00078       while((tokenPointer<queryTokens.size())&&(!nocaseCompare(currentToken,"WHERE"))){
00079          fromList.push_back(currentToken);
00080          tokenPointer++;
00081          if(tokenPointer<queryTokens.size())
00082             currentToken=queryTokens[tokenPointer];        
00083       }
00084    
00085       if(tokenPointer<queryTokens.size()){
00086          //the rest conforms the predicate tree
00087          short int pos=queryIndices[tokenPointer]+currentToken.length();
00088          string predicate=orgQuery.substr(pos, orgQuery.length()-pos+1);
00089          unescapeLiterals(predicate, CHARS_TO_DIVIDE_SQL_WORDS); //undo the previous escapes
00090          pPred.insertPredicate(predicate);
00091       
00092          //Now, translate first the predicate tree
00093          pPred.translate(mTRowT, &fromList, &pNewTableList); 
00094       }
00095 
00096       //Second, process the rows to be returned      
00097       for(vector<string>::iterator i=pRowsToReturn.begin(); i!=pRowsToReturn.end(); i++){
00098          translated.clear();
00099          currentToken=*i;
00100          if(currentToken.find('.')==string::npos){  //if there is no table name...
00101             for(vector<string>::iterator j=fromList.begin(); j!=fromList.end(); j++){
00102                translated=(*j) + '.' + currentToken;
00103                try{
00104                   translated=mTRowT->mapTableRow(translated);
00105                   break;
00106                }catch(LcgConfigBuffer::CBException & e){
00107                    if (e.what()=="+CB EXCEPTION: Attribute does not exist"){ //it's not of that table
00108                       string::size_type auxPos=translated.find_last_of('.',translated.size()-1);
00109                       translated.erase(auxPos,1); // just remove the extra "."
00110                    }
00111                    else{
00112                       string msg="The attribute matching is not working properly.\n";
00113                       msg+= "Underlying LcgConfigBuffer::CBException message: " + e.what();
00114                       msg+= " +line: " + int2str(e.get_line()) + " +file: " + e.get_file();
00115                       throw QueryTranslationException(msg,__FILE__,__LINE__);
00116                    }
00117                }
00118             }
00119          }
00120          else{ //it contains the table and all
00121             try{
00122                 translated=mTRowT->mapTableRow(currentToken);
00123             }catch(LcgConfigBuffer::CBException& e){
00124                 if (e.what()=="+CB EXCEPTION: Attribute does not exist")
00125                    {} //it's not an attribute of that table, just go on
00126                 else{
00127                    string msg="The attribute matching is not working properly.\n";
00128                    msg+= "Underlying LcgConfigBuffer::CBException message: " + e.what() + " +line: ";
00129                    msg+= int2str(e.get_line()) + " +file: " + e.get_file();
00130                    throw QueryTranslationException(msg,__FILE__,__LINE__);
00131                 }
00132              }
00133          }
00134          if(translated.empty()) translated=currentToken; //it is not in the mapping, let it be
00135          pNewTableList.insert(extractTable(translated)); // update new table list
00136 
00137          if(mTRowT->thereIsStructChange()) 
00138             for(vector<string>::iterator j=mTRowT->getPredicatesBegin();
00139              j!=mTRowT->getPredicatesEnd(); j++){
00140                 if((*j).at(0)=='+'){
00141                    string aux=(*j).substr(1);
00142                    pPred.addAndPredicate(aux, pNewTableList);
00143                 }
00144                 else{
00145                   string msg="Parsing error. Currently, a predicate rule must start with \"+\"";
00146                   msg+="\nPredicate: "+ (*j);
00147                   throw QueryTranslationException(msg,__FILE__,__LINE__);
00148                 }
00149             }
00150          pRowsToReturn.erase(i); //remove the old table.row name
00151          if(i!=pRowsToReturn.end()) pRowsToReturn.insert(i,translated); //now add the translated one
00152          else pRowsToReturn.push_back(translated);
00153       }//end of for(rows to return)
00154    }//end of if("SELECT")
00155 
00156 //   //INSERT
00157 //   else if(nocaseCompare(currentToken,"INSERT")){
00158 //   }
00159 
00160    else{
00161       string msg="Malformed SQL query: no SELECT clause detected.";
00162       msg+="\nCurrently, only SELECT queries are supported.";
00163       msg+="\nQuery: " + orgQuery;
00164       throw QueryTranslationException(msg,__FILE__,__LINE__);
00165    }
00166 }//end of translateSemantic
00167 
00168    

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