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 <unistd.h>
00026 #include <fcntl.h>
00027 #include <wctype.h>
00028 #include <sys/stat.h>
00029
00030 #include "oql_p.h"
00031
00032
00033
00034 namespace eyedb {
00035
00036
00037
00038
00039
00040
00041
00042 oqmlAdd::oqmlAdd(oqmlNode * _qleft, oqmlNode * _qright, oqmlBool _unary) :
00043 oqmlNode(oqmlADD)
00044 {
00045 qleft = _qleft;
00046 qright = _qright;
00047 unary = _unary;
00048 }
00049
00050 oqmlAdd::oqmlAdd(oqmlNode * _qleft, oqmlNode * _qright) : oqmlNode(oqmlADD)
00051 {
00052 qleft = _qleft;
00053 qright = _qright;
00054 unary = oqml_False;
00055 }
00056
00057 oqmlAdd::~oqmlAdd()
00058 {
00059 }
00060
00061 oqmlStatus *oqmlAdd::compile(Database *db, oqmlContext *ctx)
00062 {
00063 oqmlBool iscts;
00064 oqmlStatus *s;
00065
00066 s = binopCompile(db, ctx, "+", qleft, qright, eval_type,
00067 oqmlDoubleConcatOK, iscts);
00068
00069 if (s)
00070 return s;
00071
00072 if (isConstant() && !cst_list)
00073 {
00074 oqmlAtomList *al;
00075 s = eval(db, ctx, &al);
00076 if (s) return s;
00077 cst_list = al->copy();
00078 if (isLocked())
00079 oqmlLock(cst_list, oqml_True);
00080 }
00081
00082 return oqmlSuccess;
00083 }
00084
00085 oqmlStatus *oqmlAdd::eval(Database *db, oqmlContext *ctx, oqmlAtomList **alist, oqmlComp *, oqmlAtom *)
00086 {
00087 if (cst_list) {
00088 *alist = new oqmlAtomList(cst_list);
00089 return oqmlSuccess;
00090 }
00091
00092 oqmlAtomList *al_left, *al_right;
00093 oqmlStatus *s = binopEval(db, ctx, "+", eval_type,
00094 qleft, qright, oqmlDoubleConcatOK,
00095 &al_left, &al_right);
00096
00097 if (s)
00098 return s;
00099
00100 oqmlAtom *aleft = al_left->first, *aright = al_right->first;
00101
00102 oqmlATOMTYPE atleft = aleft->type.type;
00103 oqmlATOMTYPE atright = aright->type.type;
00104
00105
00106 if (OQML_IS_COLL(aleft)) {
00107 oqmlAtomList *al = new oqmlAtomList();
00108
00109 al->append(OQML_ATOM_COLLVAL(aleft), oqml_False);
00110 #ifdef NEW_ADD_COLL
00111 if (!aright->as_nil())
00112 al->append(aright->copy());
00113 #else
00114 if (OQML_IS_COLL(aright)) {
00115 if (atleft != atright)
00116 return oqmlStatus::expected(this, &aleft->type, &aright->type);
00117 al->append(OQML_ATOM_COLLVAL(aright)->copy(), oqml_False);
00118 }
00119 else if (!aright->as_nil())
00120 al->append(aright->copy());
00121 #endif
00122
00123 if (OQML_IS_LIST(aleft))
00124 *alist = new oqmlAtomList(new oqmlAtom_list(al));
00125 else if (OQML_IS_BAG(aleft))
00126 *alist = new oqmlAtomList(new oqmlAtom_bag(al));
00127 else if (OQML_IS_ARRAY(aleft))
00128 *alist = new oqmlAtomList(new oqmlAtom_array(al));
00129 else if (OQML_IS_SET(aleft))
00130 *alist = new oqmlAtomList(new oqmlAtom_set(al));
00131
00132 #ifdef SYNC_GARB
00133
00134
00135
00136
00137
00138 #endif
00139 return oqmlSuccess;
00140 }
00141
00142 if (OQML_IS_COLL(aright)) {
00143 oqmlAtomList *al = new oqmlAtomList();
00144
00145 if (OQML_IS_COLL(aleft)) {
00146 #ifdef NEW_ADD_COLL
00147 assert(0);
00148 #endif
00149 if (atleft != atright)
00150 return oqmlStatus::expected(this, &aright->type, &aleft->type);
00151 al->append(OQML_ATOM_COLLVAL(aleft), oqml_False);
00152 }
00153 else if (!aleft->as_nil())
00154 al->append(aleft);
00155
00156 al->append(OQML_ATOM_COLLVAL(aright), oqml_False);
00157
00158 if (OQML_IS_LIST(aright))
00159 *alist = new oqmlAtomList(new oqmlAtom_list(al));
00160 else if (OQML_IS_BAG(aright))
00161 *alist = new oqmlAtomList(new oqmlAtom_bag(al));
00162 else if (OQML_IS_ARRAY(aright))
00163 *alist = new oqmlAtomList(new oqmlAtom_array(al));
00164 else if (OQML_IS_SET(aright))
00165 *alist = new oqmlAtomList(new oqmlAtom_set(al));
00166
00167 #ifdef SYNC_GARB
00168
00169
00170
00171
00172
00173 #endif
00174 return oqmlSuccess;
00175 }
00176
00177 if (atleft == oqmlATOM_INT)
00178 *alist = new oqmlAtomList
00179 (new oqmlAtom_int(OQML_ATOM_INTVAL(aleft) + OQML_ATOM_INTVAL(aright)));
00180
00181 else if (atleft == oqmlATOM_CHAR)
00182 *alist = new oqmlAtomList
00183 (new oqmlAtom_int(OQML_ATOM_CHARVAL(aleft) + OQML_ATOM_CHARVAL(aright)));
00184
00185 else if (atleft == oqmlATOM_DOUBLE)
00186 *alist = new oqmlAtomList
00187 (new oqmlAtom_double(OQML_ATOM_DBLVAL(aleft) + OQML_ATOM_DBLVAL(aright)));
00188
00189 else if (atleft == oqmlATOM_STRING) {
00190 char *s = new char[OQML_ATOM_STRLEN(aleft) +
00191 OQML_ATOM_STRLEN(aright)+1];
00192 s[0] = 0;
00193 strcat(s, OQML_ATOM_STRVAL(aleft));
00194 strcat(s, OQML_ATOM_STRVAL(aright));
00195
00196 *alist = new oqmlAtomList(new oqmlAtom_string(s));
00197 delete [] s;
00198 }
00199 else
00200 return new oqmlStatus(this, "unexpected type %s", aleft->type.getString());
00201
00202 #ifdef SYNC_GARB
00203 OQL_DELETE(al_left);
00204 OQL_DELETE(al_right);
00205 #endif
00206 return oqmlSuccess;
00207 }
00208
00209 void oqmlAdd::evalType(Database *db, oqmlContext *ctx, oqmlAtomType *at)
00210 {
00211 *at = eval_type;
00212 }
00213
00214 oqmlBool oqmlAdd::isConstant() const
00215 {
00216 return OQMLBOOL(qleft->isConstant() && qright->isConstant());
00217 }
00218
00219 std::string
00220 oqmlAdd::toString(void) const
00221 {
00222 if (unary)
00223 return oqml_unop_string(qright, "+", is_statement);
00224 return oqml_binop_string(qleft, qright, "+", is_statement);
00225 }
00226
00227 oqmlSub::oqmlSub(oqmlNode * _qleft, oqmlNode * _qright, oqmlBool _unary) :
00228 oqmlNode(oqmlSUB)
00229 {
00230 qleft = _qleft;
00231 qright = _qright;
00232 unary = _unary;
00233 }
00234
00235 oqmlSub::oqmlSub(oqmlNode * _qleft, oqmlNode * _qright) : oqmlNode(oqmlSUB)
00236 {
00237 qleft = _qleft;
00238 qright = _qright;
00239 unary = oqml_False;
00240 }
00241
00242 oqmlSub::~oqmlSub()
00243 {
00244 }
00245
00246 oqmlStatus *oqmlSub::compile(Database *db, oqmlContext *ctx)
00247 {
00248 oqmlBool iscts;
00249 oqmlStatus *s;
00250 s = binopCompile(db, ctx, "-", qleft, qright, eval_type, oqmlDoubleOK, iscts);
00251
00252 if (s)
00253 return s;
00254
00255 if (isConstant() && !cst_list)
00256 {
00257 oqmlAtomList *al;
00258 s = eval(db, ctx, &al);
00259 if (s) return s;
00260 cst_list = al->copy();
00261 if (isLocked())
00262 oqmlLock(cst_list, oqml_True);
00263 }
00264
00265 return oqmlSuccess;
00266 }
00267
00268 oqmlStatus *oqmlSub::eval(Database *db, oqmlContext *ctx, oqmlAtomList **alist, oqmlComp *, oqmlAtom *)
00269 {
00270 if (cst_list)
00271 {
00272 *alist = new oqmlAtomList(cst_list);
00273 return oqmlSuccess;
00274 }
00275
00276 oqmlAtomList *al_left, *al_right;
00277 oqmlStatus *s = binopEval(db, ctx, "-", eval_type, qleft, qright, oqmlDoubleOK, &al_left, &al_right);
00278
00279 if (s)
00280 return s;
00281
00282 oqmlAtom *aleft = al_left->first, *aright = al_right->first;
00283
00284 oqmlATOMTYPE at = aleft->type.type;
00285
00286 if (at == oqmlATOM_INT)
00287 *alist = new oqmlAtomList
00288 (new oqmlAtom_int(OQML_ATOM_INTVAL(aleft) - OQML_ATOM_INTVAL(aright)));
00289 else if (at == oqmlATOM_CHAR)
00290 *alist = new oqmlAtomList
00291 (new oqmlAtom_int(OQML_ATOM_CHARVAL(aleft) - OQML_ATOM_CHARVAL(aright)));
00292 else if (at == oqmlATOM_DOUBLE)
00293 *alist = new oqmlAtomList
00294 (new oqmlAtom_double(OQML_ATOM_DBLVAL(aleft) - OQML_ATOM_DBLVAL(aright)));
00295 else
00296 return oqmlStatus::expected(this, "integer, character or double", aleft->type.getString());
00297
00298 #ifdef SYNC_GARB
00299 OQL_DELETE(al_left);
00300 OQL_DELETE(al_right);
00301 #endif
00302 return oqmlSuccess;
00303 }
00304
00305 void oqmlSub::evalType(Database *db, oqmlContext *ctx, oqmlAtomType *at)
00306 {
00307 *at = eval_type;
00308 }
00309
00310 oqmlBool oqmlSub::isConstant() const
00311 {
00312 return OQMLBOOL(qleft->isConstant() && qright->isConstant());
00313 }
00314 std::string oqmlSub::toString(void) const
00315 {
00316 if (unary)
00317 return oqml_unop_string(qright, "-", is_statement);
00318 return oqml_binop_string(qleft, qright, "-", is_statement);
00319 }
00320
00321
00322
00323
00324
00325
00326
00327 #define OQML_STD_BINOP(X, PARENT, XX, OPSTR) \
00328 X::X(oqmlNode * _qleft, oqmlNode * _qright) : \
00329 PARENT(XX, _qleft, _qright, OPSTR) { } \
00330 \
00331 X::~X() { }
00332
00333 OQML_STD_BINOP(oqmlEqual, oqmlComp, oqmlEQUAL, "==")
00334 OQML_STD_BINOP(oqmlDiff, oqmlComp, oqmlDIFF, "!=")
00335 OQML_STD_BINOP(oqmlInf, oqmlComp, oqmlINF, "<")
00336 OQML_STD_BINOP(oqmlInfEq, oqmlComp, oqmlINFEQ, "<=")
00337 OQML_STD_BINOP(oqmlSup, oqmlComp, oqmlSUP, ">")
00338 OQML_STD_BINOP(oqmlSupEq, oqmlComp, oqmlSUPEQ, ">=")
00339 OQML_STD_BINOP(oqmlBetween, oqmlComp, oqmlBETWEEN, " between ")
00340 OQML_STD_BINOP(oqmlNotBetween, oqmlComp, oqmlNOTBETWEEN, " not between ")
00341
00342 oqmlNode *oqmlBetween::requalifyNot()
00343 {
00344 oqmlNode *node = new oqmlNotBetween(qleft, qright);
00345 qleft = qright = 0;
00346 return node;
00347 }
00348
00349 OQML_STD_BINOP(oqmlRegCmp, oqmlRegex, oqmlREGCMP, "~")
00350 OQML_STD_BINOP(oqmlRegICmp, oqmlRegex, oqmlREGICMP, "~~")
00351 OQML_STD_BINOP(oqmlRegDiff, oqmlRegex, oqmlREGDIFF, "!~")
00352 OQML_STD_BINOP(oqmlRegIDiff, oqmlRegex, oqmlREGIDIFF, "!~~")
00353
00354
00355
00356
00357
00358
00359
00360 static oqmlStatus *
00361 oqml_logical_error(oqmlNode *node, oqmlAtomType *at, bool strict)
00362 {
00363 std::string msg = (strict ? "bool": "bool, int, char or double");
00364 if (at)
00365 return oqmlStatus::expected(node, msg.c_str(), at->getString());
00366
00367 return new oqmlStatus(node, (msg + " expected").c_str());
00368 }
00369
00370 static oqmlStatus *
00371 oqml_check_type(oqmlNode *node, Database *db, oqmlContext *ctx,
00372 oqmlNode *ql, const char *name, bool strict = false)
00373 {
00374 if (ql->getType() == oqmlASSIGN)
00375 return oqmlSuccess;
00376
00377 oqmlAtomType at;
00378 ql->evalType(db, ctx, &at);
00379
00380
00381
00382
00383
00384
00385
00386
00387 if (at.type == oqmlATOM_UNKNOWN_TYPE)
00388 return oqmlSuccess;
00389
00390 if (strict) {
00391 if (at.type != oqmlATOM_BOOL)
00392 return oqml_logical_error(node, &at, strict);
00393 }
00394
00395 if (at.type != oqmlATOM_INT &&
00396 at.type != oqmlATOM_CHAR &&
00397 at.type != oqmlATOM_DOUBLE &&
00398 at.type != oqmlATOM_BOOL)
00399 return oqml_logical_error(node, &at, strict);
00400
00401 return oqmlSuccess;
00402 }
00403
00404 oqmlStatus *
00405 oqml_check_logical(oqmlNode *node, oqmlAtomList *al, oqmlBool &b,
00406 bool strict)
00407 {
00408 if (al->cnt != 1)
00409 return oqml_logical_error(node, 0, strict);
00410
00411 oqmlAtom *a = al->first;
00412 if (a->type.type == oqmlATOM_BOOL) {
00413 b = (((oqmlAtom_bool *)a)->b) ? oqml_True : oqml_False;
00414 return oqmlSuccess;
00415 }
00416
00417 if (!strict) {
00418 if (a->type.type == oqmlATOM_INT) {
00419 b = (((oqmlAtom_int *)a)->i) ? oqml_True : oqml_False;
00420 return oqmlSuccess;
00421 }
00422
00423 if (a->type.type == oqmlATOM_CHAR) {
00424 b = (((oqmlAtom_char *)a)->c) ? oqml_True : oqml_False;
00425 return oqmlSuccess;
00426 }
00427
00428 if (a->type.type == oqmlATOM_DOUBLE) {
00429 b = (((oqmlAtom_double *)a)->d) ? oqml_True : oqml_False;
00430 return oqmlSuccess;
00431 }
00432 }
00433
00434 return oqml_logical_error(node, &a->type, strict);
00435 }
00436
00437
00438
00439
00440
00441
00442
00443 oqmlLOr::oqmlLOr(oqmlNode * _qleft, oqmlNode * _qright,
00444 oqmlBool _isLiteral) : oqmlNode(oqmlLOR)
00445 {
00446 qleft = _qleft;
00447 qright = _qright;
00448 eval_type.type = oqmlATOM_BOOL;
00449 isLiteral = _isLiteral;
00450 node = 0;
00451 }
00452
00453 oqmlLOr::~oqmlLOr()
00454 {
00455 }
00456
00457 #define STRICT_SELECT
00458
00459 oqmlStatus *oqmlLOr::compile(Database *db, oqmlContext *ctx)
00460 {
00461 node = 0;
00462
00463 if (ctx->isSelectContext())
00464 {
00465 #ifdef STRICT_SELECT
00466 return new oqmlStatus(this, "this type of query constructs is no more supported: use select/from/where clause");
00467 #else
00468 node = new oqmlOr(qleft, qright);
00469 if (isLocked())
00470 node->lock();
00471 return node->compile(db, ctx);
00472 #endif
00473 }
00474
00475 oqmlStatus *s;
00476
00477 s = qleft->compile(db, ctx);
00478 if (s)
00479 return s;
00480
00481 s = oqml_check_type(this, db, ctx, qleft, "||");
00482 if (s)
00483 return s;
00484
00485 s = qright->compile(db, ctx);
00486 if (s)
00487 return s;
00488
00489 s = oqml_check_type(this, db, ctx, qright, "||");
00490 if (s)
00491 return s;
00492 return oqmlSuccess;
00493 }
00494
00495 oqmlStatus *oqmlLOr::eval(Database *db, oqmlContext *ctx, oqmlAtomList **alist, oqmlComp *, oqmlAtom *)
00496 {
00497 if (node)
00498 return node->eval(db, ctx, alist);
00499
00500 oqmlStatus *s;
00501 oqmlAtomList *al_left, *al_right;
00502
00503 *alist = new oqmlAtomList;
00504
00505 s = qleft->eval(db, ctx, &al_left);
00506 if (s)
00507 return s;
00508
00509 oqmlBool b;
00510
00511 s = oqml_check_logical(this, al_left, b);
00512 if (s)
00513 return s;
00514
00515 if (b)
00516 {
00517 (*alist)->append(new oqmlAtom_bool(oqml_True));
00518 return oqmlSuccess;
00519 }
00520
00521 s = qright->eval(db, ctx, &al_right);
00522 if (s)
00523 return s;
00524
00525 s = oqml_check_logical(this, al_right, b);
00526 if (s)
00527 return s;
00528
00529 if (b)
00530 (*alist)->append(new oqmlAtom_bool(oqml_True));
00531 else
00532 (*alist)->append(new oqmlAtom_bool(oqml_False));
00533
00534 return oqmlSuccess;
00535 }
00536
00537 void oqmlLOr::evalType(Database *db, oqmlContext *ctx, oqmlAtomType *at)
00538 {
00539 *at = eval_type;
00540 }
00541
00542 oqmlStatus *
00543 oqmlLOr::preEvalSelect(Database *db, oqmlContext *ctx,
00544 const char *ident, oqmlBool &done,
00545 unsigned int &cnt, oqmlBool firstPass)
00546 {
00547 if (node)
00548 return node->preEvalSelect(db, ctx, ident, done, cnt, firstPass);
00549
00550 oqmlStatus *s;
00551
00552 ctx->incrOrContext();
00553 s = qleft->preEvalSelect(db, ctx, ident, done, cnt, firstPass);
00554
00555 if (!s)
00556 {
00557 unsigned int cnt_r;
00558 s = qright->preEvalSelect(db, ctx, ident, done, cnt_r, firstPass);
00559 if (!s) cnt += cnt_r;
00560 }
00561
00562 ctx->decrOrContext();
00563 return s;
00564 }
00565
00566 oqmlBool oqmlLOr::isConstant() const
00567 {
00568 return oqml_False;
00569 }
00570
00571 void
00572 oqmlLOr::lock()
00573 {
00574 oqmlNode::lock();
00575 qleft->lock();
00576 qright->lock();
00577 if (node) node->lock();
00578 }
00579
00580 void
00581 oqmlLOr::unlock()
00582 {
00583 oqmlNode::unlock();
00584 qleft->unlock();
00585 qright->unlock();
00586 if (node) node->unlock();
00587 }
00588
00589 std::string
00590 oqmlLOr::toString(void) const
00591 {
00592 return (node ? node->toString() :
00593 oqml_binop_string(qleft, qright, (isLiteral ? " or " : "||"),
00594 is_statement));
00595 }
00596
00597
00598
00599
00600
00601
00602
00603 oqmlLAnd::oqmlLAnd(oqmlNode * _qleft, oqmlNode * _qright,
00604 oqmlBool _isLiteral, oqmlNode *_intersect_pred) :
00605 oqmlNode(oqmlLAND)
00606 {
00607 qleft = _qleft;
00608 qright = _qright;
00609 isLiteral = _isLiteral;
00610 eval_type.type = oqmlATOM_BOOL;
00611 node = 0;
00612 intersect_pred = _intersect_pred;
00613 must_intersect = oqml_False;
00614 estimated = oqml_False;
00615 r_first = r_second = 0;
00616 }
00617
00618 oqmlLAnd::~oqmlLAnd()
00619 {
00620 }
00621
00622 oqmlStatus *oqmlLAnd::compile(Database *db, oqmlContext *ctx)
00623 {
00624 node = 0;
00625 requalified = oqml_False;
00626
00627 if (ctx->isSelectContext())
00628 {
00629 #ifdef STRICT_SELECT
00630 return new oqmlStatus(this, "this type of query constructs is no more supported: use select/from/where clause");
00631 #else
00632 node = new oqmlAnd(qleft, qright);
00633 if (isLocked())
00634 node->lock();
00635 return node->compile(db, ctx);
00636 #endif
00637 }
00638
00639 oqmlStatus *s;
00640
00641 s = qleft->compile(db, ctx);
00642 if (s)
00643 return s;
00644
00645 s = oqml_check_type(this, db, ctx, qleft, "&&");
00646 if (s)
00647 return s;
00648
00649 s = qright->compile(db, ctx);
00650 if (s)
00651 return s;
00652
00653 s = oqml_check_type(this, db, ctx, qright, "&&");
00654 if (s)
00655 return s;
00656
00657 return oqmlSuccess;
00658 }
00659
00660 oqmlStatus *oqmlLAnd::eval(Database *db, oqmlContext *ctx, oqmlAtomList **alist, oqmlComp *, oqmlAtom *)
00661 {
00662 if (node)
00663 return node->eval(db, ctx, alist);
00664
00665 oqmlStatus *s;
00666 oqmlAtomList *al_left, *al_right;
00667
00668 *alist = new oqmlAtomList;
00669
00670 s = qleft->eval(db, ctx, &al_left);
00671 if (s)
00672 return s;
00673
00674 oqmlBool b;
00675
00676 s = oqml_check_logical(this, al_left, b);
00677 if (s)
00678 return s;
00679
00680 if (!b)
00681 {
00682 (*alist)->append(new oqmlAtom_bool(oqml_False));
00683 return oqmlSuccess;
00684 }
00685
00686 s = qright->eval(db, ctx, &al_right);
00687 if (s)
00688 return s;
00689
00690 s = oqml_check_logical(this, al_right, b);
00691 if (s)
00692 return s;
00693
00694 if (b)
00695 (*alist)->append(new oqmlAtom_bool(oqml_True));
00696 else
00697 (*alist)->append(new oqmlAtom_bool(oqml_False));
00698
00699 return oqmlSuccess;
00700 }
00701
00702 void oqmlLAnd::evalType(Database *db, oqmlContext *ctx, oqmlAtomType *at)
00703 {
00704 *at = eval_type;
00705 }
00706
00707 class OptimContext {
00708
00709 LinkedList varlist;
00710 oqmlNode *node;
00711 Database *db;
00712 oqmlContext *ctx;
00713
00714 oqmlStatus *push(const char *ident, oqmlAtom *x) {
00715 oqmlStatus *s = ctx->pushSymbol(ident, &x->type, x, oqml_True, oqml_True);
00716 if (s) return s;
00717 varlist.insertObject((void *)ident);
00718 return s;
00719 }
00720
00721 public:
00722 OptimContext(oqmlNode *_node, Database *_db, oqmlContext *_ctx) :
00723 node(_node), db(_db), ctx(_ctx) { }
00724
00725 oqmlStatus *realize(oqmlNode *intersect_pred, oqmlBool done,
00726 unsigned int r_first, unsigned int r_second,
00727 unsigned int cnt, oqmlBool &make_intersect)
00728 {
00729 if (!intersect_pred)
00730 {
00731 make_intersect = oqml_False;
00732 return oqmlSuccess;
00733 }
00734
00735 oqmlStatus *s = push("oql$done_1", new oqmlAtom_bool(done));
00736 if (s) return s;
00737
00738 s = push("oql$estim_1", new oqmlAtom_int(r_first));
00739 if (s) return s;
00740
00741 s = push("oql$estim_2", new oqmlAtom_int(r_second));
00742 if (s) return s;
00743
00744 s = push("oql$count_1", new oqmlAtom_int(cnt));
00745 if (s) return s;
00746
00747 int select_ctx_cnt = ctx->getSelectContextCount();
00748
00749 s = intersect_pred->compile(db, ctx);
00750 oqmlAtomList *al = 0;
00751 if (!s)
00752 s = intersect_pred->eval(db, ctx, &al);
00753
00754 ctx->setSelectContextCount(select_ctx_cnt);
00755
00756 if (s) return s;
00757
00758 if (al->cnt != 1 || !OQML_IS_BOOL(al->first))
00759 return new oqmlStatus(node, "and hint: bool expected, got %s",
00760 al->first ? al->first->type.getString() :
00761 "nothing");
00762
00763 make_intersect = OQML_ATOM_BOOLVAL(al->first);
00764 return oqmlSuccess;
00765 }
00766
00767 ~OptimContext() {
00768 LinkedListCursor c(varlist);
00769 const char *ident;
00770 while (c.getNext((void *&)ident))
00771 ctx->popSymbol(ident, oqml_True);
00772 }
00773
00774 };
00775
00776 const char *
00777 oqmlLAnd::getDefaultRule()
00778 {
00779
00780 return "!oql$done_1 || (oql$estim_2 != oql$ESTIM_MAX && oql$estim_2 <= oql$estim_1 && oql$count_1 > 100)";
00781 }
00782
00783 oqmlStatus *
00784 oqmlLAnd::estimateLAnd(Database *db, oqmlContext *ctx)
00785 {
00786 if (estimated)
00787 return oqmlSuccess;
00788
00789 unsigned int r_left, r_right;
00790 oqmlStatus *s;
00791
00792 s = qleft->estimate(db, ctx, r_left);
00793 if (s) return s;
00794
00795 ctx->incrAndContext();
00796 s = qright->estimate(db, ctx, r_right);
00797 ctx->decrAndContext();
00798 if (s) return s;
00799
00800 estimated = oqml_True;
00801
00802 if (r_left <= r_right)
00803 {
00804 r_first = r_left;
00805 r_second = r_right;
00806 return oqmlSuccess;
00807 }
00808
00809 oqmlNode *ql = qleft;
00810 qleft = qright;
00811 qright = ql;
00812 r_first = r_right;
00813 r_second = r_left;
00814 return oqmlSuccess;
00815 }
00816
00817 oqmlStatus *
00818 oqmlLAnd::preEvalSelect_optim(Database *db, oqmlContext *ctx,
00819 const char *ident, oqmlBool &done,
00820 unsigned int &cnt, oqmlBool firstPass)
00821 {
00822 if (node)
00823 return node->preEvalSelect(db, ctx, ident, done, cnt, firstPass);
00824
00825 oqmlStatus *s;
00826 s = estimateLAnd(db, ctx);
00827 if (s) return s;
00828
00829 s = qleft->preEvalSelect(db, ctx, ident, done, cnt, firstPass);
00830 if (s) return s;
00831
00832 OptimContext optim_ctx(this, db, ctx);
00833 oqmlBool make_intersect;
00834 s = optim_ctx.realize(intersect_pred, done, r_first, r_second, cnt,
00835 make_intersect);
00836 if (s) return s;
00837
00838
00839
00840
00841
00842
00843 if (!must_intersect && intersect_pred && !make_intersect)
00844 return oqmlSuccess;
00845
00846 if (firstPass &&
00847 (must_intersect || make_intersect ||
00848
00849 !done || (r_second != oqml_ESTIM_MAX && r_second <= r_first && cnt > 100)))
00850 {
00851 unsigned int cnt_r;
00852 oqmlBool odone = done;
00853 if (odone) ctx->incrAndContext();
00854 s = qright->preEvalSelect(db, ctx, ident, done, cnt_r, firstPass);
00855 if (odone) ctx->decrAndContext();
00856 return s;
00857 }
00858
00859 return oqmlSuccess;
00860 }
00861
00862 oqmlStatus *
00863 oqmlLAnd::preEvalSelect_nooptim(Database *db, oqmlContext *ctx,
00864 const char *ident, oqmlBool &done,
00865 unsigned int &cnt, oqmlBool firstPass)
00866 {
00867 if (node)
00868 return node->preEvalSelect(db, ctx, ident, done, cnt, firstPass);
00869
00870 oqmlStatus *s;
00871
00872
00873
00874 #if 1
00875 s = qleft->preEvalSelect(db, ctx, ident, done, cnt, firstPass);
00876 if (s || done) return s;
00877 return qright->preEvalSelect(db, ctx, ident, done, cnt, firstPass);
00878 #else
00879 unsigned int r_left, r_right;
00880
00881 s = qleft->estimate(db, ctx, r_left);
00882 if (s) return s;
00883
00884 if (r_left != oqml_ESTIM_MIN)
00885 {
00886 s = qright->estimate(db, ctx, r_right);
00887 if (s) return s;
00888 }
00889 else
00890 r_right = oqml_ESTIM_MAX;
00891
00892 if (r_left <= r_right)
00893 {
00894 s = qleft->preEvalSelect(db, ctx, ident, done, cnt, firstPass);
00895 if (s || done) return s;
00896 return qright->preEvalSelect(db, ctx, ident, done, cnt, firstPass);
00897 }
00898
00899 s = qright->preEvalSelect(db, ctx, ident, done, cnt, firstPass);
00900 if (s || done) return s;
00901 return qleft->preEvalSelect(db, ctx, ident, done, cnt, firstPass);
00902 #endif
00903 }
00904
00905 #define REQUALIFY_AND(OPL, OPLEQ, OPR, OPREQ, \
00906 getL1, getR1, getL2, getR2) \
00907 if ((left_type == OPL || left_type == OPLEQ) && \
00908 (right_type == OPR || right_type == OPREQ))\
00909 { \
00910 oqmlComp *cleft = ((oqmlComp *)qleft); \
00911 oqmlComp *cright = ((oqmlComp *)qright); \
00912 \
00913 if (cleft->getL1()->toString() == cright->getR1()->toString()) \
00914 return new oqmlBetween \
00915 (cleft->getL1(), \
00916 new oqmlRange(cleft->getL2(), \
00917 (left_type == OPL ? oqml_False : oqml_True), \
00918 cright->getR2(), \
00919 (right_type == OPR ? oqml_False : oqml_True))); \
00920 }
00921
00922 oqmlNode *
00923 oqmlLAnd::requalifyRange()
00924 {
00925 oqmlTYPE left_type = qleft->getType();
00926 oqmlTYPE right_type = qright->getType();
00927
00928 REQUALIFY_AND(oqmlSUP, oqmlSUPEQ, oqmlINF, oqmlINFEQ,
00929 getLeft, getLeft, getRight, getRight);
00930
00931 REQUALIFY_AND(oqmlINF, oqmlINFEQ, oqmlSUP, oqmlSUPEQ,
00932 getRight, getRight, getLeft, getLeft);
00933 REQUALIFY_AND(oqmlINF, oqmlINFEQ, oqmlINF, oqmlINFEQ,
00934 getRight, getLeft, getLeft, getRight);
00935 REQUALIFY_AND(oqmlSUP, oqmlSUPEQ, oqmlSUP, oqmlSUPEQ,
00936 getLeft, getRight, getRight, getLeft);
00937
00938 return (oqmlNode *)0;
00939 }
00940
00941 oqmlStatus *
00942 oqmlLAnd::requalify(Database *db, oqmlContext *ctx,
00943 const char *_ident, oqmlNode *_node, oqmlBool& done)
00944 {
00945 if (requalified)
00946 return oqmlSuccess;
00947
00948
00949 oqmlBool done_left = oqml_False, done_right = oqml_False;
00950 oqmlStatus *s = requalify_node(db, ctx, qleft, _ident, _node, done_left);
00951 if (s) return s;
00952 s = requalify_node(db, ctx, qright, _ident, _node, done_right);
00953 if (s) return s;
00954
00955
00956 oqmlBool and_optim = isAndOptim(ctx);
00957
00958 if (and_optim) {
00959 s = estimateLAnd(db, ctx);
00960 if (s) return s;
00961 }
00962
00963
00964
00965 if (done_left && done_right)
00966 {
00967 s = requalify_back(db, ctx);
00968 if (s) return s;
00969 }
00970
00971 if (and_optim) {
00972 must_intersect = OQMLBOOL((done_left && !done_right) ||
00973 (!done_left && done_right));
00974
00975 }
00976
00977
00978
00979
00980
00981
00982 if (OQMLBOOL(done_left || done_right))
00983 done = oqml_True;
00984
00985 requalified = oqml_True;
00986 return oqmlSuccess;
00987 }
00988
00989 oqmlStatus *
00990 oqmlLAnd::requalify_back(Database *db, oqmlContext *ctx)
00991 {
00992 return requalify_node_back(db, ctx, qright);
00993 }
00994
00995 oqmlBool
00996 oqmlLAnd::isAndOptim(oqmlContext *ctx)
00997 {
00998 static const char oql_no_and_optim[] = "oql$no_and_optim";
00999 return oqml_is_symbol(ctx, oql_no_and_optim) ? oqml_False : oqml_True;
01000 }
01001
01002 oqmlStatus *
01003 oqmlLAnd::preEvalSelect(Database *db, oqmlContext *ctx,
01004 const char *ident, oqmlBool &done,
01005 unsigned int &cnt, oqmlBool firstPass)
01006 {
01007 if (isAndOptim(ctx))
01008 return preEvalSelect_optim(db, ctx, ident, done, cnt, firstPass);
01009 return preEvalSelect_nooptim(db, ctx, ident, done, cnt, firstPass);
01010 }
01011
01012 oqmlBool oqmlLAnd::isConstant() const
01013 {
01014 return oqml_False;
01015 }
01016
01017 void
01018 oqmlLAnd::lock()
01019 {
01020 oqmlNode::lock();
01021 qleft->lock();
01022 qright->lock();
01023 if (node) node->lock();
01024 if (intersect_pred) intersect_pred->lock();
01025 }
01026
01027 void
01028 oqmlLAnd::unlock()
01029 {
01030 oqmlNode::unlock();
01031 qleft->unlock();
01032 qright->unlock();
01033 if (node) node->unlock();
01034 if (intersect_pred) intersect_pred->unlock();
01035 }
01036
01037 std::string
01038 oqmlLAnd::toString(void) const
01039 {
01040 return (node ? node->toString() :
01041 oqml_binop_string(qleft, qright, (isLiteral ? " and " : "&&"),
01042 is_statement));
01043 }
01044
01045
01046
01047
01048
01049
01050
01051 oqmlLNot::oqmlLNot(oqmlNode * _ql) : oqmlNode(oqmlLNOT)
01052 {
01053 ql = _ql;
01054 eval_type.type = oqmlATOM_BOOL;
01055 }
01056
01057 oqmlLNot::~oqmlLNot()
01058 {
01059 }
01060
01061 oqmlStatus *oqmlLNot::compile(Database *db, oqmlContext *ctx)
01062 {
01063 oqmlStatus *s;
01064
01065 s = ql->compile(db, ctx);
01066 if (s)
01067 return s;
01068
01069 return oqml_check_type(this, db, ctx, ql, "!");
01070 }
01071
01072 oqmlStatus *oqmlLNot::eval(Database *db, oqmlContext *ctx, oqmlAtomList **alist, oqmlComp *, oqmlAtom *)
01073 {
01074 oqmlStatus *s;
01075 oqmlAtomList *al;
01076
01077 *alist = new oqmlAtomList;
01078
01079 s = ql->eval(db, ctx, &al);
01080 if (s)
01081 return s;
01082
01083 oqmlBool b;
01084
01085 s = oqml_check_logical(this, al, b);
01086 if (s)
01087 return s;
01088
01089 if (b)
01090 (*alist)->append(new oqmlAtom_bool(oqml_False));
01091 else
01092 (*alist)->append(new oqmlAtom_bool(oqml_True));
01093
01094 return oqmlSuccess;
01095 }
01096
01097 void oqmlLNot::evalType(Database *db, oqmlContext *ctx, oqmlAtomType *at)
01098 {
01099 *at = eval_type;
01100 }
01101
01102 oqmlBool oqmlLNot::isConstant() const
01103 {
01104 return ql->isConstant();
01105 }
01106
01107 std::string
01108 oqmlLNot::toString(void) const
01109 {
01110 return oqml_unop_string(ql, "!", is_statement);
01111 }
01112
01113
01114
01115
01116
01117
01118
01119 oqmlComma::oqmlComma(oqmlNode * _qleft, oqmlNode * _qright, oqmlBool _is_statement) :
01120 oqmlNode(oqmlCOMMA)
01121 {
01122 qleft = _qleft;
01123 qright = _qright;
01124 is_statement = _is_statement;
01125 }
01126
01127 oqmlComma::~oqmlComma()
01128 {
01129 }
01130
01131 oqmlStatus *oqmlComma::compile(Database *db, oqmlContext *ctx)
01132 {
01133 oqmlStatus *s;
01134
01135 s = qleft->compile(db, ctx);
01136 if (s)
01137 return s;
01138
01139 s = qright->compile(db, ctx);
01140 if (s)
01141 return s;
01142
01143 return oqmlSuccess;
01144 }
01145
01146 oqmlStatus *oqmlComma::eval(Database *db, oqmlContext *ctx, oqmlAtomList **alist, oqmlComp *, oqmlAtom *)
01147 {
01148 oqmlStatus *s;
01149 oqmlAtomList *al_left, *al_right;
01150
01151 *alist = new oqmlAtomList();
01152
01153 s = qleft->eval(db, ctx, &al_left);
01154 if (s)
01155 return s;
01156
01157 #ifdef SYNC_GARB
01158 OQL_DELETE(al_left);
01159 #endif
01160 s = qright->eval(db, ctx, &al_right);
01161 if (s)
01162 return s;
01163
01164 (*alist)->append(al_right);
01165
01166
01167
01168
01169
01170
01171
01172 return oqmlSuccess;
01173 }
01174
01175 void oqmlComma::evalType(Database *db, oqmlContext *ctx, oqmlAtomType *at)
01176 {
01177 oqmlAtomType at_left, at_right;
01178 oqmlStatus *s;
01179
01180 qright->evalType(db, ctx, &at_right);
01181
01182 *at = at_right;
01183 }
01184
01185 oqmlBool oqmlComma::isConstant() const
01186 {
01187 return oqml_False;
01188 }
01189
01190 std::string
01191 oqmlComma::toString(void) const
01192 {
01193 if (!is_statement)
01194 return oqml_binop_string(qleft, qright, ",", is_statement);
01195
01196 return qleft->toString() + qright->toString();
01197 }
01198
01199
01200
01201
01202
01203
01204
01205 oqmlAssign::oqmlAssign(oqmlNode * _qleft, oqmlNode * _qright)
01206 : oqmlNode(oqmlASSIGN)
01207 {
01208 qleft = _qleft;
01209 qright = _qright;
01210 ident = 0;
01211 }
01212
01213 oqmlAssign::~oqmlAssign()
01214 {
01215 free(ident);
01216 }
01217
01218 oqmlStatus *oqmlAssign::compile(Database *db, oqmlContext *ctx)
01219 {
01220 oqmlStatus *s;
01221
01222 free(ident); ident = 0;
01223
01224 s = qleft->compile(db, ctx);
01225 if (s) return s;
01226
01227 s = qright->compile(db, ctx);
01228 if (s) return s;
01229
01230 if (qleft->getType() == oqmlIDENT)
01231 {
01232 ident = strdup(((oqmlIdent *)qleft)->getName());
01233 return oqmlSuccess;
01234 }
01235
01236 if (qleft->asDot())
01237 {
01238 oqmlAtomType at_left, at_right;
01239
01240 qleft->evalType(db, ctx, &at_left);
01241 qright->evalType(db, ctx, &at_right);
01242
01243 if (at_left.type != oqmlATOM_UNKNOWN_TYPE &&
01244 at_right.type != oqmlATOM_UNKNOWN_TYPE &&
01245 !at_left.cmp(at_right))
01246 {
01247 if (at_left.type == oqmlATOM_OID && at_right.type != oqmlATOM_NULL)
01248 return new oqmlStatus(this, "incompatible types for assignation: "
01249 "%s expected, got %s.",
01250 at_left.getString(), at_right.getString());
01251 }
01252
01253 return oqmlSuccess;
01254 }
01255
01256 return oqmlSuccess;
01257 }
01258
01259 oqmlStatus *oqmlAssign::eval(Database *db, oqmlContext *ctx,
01260 oqmlAtomList **alist, oqmlComp *, oqmlAtom *)
01261 {
01262 oqmlAtomList *al_right = 0;
01263 oqmlStatus *s;
01264 oqmlAtom *leftValue = 0;
01265 oqmlSymbolEntry *entry = 0;
01266 int idx = -1;
01267
01268 s = qright->eval(db, ctx, &al_right);
01269 if (s) return s;
01270
01271 if (!ident && qleft->getType() != oqmlDOT)
01272 {
01273 s = qleft->evalLeft(db, ctx, &leftValue, idx);
01274 if (s) return s;
01275
01276 if (!leftValue)
01277 return new oqmlStatus(this, "not a left value");
01278
01279 if (leftValue->as_ident())
01280 {
01281 ident = strdup(OQML_ATOM_IDENTVAL(leftValue));
01282 entry = leftValue->as_ident()->entry;
01283 }
01284 }
01285
01286 if (ident)
01287 {
01288 oqmlAtom *a;
01289 if (al_right->cnt == 1) {
01290 a = al_right->first;
01291 #ifdef SYNC_GARB
01292 if (al_right && !al_right->refcnt) {
01293 al_right->first = 0;
01294 OQL_DELETE(al_right);
01295 }
01296 #endif
01297 }
01298 else if (al_right->cnt)
01299 a = new oqmlAtom_list(al_right);
01300 else
01301 a = NULL;
01302
01303 oqmlBool global;
01304
01305 if (entry)
01306 {
01307
01308
01309 if (entry->global)
01310 {
01311 s = ctx->setSymbol(entry->ident, (a ? &a->type : 0), a, oqml_True);
01312 if (s) return s;
01313 }
01314
01315 else
01316 entry->set((a ? &a->type : 0), a);
01317 }
01318 else
01319 {
01320 if (!ctx->getSymbol(ident, 0, 0, &global) || global ||
01321 !strncmp(ident, oqml_global_scope, oqml_global_scope_len))
01322 s = ctx->setSymbol(ident, (a ? &a->type : 0), a, oqml_True);
01323 else
01324 s = ctx->setSymbol(ident, (a ? &a->type : 0), a, oqml_False);
01325
01326 if (s) return s;
01327 }
01328
01329 *alist = new oqmlAtomList(a);
01330 free(ident); ident = 0;
01331 return oqmlSuccess;
01332 }
01333
01334 if (leftValue)
01335 {
01336 if (idx < 0)
01337 return new oqmlStatus(this, "not a left value");
01338
01339 oqmlAtom *a = 0;
01340
01341 if (al_right->cnt == 1) {
01342 a = al_right->first;
01343 #ifdef SYNC_GARB
01344 if (al_right && !al_right->refcnt) {
01345 al_right->first = 0;
01346 OQL_DELETE(al_right);
01347 }
01348 #endif
01349 }
01350
01351 if (leftValue->as_string()) {
01352 s = leftValue->as_string()->setAtom(a, idx, this);
01353 if (s) return s;
01354 }
01355 else if (leftValue->as_list()) {
01356 s = leftValue->as_list()->setAtom(a, idx, this);
01357 if (s) return s;
01358 }
01359 else if (leftValue->as_array()) {
01360 s = leftValue->as_array()->setAtom(a, idx, this);
01361 if (s) return s;
01362 }
01363 else if (leftValue->as_struct()) {
01364 s = leftValue->as_struct()->setAtom(a, idx, this);
01365 if (s) return s;
01366 }
01367 else if (OQML_IS_OBJECT(leftValue)) {
01368 Object *o = 0;
01369 s = oqmlObjectManager::getObject(this, db, leftValue, o, oqml_False,
01370 oqml_True);
01371 if (s) return s;
01372
01373 if (!o->asCollArray()) {
01374 oqmlObjectManager::releaseObject(o, oqml_False);
01375 return new oqmlStatus(this, "not a left value");
01376 }
01377
01378 Status is;
01379
01380 if (a->as_null() || (a->as_oid() && !OQML_ATOM_OIDVAL(a).isValid())
01381 || (a->as_obj() && !OQML_ATOM_OBJVAL(a)))
01382 is = o->asCollArray()->suppressAt(idx);
01383 else if (a->as_oid())
01384 is = o->asCollArray()->insertAt(idx, OQML_ATOM_OIDVAL(a));
01385 else if (a->as_obj()) {
01386 OQL_CHECK_OBJ(a);
01387 is = o->asCollArray()->insertAt(idx, OQML_ATOM_OBJVAL(a));
01388 }
01389 else {
01390 oqmlObjectManager::releaseObject(o, oqml_False);
01391 return new oqmlStatus(this, "left value: only support collection array of objects");
01392 }
01393
01394 if (!is)
01395 is = o->store();
01396 oqmlObjectManager::releaseObject(o, oqml_False);
01397 if (is) return new oqmlStatus(this, is);
01398 }
01399 else
01400 return new oqmlStatus(this, "not a left value");
01401
01402 *alist = new oqmlAtomList(a);
01403 return oqmlSuccess;
01404 }
01405
01406 if (qleft->asDot()) {
01407 if (al_right->cnt != 1)
01408 return new oqmlStatus(this, "invalid right part for dot");
01409
01410 return qleft->asDot()->set(db, ctx, al_right->first, alist);
01411 }
01412
01413 return new oqmlStatus(this, "not a left value");
01414 }
01415
01416 void oqmlAssign::evalType(Database *db, oqmlContext *ctx, oqmlAtomType *at)
01417 {
01418 *at = eval_type;
01419 }
01420
01421 oqmlBool oqmlAssign::isConstant() const
01422 {
01423 return oqml_False;
01424 }
01425
01426 std::string
01427 oqmlAssign::toString(void) const
01428 {
01429 return oqml_binop_string(qleft, qright, ":=", is_statement);
01430 }
01431
01432
01433
01434
01435
01436
01437
01438 oqmlCompoundStatement::oqmlCompoundStatement(oqmlNode * _node) : oqmlNode(oqmlCOMPOUND_STATEMENT)
01439 {
01440 node = _node;
01441 }
01442
01443 oqmlCompoundStatement::~oqmlCompoundStatement()
01444 {
01445 }
01446
01447 oqmlStatus *oqmlCompoundStatement::compile(Database *db, oqmlContext *ctx)
01448 {
01449 if (!node)
01450 return oqmlSuccess;
01451
01452 return node->compile(db, ctx);
01453 }
01454
01455 oqmlStatus *oqmlCompoundStatement::eval(Database *db, oqmlContext *ctx, oqmlAtomList **alist, oqmlComp *, oqmlAtom *)
01456 {
01457 if (!node)
01458 return oqmlSuccess;
01459
01460 *alist = new oqmlAtomList();
01461 oqmlAtomList *dlist = 0;
01462 oqmlStatus *s = node->eval(db, ctx, &dlist);
01463 #ifdef SYNC_GARB
01464 OQL_DELETE(dlist);
01465 #endif
01466 return s;
01467 }
01468
01469 void oqmlCompoundStatement::evalType(Database *db, oqmlContext *ctx, oqmlAtomType *at)
01470 {
01471 *at = eval_type;
01472 }
01473
01474 oqmlBool oqmlCompoundStatement::isConstant() const
01475 {
01476 return oqml_False;
01477 }
01478
01479 std::string
01480 oqmlCompoundStatement::toString(void) const
01481 {
01482 return std::string("{ ") + (node ? node->toString() : std::string("")) +
01483 "}";
01484 }
01485
01486
01487
01488
01489
01490
01491
01492 oqmlTypeOf::oqmlTypeOf(oqmlNode * _ql) : oqmlNode(oqmlTYPEOF)
01493 {
01494 ql = _ql;
01495 eval_type.type = oqmlATOM_STRING;
01496 eval_type.comp = oqml_True;
01497 }
01498
01499 oqmlTypeOf::~oqmlTypeOf()
01500 {
01501 }
01502
01503 oqmlStatus *oqmlTypeOf::compile(Database *db, oqmlContext *ctx)
01504 {
01505 return ql->compile(db, ctx);
01506 }
01507
01508 oqmlStatus *oqmlTypeOf::eval(Database *db, oqmlContext *ctx, oqmlAtomList **alist, oqmlComp *, oqmlAtom *)
01509 {
01510 oqmlStatus *s;
01511
01512 oqmlAtomList *al;
01513 s = ql->eval(db, ctx, &al);
01514 if (s)
01515 return s;
01516
01517 if (!al->cnt)
01518 *alist = new oqmlAtomList(new oqmlAtom_string("nil"));
01519 else
01520 *alist = new oqmlAtomList(new oqmlAtom_string(al->first->type.getString()));
01521 return oqmlSuccess;
01522 }
01523
01524 void oqmlTypeOf::evalType(Database *db, oqmlContext *ctx, oqmlAtomType *at)
01525 {
01526 *at = eval_type;
01527 }
01528
01529 oqmlBool oqmlTypeOf::isConstant() const
01530 {
01531 return OQMLBOOL(ql->isConstant());
01532 }
01533
01534 std::string
01535 oqmlTypeOf::toString(void) const
01536 {
01537 return oqml_unop_string(ql, "typeof ", is_statement);
01538 }
01539
01540
01541
01542
01543
01544
01545
01546 oqmlUnval::oqmlUnval(oqmlNode * _ql) : oqmlNode(oqmlUNVAL)
01547 {
01548 ql = _ql;
01549 eval_type.type = oqmlATOM_STRING;
01550 eval_type.comp = oqml_True;
01551 }
01552
01553 oqmlUnval::~oqmlUnval()
01554 {
01555 }
01556
01557 oqmlStatus *oqmlUnval::compile(Database *db, oqmlContext *ctx)
01558 {
01559 return oqmlSuccess;
01560 }
01561
01562 oqmlStatus *oqmlUnval::eval(Database *db, oqmlContext *ctx, oqmlAtomList **alist, oqmlComp *, oqmlAtom *)
01563 {
01564 *alist = new oqmlAtomList(new oqmlAtom_string
01565 ((ql->toString() +
01566 (ql->is_statement ? "; " : "")).c_str()));
01567 return oqmlSuccess;
01568 }
01569
01570 void oqmlUnval::evalType(Database *db, oqmlContext *ctx,
01571 oqmlAtomType *at)
01572 {
01573 *at = eval_type;
01574 }
01575
01576 oqmlBool oqmlUnval::isConstant() const
01577 {
01578 return oqml_True;
01579 }
01580
01581 std::string
01582 oqmlUnval::toString(void) const
01583 {
01584 return std::string("unval(") + ql->toString() + std::string(")");
01585 }
01586
01587
01588
01589
01590
01591
01592
01593 oqmlEval::oqmlEval(oqmlNode * _ql) : oqmlNode(oqmlEVAL)
01594 {
01595 ql = _ql;
01596 }
01597
01598 oqmlEval::~oqmlEval()
01599 {
01600 }
01601
01602 oqmlStatus *oqmlEval::compile(Database *db, oqmlContext *ctx)
01603 {
01604 oqmlStatus *s;
01605
01606 s = ql->compile(db, ctx);
01607 if (s)
01608 return s;
01609
01610 return oqmlSuccess;
01611 }
01612
01613 oqmlStatus *oqmlEval::eval(Database *db, oqmlContext *ctx, oqmlAtomList **alist, oqmlComp *, oqmlAtom *)
01614 {
01615 oqmlStatus *s;
01616
01617 oqmlAtomList *al;
01618 s = ql->eval(db, ctx, &al);
01619 if (s)
01620 return s;
01621
01622 if (al->cnt == 1 && al->first->as_string())
01623 {
01624 char *str = strdup((std::string(OQML_ATOM_STRVAL(al->first)) + ";").c_str());
01625 s = oqml_realize(db, str, alist);
01626 free(str);
01627 return s;
01628 }
01629
01630 return new oqmlStatus(this, "string expected");
01631 }
01632
01633 void oqmlEval::evalType(Database *db, oqmlContext *ctx,
01634 oqmlAtomType *at)
01635 {
01636 *at = eval_type;
01637 }
01638
01639 oqmlBool oqmlEval::isConstant() const
01640 {
01641 return OQMLBOOL(ql->isConstant());
01642 }
01643
01644 std::string
01645 oqmlEval::toString(void) const
01646 {
01647 return oqml_unop_string(ql, "eval ", is_statement);
01648 }
01649
01650
01651
01652
01653
01654
01655
01656 oqmlPrint::oqmlPrint(oqmlNode * _ql) : oqmlNode(oqmlPRINT)
01657 {
01658 ql = _ql;
01659 }
01660
01661 oqmlPrint::~oqmlPrint()
01662 {
01663 }
01664
01665 oqmlStatus *oqmlPrint::compile(Database *db, oqmlContext *ctx)
01666 {
01667 oqmlStatus *s;
01668
01669 s = ql->compile(db, ctx);
01670 if (s)
01671 return s;
01672
01673 return oqmlSuccess;
01674 }
01675
01676 oqmlStatus *oqmlPrint::eval(Database *db, oqmlContext *ctx, oqmlAtomList **alist, oqmlComp *, oqmlAtom *)
01677 {
01678 oqmlStatus *s;
01679
01680 oqmlAtomList *al;
01681 s = ql->eval(db, ctx, &al);
01682 if (s)
01683 return s;
01684
01685 if (al->cnt == 1 && al->first->as_string())
01686 {
01687
01688
01689
01690
01691 Connection::setServerMessage(OQML_ATOM_STRVAL(al->first));
01692 *alist = new oqmlAtomList();
01693 return oqmlSuccess;
01694 }
01695
01696 return new oqmlStatus(this, "string expected");
01697 }
01698
01699 void oqmlPrint::evalType(Database *db, oqmlContext *ctx,
01700 oqmlAtomType *at)
01701 {
01702 *at = eval_type;
01703 }
01704
01705 oqmlBool oqmlPrint::isConstant() const
01706 {
01707 return OQMLBOOL(ql->isConstant());
01708 }
01709
01710 std::string
01711 oqmlPrint::toString(void) const
01712 {
01713 return oqml_unop_string(ql, "print ", is_statement);
01714 }
01715
01716
01717
01718
01719
01720
01721
01722 oqmlImport::oqmlImport(oqmlNode * _ql) : oqmlNode(oqmlIMPORT)
01723 {
01724 ql = _ql;
01725 }
01726
01727 oqmlImport::~oqmlImport()
01728 {
01729 }
01730
01731 oqmlStatus *oqmlImport::compile(Database *db, oqmlContext *ctx)
01732 {
01733 oqmlStatus *s;
01734
01735 s = ql->compile(db, ctx);
01736 if (s)
01737 return s;
01738
01739 return oqmlSuccess;
01740 }
01741
01742 oqmlStatus *oqmlImport::eval(Database *db, oqmlContext *ctx,
01743 oqmlAtomList **alist, oqmlComp *, oqmlAtom *)
01744 {
01745 oqmlStatus *s;
01746
01747 oqmlAtomList *al;
01748 s = ql->eval(db, ctx, &al);
01749 if (s)
01750 return s;
01751
01752 if (al->cnt == 1 && al->first->as_string())
01753 {
01754 char *file = OQML_ATOM_STRVAL(al->first);
01755 const char *oqmlpath = eyedb::ServerConfig::getSValue("oqlpath");
01756
01757 oqmlBool check;
01758 if (!oqmlpath || file[0] == '/')
01759 {
01760 check = oqml_False;
01761 return import_realize(db, alist, file, 0, check);
01762 }
01763
01764 const char *x;
01765 int idx = 0;
01766 while (*(x = get_next_path(oqmlpath, idx)))
01767 {
01768 check = oqml_True;
01769 s = import_realize(db, alist, file, x, check);
01770 if (check || s)
01771 return s;
01772 }
01773
01774 return new oqmlStatus(this, "cannot find file '%s'", file);
01775 }
01776
01777 return new oqmlStatus(this, "string expected");
01778 }
01779
01780 void oqmlImport::evalType(Database *db, oqmlContext *ctx, oqmlAtomType *at)
01781 {
01782 *at = eval_type;
01783 }
01784
01785 oqmlBool oqmlImport::isConstant() const
01786 {
01787 return oqml_False;
01788 }
01789
01790 std::string
01791 oqmlImport::toString(void) const
01792 {
01793 return oqml_unop_string(ql, "import ", is_statement);
01794 }
01795
01796 oqmlStatus *
01797 oqmlImport::import_realize(Database *db,
01798 oqmlAtomList **alist,
01799 const char *file, const char *dir, oqmlBool &check)
01800 {
01801 static const char suffix[] = ".oql";
01802 static const unsigned int suffix_len = strlen(suffix);
01803 std::string sfile;
01804
01805 sfile = (dir ? std::string(dir) + "/" + file : std::string(file));
01806 int len = strlen(file);
01807 if (len <= suffix_len || strcmp(&file[len-suffix_len], suffix))
01808 sfile += suffix;
01809
01810 int fd = open(sfile.c_str(), O_RDONLY);
01811
01812 *alist = new oqmlAtomList();
01813 (*alist)->append(new oqmlAtom_string(sfile.c_str()));
01814
01815 if (fd >= 0)
01816 {
01817 extern char *oqml_file;
01818 oqmlAtomList *xal;
01819 char *str;
01820 oqmlStatus *s = file_to_buf(sfile.c_str(), fd, str);
01821 if (s) return s;
01822 char *lastfile = oqml_file;
01823 oqml_file = strdup(sfile.c_str());
01824 s = oqml_realize(db, str, &xal);
01825 close(fd);
01826 free(str);
01827 if (!s) check = oqml_True;
01828 free(oqml_file);
01829 oqml_file = lastfile;
01830 return s;
01831 }
01832
01833 if (check)
01834 {
01835 check = oqml_False;
01836 return oqmlSuccess;
01837 }
01838
01839 return new oqmlStatus("cannot find file '%s'", sfile.c_str());
01840 }
01841
01842 const char *
01843 oqmlImport::get_next_path(const char *oqmlpath, int &idx)
01844 {
01845 static char path[512];
01846
01847 const char *s = strchr(oqmlpath+idx, ':');
01848 if (!s)
01849 {
01850 s = oqmlpath+idx;
01851 idx += strlen(oqmlpath+idx)+1;
01852 return s;
01853 }
01854
01855 int len = s-oqmlpath-idx;
01856 strncpy(path, oqmlpath+idx, len);
01857 path[len] = 0;
01858 idx += strlen(path)+1;
01859 return path;
01860 }
01861
01862 oqmlStatus *
01863 oqmlImport::file_to_buf(const char *file, int fd, char *&str)
01864 {
01865 struct stat st;
01866 if (fstat(fd, &st) < 0)
01867 return new oqmlStatus(this, "stat error on file '%s'",
01868 file);
01869
01870 str = (char *)malloc(st.st_size+1);
01871 if (read(fd, str, st.st_size) != st.st_size)
01872 {
01873 free(str);
01874 return new oqmlStatus(this, "read error on file '%s'",
01875 file);
01876 }
01877
01878 str[st.st_size] = 0;
01879 return oqmlSuccess;
01880 }
01881
01882
01883
01884
01885
01886
01887
01888 oqmlSelfIncr::oqmlSelfIncr(oqmlNode * _ql, int _incr, oqmlBool _post)
01889 : oqmlNode(oqmlASSIGN)
01890 {
01891 ql = _ql;
01892 incr = _incr;
01893 post = _post;
01894 if (incr > 0)
01895 qlassign = new oqmlAssign(ql, new oqmlAdd(ql, new oqmlInt(incr)));
01896 else
01897 qlassign = new oqmlAssign(ql, new oqmlSub(ql, new oqmlInt(-incr)));
01898 }
01899
01900 oqmlSelfIncr::~oqmlSelfIncr()
01901 {
01902 }
01903
01904 oqmlStatus *oqmlSelfIncr::compile(Database *db, oqmlContext *ctx)
01905 {
01906 return qlassign->compile(db, ctx);
01907 }
01908
01909 oqmlStatus *oqmlSelfIncr::eval(Database *db, oqmlContext *ctx, oqmlAtomList **alist, oqmlComp *, oqmlAtom *)
01910 {
01911 oqmlStatus *s;
01912
01913 oqmlAtomList *al;
01914 s = qlassign->eval(db, ctx, &al);
01915
01916 if (s)
01917 return s;
01918
01919 if (!post)
01920 {
01921 *alist = al;
01922 return oqmlSuccess;
01923 }
01924
01925 *alist = new oqmlAtomList();
01926 oqmlAtom *a = al->first;
01927 while (a)
01928 {
01929 oqmlAtom *x;
01930 if (a->type.type == oqmlATOM_INT)
01931 x = new oqmlAtom_int(OQML_ATOM_INTVAL(a)-incr);
01932 else if (a->type.type == oqmlATOM_DOUBLE)
01933 x = new oqmlAtom_double(OQML_ATOM_DBLVAL(a)-incr);
01934 else if (a->type.type == oqmlATOM_CHAR)
01935 x = new oqmlAtom_int(OQML_ATOM_CHARVAL(a)-incr);
01936 else
01937 new oqmlStatus(this, "cannot performed operation on '%s'",
01938 (incr > 0 ? "++" : "--"), a->type.getString());
01939 (*alist)->append(x);
01940 a = a->next;
01941 }
01942
01943 return oqmlSuccess;
01944 }
01945
01946 void oqmlSelfIncr::evalType(Database *db, oqmlContext *ctx, oqmlAtomType *at)
01947 {
01948 qlassign->evalType(db, ctx, at);
01949 }
01950
01951 oqmlBool oqmlSelfIncr::isConstant() const
01952 {
01953 return qlassign->isConstant();
01954 }
01955
01956 std::string
01957 oqmlSelfIncr::toString(void) const
01958 {
01959 const char *opstr = (incr > 0 ? "++" : "--");
01960 if (post)
01961 {
01962 if (is_statement)
01963 return ql->toString() + opstr + "; ";
01964 return std::string("(") + ql->toString() + opstr + std::string(")");
01965 }
01966
01967 return oqml_unop_string(ql, opstr, is_statement);
01968 }
01969
01970
01971
01972
01973
01974
01975
01976 oqmlTilde::oqmlTilde(oqmlNode * _ql) : oqmlNode(oqmlTILDE)
01977 {
01978 ql = _ql;
01979 }
01980
01981 oqmlTilde::~oqmlTilde()
01982 {
01983 }
01984
01985 oqmlStatus *oqmlTilde::compile(Database *db, oqmlContext *ctx)
01986 {
01987 oqmlStatus *s;
01988
01989 s = ql->compile(db, ctx);
01990 if (s)
01991 return s;
01992
01993 return oqmlSuccess;
01994 }
01995
01996 oqmlStatus *oqmlTilde::eval(Database *db, oqmlContext *ctx, oqmlAtomList **alist, oqmlComp *, oqmlAtom *)
01997 {
01998 oqmlStatus *s;
01999
02000 oqmlAtomList *al;
02001 s = ql->eval(db, ctx, &al);
02002 if (s)
02003 return s;
02004
02005 if (al->cnt > 1)
02006 return new oqmlStatus(this, "cannot perform operation on"
02007 " a non atomic operand");
02008 if (al->cnt == 0)
02009 return new oqmlStatus(this, "cannot perform operation on"
02010 " a nil operand");
02011
02012 oqmlAtom *a = al->first;
02013 if (a->type.type == oqmlATOM_INT)
02014 *alist = new oqmlAtomList(new oqmlAtom_int(~((oqmlAtom_int *)a)->i));
02015 else if (a->type.type == oqmlATOM_CHAR)
02016 *alist = new oqmlAtomList(new oqmlAtom_int(~(int)((oqmlAtom_char *)a)->c));
02017 else
02018 return new oqmlStatus(this, "operation '~%s' is not valid",
02019 a->type.getString());
02020 return oqmlSuccess;
02021 }
02022
02023 void oqmlTilde::evalType(Database *db, oqmlContext *ctx, oqmlAtomType *at)
02024 {
02025 *at = eval_type;
02026 }
02027
02028 oqmlBool oqmlTilde::isConstant() const
02029 {
02030 return OQMLBOOL(ql->isConstant());
02031 }
02032
02033 std::string
02034 oqmlTilde::toString(void) const
02035 {
02036 return oqml_unop_string(ql, "~", is_statement);
02037 }
02038
02039
02040
02041
02042
02043
02044
02045 typedef oqmlStatus * (*oqml_check_fun)(oqmlNode *node, oqmlAtom *, oqmlAtom *a);
02046
02047 static oqmlStatus *
02048 check_right_nonzero(oqmlNode *node, oqmlAtom *, oqmlAtom *a)
02049 {
02050 oqmlATOMTYPE at = a->type.type;
02051
02052 if (at == oqmlATOM_INT)
02053 {
02054 if (!OQML_ATOM_INTVAL(a))
02055 return new oqmlStatus(node,
02056 "right operand: invalid null integer value");
02057 return oqmlSuccess;
02058 }
02059
02060 if (at == oqmlATOM_DOUBLE)
02061 {
02062 if (!OQML_ATOM_DBLVAL(a))
02063 return new oqmlStatus(node,
02064 "right operand: invalid null float value");
02065 return oqmlSuccess;
02066 }
02067
02068 if (at == oqmlATOM_CHAR)
02069 {
02070 if (!OQML_ATOM_CHARVAL(a))
02071 return new oqmlStatus(node,
02072 "right operand: invalid null character value");
02073 return oqmlSuccess;
02074 }
02075
02076 return oqmlSuccess;
02077 }
02078
02079 std::string
02080 oqml_binop_string(oqmlNode *qleft, oqmlNode *qright, const char *opstr,
02081 oqmlBool is_statement)
02082 {
02083 if (is_statement)
02084 return qleft->toString() + opstr + qright->toString() + "; ";
02085
02086 return std::string("(") + qleft->toString() + opstr +
02087 qright->toString() + std::string(")");
02088 }
02089
02090 std::string
02091 oqml_unop_string(oqmlNode *ql, const char *opstr, oqmlBool is_statement)
02092 {
02093 if (is_statement)
02094 return std::string(opstr) + ql->toString() + "; ";
02095 return std::string("(") + opstr + ql->toString() + std::string(")");
02096 }
02097
02098 #define OQML_INT_BINOP(oqml_x, oqml_XX, OP, OPSTR, CHECK_FUN) \
02099 oqml_x::oqml_x(oqmlNode * _qleft, oqmlNode * _qright) : oqmlNode(oqml_XX) \
02100 { \
02101 qleft = _qleft; \
02102 qright = _qright; \
02103 } \
02104 \
02105 oqml_x::~oqml_x() \
02106 { \
02107 } \
02108 \
02109 oqmlStatus *oqml_x::compile(Database *db, oqmlContext *ctx) \
02110 { \
02111 oqmlBool iscts; \
02112 oqmlStatus *s; \
02113 s = binopCompile(db, ctx, OPSTR, qleft, qright, eval_type, oqmlIntOK, iscts); \
02114 \
02115 if (s) \
02116 return s; \
02117 \
02118 if (isConstant() && !cst_list) \
02119 { \
02120 oqmlAtomList *al; \
02121 s = eval(db, ctx, &al); \
02122 if (s) return s; \
02123 cst_list = al->copy(); \
02124 if (isLocked()) \
02125 oqmlLock(cst_list, oqml_True); \
02126 } \
02127 \
02128 return oqmlSuccess; \
02129 } \
02130 \
02131 oqmlStatus *oqml_x::eval(Database *db, oqmlContext *ctx, oqmlAtomList **alist, oqmlComp *, oqmlAtom *) \
02132 { \
02133 if (cst_list) \
02134 { \
02135 *alist = new oqmlAtomList(cst_list); \
02136 return oqmlSuccess; \
02137 } \
02138 \
02139 oqmlAtomList *al_left, *al_right; \
02140 oqmlStatus *s = binopEval(db, ctx, OPSTR, eval_type, qleft, qright, oqmlIntOK, &al_left, &al_right); \
02141 \
02142 if (s) \
02143 return s; \
02144 \
02145 oqmlAtom *aleft = al_left->first, *aright = al_right->first; \
02146 \
02147 if (CHECK_FUN) \
02148 { \
02149 s = ((oqml_check_fun)CHECK_FUN)(this, aleft, aright); \
02150 if (s) return s; \
02151 } \
02152 \
02153 oqmlATOMTYPE at = aleft->type.type; \
02154 \
02155 if (at == oqmlATOM_INT) \
02156 *alist = new oqmlAtomList\
02157 (new oqmlAtom_int(OQML_ATOM_INTVAL(aleft) OP OQML_ATOM_INTVAL(aright))); \
02158 \
02159 else if (at == oqmlATOM_CHAR) \
02160 *alist = new oqmlAtomList\
02161 (new oqmlAtom_int(OQML_ATOM_CHARVAL(aleft) OP OQML_ATOM_CHARVAL(aright))); \
02162 else \
02163 return oqmlStatus::expected(this, "integer or character", aleft->type.getString()); \
02164 \
02165 OQL_DELETE(al_left); \
02166 OQL_DELETE(al_right); \
02167 \
02168 return oqmlSuccess; \
02169 } \
02170 \
02171 void oqml_x::evalType(Database *db, oqmlContext *ctx, oqmlAtomType *at) \
02172 { \
02173 *at = eval_type; \
02174 } \
02175 \
02176 oqmlBool oqml_x::isConstant() const \
02177 { \
02178 return OQMLBOOL(qleft->isConstant() && qright->isConstant()); \
02179 } \
02180 \
02181 std::string oqml_x::toString(void) const \
02182 { \
02183 return oqml_binop_string(qleft, qright, OPSTR, is_statement); \
02184 }
02185
02186 #define OQML_BINOP(oqml_x, oqml_XX, OP, OPSTR, CHECK_FUN) \
02187 oqml_x::oqml_x(oqmlNode * _qleft, oqmlNode * _qright) : oqmlNode(oqml_XX) \
02188 { \
02189 qleft = _qleft; \
02190 qright = _qright; \
02191 } \
02192 \
02193 oqml_x::~oqml_x() \
02194 { \
02195 } \
02196 \
02197 oqmlStatus *oqml_x::compile(Database *db, oqmlContext *ctx) \
02198 { \
02199 oqmlBool iscts; \
02200 oqmlStatus *s; \
02201 s = binopCompile(db, ctx, OPSTR, qleft, qright, eval_type, oqmlDoubleOK, iscts); \
02202 \
02203 if (s) \
02204 return s; \
02205 \
02206 if (isConstant() && !cst_list) \
02207 { \
02208 oqmlAtomList *al; \
02209 s = eval(db, ctx, &al); \
02210 if (s) return s; \
02211 cst_list = al->copy(); \
02212 if (isLocked()) \
02213 oqmlLock(cst_list, oqml_True); \
02214 } \
02215 \
02216 return oqmlSuccess; \
02217 } \
02218 \
02219 oqmlStatus *oqml_x::eval(Database *db, oqmlContext *ctx, oqmlAtomList **alist, oqmlComp *, oqmlAtom *) \
02220 { \
02221 if (cst_list) \
02222 { \
02223 *alist = new oqmlAtomList(cst_list); \
02224 return oqmlSuccess; \
02225 } \
02226 \
02227 oqmlAtomList *al_left, *al_right; \
02228 oqmlStatus *s = binopEval(db, ctx, OPSTR, eval_type, qleft, qright, oqmlDoubleOK, &al_left, &al_right); \
02229 \
02230 if (s) \
02231 return s; \
02232 \
02233 oqmlAtom *aleft = al_left->first, *aright = al_right->first; \
02234 \
02235 if (CHECK_FUN) \
02236 { \
02237 s = ((oqml_check_fun)CHECK_FUN)(this, aleft, aright); \
02238 if (s) return s; \
02239 } \
02240 \
02241 oqmlATOMTYPE at = aleft->type.type; \
02242 \
02243 if (at == oqmlATOM_INT) \
02244 *alist = new oqmlAtomList \
02245 (new oqmlAtom_int(OQML_ATOM_INTVAL(aleft) OP OQML_ATOM_INTVAL(aright))); \
02246 \
02247 else if (at == oqmlATOM_CHAR) \
02248 *alist = new oqmlAtomList \
02249 (new oqmlAtom_int(OQML_ATOM_CHARVAL(aleft) OP OQML_ATOM_CHARVAL(aright))); \
02250 else if (at == oqmlATOM_DOUBLE) \
02251 *alist = new oqmlAtomList \
02252 (new oqmlAtom_double(OQML_ATOM_DBLVAL(aleft) OP OQML_ATOM_DBLVAL(aright))); \
02253 else \
02254 return oqmlStatus::expected(this, "integer, character or double", aleft->type.getString()); \
02255 \
02256 OQL_DELETE(al_left); \
02257 OQL_DELETE(al_right); \
02258 \
02259 return oqmlSuccess; \
02260 } \
02261 \
02262 void oqml_x::evalType(Database *db, oqmlContext *ctx, oqmlAtomType *at) \
02263 { \
02264 *at = eval_type; \
02265 } \
02266 \
02267 oqmlBool oqml_x::isConstant() const \
02268 { \
02269 return OQMLBOOL(qleft->isConstant() && qright->isConstant()); \
02270 } \
02271 std::string oqml_x::toString(void) const \
02272 { \
02273 if (qleft->getType() == oqmlINT)\
02274 return oqml_unop_string(qright, OPSTR, is_statement); \
02275 return oqml_binop_string(qleft, qright, OPSTR, is_statement); \
02276 }
02277
02278 OQML_BINOP(oqmlMul, oqmlMUL, *, "*", 0)
02279 OQML_BINOP(oqmlDiv, oqmlDIV, /, "/", check_right_nonzero)
02280
02281 OQML_INT_BINOP(oqmlMod, oqmlMOD, %, "%", check_right_nonzero)
02282 OQML_INT_BINOP(oqmlAAnd, oqmlAAND, &, "&", 0)
02283 OQML_INT_BINOP(oqmlAOr, oqmlAOR, |, "|", 0)
02284 OQML_INT_BINOP(oqmlXor, oqmlXOR, ^, "^", 0)
02285 OQML_INT_BINOP(oqmlShr, oqmlSHR, >>, ">>", 0)
02286 OQML_INT_BINOP(oqmlShl, oqmlSHL, <<, "<<", 0)
02287 }