00001
00002
00003
00004
00005
00006 #include "SQLtoLDAPQuerier.h"
00007
00008 using namespace std;
00009 using namespace LcgInfo;
00010
00011 typedef vector<vector<string> >::iterator matrStrIt;
00012 typedef vector<string>::iterator vecStrIt;
00013 typedef string::size_type strPos;
00014
00015
00019 extern "C" {
00020 Querier* SQLtoLDAPQuerier_create(){
00021 return new SQLtoLDAPQuerier();
00022 }
00023 }
00024
00028 extern "C" {
00029 void SQLtoLDAPQuerier_destroy(Querier *p){
00030 delete p;
00031 }
00032 }
00033
00034
00035
00036 SQLtoLDAPQuerier::SQLtoLDAPQuerier()
00037 :mConf(0),mTranslator(0),mLdap(0){
00038 }
00039
00040 SQLtoLDAPQuerier::~SQLtoLDAPQuerier(){
00041 delete mConf;
00042 mConf=0;
00043 }
00044
00045 void SQLtoLDAPQuerier::setConfig(LcgConfigBuffer::ConfigBuffer & pConf){
00046 mConf=&pConf;
00047 mLdap=new InfoFromLDAP();
00048 mLdap->setConfig(pConf);
00049 mMap=new LcgConfigBuffer::ConfigBuffer();
00050
00051
00052 try{
00053 string mappingFile=mConf->get_attribute_value("SCHEMA_MAPPING_FILE");
00054 mMap->populate_from_config(mappingFile);
00055 }catch(LcgConfigBuffer::CBException& e){
00056 string msg="No valid mapping file. Aborting.";
00057 msg += "\nUnderlying CBException message: " + e.what() + " +line: ";
00058 msg += int2str(e.get_line()) + " +file: " + e.get_file();
00059 throw QueryTranslationException(msg,__FILE__,__LINE__);
00060 }
00061 mTranslator=new SQLtoLDAPQueryTranslator(*mMap);
00062 }
00063
00064 vector<vector<string> > SQLtoLDAPQuerier::query(string const & pCanonical){
00065 vector<vector<string> > resultsBuffer;
00066 try{
00067 string input=pCanonical;
00068 vector<string> translation=mTranslator->translateQuery(input);
00069
00070 vector<strPos> subqueries;
00071 vector<strPos> priorQueries;
00072 vector<strPos> cols;
00073
00074 strPos pos;
00075 vector<strPos> posList;
00076 bool nplicate=false;
00077 bool replace=false;
00078
00079
00080 for(vecStrIt orgQry=translation.begin(); orgQry!=(translation.end()-1); orgQry++){
00081 if(orgQry!=translation.begin()) nplicate=true;
00082 else nplicate=false;
00083 replace=false;
00084 priorQueries.clear();
00085 posList.clear();
00086 cols.clear();
00087
00088
00089
00090
00091
00092
00093
00094 pos=(*orgQry).find('#',0);
00095 while (pos != string::npos){
00096 int count=0;
00097 bool substitute=true;
00098 for(int i=pos-1; (*orgQry).at(i)=='\\'; i--, count++);
00099 if(count>0){
00100 (*orgQry).erase(pos-count/2,count/2);
00101 pos-=count/2;
00102 if(count%2!=0) substitute=false;
00103 }
00104 if(substitute){
00105 replace=true;
00106 nplicate=true;
00107 strPos queryNumber=str2int(string(1,(*orgQry).at(pos+1)));
00108 (*orgQry).erase(pos,3);
00109 if(subqueries.size()<=queryNumber){
00110 string msg="Trying to substitute a query whose results are not present";
00111 msg+="\nQuery number: " + int2str(queryNumber);
00112 throw QueryTranslationException(msg,__FILE__,__LINE__);
00113 }
00114 priorQueries.push_back(queryNumber);
00115 posList.push_back(pos);
00116 }
00117 else (*orgQry).erase(pos-1,1);
00118
00119 pos = (*orgQry).find("#", pos+1);
00120 }
00121
00122
00123 vector<string> theQueries;
00124 vector<string> auxQueries;
00125 string toQuery;
00126 strPos maxsub;
00127
00128 if(replace){
00129
00130 for(vector<strPos>::iterator i=posList.begin(); i!=posList.end(); i++){
00131 (*i) = (*orgQry).size()-(*i);
00132 }
00133
00134 if(priorQueries.size()>0) maxsub=priorQueries.back();
00135 for(strPos priorIndx=0; priorIndx<priorQueries.size(); priorIndx++){
00136 strPos auxPrev=priorQueries.at(priorIndx);
00137 if(auxPrev>maxsub) {
00138 maxsub=auxPrev;
00139 priorQueries.erase(priorQueries.begin()+priorIndx);
00140 priorQueries.push_back(maxsub);
00141 posList.push_back(posList.at(priorIndx));
00142 posList.erase(posList.begin()+priorIndx);
00143 }
00144 }
00145
00146 vector<string> prior=resultsBuffer[subqueries[priorQueries.back()]];
00147
00148
00149 for(strPos colNum=0; colNum<prior.size() ; colNum++){
00150 if(colNum>0) {if(prior.at(colNum)==prior.at(colNum-1)) continue;}
00151 toQuery=*orgQry;
00152
00153 for(strPos priorIndx=0; priorIndx<priorQueries.size(); priorIndx++){
00154 prior=resultsBuffer[subqueries[priorQueries[priorIndx]]];
00155 toQuery.insert(toQuery.size()-posList[priorIndx], prior[colNum]);
00156 }
00157 cols.push_back(colNum);
00158 theQueries.push_back(toQuery);
00159 }
00160 }
00161 else{
00162 theQueries.push_back(*orgQry);
00163 }
00164
00165
00166 strPos qryIndx=0;
00167 strPos offset=0;
00168 for(vecStrIt currQry=theQueries.begin(); currQry!=theQueries.end(); currQry++, qryIndx++){
00169 string filter;
00170 vector<string> attribs;
00171 vector<vector<string> > partialResults;
00172 strPos differentValues=1;
00173
00174
00175 pos=(*currQry).find_last_of(')',(*currQry).size()-1);
00176 filter=(*currQry).substr(0,pos+1);
00177 tokenizeStr((*currQry).substr(pos+1),attribs);
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189 partialResults.clear();
00190 try{
00191 partialResults=mLdap->query(filter,attribs);
00192 }catch(LcgConfigBuffer::CBException e){
00193 string msg="Error while querying the ldap interface. Aborting.";
00194 msg += "\nUnderlying CBException message: " + e.what() + " +line: ";
00195 msg += int2str(e.get_line()) + " +file: " + e.get_file();
00196 throw LcgInfoException(msg,__FILE__,__LINE__);
00197 }
00198 differentValues=partialResults[0].size();
00199
00200
00201 string::size_type which=0;
00202 for(vecStrIt attr=attribs.begin(); attr!=attribs.end(); attr++, which++){
00203 if(((*attr)=="GlueForeignKey")||(*attr)=="GlueChunkKey"){
00204 for(vecStrIt value=partialResults[which].begin();
00205 value!=partialResults[which].end(); value++){
00206 string::size_type auxPos=(*value).find_last_of('=',(*value).size()-1);
00207 if(auxPos!=string::npos) (*value)=(*value).substr(auxPos+1);
00208 }
00209 }
00210 }
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223 if(nplicate){
00224 strPos limit, ini;
00225 vector<string> prior;
00226 if(replace){
00227 ini=cols.at(qryIndx)+offset;
00228 limit=ini+1;
00229 }
00230 else{
00231 limit=differentValues;
00232 ini=0;
00233 }
00234
00235 for(strPos i=ini; i<limit; i++){
00236 strPos baseCol;
00237 if(replace){
00238 baseCol=i;
00239 prior=resultsBuffer[subqueries.at(maxsub)];
00240 }
00241 else{
00242 prior=resultsBuffer[subqueries.back()];
00243 baseCol=differentValues * i;
00244 }
00245
00246 for(strPos colNum=baseCol; colNum<prior.size() && prior.at(colNum)==prior.at(baseCol); colNum++){
00247
00248 for(matrStrIt bufRow=resultsBuffer.begin();bufRow!=resultsBuffer.end();bufRow++){
00249 if((*bufRow).size()>colNum){
00250
00251 for(strPos j=0; j<differentValues-1; j++){
00252 (*bufRow).insert(((*bufRow).begin())+colNum, (*bufRow).at(colNum));
00253 }
00254 }
00255 }
00256 }
00257
00258 }
00259 }
00260
00261
00262 if(replace && (cols.at(qryIndx)!=0)){
00263 for(matrStrIt toStore=partialResults.begin(); toStore!=partialResults.end(); toStore++){
00264 resultsBuffer.back().insert(resultsBuffer.back().end(), (*toStore).begin(), (*toStore).end());
00265 }
00266 }
00267 else if((!replace) && nplicate){
00268 for(matrStrIt toStore=partialResults.begin(); toStore!=partialResults.end(); toStore++){
00269 resultsBuffer.push_back(*toStore);
00270 }
00271 for(strPos i=0; i<differentValues-1; i++){
00272 for(matrStrIt toStore=partialResults.begin(); toStore!=partialResults.end(); toStore++){
00273 resultsBuffer.back().insert(resultsBuffer.back().end(),(*toStore).begin(), (*toStore).end());
00274 }
00275 }
00276 }
00277 else{
00278 for(matrStrIt toStore=partialResults.begin(); toStore!=partialResults.end(); toStore++){
00279 resultsBuffer.push_back(*toStore);
00280 }
00281 }
00282
00283
00284 if ((!replace) || (cols.at(qryIndx)==0))
00285 subqueries.push_back(resultsBuffer.size()-partialResults.size());
00286
00287
00288 offset+=differentValues-1;
00289 }
00290
00291 }
00292
00293
00294
00295 vector<vector<string> > finalResults;
00296 vector<string> listOfResults;
00297 tokenizeStr(translation.back(), listOfResults, ",");
00298 for(vecStrIt i=listOfResults.begin(); i!=listOfResults.end(); i++){
00299 vector<string> numbers;
00300 tokenizeStr(*i, numbers, "-");
00301 strPos theLine=str2int(numbers[0]);
00302 string::size_type aux;
00303 if(numbers[1]=="1"){
00304 if((aux=subqueries.at(theLine))!=string::npos){
00305 subqueries.at(theLine)=string::npos;
00306 strPos limit;
00307 if(subqueries.size()>theLine+1) limit=subqueries.at(theLine+1);
00308 else limit=resultsBuffer.size();
00309 for(string::size_type j=aux+1; j<limit; j++){
00310 finalResults.push_back(resultsBuffer.at(j));
00311 }
00312 }
00313 }
00314 else{
00315 aux=subqueries.at(theLine);
00316 finalResults.push_back(resultsBuffer.at(aux));
00317 }
00318
00319 }
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334 return finalResults;
00335
00336 }catch(QueryTranslationException &e){
00337 cerr << e.what() << " +line: " << e.get_line() << " +file: " << e.get_file() << endl;;
00338 return resultsBuffer;
00339 }
00340
00341 }