oqlset.cc

00001 /* 
00002    EyeDB Object Database Management System
00003    Copyright (C) 1994-2008 SYSRA
00004    
00005    EyeDB is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Lesser General Public
00007    License as published by the Free Software Foundation; either
00008    version 2.1 of the License, or (at your option) any later version.
00009    
00010    EyeDB is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Lesser General Public License for more details.
00014    
00015    You should have received a copy of the GNU Lesser General Public
00016    License along with this library; if not, write to the Free Software
00017    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA 
00018 */
00019 
00020 /*
00021    Author: Eric Viara <viara@sysra.com>
00022 */
00023 
00024 
00025 #include "oql_p.h"
00026 
00027 namespace eyedb {
00028 
00029 // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
00030 //
00031 // set utility functions
00032 //
00033 // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
00034 
00035 static oqmlStatus *
00036 check_bag_set(oqmlNode *node, oqmlAtomList *alist)
00037 {
00038   if (alist->cnt != 1 ||
00039       (!OQML_IS_SET(alist->first) && !OQML_IS_BAG(alist->first)))
00040     return oqmlStatus::expected(node, "set or bag",
00041                                 (alist->first ? alist->first->type.getString() :
00042                                  "nothing"));
00043 
00044   return oqmlSuccess;
00045 }
00046 
00047 static oqmlStatus *
00048 check_bag_set(oqmlNode *node, oqmlAtom *x)
00049 {
00050   if (!OQML_IS_SET(x) && !OQML_IS_BAG(x))
00051     return oqmlStatus::expected(node, "set or bag", x->type.getString());
00052 
00053   return oqmlSuccess;
00054 }
00055 
00056 static oqmlBool
00057 is_in(oqmlAtom *x, oqmlAtomList *list)
00058 {
00059   oqmlAtom *a = list->first;
00060   std::string sx = x->getString();
00061   while (a)
00062     {
00063       if (sx == std::string(a->getString()))
00064         return oqml_True;
00065       a = a->next;
00066     }
00067 
00068   return oqml_False;
00069 }
00070 
00071 static oqmlStatus *
00072 set_make(oqmlAtom *left, oqmlAtom *right, oqmlAtomList *list,
00073          oqmlAtomList **alist)
00074 {
00075   if (OQML_IS_BAG(left) || OQML_IS_BAG(right))
00076     {
00077       (*alist) = new oqmlAtomList(new oqmlAtom_bag(list));
00078       return oqmlSuccess;
00079     }
00080 
00081   (*alist) = new oqmlAtomList(new oqmlAtom_set(list));
00082   return oqmlSuccess;
00083 }
00084 
00085 // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
00086 //
00087 // oqmlUnion operator methods
00088 //
00089 // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
00090 
00091 oqmlUnion::oqmlUnion(oqmlNode * _qleft, oqmlNode * _qright) : oqmlNode(oqmlUNION)
00092 {
00093   qleft = _qleft;
00094   qright = _qright;
00095 }
00096 
00097 oqmlUnion::~oqmlUnion()
00098 {
00099 }
00100 
00101 oqmlStatus *oqmlUnion::compile(Database *db, oqmlContext *ctx)
00102 {
00103   oqmlStatus *s;
00104 
00105   s = qleft->compile(db, ctx);
00106   if (s) return s;
00107 
00108   s = qright->compile(db, ctx);
00109   if (s) return s;
00110 
00111   return oqmlSuccess;
00112 }
00113 
00114 oqmlStatus *oqmlUnion::eval(Database *db, oqmlContext *ctx, oqmlAtomList **alist, oqmlComp *, oqmlAtom *)
00115 {
00116   oqmlAtomList *aleft;
00117   oqmlStatus *s;
00118 
00119   s = qleft->eval(db, ctx, &aleft);
00120   if (s) return s;
00121 
00122   s = check_bag_set(this, aleft);
00123   if (s) return s;
00124 
00125   oqmlAtomList *aright;
00126   s = qright->eval(db, ctx, &aright);
00127   if (s) return s;
00128 
00129   s = check_bag_set(this, aright);
00130   if (s) return s;
00131 
00132   oqmlAtomList *left = OQML_ATOM_COLLVAL(aleft->first);
00133   oqmlAtomList *right = OQML_ATOM_COLLVAL(aright->first);
00134 
00135   oqmlAtomList *list = new oqmlAtomList(left);
00136   list->append(right);
00137 
00138   return set_make(aleft->first, aright->first, list, alist);
00139 }
00140 
00141 void oqmlUnion::evalType(Database *db, oqmlContext *ctx, oqmlAtomType *at)
00142 {
00143   *at = eval_type;
00144 }
00145 
00146 oqmlBool oqmlUnion::isConstant() const
00147 {
00148   return oqml_False;
00149 }
00150 
00151 std::string
00152 oqmlUnion::toString(void) const
00153 {
00154   if (is_statement)
00155     return std::string(qleft->toString()) + " union " + qright->toString() + "; ";
00156   return std::string("(") + qleft->toString() + " union " + qright->toString() +
00157   ")";
00158 }
00159 
00160 // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
00161 //
00162 // oqmlIntersect operator methods
00163 //
00164 // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
00165 
00166 oqmlIntersect::oqmlIntersect(oqmlNode * _qleft, oqmlNode * _qright) : oqmlNode(oqmlINTERSECT)
00167 {
00168   qleft = _qleft;
00169   qright = _qright;
00170 }
00171 
00172 oqmlIntersect::~oqmlIntersect()
00173 {
00174 }
00175 
00176 oqmlStatus *oqmlIntersect::compile(Database *db, oqmlContext *ctx)
00177 {
00178   oqmlStatus *s;
00179 
00180   s = qleft->compile(db, ctx);
00181   if (s) return s;
00182 
00183   s = qright->compile(db, ctx);
00184   if (s) return s;
00185 
00186   return oqmlSuccess;
00187 }
00188 
00189 oqmlStatus *oqmlIntersect::eval(Database *db, oqmlContext *ctx, oqmlAtomList **alist, oqmlComp *, oqmlAtom *)
00190 {
00191   oqmlAtomList *aleft;
00192   oqmlStatus *s;
00193 
00194   s = qleft->eval(db, ctx, &aleft);
00195   if (s) return s;
00196 
00197   s = check_bag_set(this, aleft);
00198   if (s) return s;
00199 
00200   oqmlAtomList *aright;
00201   s = qright->eval(db, ctx, &aright);
00202   if (s) return s;
00203 
00204   s = check_bag_set(this, aright);
00205   if (s) return s;
00206 
00207   oqmlAtomList *left = OQML_ATOM_COLLVAL(aleft->first);
00208   oqmlAtomList *right = OQML_ATOM_COLLVAL(aright->first);
00209   oqmlAtomList *list = new oqmlAtomList();
00210 
00211   oqmlAtom *leftx = left->first;
00212   while (leftx)
00213     {
00214       oqmlAtom *next = leftx->next;
00215       if (is_in(leftx, right))
00216         list->append(leftx);
00217       leftx = next;
00218     }
00219 
00220   return set_make(aleft->first, aright->first, list, alist);
00221 }
00222 
00223 void oqmlIntersect::evalType(Database *db, oqmlContext *ctx, oqmlAtomType *at)
00224 {
00225   *at = eval_type;
00226 }
00227 
00228 oqmlBool oqmlIntersect::isConstant() const
00229 {
00230   return oqml_False;
00231 }
00232 
00233 std::string
00234 oqmlIntersect::toString(void) const
00235 {
00236   if (is_statement)
00237     return std::string(qleft->toString()) + " intersect " + qright->toString() + "; ";
00238   return std::string("(") + qleft->toString() + " intersect " + qright->toString() +
00239   ")";
00240 }
00241 
00242 // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
00243 //
00244 // oqmlExcept operator methods
00245 //
00246 // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
00247 
00248 oqmlExcept::oqmlExcept(oqmlNode * _qleft, oqmlNode * _qright) : oqmlNode(oqmlEXCEPT)
00249 {
00250   qleft = _qleft;
00251   qright = _qright;
00252 }
00253 
00254 oqmlExcept::~oqmlExcept()
00255 {
00256 }
00257 
00258 oqmlStatus *oqmlExcept::compile(Database *db, oqmlContext *ctx)
00259 {
00260   oqmlStatus *s;
00261 
00262   s = qleft->compile(db, ctx);
00263   if (s) return s;
00264 
00265   s = qright->compile(db, ctx);
00266   if (s) return s;
00267 
00268   return oqmlSuccess;
00269 }
00270 
00271 oqmlStatus *oqmlExcept::eval(Database *db, oqmlContext *ctx, oqmlAtomList **alist, oqmlComp *, oqmlAtom *)
00272 {
00273   oqmlAtomList *aleft;
00274   oqmlStatus *s;
00275 
00276   s = qleft->eval(db, ctx, &aleft);
00277   if (s) return s;
00278 
00279   s = check_bag_set(this, aleft);
00280   if (s) return s;
00281 
00282   oqmlAtomList *aright;
00283   s = qright->eval(db, ctx, &aright);
00284   if (s) return s;
00285 
00286   s = check_bag_set(this, aright);
00287   if (s) return s;
00288 
00289   oqmlAtomList *left = OQML_ATOM_COLLVAL(aleft->first);
00290   oqmlAtomList *right = OQML_ATOM_COLLVAL(aright->first);
00291   oqmlAtomList *list = new oqmlAtomList();
00292 
00293   oqmlAtom *leftx = left->first;
00294   while (leftx)
00295     {
00296       oqmlAtom *next = leftx->next;
00297       if (!is_in(leftx, right))
00298         list->append(leftx);
00299       leftx = next;
00300     }
00301 
00302   return set_make(aleft->first, aright->first, list, alist);
00303 }
00304 
00305 void oqmlExcept::evalType(Database *db, oqmlContext *ctx, oqmlAtomType *at)
00306 {
00307   *at = eval_type;
00308 }
00309 
00310 oqmlBool oqmlExcept::isConstant() const
00311 {
00312   return oqml_False;
00313 }
00314 
00315 std::string
00316 oqmlExcept::toString(void) const
00317 {
00318   if (is_statement)
00319     return std::string(qleft->toString()) + " except " + qright->toString() + "; ";
00320   return std::string("(") + qleft->toString() + " except " + qright->toString() +
00321   ")";
00322 }
00323 
00324 // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
00325 //
00326 // set comparison functions
00327 //
00328 // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
00329 
00330 static oqmlStatus *
00331 oqml_set_inf(oqmlNode *node, oqmlAtomList *left, oqmlAtomList *right,
00332              oqmlBool &b)
00333 {
00334   if (left->cnt >= right->cnt)
00335     {
00336       b = oqml_False;
00337       return oqmlSuccess;
00338     }
00339 
00340   oqmlAtom *x = left->first;
00341   while (x)
00342     {
00343       if (!is_in(x, right))
00344         {
00345           b = oqml_False;
00346           return oqmlSuccess;
00347         }
00348 
00349       x = x->next;
00350     }
00351 
00352   b = oqml_True;
00353   return oqmlSuccess;
00354 }
00355 
00356 static oqmlStatus *
00357 oqml_set_infeq(oqmlNode *node, oqmlAtomList *left, oqmlAtomList *right,
00358              oqmlBool &b)
00359 {
00360   oqmlAtom *x = left->first;
00361   while (x)
00362     {
00363       if (!is_in(x, right))
00364         {
00365           b = oqml_False;
00366           return oqmlSuccess;
00367         }
00368 
00369       x = x->next;
00370     }
00371 
00372   b = oqml_True;
00373   return oqmlSuccess;
00374 }
00375 
00376 static oqmlStatus *
00377 oqml_set_sup(oqmlNode *node, oqmlAtomList *left, oqmlAtomList *right,
00378              oqmlBool &b)
00379 {
00380   if (right->cnt >= left->cnt)
00381     {
00382       b = oqml_False;
00383       return oqmlSuccess;
00384     }
00385 
00386   oqmlAtom *x = right->first;
00387   while (x)
00388     {
00389       if (!is_in(x, left))
00390         {
00391           b = oqml_False;
00392           return oqmlSuccess;
00393         }
00394 
00395       x = x->next;
00396     }
00397 
00398   b = oqml_True;
00399   return oqmlSuccess;
00400 }
00401 
00402 static oqmlStatus *
00403 oqml_set_supeq(oqmlNode *node, oqmlAtomList *left, oqmlAtomList *right,
00404              oqmlBool &b)
00405 {
00406   oqmlAtom *x = right->first;
00407   while (x)
00408     {
00409       if (!is_in(x, left))
00410         {
00411           b = oqml_False;
00412           return oqmlSuccess;
00413         }
00414 
00415       x = x->next;
00416     }
00417 
00418   b = oqml_True;
00419   return oqmlSuccess;
00420 }
00421 
00422 static oqmlStatus *
00423 oqml_set_equal(oqmlNode *node, oqmlAtom *xleft, oqmlAtom *xright,
00424                oqmlBool &b)
00425 {
00426   oqmlAtomList *left  = OQML_ATOM_COLLVAL(xleft);
00427   oqmlAtomList *right = OQML_ATOM_COLLVAL(xright);
00428 
00429   if (xleft->type.type != xright->type.type || right->cnt != left->cnt)
00430     {
00431       b = oqml_False;
00432       return oqmlSuccess;
00433     }
00434 
00435 
00436   oqmlAtom *x = right->first;
00437   while (x)
00438     {
00439       if (!is_in(x, left))
00440         {
00441           b = oqml_False;
00442           return oqmlSuccess;
00443         }
00444 
00445       x = x->next;
00446     }
00447 
00448   b = oqml_True;
00449   return oqmlSuccess;
00450 }
00451 
00452 static oqmlStatus *
00453 oqml_set_diff(oqmlNode *node, oqmlAtom *xleft, oqmlAtom *xright,
00454               oqmlBool &b)
00455 {
00456   oqmlAtomList *left  = OQML_ATOM_COLLVAL(xleft);
00457   oqmlAtomList *right = OQML_ATOM_COLLVAL(xright);
00458 
00459   if (xleft->type.type != xright->type.type || right->cnt != left->cnt)
00460     {
00461       b = oqml_True;
00462       return oqmlSuccess;
00463     }
00464 
00465   oqmlAtom *x = right->first;
00466   while (x)
00467     {
00468       if (!is_in(x, left))
00469         {
00470           b = oqml_True;
00471           return oqmlSuccess;
00472         }
00473 
00474       x = x->next;
00475     }
00476 
00477   b = oqml_False;
00478   return oqmlSuccess;
00479 }
00480 
00481 oqmlStatus *
00482 oqml_set_compare(oqmlNode *node, oqmlTYPE type, const char *opstr,
00483                  oqmlAtom *aleft, oqmlAtom *aright, oqmlBool &b)
00484 {
00485   oqmlStatus *s;
00486 
00487   s = check_bag_set(node, aleft);
00488   if (s) return s;
00489 
00490   s = check_bag_set(node, aright);
00491   if (s) return s;
00492 
00493   if (type == oqmlINF)
00494     return oqml_set_inf(node, OQML_ATOM_COLLVAL(aleft),
00495                         OQML_ATOM_COLLVAL(aright), b);
00496 
00497   if (type == oqmlINFEQ)
00498     return oqml_set_infeq(node, OQML_ATOM_COLLVAL(aleft),
00499                           OQML_ATOM_COLLVAL(aright), b);
00500 
00501   if (type == oqmlSUP)
00502     return oqml_set_sup(node, OQML_ATOM_COLLVAL(aleft),
00503                         OQML_ATOM_COLLVAL(aright), b);
00504 
00505   if (type == oqmlSUPEQ)
00506     return oqml_set_supeq(node, OQML_ATOM_COLLVAL(aleft),
00507                           OQML_ATOM_COLLVAL(aright), b);
00508 
00509   if (type == oqmlEQUAL)
00510     return oqml_set_equal(node, aleft, aright, b);
00511 
00512   if (type == oqmlDIFF)
00513     return oqml_set_diff(node, aleft, aright, b);
00514 
00515   return new oqmlStatus(node,
00516                         "operation '%s %s %s' is not valid",
00517                         aleft->type.getString(), opstr,
00518                         aright->type.getString());
00519 }
00520 }

Generated on Mon Dec 22 18:16:06 2008 for eyedb by  doxygen 1.5.3