00001
00002
00003
00004
00005
00006 #include "SQLQueryTranslator.h"
00007
00008 using namespace LcgInfo;
00009 using namespace std;
00010
00011
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;
00042
00043 pNewTableList.clear();
00044 pRowsToReturn.clear();
00045 pPred.clear();
00046
00047
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++);
00052 if(count%2 !=0 ){
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);
00060 }
00061
00062 escapeLiterals(orgQuery, CHARS_TO_DIVIDE_SQL_WORDS);
00063 tokenizeStrWithIndices(orgQuery, queryTokens, queryIndices, CHARS_TO_DIVIDE_SQL_WORDS);
00064 currentToken=queryTokens[tokenPointer];
00065
00066
00067 if(nocaseCompare(currentToken,"SELECT")){
00068
00069
00070 currentToken=queryTokens[++tokenPointer];
00071 while(!nocaseCompare(currentToken,"FROM")){
00072 pRowsToReturn.push_back(currentToken);
00073 currentToken=queryTokens[++tokenPointer];
00074 }
00075
00076
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
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);
00090 pPred.insertPredicate(predicate);
00091
00092
00093 pPred.translate(mTRowT, &fromList, &pNewTableList);
00094 }
00095
00096
00097 for(vector<string>::iterator i=pRowsToReturn.begin(); i!=pRowsToReturn.end(); i++){
00098 translated.clear();
00099 currentToken=*i;
00100 if(currentToken.find('.')==string::npos){
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"){
00108 string::size_type auxPos=translated.find_last_of('.',translated.size()-1);
00109 translated.erase(auxPos,1);
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{
00121 try{
00122 translated=mTRowT->mapTableRow(currentToken);
00123 }catch(LcgConfigBuffer::CBException& e){
00124 if (e.what()=="+CB EXCEPTION: Attribute does not exist")
00125 {}
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;
00135 pNewTableList.insert(extractTable(translated));
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);
00151 if(i!=pRowsToReturn.end()) pRowsToReturn.insert(i,translated);
00152 else pRowsToReturn.push_back(translated);
00153 }
00154 }
00155
00156
00157
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 }
00167
00168