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 <math.h>
00026 #include <ctype.h>
00027 #include "oql_p.h"
00028
00029
00030
00031
00032
00033
00034
00035 namespace eyedb {
00036
00037 oqmlString::oqmlString(const char * _s) : oqmlNode(oqmlSTRING)
00038 {
00039 s = strdup(_s);
00040 eval_type.type = oqmlATOM_STRING;
00041 eval_type.cls = 0;
00042 eval_type.comp = oqml_True;
00043 }
00044
00045 oqmlString::~oqmlString()
00046 {
00047 free(s);
00048 }
00049
00050 oqmlStatus *oqmlString::compile(Database *db, oqmlContext *ctx)
00051 {
00052 return oqmlSuccess;
00053 }
00054
00055 oqmlStatus *oqmlString::eval(Database *db, oqmlContext *ctx, oqmlAtomList **alist, oqmlComp *, oqmlAtom *)
00056 {
00057 *alist = new oqmlAtomList(new oqmlAtom_string(s));
00058 return oqmlSuccess;
00059 }
00060
00061 void oqmlString::evalType(Database *db, oqmlContext *ctx, oqmlAtomType *at)
00062 {
00063 *at = eval_type;
00064 }
00065
00066 oqmlBool oqmlString::isConstant() const
00067 {
00068 return oqml_True;
00069 }
00070
00071 std::string
00072 oqmlString::toString(void) const
00073 {
00074 return std::string("\"") + s + "\"" + oqml_isstat();
00075 }
00076
00077
00078
00079
00080
00081
00082
00083 oqmlInt::oqmlInt(eyedblib::int64 _i) : oqmlNode(oqmlINT)
00084 {
00085 i = _i;
00086 eval_type.type = oqmlATOM_INT;
00087 ql = 0;
00088 }
00089
00090 oqmlInt::oqmlInt(oqmlNode *_ql) : oqmlNode(oqmlINT)
00091 {
00092 ql = _ql;
00093 eval_type.type = oqmlATOM_INT;
00094 i = 0;
00095 }
00096
00097 oqmlInt::~oqmlInt()
00098 {
00099 }
00100
00101 oqmlStatus *oqmlInt::compile(Database *db, oqmlContext *ctx)
00102 {
00103 if (ql)
00104 {
00105 oqmlStatus *s;
00106
00107 s = ql->compile(db, ctx);
00108
00109 if (s)
00110 return s;
00111
00112 oqmlAtomType at;
00113
00114 ql->evalType(db, ctx, &at);
00115
00116 if (at.type != oqmlATOM_DOUBLE &&
00117 at.type != oqmlATOM_INT &&
00118 at.type != oqmlATOM_UNKNOWN_TYPE)
00119 return new oqmlStatus("int() function expects a 'float' or an 'int'.");
00120
00121 return oqmlSuccess;
00122 }
00123
00124 return oqmlSuccess;
00125 }
00126
00127 oqmlStatus *oqmlInt::eval(Database *db, oqmlContext *ctx, oqmlAtomList **alist, oqmlComp *, oqmlAtom *)
00128 {
00129 if (ql)
00130 {
00131 oqmlStatus *s;
00132 oqmlAtomList *al;
00133
00134 *alist = new oqmlAtomList();
00135
00136 s = ql->eval(db, ctx, &al);
00137
00138 if (s)
00139 return s;
00140
00141 if (al->cnt == 1)
00142 {
00143 if (al->first->type.type == oqmlATOM_INT)
00144 {
00145 *alist = new oqmlAtomList(al->first);
00146 return oqmlSuccess;
00147 }
00148
00149 if (al->first->type.type == oqmlATOM_DOUBLE)
00150 {
00151 *alist = new oqmlAtomList
00152 (new oqmlAtom_int(floor(((oqmlAtom_double *)al->first)->d)));
00153 return oqmlSuccess;
00154 }
00155
00156 }
00157
00158 return new oqmlStatus("int() function expects a 'float' or an 'int'.");
00159 }
00160
00161 *alist = new oqmlAtomList(new oqmlAtom_int(i));
00162 return oqmlSuccess;
00163 }
00164
00165 void oqmlInt::evalType(Database *db, oqmlContext *ctx, oqmlAtomType *at)
00166 {
00167 *at = eval_type;
00168 }
00169
00170 oqmlBool oqmlInt::isConstant() const
00171 {
00172 return oqml_True;
00173 }
00174
00175 std::string
00176 oqmlInt::toString(void) const
00177 {
00178 return str_convert(i) + oqml_isstat();
00179 }
00180
00181
00182
00183
00184
00185
00186
00187 oqmlChar::oqmlChar(char _c) : oqmlNode(oqmlCHAR)
00188 {
00189 c = _c;
00190 eval_type.type = oqmlATOM_CHAR;
00191 }
00192
00193 oqmlChar::~oqmlChar()
00194 {
00195 }
00196
00197 oqmlStatus *oqmlChar::compile(Database *db, oqmlContext *ctx)
00198 {
00199 return oqmlSuccess;
00200 }
00201
00202 oqmlStatus *oqmlChar::eval(Database *db, oqmlContext *ctx, oqmlAtomList **alist, oqmlComp *, oqmlAtom *)
00203 {
00204 *alist = new oqmlAtomList(new oqmlAtom_char(c));
00205 return oqmlSuccess;
00206 }
00207
00208 void oqmlChar::evalType(Database *db, oqmlContext *ctx, oqmlAtomType *at)
00209 {
00210 *at = eval_type;
00211 }
00212
00213 oqmlBool oqmlChar::isConstant() const
00214 {
00215 return oqml_True;
00216 }
00217
00218 std::string
00219 oqmlChar::toString(void) const
00220 {
00221 if (c && !iscntrl(c))
00222 return std::string("'") + str_convert(c) + "'" + oqml_isstat();
00223
00224 return std::string("'") + str_convert(c, "\\%03o") + "'" + oqml_isstat();
00225 }
00226
00227
00228
00229
00230
00231
00232
00233 oqmlFloat::oqmlFloat(double _f) : oqmlNode(oqmlFLOAT)
00234 {
00235 f = _f;
00236 eval_type.type = oqmlATOM_DOUBLE;
00237 }
00238
00239 oqmlFloat::~oqmlFloat()
00240 {
00241 }
00242
00243 oqmlStatus *oqmlFloat::compile(Database *db, oqmlContext *ctx)
00244 {
00245 return oqmlSuccess;
00246 }
00247
00248 oqmlStatus *oqmlFloat::eval(Database *db, oqmlContext *ctx, oqmlAtomList **alist, oqmlComp *, oqmlAtom *)
00249 {
00250 *alist = new oqmlAtomList(new oqmlAtom_double(f));
00251 return oqmlSuccess;
00252 }
00253
00254 void oqmlFloat::evalType(Database *db, oqmlContext *ctx, oqmlAtomType *at)
00255 {
00256 *at = eval_type;
00257 }
00258
00259 oqmlBool oqmlFloat::isConstant() const
00260 {
00261 return oqml_True;
00262 }
00263
00264 std::string
00265 oqmlFloat::toString(void) const
00266 {
00267 return str_convert(f) + + oqml_isstat();
00268 }
00269
00270
00271
00272
00273
00274
00275
00276 oqmlOid::oqmlOid(const Oid &_oid) : oqmlNode(oqmlOID)
00277 {
00278 oid = _oid;
00279 eval_type.type = oqmlATOM_OID;
00280 cls = 0;
00281 ql = 0;
00282 }
00283
00284 oqmlOid::oqmlOid(oqmlNode *_ql) : oqmlNode(oqmlOID)
00285 {
00286 eval_type.type = oqmlATOM_OID;
00287 cls = 0;
00288 ql = _ql;
00289 }
00290
00291 oqmlOid::~oqmlOid()
00292 {
00293
00294 }
00295
00296 oqmlStatus *oqmlOid::compile(Database *db, oqmlContext *ctx)
00297 {
00298 if (ql)
00299 {
00300 oqmlStatus *s;
00301
00302 s = ql->compile(db, ctx);
00303
00304 if (s)
00305 return s;
00306
00307 oqmlAtomType at;
00308
00309 ql->evalType(db, ctx, &at);
00310
00311 if (at.type != oqmlATOM_STRING && at.type != oqmlATOM_UNKNOWN_TYPE)
00312 return new oqmlStatus("oid() function expects a 'string'.");
00313
00314 return oqmlSuccess;
00315 }
00316
00317 if (oid.isValid())
00318 return oqml_get_class(db, oid, &cls);
00319
00320 return oqmlSuccess;
00321 }
00322
00323 oqmlStatus *oqmlOid::eval(Database *db, oqmlContext *ctx, oqmlAtomList **alist, oqmlComp *, oqmlAtom *)
00324 {
00325 if (ql)
00326 {
00327 oqmlStatus *s;
00328 oqmlAtomList *al;
00329
00330 *alist = new oqmlAtomList();
00331
00332 s = ql->eval(db, ctx, &al);
00333
00334 if (s)
00335 return s;
00336
00337 if (al->cnt != 1 || al->first->type.type != oqmlATOM_STRING)
00338 return new oqmlStatus("oid() function expects a 'string'.");
00339
00340 oid = Oid(OQML_ATOM_STRVAL(al->first));
00341 s = oqml_get_class(db, oid, &cls);
00342
00343 if (s) return s;
00344 *alist = new oqmlAtomList(new oqmlAtom_oid(oid, cls));
00345
00346 return oqmlSuccess;
00347 }
00348
00349 *alist = new oqmlAtomList(new oqmlAtom_oid(oid, cls));
00350 return oqmlSuccess;
00351 }
00352
00353 void oqmlOid::evalType(Database *db, oqmlContext *ctx, oqmlAtomType *at)
00354 {
00355 *at = eval_type;
00356 }
00357
00358 oqmlBool oqmlOid::isConstant() const
00359 {
00360 return oqml_True;
00361 }
00362
00363 std::string
00364 oqmlOid::toString(void) const
00365 {
00366 return std::string(oid.toString()) + + oqml_isstat();
00367 }
00368
00369
00370
00371
00372
00373
00374
00375 oqmlObject::oqmlObject(const char *_s) : oqmlNode(oqmlOBJECT)
00376 {
00377 eval_type.type = oqmlATOM_OBJ;
00378 s = strdup(_s);
00379 o = 0;
00380 idx = 0;
00381 }
00382
00383 oqmlObject::oqmlObject(Object *_o, unsigned int _idx) : oqmlNode(oqmlOBJECT)
00384 {
00385 s = 0;
00386 o = _o;
00387 idx = _idx;
00388 }
00389
00390 oqmlObject::oqmlObject(oqmlNode *) : oqmlNode(oqmlOBJECT)
00391 {
00392 abort();
00393 }
00394
00395 oqmlStatus *oqmlObject::compile(Database *db, oqmlContext *ctx)
00396 {
00397 if (!o)
00398 return oqmlObjectManager::getObject(this, s, o, idx);
00399 return oqmlSuccess;
00400 }
00401
00402 oqmlStatus *oqmlObject::eval(Database *db, oqmlContext *ctx, oqmlAtomList **alist, oqmlComp *, oqmlAtom *)
00403 {
00404 *alist = new oqmlAtomList(oqmlObjectManager::registerObject(o));
00405 return oqmlSuccess;
00406 }
00407
00408 void
00409 oqmlObject::evalType(Database *db, oqmlContext *ctx, oqmlAtomType *at)
00410 {
00411 *at = eval_type;
00412 }
00413
00414 oqmlBool oqmlObject::isConstant() const
00415 {
00416 return oqml_True;
00417 }
00418
00419 std::string
00420 oqmlObject::toString() const
00421 {
00422 return (s ? std::string(s) : str_convert((long)idx, "%x") + ":obj") + oqml_isstat();;
00423 }
00424
00425 oqmlObject::~oqmlObject()
00426 {
00427 free(s);
00428 }
00429
00430
00431
00432
00433
00434
00435
00436 oqmlNil::oqmlNil() : oqmlNode(oqmlNIL)
00437 {
00438 }
00439
00440 oqmlNil::~oqmlNil()
00441 {
00442 }
00443
00444 oqmlStatus *oqmlNil::compile(Database *db, oqmlContext *ctx)
00445 {
00446 return oqmlSuccess;
00447 }
00448
00449 oqmlStatus *oqmlNil::eval(Database *db, oqmlContext *ctx, oqmlAtomList **alist, oqmlComp *, oqmlAtom *)
00450 {
00451
00452
00453 *alist = new oqmlAtomList();
00454 return oqmlSuccess;
00455 }
00456
00457 void oqmlNil::evalType(Database *db, oqmlContext *ctx, oqmlAtomType *at)
00458 {
00459 *at = eval_type;
00460 }
00461
00462 oqmlBool oqmlNil::isConstant() const
00463 {
00464 return oqml_True;
00465 }
00466
00467 std::string
00468 oqmlNil::toString(void) const
00469 {
00470 return std::string("nil") + oqml_isstat();;
00471 }
00472
00473
00474
00475
00476
00477
00478
00479 oqmlNull::oqmlNull() : oqmlNode(oqmlNULL)
00480 {
00481 eval_type.type = oqmlATOM_NULL;
00482 }
00483
00484 oqmlNull::~oqmlNull()
00485 {
00486 }
00487
00488 oqmlStatus *oqmlNull::compile(Database *db, oqmlContext *ctx)
00489 {
00490 return oqmlSuccess;
00491 }
00492
00493 oqmlStatus *oqmlNull::eval(Database *db, oqmlContext *ctx, oqmlAtomList **alist, oqmlComp *, oqmlAtom *)
00494 {
00495 *alist = new oqmlAtomList(new oqmlAtom_null);
00496 return oqmlSuccess;
00497 }
00498
00499 void oqmlNull::evalType(Database *db, oqmlContext *ctx, oqmlAtomType *at)
00500 {
00501 *at = eval_type;
00502 }
00503
00504 oqmlBool oqmlNull::isConstant() const
00505 {
00506 return oqml_True;
00507 }
00508
00509 std::string
00510 oqmlNull::toString(void) const
00511 {
00512 return std::string("NULL") + oqml_isstat();
00513 }
00514
00515
00516
00517
00518
00519
00520
00521 oqmlTrue::oqmlTrue() : oqmlNode(oqmlTRUE)
00522 {
00523 eval_type.type = oqmlATOM_BOOL;
00524 }
00525
00526 oqmlTrue::~oqmlTrue()
00527 {
00528 }
00529
00530 oqmlStatus *oqmlTrue::compile(Database *db, oqmlContext *ctx)
00531 {
00532 return oqmlSuccess;
00533 }
00534
00535 oqmlStatus *oqmlTrue::eval(Database *db, oqmlContext *ctx, oqmlAtomList **alist, oqmlComp *, oqmlAtom *)
00536 {
00537 *alist = new oqmlAtomList(new oqmlAtom_bool(oqml_True));
00538 return oqmlSuccess;
00539 }
00540
00541 void oqmlTrue::evalType(Database *db, oqmlContext *ctx, oqmlAtomType *at)
00542 {
00543 *at = eval_type;
00544 }
00545
00546 oqmlBool oqmlTrue::isConstant() const
00547 {
00548 return oqml_True;
00549 }
00550
00551 std::string
00552 oqmlTrue::toString(void) const
00553 {
00554 return std::string("true") + oqml_isstat();
00555 }
00556
00557
00558
00559
00560
00561
00562
00563 oqmlFalse::oqmlFalse() : oqmlNode(oqmlFALSE)
00564 {
00565 eval_type.type = oqmlATOM_BOOL;
00566 }
00567
00568 oqmlFalse::~oqmlFalse()
00569 {
00570 }
00571
00572 oqmlStatus *oqmlFalse::compile(Database *db, oqmlContext *ctx)
00573 {
00574 return oqmlSuccess;
00575 }
00576
00577 oqmlStatus *oqmlFalse::eval(Database *db, oqmlContext *ctx, oqmlAtomList **alist, oqmlComp *, oqmlAtom *)
00578 {
00579 *alist = new oqmlAtomList(new oqmlAtom_bool(oqml_False));
00580 return oqmlSuccess;
00581 }
00582
00583 void oqmlFalse::evalType(Database *db, oqmlContext *ctx, oqmlAtomType *at)
00584 {
00585 *at = eval_type;
00586 }
00587
00588 oqmlBool oqmlFalse::isConstant() const
00589 {
00590 return oqml_True;
00591 }
00592
00593 std::string
00594 oqmlFalse::toString(void) const
00595 {
00596 return std::string("false") + oqml_isstat();
00597 }
00598
00599
00600
00601
00602
00603
00604
00605 oqmlRange::oqmlRange(oqmlNode *_qleft, oqmlBool _left_incl,
00606 oqmlNode *_qright, oqmlBool _right_incl,
00607 oqmlBool _is_between) :
00608 oqmlNode(oqmlRANGE)
00609 {
00610 qleft = _qleft;
00611 qright = _qright;
00612 left_incl = _left_incl;
00613 right_incl = _right_incl;
00614 is_between = _is_between;
00615 eval_type.type = oqmlATOM_RANGE;
00616 }
00617
00618 oqmlRange::~oqmlRange()
00619 {
00620 }
00621
00622 oqmlStatus *oqmlRange::compile(Database *db, oqmlContext *ctx)
00623 {
00624 oqmlStatus *s = qleft->compile(db, ctx);
00625 if (s) return s;
00626 return qright->compile(db, ctx);
00627 }
00628
00629 oqmlStatus *oqmlRange::eval(Database *db, oqmlContext *ctx, oqmlAtomList **alist, oqmlComp *, oqmlAtom *)
00630 {
00631 static const char fmt[] = "invalid %s operand: expected int, float, char or string, got %s";
00632
00633 oqmlStatus *s;
00634 oqmlAtomList *aleft, *aright;
00635
00636 s = qleft->eval(db, ctx, &aleft);
00637 if (s) return s;
00638
00639 s = qright->eval(db, ctx, &aright);
00640 if (s) return s;
00641
00642 oqmlAtom *left = (aleft->cnt == 1 ? aleft->first : 0);
00643 oqmlAtom *right = (aright->cnt == 1 ? aright->first : 0);
00644
00645 if (!left)
00646 return new oqmlStatus(this, fmt, "left", "nil");
00647
00648 if (!right)
00649 return new oqmlStatus(this, fmt, "right", "nil");
00650
00651 if (left->type.type != right->type.type)
00652 return new oqmlStatus(this, "operand types differ");
00653
00654 if (!OQML_IS_INT(left) &&
00655 !OQML_IS_DOUBLE(left) &&
00656 !OQML_IS_CHAR(left) &&
00657 !OQML_IS_STRING(left))
00658 return new oqmlStatus(this, fmt, "left", left->type.getString());
00659
00660 *alist = new oqmlAtomList(new oqmlAtom_range(left, left_incl,
00661 right, right_incl));
00662 return oqmlSuccess;
00663 }
00664
00665 void oqmlRange::evalType(Database *db, oqmlContext *ctx, oqmlAtomType *at)
00666 {
00667 *at = eval_type;
00668 }
00669
00670 oqmlBool oqmlRange::isConstant() const
00671 {
00672 return OQMLBOOL(qleft->isConstant() && qright->isConstant());
00673 }
00674
00675 std::string
00676 oqmlRange::toString(void) const
00677 {
00678 if (is_between)
00679 return qleft->toString() + " and " + qright->toString();
00680
00681 return (left_incl ? std::string("[") : std::string("]")) +
00682 qleft->toString() + "," + qright->toString() +
00683 (right_incl ? std::string("]") : std::string("["));
00684 }
00685 }