00001
00002
00003
00004
00005
00006 #include "PredicateTree.h"
00007
00008 using namespace LcgInfo;
00009 using namespace std;
00010
00011
00012
00013
00014 string const PredicateTree::CHARS_TO_ESCAPE_IN_LITERALS = "\t ><=!()";
00015
00016
00017
00018 PredicateTree::PredicateTree() {
00019 mType=LEAF; mValue="EMPTY"; mDepth=0; mLeft=0; mRight=0;
00020 }
00021
00022 PredicateTree::~PredicateTree(){
00023 if(left()!=0){
00024 delete left();
00025 setLeft(0);
00026 }
00027 if(right()!=0){
00028 delete right();
00029 setRight(0);
00030 }
00031 }
00032
00033 bool const PredicateTree::operator==(PredicateTree const & other){
00034 bool leftPart=false, rightPart=false;
00035
00036
00037 if ((value()!=other.value()) || (type()!=other.type())) return false;
00038
00039
00040 if(other.left()!=NULL){
00041 if (left()==NULL) return false;
00042 else leftPart=(*left() == *(other.left()));
00043 }
00044 if(other.left()==NULL){
00045 if (left()!=NULL) return false;
00046 else leftPart=true;
00047 }
00048
00049
00050 if(other.right()!=NULL){
00051 if (right()==NULL) return false;
00052 else rightPart=(*right() == *(other.right()));
00053 }
00054 if(other.right()==NULL){
00055 if (right()!=NULL) return false;
00056 else rightPart=true;
00057 }
00058
00059 return (leftPart && rightPart);
00060 }
00061
00062 void PredicateTree::clear(){
00063 if(left()!=0){
00064 delete left();
00065 setLeft(0);
00066 }
00067 if(right()!=0){
00068 delete right();
00069 setRight(0);
00070 }
00071 setValue("");
00072 setDepth(0);
00073 }
00074
00075 bool PredicateTree::empty(){
00076 if(left()!=0) return false;
00077 if(right()!=0) return false;
00078 if(value()!="") return false;
00079 if(depth()!=0) return false;
00080 return true;
00081 }
00082
00083 void PredicateTree::translate(TableRowTranslator * pTRowT, vector<string> * pOrgTables,
00084 set<string> * pNewTables){
00085
00086 vector<string> predicatesToAdd;
00087
00088
00089 if(type()==BOOLEAN){
00090 if(left()!=0) left()->translate(pTRowT, pOrgTables, pNewTables);
00091 if(right()!=0) right()->translate(pTRowT, pOrgTables, pNewTables);
00092
00093 if((left()!=0) && (left()->isIdentity())){
00094 if(value()=="OR"){
00095 delete right();
00096 setRight(0);
00097 }
00098 delete left();
00099 setLeft(0);
00100 }
00101 if((right()!=0) && (right()->isIdentity())){
00102 if(value()=="OR"){
00103 delete left();
00104 setLeft(0);
00105 }
00106 delete right();
00107 setRight(0);
00108 }
00109 }
00110
00111 if(type()==LEAF){
00112 string translated;
00113 if((isNumber(value()))||isLiteral(value())) return;
00114 else{
00115 if(value().find('.')==string::npos)
00116
00117 for(vector<string>::iterator j=pOrgTables->begin(); j!=pOrgTables->end(); j++)
00118 try{
00119 translated=pTRowT->mapTableRow((*j)+'.'+value());
00120 }catch(LcgConfigBuffer::CBException & e){
00121 if (e.what()=="+CB EXCEPTION: Attribute does not exist")
00122 {}
00123 else{
00124 string msg="The attribute matching is not working properly.";
00125 msg+= "\nUnderlying LcgConfigBuffer::CBException message: " + e.what() + " +line: ";
00126 msg+= int2str(e.get_line()) + " +file: " + e.get_file();
00127 throw QueryTranslationException(msg,__FILE__,__LINE__);
00128 }
00129 }
00130 else
00131 try{
00132 translated=pTRowT->mapTableRow(value());
00133 }catch(LcgConfigBuffer::CBException& e){
00134 if (e.what()=="+CB EXCEPTION: Attribute does not exist")
00135 {}
00136 else{
00137 string msg="The attribute matching is not working properly.";
00138 msg+= "\nUnderlying LcgConfigBuffer::CBException message: " + e.what() + " +line: ";
00139 msg+= int2str(e.get_line()) + " +file: " + e.get_file();
00140 throw QueryTranslationException(msg,__FILE__,__LINE__);
00141 }
00142 }
00143 pNewTables->insert(extractTable(translated));
00144 if(!translated.empty()) setValue(translated);
00145 }
00146 }
00147
00148 if(type()==COMPARISON){
00149 if(left()!=NULL) left()->translate(pTRowT, pOrgTables, pNewTables);
00150 if(pTRowT->thereIsStructChange()){
00151 for(vector<string>::iterator i=pTRowT->getPredicatesBegin();
00152 i!=pTRowT->getPredicatesEnd(); i++){
00153 if((*i).at(0)=='+') predicatesToAdd.push_back((*i).substr(1));
00154 else{
00155 string msg="Parsing error. Currently, a predicate rule must start with \"+\"";
00156 msg+="\nPredicate: "+ (*i);
00157 throw QueryTranslationException(msg,__FILE__,__LINE__);
00158 }
00159 }
00160
00161 }
00162 if(right()!=NULL) right()->translate(pTRowT, pOrgTables, pNewTables);
00163 if(pTRowT->thereIsStructChange())
00164 for(vector<string>::iterator i=pTRowT->getPredicatesBegin();
00165 i!=pTRowT->getPredicatesEnd(); i++){
00166 if((*i).at(0)=='+') predicatesToAdd.push_back((*i).substr(1));
00167 else{
00168 string msg="Parsing error. Currently, a predicate rule must start with \"+\"";
00169 msg+="\nPredicate: "+ (*i);
00170 throw QueryTranslationException(msg,__FILE__,__LINE__);
00171 }
00172 }
00173 for(vector<string>::iterator i=predicatesToAdd.begin();i!=predicatesToAdd.end(); i++){
00174 this->addAndPredicate(*i, *pNewTables);
00175 }
00176 }
00177 }
00178
00179 void PredicateTree::print(){
00180 cout << value();
00181 if(mLeft!=NULL){
00182 cout << "\t";
00183 mLeft->print();
00184 }
00185 if(mRight!=NULL){
00186 cout << endl;
00187 for(int i=0; i<=mDepth; i++) cout << "\t";
00188 mRight->print();
00189 }
00190 }
00191
00192
00193
00194 void PredicateTree::setLeft(PredicateTree* pLeft){
00195 mLeft=pLeft;
00196 if(mLeft!=NULL) mLeft->incrementDepth(depth()+1);
00197 }
00198 void PredicateTree::setRight(PredicateTree* pRight){
00199 mRight=pRight;
00200 if(mRight!=NULL) mRight->incrementDepth(depth()+1);
00201 }
00202
00203 void PredicateTree::incrementDepth(int pAmount){
00204 setDepth(pAmount);
00205 if(left()!=NULL) left()->incrementDepth(pAmount+1);
00206 if(right()!=NULL) right()->incrementDepth(pAmount+1);
00207 }
00208
00209 bool PredicateTree::relatesTables(){
00210 if(type()!=COMPARISON) return false;
00211 if(right()==0) return false;
00212 if((isNumber(right()->value())) || (isLiteral(right()->value()))) return false;
00213 else return true;
00214 }
00215
00216 bool PredicateTree::isIdentity() const{
00217 if (type()==COMPARISON){
00218 if(((left())!=NULL)&&((right())!=NULL))
00219 if((left()->value())==(right()->value())) return true;
00220 }
00221 return false;
00222 }
00223
00224 bool PredicateTree::isRedundant(PredicateTree const & pPred){
00225
00226 if(pPred.isIdentity()) return true;
00227
00228 if((type() == BOOLEAN) && (value() == "AND")) {
00229 if(left()!=NULL) if(left()->isRedundant(pPred)) return true;
00230 if(right()!=NULL) if(right()->isRedundant(pPred)) return true;
00231 }
00232 if((*this) == (pPred)) return true;
00233
00234 return false;
00235 }
00236
00237 void PredicateTree::addAndPredicate(string const& pPred, set<string> & pNewTables){
00238 PredicateTree* newPred;
00239
00240
00241 newPred=create();
00242 newPred->insertPredicate(pPred);
00243 if(this->isRedundant(*newPred)) return;
00244
00245
00246 PredicateTree* tempLeft;
00247 PredicateTree* tempRight;
00248 tempLeft=this->left();
00249 tempRight=this->right();
00250
00251 this->setLeft(NULL);
00252 this->setRight(NULL);
00253
00254 this->setLeft(this->clone());
00255
00256 this->left()->setLeft(tempLeft);
00257 this->left()->setRight(tempRight);
00258
00259 this->setType(BOOLEAN);
00260 this->setValue("AND");
00261
00262 this->setRight(newPred);
00263
00264
00265 string aux=pPred;
00266 escapeLiterals(aux, this->getCHARS_TO_TOKENIZE_PREDICATES());
00267 vector<string> tokens;
00268 tokenizeStr(aux, tokens, this->getCHARS_TO_TOKENIZE_PREDICATES());
00269 for(vector<string>::iterator k=tokens.begin(); k!=tokens.end(); k++){
00270 if((!isNumber(*k))&&(!isLiteral(*k))){
00271 pNewTables.insert(extractTable(*k));
00272 }
00273 }
00274 unescapeLiterals(aux, this->getCHARS_TO_TOKENIZE_PREDICATES());
00275 }
00276
00277 bool PredicateTree::isBooleanOp(string pStr){
00278 return nocaseCompare(pStr,"NOT") || nocaseCompare(pStr,"AND") || nocaseCompare(pStr,"OR");
00279 }
00280
00281 string PredicateTree::getCHARS_TO_TOKENIZE_PREDICATES(){
00282 return "\t ><=!()";
00283 }