00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "oql_p.h"
00026
00027 namespace eyedb {
00028
00029
00030
00031
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
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
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
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
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 }