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 <stdlib.h>
00026 #include <stdio.h>
00027 #include <string.h>
00028 #include <math.h>
00029 #include <assert.h>
00030
00031 #include "oql_p.h"
00032 #define OQML_NEW_COLL
00033
00034 namespace eyedb {
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048 static oqmlStatus *
00049 append_perform(oqmlNode *node, Collection *coll, const Oid *oid,
00050 Data data, int size, oqmlAtom *a,
00051 oqmlAtomList *atom_coll, oqmlAtomList *alist);
00052
00053 static oqmlStatus *
00054 oqml_check_coll_type(Collection *coll, oqmlATOMTYPE &t)
00055 {
00056 Bool isref;
00057 eyedblib::int16 dim;
00058 if (!coll->asCollection() || !coll->getClass()->asCollectionClass())
00059 return new oqmlStatus("object '%s' is not a collection",
00060 coll->getOid().toString());
00061
00062 const Class *coll_class =
00063 coll->getClass()->asCollectionClass()->getCollClass(&isref, &dim);
00064 const char *name = coll_class->getName();
00065
00066 if (isref)
00067 t = oqmlATOM_OID;
00068 else if (dim > 1) {
00069 if (!strcmp(name, char_class_name))
00070 t = oqmlATOM_STRING;
00071 else {
00072 return new oqmlStatus("OQL cannot deal with collection of "
00073 "non basic types");
00074 }
00075 }
00076 else if (!strcmp(name, int32_class_name) ||
00077 !strcmp(name, int16_class_name) ||
00078 !strcmp(name, int64_class_name))
00079 t = oqmlATOM_INT;
00080 else if (!strcmp(name, "char"))
00081 t = oqmlATOM_CHAR;
00082 else if (!strcmp(name, "float"))
00083 t = oqmlATOM_DOUBLE;
00084 else {
00085 t = oqmlATOM_OBJ;
00086 }
00087
00088 return oqmlSuccess;
00089 }
00090
00091 static oqmlStatus *
00092 oqml_coll_eval(oqmlNode *node, Database *db, oqmlContext *ctx,
00093 oqmlAtom *a, oqmlAtomList *rlist, const Class *&cls,
00094 Bool indexed = False)
00095 {
00096 oqmlStatus *s;
00097
00098 if (!a)
00099 return oqmlStatus::expected(node, "oid or object", "nil");
00100
00101 if (!OQML_IS_OBJECT(a))
00102 return oqmlStatus::expected(node, "oid or object", a->type.getString());
00103
00104 Object *o;
00105 s = oqmlObjectManager::getObject(node, db, a, o, oqml_False);
00106 if (s) return s;
00107 if (!o) {
00108 return new oqmlStatus(node, "invalid null object");
00109 }
00110
00111 cls = o->getClass();
00112 if (!cls->asCollectionClass()) {
00113 oqmlObjectManager::releaseObject(o);
00114 return oqmlStatus::expected(node, "collection", o->getClass()->getName());
00115 }
00116
00117 oqmlATOMTYPE t;
00118
00119 s = oqml_check_coll_type((Collection *)o, t);
00120
00121 if (s) {
00122 oqmlObjectManager::releaseObject(o);
00123 return s;
00124 }
00125
00126
00127 #if 1
00128 OQML_CHECK_INTR();
00129 #if 1
00130 Bool is_indexed = (indexed && o->asCollArray() && !ctx->isWhereContext()) ? True : False;
00131 CollectionIterator iter(o->asCollection(), is_indexed);
00132
00133 Value v;
00134 int idx;
00135 for (int n = 0; iter.next(v); n++) {
00136 if (is_indexed && !(n & 1)) {
00137 idx = v.i;
00138 continue;
00139 }
00140
00141 oqmlAtom *x;
00142 Value::Type type = v.getType();
00143 if (type == Value::tOid)
00144 x = new oqmlAtom_oid(*v.oid, (Class *)cls);
00145 else if (type == Value::tObject) {
00146 v.o->trace();
00147 x = oqmlObjectManager::registerObject(v.o->clone());
00148 }
00149 else if (type == Value::tString)
00150 x = new oqmlAtom_string(v.str);
00151 else if (type == Value::tInt)
00152 x = new oqmlAtom_int(v.i);
00153 else if (type == Value::tLong)
00154 x = new oqmlAtom_int(v.l);
00155 else if (type == Value::tChar)
00156 x = new oqmlAtom_char(v.c);
00157 else if (type == Value::tDouble)
00158 x = new oqmlAtom_double(v.d);
00159 else {
00160 oqmlObjectManager::releaseObject(o);
00161 return new oqmlStatus(node, "unsupported value type %s\n",
00162 v.getStringType());
00163 }
00164
00165 if (is_indexed)
00166 rlist->append(oqml_make_struct_array(db, ctx, idx, x));
00167 else
00168 rlist->append(x);
00169 }
00170
00171 #else
00172 ValueArray val_arr;
00173 Status status = o->asCollection()->getElements(val_arr);
00174 if (status) {
00175 oqmlObjectManager::releaseObject(o);
00176 return new oqmlStatus(node, status);
00177 }
00178 OQML_CHECK_INTR();
00179 int count = val_arr.getCount();
00180 for (int n = 0; n < count; n++) {
00181 Value &v = val_arr[n];
00182 Value::Type type = v.getType();
00183 if (type == Value::tOid)
00184 rlist->append(new oqmlAtom_oid(*v.oid, (Class *)cls));
00185 else if (type == Value::tObject)
00186 rlist->append(oqmlObjectManager::registerObject(v.o));
00187 else if (type == Value::tString)
00188 rlist->append(new oqmlAtom_string(v.str));
00189 else if (type == Value::tInt)
00190 rlist->append(new oqmlAtom_int(v.i));
00191 else if (type == Value::tLong)
00192 rlist->append(new oqmlAtom_int(v.l));
00193 else if (type == Value::tChar)
00194 rlist->append(new oqmlAtom_char(v.c));
00195 else if (type == Value::tDouble)
00196 rlist->append(new oqmlAtom_double(v.d));
00197 else {
00198 oqmlObjectManager::releaseObject(o);
00199 return new oqmlStatus(node, "unsupported value type %s\n",
00200 v.getStringType());
00201 }
00202 }
00203 #endif
00204
00205 oqmlObjectManager::releaseObject(o);
00206 return oqmlSuccess;
00207 #else
00208 Iterator *q = new Iterator(o->asCollection(),
00209 (indexed && o->asCollArray() && !ctx->isWhereContext()) ? True : False);
00210
00211 if (q->getStatus()) {
00212 Status s = q->getStatus();
00213 delete q;
00214 return new oqmlStatus(node, s);
00215 }
00216
00217 s = oqml_scan(ctx, q, ((CollectionClass *)
00218 (o->getClass()))->getCollClass(), rlist, t);
00219
00220 oqmlObjectManager::releaseObject(o);
00221 return s;
00222 #endif
00223 }
00224
00225
00226
00227
00228
00229
00230
00231 oqmlCollection::oqmlCollection(oqmlNode *_location, oqml_CollSpec *_coll_spec,
00232 oqmlNode * _ql) : oqmlNode(oqmlCOLLECTION)
00233 {
00234 location = _location;
00235 coll_spec = _coll_spec;
00236 ql = _ql;
00237
00238 if (!location)
00239 eval_type.type = oqmlATOM_OBJ;
00240 else
00241 eval_type.type = oqmlATOM_OID;
00242 }
00243
00244 oqmlCollection::~oqmlCollection()
00245 {
00246 delete coll_spec;
00247 }
00248
00249 oqmlStatus *oqmlCollection::compile(Database *db, oqmlContext *ctx)
00250 {
00251 Bool modify = False;
00252 const char *which = coll_spec->coll_type;
00253
00254 if (!strcmp(which, "set"))
00255 what = collset;
00256 else if (!strcmp(which, "array"))
00257 what = collarray;
00258 else if (!strcmp(which, "bag"))
00259 what = collbag;
00260 else if (!strcmp(which, "list"))
00261 return new oqmlStatus(this, "list collection type '%s' is not yet "
00262 "implemented");
00263 else
00264 return new oqmlStatus(this, "invalid collection type '%s'", which);
00265
00266 const char *type_spec = coll_spec->type_spec;
00267 char *ident = coll_spec->ident;
00268
00269 Bool isref = coll_spec->isref;
00270
00271 Schema *m = db->getSchema();
00272
00273 if (type_spec) {
00274 if (!strcmp(type_spec, "int"))
00275 cls = m->Int32_Class;
00276 else
00277 cls = m->getClass(type_spec);
00278
00279 if (!cls)
00280 return new oqmlStatus(this, "unknown class '%s'",
00281 type_spec);
00282 }
00283
00284 if (coll_spec->coll_spec) {
00285 oqml_CollSpec *cs = coll_spec->coll_spec;
00286 oqml_CollSpec *coll_spec_arr[64];
00287 int coll_spec_cnt = 0;
00288
00289 while (cs) {
00290 coll_spec_arr[coll_spec_cnt++] = cs;
00291 cs = cs->coll_spec;
00292 }
00293
00294 char coll_typname[256];
00295 strcpy(coll_typname, coll_spec_arr[coll_spec_cnt-1]->type_spec);
00296
00297 Class *mcoll = NULL;
00298
00299 for (int i = coll_spec_cnt-1; i >= 0; i--) {
00300 cs = coll_spec_arr[i];
00301 cls = m->getClass(coll_typname);
00302
00303 if (!cls)
00304 return new oqmlStatus(this, "unknown class '%s'",
00305 type_spec);
00306
00307 if (!strcmp(cs->coll_type, "set"))
00308 mcoll = new CollSetClass(cls, (Bool)cs->isref);
00309 else if (!strcmp(cs->coll_type, "bag"))
00310 mcoll = new CollBagClass(cls, (Bool)cs->isref);
00311 else if (!strcmp(cs->coll_type, "array"))
00312 mcoll = new CollArrayClass(cls, (Bool)cs->isref);
00313 else if (!strcmp(cs->coll_type, "list"))
00314 mcoll = new CollListClass(cls, (Bool)cs->isref);
00315 else
00316 return new oqmlStatus(this, "invalid collection type '%s'",
00317 cs->coll_type);
00318
00319 strcpy(coll_typname, mcoll->getName());
00320
00321 if (!m->getClass(mcoll->getName())) {
00322 m->addClass(mcoll);
00323 modify = True;
00324 }
00325 }
00326
00327 cls = mcoll;
00328 }
00329
00330 atref.cls = 0;
00331 atref.comp = oqml_False;
00332
00333 if (isref) {
00334 atref.type = oqmlATOM_OID;
00335 atref.cls = cls;
00336 }
00337 else if (cls->asInt16Class() || cls->asInt32Class() ||
00338 cls->asInt64Class() || cls->asEnumClass())
00339 atref.type = oqmlATOM_INT;
00340 else if (!strcmp(cls->getName(), m->Char_Class->getName())||
00341 !strcmp(cls->getName(), m->Byte_Class->getName()))
00342 atref.type = oqmlATOM_CHAR;
00343 else if (!strcmp(cls->getName(), m->Float_Class->getName()))
00344 atref.type = oqmlATOM_DOUBLE;
00345 else if (!strcmp(cls->getName(), m->OidP_Class->getName()))
00346 atref.type = oqmlATOM_OID;
00347 else {
00348 atref.type = oqmlATOM_OBJ;
00349 atref.cls = cls;
00350 }
00351
00352
00353
00354
00355 oqmlStatus *s = oqml_get_location(db, ctx, location);
00356 if (s) return s;
00357 newdb = db;
00358
00359 return ql ? ql->compile(db, ctx) : oqmlSuccess;
00360 }
00361
00362 oqmlStatus *oqmlCollection::eval(Database *db, oqmlContext *ctx, oqmlAtomList **alist, oqmlComp *, oqmlAtom *)
00363 {
00364 oqmlStatus *s;
00365 Collection *coll = 0;
00366
00367 db = newdb;
00368
00369 char *ident = coll_spec->ident;
00370 Bool isref = coll_spec->isref;
00371
00372 IndexImpl *idximpl = 0;
00373 if (coll_spec->impl_hints) {
00374 Status status = IndexImpl::make(db, coll_spec->ishash ?
00375 IndexImpl::Hash :
00376 IndexImpl::BTree,
00377 coll_spec->impl_hints, idximpl);
00378 if (status) return new oqmlStatus(this, status);
00379 }
00380
00381 if (what == collset)
00382 coll = new CollSet(ident, cls, isref, idximpl);
00383 else if (what == collbag)
00384 coll = new CollBag(ident, cls, isref, idximpl);
00385 else if (what == collarray)
00386 coll = new CollArray(ident, cls, isref, idximpl);
00387
00388
00389
00390
00391
00392 if (!coll)
00393 return new oqmlStatus(this, "internal error in collection create");
00394
00395 Status status = coll->setDatabase(db);
00396 if (status) {
00397 coll->release();
00398 return new oqmlStatus(this, status);
00399 }
00400
00401 if (!ql) {
00402 if (!location) {
00403 *alist = new oqmlAtomList(oqmlObjectManager::registerObject(coll));
00404 return oqmlSuccess;
00405 }
00406
00407 Status is = coll->realize();
00408
00409 if (is) {
00410 coll->release();
00411 return new oqmlStatus(this, is);
00412 }
00413
00414 *alist = new oqmlAtomList(new oqmlAtom_oid(coll->getOid()));
00415
00416 coll->release();
00417 return oqmlSuccess;
00418 }
00419
00420 Status is;
00421 int ii = 0;
00422
00423 oqmlAtomList *al;
00424 s = ql->eval(db, ctx, &al);
00425 if (s) return s;
00426
00427 if (!al->cnt)
00428 return oqmlStatus::expected(this, "atom list", "nil");
00429
00430 oqmlAtom *a = al->first;
00431
00432 if (OQML_IS_COLL(a))
00433 a = OQML_ATOM_COLLVAL(a)->first;
00434
00435
00436
00437
00438
00439 while (a) {
00440 oqmlAtom *next = a->next;
00441
00442 if (!atref.cmp(a->type)) {
00443 coll->release();
00444 return oqmlStatus::expected(this, &atref, &a->type);
00445 }
00446
00447 if (isref) {
00448 if (what == collarray)
00449 is = coll->asCollArray()->insertAt(ii, ((oqmlAtom_oid *)a)->oid);
00450 else
00451 is = coll->insert(((oqmlAtom_oid *)a)->oid);
00452 }
00453 else if (a->type.type == oqmlATOM_OBJ) {
00454 OQL_CHECK_OBJ(a);
00455 if (what == collarray)
00456 is = coll->asCollArray()->insertAt(ii, OQML_ATOM_OBJVAL(a));
00457 else
00458 is = coll->insert(OQML_ATOM_OBJVAL(a));
00459 }
00460 else {
00461 Data val;
00462 unsigned char buff[16];
00463 Size size;
00464 int len;
00465
00466 size = sizeof(buff);
00467 if (a->getData(buff, &val, size, len, cls)) {
00468 Data data = (val ? val : buff);
00469 if (what == collarray)
00470 is = coll->asCollArray()->insertAt_p(ii, data, size);
00471 else
00472 is = coll->insert_p(data, False, size);
00473 }
00474 else
00475 is = Success;
00476 }
00477
00478 if (is) {
00479 coll->release();
00480 return new oqmlStatus(this, is);
00481 }
00482 a = next;
00483 ii++;
00484 }
00485
00486 if (!location) {
00487 *alist = new oqmlAtomList(oqmlObjectManager::registerObject(coll));
00488 return oqmlSuccess;
00489 }
00490
00491 is = coll->realize();
00492
00493 if (is) {
00494 coll->release();
00495 return new oqmlStatus(this, is);
00496 }
00497
00498 *alist = new oqmlAtomList(new oqmlAtom_oid(coll->getOid()));
00499
00500 coll->release();
00501
00502 return oqmlSuccess;
00503 }
00504
00505 void oqmlCollection::evalType(Database *db, oqmlContext *ctx, oqmlAtomType *at)
00506 {
00507 *at = eval_type;
00508 }
00509
00510 oqmlBool oqmlCollection::isConstant() const
00511 {
00512 return oqml_False;
00513 }
00514
00515 void
00516 oqmlCollection::lock()
00517 {
00518 oqmlNode::lock();
00519 if (ql) ql->lock();
00520 if (location) location->lock();
00521 }
00522
00523 void
00524 oqmlCollection::unlock()
00525 {
00526 oqmlNode::unlock();
00527 if (ql) ql->unlock();
00528 if (location) location->unlock();
00529 }
00530
00531 std::string
00532 oqmlCollection::toString(void) const
00533 {
00534 if (is_statement)
00535 return std::string("new ") + coll_spec->toString() + "(" +
00536 (ql ? ql->toString() : std::string("")) + "); ";
00537
00538 return std::string("(new ") + coll_spec->toString() + "(" +
00539 (ql ? ql->toString() : std::string("")) + "))";
00540 }
00541
00542
00543
00544
00545
00546
00547
00548 oqmlContents::oqmlContents(oqmlNode * _ql) : oqmlNode(oqmlCONTENTS)
00549 {
00550 ql = _ql;
00551 }
00552
00553 oqmlContents::~oqmlContents()
00554 {
00555 }
00556
00557 oqmlStatus *oqmlContents::compile(Database *db, oqmlContext *ctx)
00558 {
00559 oqmlStatus *s;
00560 s = ql->compile(db, ctx);
00561
00562 if (s)
00563 return s;
00564
00565 return oqmlSuccess;
00566 }
00567
00568 oqmlAtom *
00569 oqml_make_struct_array(Database *db, oqmlContext *ctx, int idx, oqmlAtom *x)
00570 {
00571 if (ctx->isWhereContext())
00572 return x;
00573 oqml_StructAttr *attrs = new oqml_StructAttr[2];
00574 attrs[0].set("index", new oqmlAtom_int(idx));
00575 attrs[1].set("value", x);
00576 return new oqmlAtom_struct(attrs, 2);
00577 }
00578
00579 static oqmlAtom *
00580 make_array_set(Database *db, oqmlContext *ctx, oqmlAtomList *list)
00581 {
00582 if (ctx->isWhereContext())
00583 return new oqmlAtom_set(list);
00584
00585 oqmlAtomList *rlist = new oqmlAtomList();
00586 oqmlAtom *x = list->first;
00587
00588 int idx;
00589 for (int n = 0; x; n++)
00590 {
00591 oqmlAtom *next = x->next;
00592 if (!(n & 1))
00593 idx = OQML_ATOM_INTVAL(x);
00594 else
00595 rlist->append(oqml_make_struct_array(db, ctx, idx, x));
00596
00597 x = next;
00598 }
00599
00600 return new oqmlAtom_set(rlist);
00601 }
00602
00603 oqmlStatus *oqmlContents::eval(Database *db, oqmlContext *ctx,
00604 oqmlAtomList **alist, oqmlComp *, oqmlAtom *)
00605 {
00606 oqmlStatus *s;
00607 oqmlAtomList *al;
00608
00609 s = ql->eval(db, ctx, &al);
00610
00611 if (s) return s;
00612
00613 oqmlAtomList *rlist = new oqmlAtomList();
00614
00615 if (!al->first)
00616 {
00617 *alist = new oqmlAtomList();
00618 return oqmlSuccess;
00619 }
00620
00621 const Class *cls;
00622 s = oqml_coll_eval(this, db, ctx, al->first, rlist, cls, True);
00623
00624 if (s) return s;
00625
00626 if (cls->asCollSetClass())
00627 *alist = new oqmlAtomList(new oqmlAtom_set(rlist, oqml_False));
00628
00629 else if (cls->asCollArrayClass())
00630
00631 *alist = new oqmlAtomList(new oqmlAtom_set(rlist));
00632 else if (cls->asCollBagClass())
00633 *alist = new oqmlAtomList(new oqmlAtom_bag(rlist));
00634 else if (cls->asCollListClass())
00635 *alist = new oqmlAtomList(new oqmlAtom_list(rlist));
00636 else
00637 *alist = new oqmlAtomList(new oqmlAtom_list(rlist));
00638 return oqmlSuccess;
00639 }
00640
00641 void oqmlContents::evalType(Database *db, oqmlContext *ctx, oqmlAtomType *at)
00642 {
00643 *at = eval_type;
00644 }
00645
00646 oqmlBool oqmlContents::isConstant() const
00647 {
00648 return OQMLBOOL(ql->isConstant());
00649 }
00650
00651 std::string
00652 oqmlContents::toString(void) const
00653 {
00654 if (is_statement)
00655 return std::string("contents ") + ql->toString() + "; ";
00656 return std::string("(contents ") + ql->toString() + ")";
00657 }
00658
00659
00660
00661
00662
00663
00664
00665 oqmlIn::oqmlIn(oqmlNode * _qleft, oqmlNode * _qright) : oqmlNode(oqmlIN)
00666 {
00667 qleft = _qleft;
00668 qright = _qright;
00669 eval_type.type = oqmlATOM_BOOL;
00670 evalDone = oqml_False;
00671 }
00672
00673 oqmlIn::~oqmlIn()
00674 {
00675 }
00676
00677 oqmlStatus *oqmlIn::compile(Database *db, oqmlContext *ctx)
00678 {
00679 evalDone = oqml_False;
00680 oqmlStatus *s;
00681 s = qleft->compile(db, ctx);
00682
00683 if (s) return s;
00684
00685 return qright->compile(db, ctx);
00686 }
00687
00688 static oqmlStatus *
00689 check_coll(oqmlNode *node, Database *db, oqmlAtom *aleft,
00690 Collection *&coll, oqmlATOMTYPE &t)
00691 {
00692 if (!OQML_IS_OBJECT(aleft))
00693 return oqmlStatus::expected(node, "oid or object", aleft->type.getString());
00694
00695 oqmlStatus *s;
00696 s = oqmlObjectManager::getObject(node, db, aleft, (Object *&)coll,
00697 oqml_False);
00698
00699 if (s) return s;
00700
00701 if (!coll->getClass()->asCollectionClass())
00702 {
00703 oqmlObjectManager::releaseObject(coll);
00704 return oqmlStatus::expected(node, "collection", coll->getClass()->getName());
00705 }
00706
00707 s = oqml_check_coll_type(coll, t);
00708
00709 if (s)
00710 {
00711 oqmlObjectManager::releaseObject(coll);
00712 return s;
00713 }
00714
00715 return oqmlSuccess;
00716 }
00717
00718 static oqmlStatus *
00719 coll_perform(oqmlNode *node, Database *db, oqmlContext *ctx,
00720 oqmlAtomList **alist,
00721 oqmlNode *qleft, oqmlNode *qright,
00722 oqmlStatus *(*perform)(oqmlNode *,Collection *, const Oid *,
00723 Data, int, oqmlAtom *,
00724 oqmlAtomList *, oqmlAtomList *),
00725 oqmlBool write)
00726 {
00727 oqmlStatus *s;
00728 oqmlAtomList *al_left, *al_right;
00729
00730 *alist = new oqmlAtomList();
00731
00732 s = qleft->eval(db, ctx, &al_left);
00733 if (s) return s;
00734
00735 oqmlAtom *aleft = al_left->first;
00736 if (!aleft)
00737 return new oqmlStatus(node, "invalid nil atom: %s",
00738 qleft->toString().c_str());
00739
00740 if (qright) {
00741 s = qright->eval(db, ctx, &al_right);
00742 if (s) return s;
00743 }
00744
00745 #if 0
00746 if (perform == append_perform) {
00747 printf("aleft %p aright %p\n", al_left, al_right);
00748 printf("aleft first %p aright %p\n", al_left->first, al_right->first);
00749 printf("copying %p %d\n", al_right->first, aleft->as_coll());
00750 al_right = al_right->copy();
00751 printf("after copying %p\n", al_right->first);
00752
00753
00754
00755
00756
00757
00758 }
00759 #endif
00760
00761 oqmlAtom *aright = (qright ? al_right->first : 0);
00762
00763 if (aleft->as_coll())
00764 return (*perform)(node, 0, 0, 0, 0, aright, aleft->as_coll()->list, *alist);
00765
00766 Collection *coll = 0;
00767 oqmlATOMTYPE t;
00768
00769 s = check_coll(node, db, aleft, coll, t);
00770 if (s) return s;
00771
00772 if (!qright)
00773 {
00774 s = (*perform)(node, coll, 0, 0, 0, 0, 0, *alist);
00775 if (s)
00776 {
00777 oqmlObjectManager::releaseObject(coll);
00778 return s;
00779 }
00780
00781 return oqmlSuccess;
00782 }
00783
00784 if (aright->type.type != t &&
00785 !(aright->as_null() && t == oqmlATOM_OID))
00786 {
00787 oqmlObjectManager::releaseObject(coll);
00788 return oqmlStatus::expected(node, "oid",
00789 aright->type.getString());
00790 }
00791
00792 Status status = Success;
00793
00794 if (t == oqmlATOM_OID)
00795 {
00796 Oid oid;
00797 if (!aright->as_null())
00798 oid = OQML_ATOM_OIDVAL(aright);
00799
00800 s = (*perform)(node, coll, &oid, 0, 0,
00801 aright, 0, *alist);
00802 if (s)
00803 {
00804 oqmlObjectManager::releaseObject(coll);
00805 return s;
00806 }
00807
00808 if (write)
00809 status = coll->realize();
00810
00811 oqmlObjectManager::releaseObject(coll);
00812
00813 if (status)
00814 return new oqmlStatus(node, status);
00815
00816 return oqmlSuccess;
00817 }
00818
00819 Data val;
00820 unsigned char buff[16];
00821 Size size;
00822 int len;
00823
00824 size = sizeof(buff);
00825 oqmlAtomType *at = &aleft->type;
00826 if (aright->getData(buff, &val, size, len, at->cls))
00827 {
00828 s = (*perform)(node, coll, 0, (val ? val : buff), size,
00829 aright, 0, *alist);
00830
00831 if (s)
00832 {
00833 oqmlObjectManager::releaseObject(coll);
00834 return s;
00835 }
00836 }
00837
00838 if (write)
00839 status = coll->realize();
00840
00841 oqmlObjectManager::releaseObject(coll);
00842
00843 if (status)
00844 return new oqmlStatus(node, status);
00845
00846 return oqmlSuccess;
00847 }
00848
00849 static oqmlStatus *
00850 in_perform(oqmlNode *node, Collection *coll, const Oid *oid,
00851 Data data, int size,
00852 oqmlAtom *atom, oqmlAtomList *atom_coll, oqmlAtomList *alist)
00853 {
00854 Status status;
00855
00856 if (coll)
00857 {
00858 Bool is;
00859
00860 if (oid)
00861 status = coll->isIn(*oid, is);
00862 else
00863 status = coll->isIn_p(data, is);
00864
00865 if (status)
00866 return new oqmlStatus(node, status);
00867
00868 alist->append(new oqmlAtom_bool(OQMLBOOL(is)));
00869 return oqmlSuccess;
00870 }
00871
00872 alist->append(new oqmlAtom_bool(atom_coll->isIn(atom)));
00873 return oqmlSuccess;
00874 }
00875
00876 oqmlStatus *oqmlIn::eval(Database *db, oqmlContext *ctx, oqmlAtomList **alist, oqmlComp *, oqmlAtom *)
00877 {
00878 if (evalDone)
00879 {
00880 *alist = new oqmlAtomList(new oqmlAtom_bool(oqml_True));
00881 return oqmlSuccess;
00882 }
00883
00884 return coll_perform(this, db, ctx, alist, qright, qleft, in_perform, oqml_False);
00885 }
00886
00887 void oqmlIn::evalType(Database *db, oqmlContext *ctx, oqmlAtomType *at)
00888 {
00889 *at = eval_type;
00890 }
00891
00892 oqmlBool oqmlIn::isConstant() const
00893 {
00894 return oqml_False;
00895 }
00896
00897 oqmlBool
00898 oqmlIn::hasDotIdent(const char *_ident)
00899 {
00900 if (qleft->asDot())
00901 return qleft->hasIdent(_ident);
00902 return oqml_False;
00903 }
00904
00905 static oqmlNode *
00906 get_invalid_node()
00907 {
00908 return (new oqmlAtom_oid("0:0:1:oid"))->toNode();
00909 }
00910
00911 oqmlStatus *
00912 oqmlIn::preEvalSelect(Database *db, oqmlContext *ctx,
00913 const char *ident, oqmlBool &done,
00914 unsigned int &cnt, oqmlBool firstPass)
00915 {
00916 done = oqml_False;
00917 cnt = 0;
00918
00919 if (!hasDotIdent(ident))
00920 return oqmlSuccess;
00921
00922 oqmlAtomList *alist;
00923 oqmlStatus *s = qright->eval(db, ctx, &alist);
00924 if (s) return s;
00925
00926 oqmlAtomList *list;
00927
00928 if (!alist->cnt)
00929 list = 0;
00930 else if (alist->first->as_coll())
00931 list = alist->first->as_coll()->list;
00932 else
00933 list = alist;
00934
00935 if (!list || list->cnt <= 1)
00936 {
00937 oqmlNode *node = new oqmlEqual
00938 (qleft, (list && list->first ? list->first->toNode() :
00939 get_invalid_node()));
00940 s = node->compile(db, ctx);
00941 if (s) return s;
00942 s = node->eval(db, ctx, &alist);
00943 if (!s)
00944 {
00945 done = oqml_True;
00946 evalDone = oqml_True;
00947 }
00948 return s;
00949 }
00950
00951 oqmlAtom *x = list->first;
00952 if (x)
00953 {
00954 oqmlNode *nodeOr = new oqmlEqual(qleft, x->toNode());
00955
00956 x = x->next;
00957 while (x)
00958 {
00959 nodeOr = new oqmlLOr
00960 (nodeOr, new oqmlEqual(qleft, x->toNode()), oqml_False);
00961 x = x->next;
00962 }
00963
00964 s = nodeOr->preEvalSelect(db, ctx, ident, done, cnt, firstPass);
00965 }
00966
00967 if (!s)
00968 evalDone = oqml_True;
00969 return s;
00970 }
00971
00972 std::string
00973 oqmlIn::toString(void) const
00974 {
00975 if (is_statement)
00976 return std::string("") + qleft->toString() + " in " +
00977 qright->toString() + "; ";
00978 return std::string("(") + qleft->toString() + " in " +
00979 qright->toString() + ")";
00980 }
00981
00982
00983
00984
00985
00986
00987
00988 oqmlAddTo::oqmlAddTo(oqmlNode * _qleft, oqmlNode * _qright) : oqmlNode(oqmlADDTO)
00989 {
00990 qleft = _qleft;
00991 qright = _qright;
00992 }
00993
00994 oqmlAddTo::~oqmlAddTo()
00995 {
00996 }
00997
00998 oqmlStatus *oqmlAddTo::compile(Database *db, oqmlContext *ctx)
00999 {
01000 oqmlStatus *s;
01001 s = qleft->compile(db, ctx);
01002
01003 if (s)
01004 return s;
01005
01006 s = qright->compile(db, ctx);
01007
01008 if (s)
01009 return s;
01010
01011 return oqmlSuccess;
01012 }
01013
01014 static oqmlStatus *
01015 insert_perform(oqmlNode *node, Collection *coll, const Oid *oid,
01016 Data data, int size, oqmlAtom *a, oqmlAtomList *atom_coll,
01017 oqmlAtomList *alist)
01018 {
01019 if (coll)
01020 {
01021 Status status;
01022 if (oid)
01023 status = coll->insert(*oid);
01024 else
01025 status = coll->insert_p(data, False, size);
01026
01027 if (status)
01028 return new oqmlStatus(node, status);
01029
01030 alist->append(a->copy());
01031 return oqmlSuccess;
01032 }
01033
01034 oqmlAtom *x = a->copy();
01035 atom_coll->append(x);
01036 alist->append(x);
01037 return oqmlSuccess;
01038 }
01039
01040 oqmlStatus *oqmlAddTo::eval(Database *db, oqmlContext *ctx, oqmlAtomList **alist, oqmlComp *, oqmlAtom *)
01041 {
01042 return coll_perform(this, db, ctx, alist, qright, qleft, insert_perform, oqml_True);
01043 }
01044
01045 void oqmlAddTo::evalType(Database *db, oqmlContext *ctx, oqmlAtomType *at)
01046 {
01047 *at = eval_type;
01048 }
01049
01050 oqmlBool oqmlAddTo::isConstant() const
01051 {
01052 return oqml_False;
01053 }
01054
01055 std::string
01056 oqmlAddTo::toString(void) const
01057 {
01058 if (is_statement)
01059 return std::string("add ") + qleft->toString() + " to " +
01060 qright->toString() + "; ";
01061 return std::string("(add ") + qleft->toString() + " to " +
01062 qright->toString() + ")";
01063 }
01064
01065
01066
01067
01068
01069
01070
01071 oqmlSuppressFrom::oqmlSuppressFrom(oqmlNode * _qleft, oqmlNode * _qright) : oqmlNode(oqmlSUPPRESSFROM)
01072 {
01073 qleft = _qleft;
01074 qright = _qright;
01075 }
01076
01077 oqmlSuppressFrom::~oqmlSuppressFrom()
01078 {
01079 }
01080
01081 oqmlStatus *oqmlSuppressFrom::compile(Database *db, oqmlContext *ctx)
01082 {
01083 oqmlStatus *s;
01084 s = qleft->compile(db, ctx);
01085
01086 if (s)
01087 return s;
01088
01089 s = qright->compile(db, ctx);
01090
01091 if (s)
01092 return s;
01093
01094 return oqmlSuccess;
01095 }
01096
01097 static oqmlStatus *
01098 suppress_perform(oqmlNode *node, Collection *coll, const Oid *oid,
01099 Data data, int size, oqmlAtom *a,
01100 oqmlAtomList *atom_coll, oqmlAtomList *alist)
01101 {
01102 if (coll)
01103 {
01104 Status status;
01105 if (oid)
01106 status = coll->suppress(*oid);
01107 else
01108 status = coll->suppress_p(data);
01109
01110 if (status)
01111 return new oqmlStatus(node, status);
01112
01113 alist->append(a->copy());
01114 return oqmlSuccess;
01115 }
01116
01117 oqmlStatus *s = atom_coll->suppress(a);
01118 if (s) return s;
01119 alist->append(a->copy());
01120 return oqmlSuccess;
01121 }
01122
01123 oqmlStatus *oqmlSuppressFrom::eval(Database *db, oqmlContext *ctx, oqmlAtomList **alist, oqmlComp *, oqmlAtom *)
01124 {
01125 return coll_perform(this, db, ctx, alist, qright, qleft, suppress_perform, oqml_True);
01126 }
01127
01128 void oqmlSuppressFrom::evalType(Database *db, oqmlContext *ctx, oqmlAtomType *at)
01129 {
01130 *at = eval_type;
01131 }
01132
01133 oqmlBool oqmlSuppressFrom::isConstant() const
01134 {
01135 return oqml_False;
01136 }
01137
01138 std::string
01139 oqmlSuppressFrom::toString(void) const
01140 {
01141 if (is_statement)
01142 return std::string("suppress ") + qleft->toString() + " from " +
01143 qright->toString() + "; ";
01144 return std::string("(suppress ") + qleft->toString() + " from " +
01145 qright->toString() + ")";
01146 }
01147
01148
01149
01150
01151
01152
01153
01154 oqmlAppend::oqmlAppend(oqmlNode * _qleft, oqmlNode * _qright) : oqmlNode(oqmlAPPEND)
01155 {
01156 qleft = _qleft;
01157 qright = _qright;
01158 }
01159
01160 oqmlAppend::~oqmlAppend()
01161 {
01162 }
01163
01164 oqmlStatus *oqmlAppend::compile(Database *db, oqmlContext *ctx)
01165 {
01166 oqmlStatus *s;
01167 s = qleft->compile(db, ctx);
01168
01169 if (s)
01170 return s;
01171
01172 s = qright->compile(db, ctx);
01173
01174 if (s)
01175 return s;
01176
01177 return oqmlSuccess;
01178 }
01179
01180 static oqmlStatus *
01181 append_perform(oqmlNode *node, Collection *coll, const Oid *oid,
01182 Data data, int size, oqmlAtom *a,
01183 oqmlAtomList *atom_coll, oqmlAtomList *alist)
01184 {
01185 if (coll) {
01186 if (!coll->asCollArray())
01187 return new oqmlStatus(node, "cannot append to a non-array collection");
01188 Status status;
01189 if (oid)
01190 status = coll->asCollArray()->append(*oid);
01191 else
01192 status = coll->asCollArray()->append_p(data, False, size);
01193
01194 if (status)
01195 return new oqmlStatus(node, status);
01196 return oqmlSuccess;
01197 }
01198
01199 oqmlAtom *x = a->copy();
01200 if (atom_coll->append(x, true, x->as_coll() ? true : false))
01201 return new oqmlStatus(node, "collection cycle detected");
01202
01203 alist->append(x);
01204 return oqmlSuccess;
01205 }
01206
01207 oqmlStatus *oqmlAppend::eval(Database *db, oqmlContext *ctx, oqmlAtomList **alist, oqmlComp *, oqmlAtom *)
01208 {
01209 return coll_perform(this, db, ctx, alist, qright, qleft, append_perform, oqml_True);
01210 }
01211
01212 void oqmlAppend::evalType(Database *db, oqmlContext *ctx, oqmlAtomType *at)
01213 {
01214 *at = eval_type;
01215 }
01216
01217 oqmlBool oqmlAppend::isConstant() const
01218 {
01219 return oqml_False;
01220 }
01221
01222 std::string
01223 oqmlAppend::toString(void) const
01224 {
01225 if (is_statement)
01226 return std::string("append ") + qleft->toString() + " to " +
01227 qright->toString() + "; ";
01228 return std::string("(append ") + qleft->toString() + " to " +
01229 qright->toString() + ")";
01230 }
01231
01232
01233
01234
01235
01236
01237
01238 oqmlEmpty::oqmlEmpty(oqmlNode * _ql) : oqmlNode(oqmlEMPTY)
01239 {
01240 ql = _ql;
01241 }
01242
01243 oqmlEmpty::~oqmlEmpty()
01244 {
01245 }
01246
01247 oqmlStatus *oqmlEmpty::compile(Database *db, oqmlContext *ctx)
01248 {
01249 oqmlStatus *s;
01250 s = ql->compile(db, ctx);
01251
01252 if (s)
01253 return s;
01254
01255 return oqmlSuccess;
01256 }
01257
01258 static oqmlStatus *
01259 empty_perform(oqmlNode *node, Collection *coll, const Oid *,
01260 Data, int, oqmlAtom *, oqmlAtomList *atom_coll,
01261 oqmlAtomList *alist)
01262 {
01263 if (coll)
01264 {
01265 Status status;
01266 status = coll->empty();
01267
01268 if (status)
01269 return new oqmlStatus(node, status);
01270 return oqmlSuccess;
01271 }
01272
01273 atom_coll->empty();
01274 return oqmlSuccess;
01275 }
01276
01277 oqmlStatus *oqmlEmpty::eval(Database *db, oqmlContext *ctx, oqmlAtomList **alist, oqmlComp *, oqmlAtom *)
01278 {
01279 return coll_perform(this, db, ctx, alist, ql, 0, empty_perform, oqml_True);
01280 }
01281
01282 void oqmlEmpty::evalType(Database *db, oqmlContext *ctx, oqmlAtomType *at)
01283 {
01284 *at = eval_type;
01285 }
01286
01287 oqmlBool oqmlEmpty::isConstant() const
01288 {
01289 return oqml_False;
01290 }
01291
01292 std::string
01293 oqmlEmpty::toString(void) const
01294 {
01295 if (is_statement)
01296 return std::string("empty ") + ql->toString() + "; ";
01297 return std::string("(empty ") + ql->toString() + ")";
01298 }
01299
01300
01301
01302
01303
01304
01305
01306 oqmlSetInAt::oqmlSetInAt(oqmlNode * _qleft, oqmlNode *_qright, oqmlNode *_ql3) : oqmlNode(oqmlSETINAT)
01307 {
01308 qleft = _qleft;
01309 qright = _qright;
01310 ql3 = _ql3;
01311 }
01312
01313 oqmlSetInAt::~oqmlSetInAt()
01314 {
01315 }
01316
01317 oqmlStatus *oqmlSetInAt::compile(Database *db, oqmlContext *ctx)
01318 {
01319 oqmlStatus *s;
01320
01321 s = qleft->compile(db, ctx);
01322
01323 if (s)
01324 return s;
01325
01326 s = qright->compile(db, ctx);
01327
01328 if (s)
01329 return s;
01330
01331 s = ql3->compile(db, ctx);
01332
01333 if (s)
01334 return s;
01335
01336 return oqmlSuccess;
01337 }
01338
01339 oqmlStatus *oqmlSetInAt::eval(Database *db, oqmlContext *ctx, oqmlAtomList **alist, oqmlComp *, oqmlAtom *)
01340 {
01341 oqmlAtomList *al_left, *al_right, *al3;
01342 oqmlStatus *s;
01343
01344 *alist = new oqmlAtomList();
01345
01346 s = qleft->eval(db, ctx, &al_left);
01347
01348 if (s)
01349 return s;
01350
01351 s = qright->eval(db, ctx, &al_right);
01352
01353 if (s)
01354 return s;
01355
01356 s = ql3->eval(db, ctx, &al3);
01357
01358 if (s)
01359 return s;
01360
01361 oqmlAtom *array = al3->first;
01362
01363 while (array)
01364 {
01365 Status is;
01366 if (!OQML_IS_OBJECT(array))
01367 return oqmlStatus::expected(this, "oid or object",
01368 array->type.getString());
01369
01370 Object *o;
01371 s = oqmlObjectManager::getObject(this, db, array, o, oqml_False);
01372 if (s) return s;
01373 if (!o->getClass()->asCollArrayClass())
01374 {
01375 oqmlObjectManager::releaseObject(o);
01376 return oqmlStatus::expected(this, "array",
01377 o->getClass()->getName());
01378 }
01379
01380 CollArray *arr = (CollArray *)o;
01381 oqmlAtom *aind = al_left->first;
01382
01383 oqmlATOMTYPE t;
01384 oqml_check_coll_type(arr, t);
01385
01386 while(aind)
01387 {
01388 oqmlAtom *nextaind = aind->next;
01389 if (aind->type.type != oqmlATOM_INT)
01390 return oqmlStatus::expected(this, "integer",
01391 aind->type.getString());
01392
01393 oqmlAtom *e = al_right->first;
01394 while (e)
01395 {
01396 oqmlAtom *nexte = e->next;
01397 if (t == oqmlATOM_OID)
01398 {
01399 if (e->type.type != oqmlATOM_OID)
01400 return oqmlStatus::expected(this, "oid",
01401 e->type.getString());
01402
01403 is = arr->insertAt(((oqmlAtom_int *)aind)->i, ((oqmlAtom_oid *)e)->oid);
01404 if (is)
01405 return new oqmlStatus(this, is);
01406 }
01407 else
01408 {
01409 Data val = 0;
01410 unsigned char buff[16];
01411 Size size;
01412 int len;
01413
01414 size = sizeof(buff);
01415 if (e->getData(buff, &val, size, len))
01416 {
01417 is = arr->insertAt_p(((oqmlAtom_int *)aind)->i, (val ? val : buff));
01418 if (is)
01419 return new oqmlStatus(this, is);
01420 }
01421 }
01422
01423 (*alist)->append(e->copy());
01424 e = nexte;
01425 }
01426 aind = nextaind;
01427 }
01428
01429 is = arr->realize();
01430 if (is)
01431 return new oqmlStatus(this, is);
01432
01433 oqmlObjectManager::releaseObject(o);
01434 array = array->next;
01435 }
01436
01437 return oqmlSuccess;
01438 }
01439
01440 void oqmlSetInAt::evalType(Database *db, oqmlContext *ctx, oqmlAtomType *at)
01441 {
01442 *at = eval_type;
01443 }
01444
01445 oqmlBool oqmlSetInAt::isConstant() const
01446 {
01447 return oqml_False;
01448 }
01449
01450 std::string
01451 oqmlSetInAt::toString(void) const
01452 {
01453 if (is_statement)
01454 return std::string("set ") + qleft->toString() + " in " +
01455 ql3->toString() + " at " + qright->toString() + "; ";
01456 return std::string("(set ") + qleft->toString() + " in " +
01457 ql3->toString() + " at " + qright->toString() + ")";
01458 }
01459
01460
01461
01462
01463
01464
01465
01466 oqmlUnsetInAt::oqmlUnsetInAt(oqmlNode * _qleft, oqmlNode *_qright) : oqmlNode(oqmlUNSETINAT)
01467 {
01468 qleft = _qleft;
01469 qright = _qright;
01470 }
01471
01472 oqmlUnsetInAt::~oqmlUnsetInAt()
01473 {
01474 }
01475
01476 oqmlStatus *oqmlUnsetInAt::compile(Database *db, oqmlContext *ctx)
01477 {
01478 oqmlStatus *s;
01479
01480 s = qleft->compile(db, ctx);
01481
01482 if (s)
01483 return s;
01484
01485 s = qright->compile(db, ctx);
01486
01487 if (s) return s;
01488
01489 return oqmlSuccess;
01490 }
01491
01492 oqmlStatus *oqmlUnsetInAt::eval(Database *db, oqmlContext *ctx, oqmlAtomList **alist, oqmlComp *, oqmlAtom *)
01493 {
01494 oqmlAtomList *al_left, *al_right;
01495 oqmlStatus *s;
01496
01497 *alist = new oqmlAtomList();
01498
01499 s = qleft->eval(db, ctx, &al_left);
01500
01501 if (s) return s;
01502
01503 s = qright->eval(db, ctx, &al_right);
01504
01505 if (s) return s;
01506
01507 oqmlAtom *array = al_right->first;
01508
01509 while (array)
01510 {
01511 Status is;
01512 if (!OQML_IS_OBJECT(array))
01513 return oqmlStatus::expected(this, "oid or object",
01514 array->type.getString());
01515
01516 Object *o;
01517 s = oqmlObjectManager::getObject(this, db, array, o, oqml_False);
01518 if (s) return s;
01519 if (!o->getClass()->asCollArrayClass())
01520 {
01521 oqmlObjectManager::releaseObject(o);
01522 return oqmlStatus::expected(this, "array",
01523 o->getClass()->getName());
01524 }
01525
01526 CollArray *arr = (CollArray *)o;
01527 oqmlAtom *aind = al_left->first;
01528
01529 while(aind)
01530 {
01531 if (aind->type.type != oqmlATOM_INT)
01532 return oqmlStatus::expected(this, "integer",
01533 aind->type.getString());
01534
01535 is = arr->suppressAt(((oqmlAtom_int *)aind)->i);
01536 if (is)
01537 return new oqmlStatus(this, is);
01538
01539 aind = aind->next;
01540 }
01541
01542 is = arr->realize();
01543 if (is)
01544 return new oqmlStatus(this, is);
01545
01546 oqmlObjectManager::releaseObject(o);
01547 array = array->next;
01548 }
01549
01550 return oqmlSuccess;
01551 }
01552
01553 void oqmlUnsetInAt::evalType(Database *db, oqmlContext *ctx, oqmlAtomType *at)
01554 {
01555 *at = eval_type;
01556 }
01557
01558 oqmlBool oqmlUnsetInAt::isConstant() const
01559 {
01560 return oqml_False;
01561 }
01562
01563 std::string
01564 oqmlUnsetInAt::toString(void) const
01565 {
01566 if (is_statement)
01567 return std::string("unset in ") + qright->toString() + " at " +
01568 qleft->toString() + "; ";
01569
01570 return std::string("(unset in ") + qleft->toString() + " at " +
01571 qleft->toString() + ")";
01572 }
01573
01574
01575
01576
01577
01578
01579
01580 oqmlElement::oqmlElement(oqmlNode * _ql) : oqmlNode(oqmlELEMENT)
01581 {
01582 ql = _ql;
01583 }
01584
01585 oqmlElement::~oqmlElement()
01586 {
01587 }
01588
01589 oqmlStatus *oqmlElement::compile(Database *db, oqmlContext *ctx)
01590 {
01591 return ql->compile(db, ctx);
01592 }
01593
01594 oqmlStatus *oqmlElement::eval(Database *db, oqmlContext *ctx, oqmlAtomList **alist, oqmlComp *, oqmlAtom *)
01595 {
01596 oqmlAtomList *al;
01597 oqmlStatus *s;
01598
01599 s = ql->eval(db, ctx, &al);
01600
01601 if (s) return s;
01602
01603 if (!al->cnt || !OQML_IS_COLL(al->first))
01604 return oqmlStatus::expected(this, "collection",
01605 (al->first ? al->first->type.getString() :
01606 "nil"));
01607
01608 int cnt = OQML_ATOM_COLLVAL(al->first)->cnt;
01609 if (cnt != 1)
01610 return new oqmlStatus(this, "expected collection with one and "
01611 "only one element, got %d element%s",
01612 cnt, cnt != 1 ? "s" : "");
01613
01614 *alist = new oqmlAtomList(OQML_ATOM_COLLVAL(al->first)->first);
01615 return oqmlSuccess;
01616 }
01617
01618 void oqmlElement::evalType(Database *db, oqmlContext *ctx, oqmlAtomType *at)
01619 {
01620 *at = eval_type;
01621 }
01622
01623 oqmlBool oqmlElement::isConstant() const
01624 {
01625 return oqml_False;
01626 }
01627
01628 std::string
01629 oqmlElement::toString(void) const
01630 {
01631 if (is_statement)
01632 return std::string("element ") + ql->toString() + "; ";
01633 return std::string("(element ") + ql->toString() + ")";
01634 }
01635
01636
01637
01638
01639
01640
01641
01642 oqmlElementAt::oqmlElementAt(oqmlNode * _qleft, oqmlNode *_qright) : oqmlNode(oqmlELEMENTAT)
01643 {
01644 qleft = _qleft;
01645 qright = _qright;
01646 }
01647
01648 oqmlElementAt::~oqmlElementAt()
01649 {
01650 }
01651
01652 oqmlStatus *oqmlElementAt::compile(Database *db, oqmlContext *ctx)
01653 {
01654 oqmlStatus *s;
01655
01656 s = qleft->compile(db, ctx);
01657
01658 if (s)
01659 return s;
01660
01661 s = qright->compile(db, ctx);
01662
01663 if (s)
01664 return s;
01665
01666 return oqmlSuccess;
01667 }
01668
01669 oqmlStatus *oqmlElementAt::eval(Database *db, oqmlContext *ctx, oqmlAtomList **alist, oqmlComp *, oqmlAtom *)
01670 {
01671 oqmlAtomList *al_left, *al_right;
01672 oqmlStatus *s;
01673
01674 *alist = new oqmlAtomList();
01675
01676 s = qleft->eval(db, ctx, &al_left);
01677
01678 if (s)
01679 return s;
01680
01681 s = qright->eval(db, ctx, &al_right);
01682
01683 if (s)
01684 return s;
01685
01686 oqmlAtom *array = al_right->first;
01687
01688 while (array)
01689 {
01690 Status is;
01691 if (!OQML_IS_OBJECT(array))
01692 return oqmlStatus::expected(this, "oid or object",
01693 array->type.getString());
01694
01695 Object *o;
01696 s = oqmlObjectManager::getObject(this, db, array, o, oqml_False);
01697 if (s) return s;
01698 if (!o->getClass()->asCollArrayClass())
01699 {
01700 oqmlObjectManager::releaseObject(o);
01701 return oqmlStatus::expected(this, "array",
01702 o->getClass()->getName());
01703 }
01704
01705 CollArray *arr = (CollArray *)o;
01706 oqmlAtom *aind = al_left->first;
01707
01708 oqmlATOMTYPE t;
01709 oqml_check_coll_type(arr, t);
01710
01711 while(aind)
01712 {
01713 oqmlAtom *next = aind->next;
01714 if (aind->type.type != oqmlATOM_INT)
01715 return oqmlStatus::expected(this, "integer",
01716 aind->type.getString());
01717
01718 if (t == oqmlATOM_OID)
01719 {
01720 Oid xoid;
01721 is = arr->retrieveAt(((oqmlAtom_int *)aind)->i, xoid);
01722 if (is)
01723 return new oqmlStatus(this, is);
01724 (*alist)->append(new oqmlAtom_oid(xoid));
01725 }
01726 else
01727 {
01728 unsigned char buff[256];
01729 is = arr->retrieveAt_p(((oqmlAtom_int *)aind)->i, buff);
01730 if (is)
01731 return new oqmlStatus(this, is);
01732 switch(t)
01733 {
01734 case oqmlATOM_INT:
01735 {
01736 int i;
01737 memcpy(&i, buff, sizeof(int));
01738 (*alist)->append(new oqmlAtom_int(i));
01739 break;
01740 }
01741 case oqmlATOM_DOUBLE:
01742 {
01743 double d;
01744 memcpy(&d, buff, sizeof(double));
01745 (*alist)->append(new oqmlAtom_double(d));
01746 break;
01747 }
01748 case oqmlATOM_STRING:
01749 {
01750 (*alist)->append(new oqmlAtom_string((char *)buff));
01751 break;
01752 }
01753
01754 default:
01755 return new oqmlStatus(this, "type #%d not supported", t);
01756 }
01757 }
01758
01759 aind = next;
01760 }
01761
01762 oqmlObjectManager::releaseObject(o);
01763 array = array->next;
01764 }
01765
01766 return oqmlSuccess;
01767 }
01768
01769 void oqmlElementAt::evalType(Database *db, oqmlContext *ctx, oqmlAtomType *at)
01770 {
01771 *at = eval_type;
01772 }
01773
01774 oqmlBool oqmlElementAt::isConstant() const
01775 {
01776 return oqml_False;
01777 }
01778
01779 std::string
01780 oqmlElementAt::toString(void) const
01781 {
01782 if (is_statement)
01783 return std::string("element at ") + qleft->toString() + " in " +
01784 qright->toString() + "; ";
01785 return std::string("(element at ") + qleft->toString() + " in " +
01786 qright->toString() + ")";
01787 }
01788
01789
01790
01791
01792
01793
01794
01795 oqml_Interval::oqml_Interval(oqmlNode *_from, oqmlNode *_to) :
01796 from(_from), to(_to)
01797 {
01798 from_base = 0;
01799 to_base = 0;
01800 }
01801
01802 oqmlStatus *
01803 oqml_Interval::compile(Database *db, oqmlContext *ctx)
01804 {
01805 oqmlStatus *s;
01806
01807 if (from)
01808 {
01809 s = from->compile(db, ctx);
01810 if (s) return s;
01811 }
01812
01813 if (to)
01814 return to->compile(db, ctx);
01815
01816 return oqmlSuccess;
01817 }
01818
01819 oqmlStatus *
01820 oqml_Interval::evalNode(Database *db, oqmlContext *ctx,
01821 oqmlNode *node, unsigned int &base)
01822 {
01823 oqmlStatus *s;
01824 if (!node)
01825 {
01826 base = oqml_INFINITE;
01827 return oqmlSuccess;
01828 }
01829
01830 oqmlAtomList *al;
01831 s = node->eval(db, ctx, &al);
01832 if (s) return s;
01833
01834 if (!al->first)
01835 return new oqmlStatus("interval %s: integer expected, got nil",
01836 toString().c_str());
01837
01838 if (!OQML_IS_INT(al->first))
01839 return new oqmlStatus("interval %s: integer expected, got %s",
01840 toString().c_str(),
01841 al->first->type.getString());
01842
01843 base = OQML_ATOM_INTVAL(al->first);
01844 return oqmlSuccess;
01845 }
01846
01847 oqmlBool
01848 oqml_Interval::isAll() const
01849 {
01850 return OQMLBOOL(from_base == oqml_INFINITE && to_base == oqml_INFINITE);
01851 }
01852
01853 oqml_Interval::Status
01854 oqml_Interval::isIn(unsigned int count, unsigned int max) const
01855 {
01856 if (max == oqml_INFINITE)
01857 {
01858 if (count >= from_base && count <= to_base)
01859 return Success;
01860
01861 return Error;
01862 }
01863
01864 if (count > to_base)
01865 return Error;
01866
01867 if (count >= from_base && max <= to_base)
01868 return Success;
01869
01870 return Continue;
01871 }
01872
01873 oqmlStatus *
01874 oqml_Interval::evalNodes(Database *db, oqmlContext *ctx)
01875 {
01876 oqmlStatus *s;
01877
01878 s = evalNode(db, ctx, from, from_base);
01879 if (s) return s;
01880
01881 return evalNode(db, ctx, to, to_base);
01882 }
01883
01884 std::string
01885 oqml_Interval::toString() const
01886 {
01887 if (!from && !to) return "all";
01888
01889 std::string s = "<";
01890
01891 if (from) s += from->toString();
01892 else s += "$";
01893
01894 if (to != from)
01895 {
01896 s += ":";
01897 if (to) s += to->toString();
01898 else s += "$";
01899 }
01900
01901 return s + ">";
01902 }
01903
01904
01905
01906
01907
01908
01909
01910 oqmlFor::oqmlFor(oqml_Interval *_interval, const char *_ident,
01911 oqmlNode * _qcoll, oqmlNode * _qpred,
01912 oqmlBool _exists) : oqmlNode(_exists ? oqmlEXISTS : oqmlFOR)
01913 {
01914 interval = _interval;
01915 qcoll = _qcoll;
01916 qpred = _qpred;
01917 ident = strdup(_ident);
01918 exists = _exists;
01919 eval_type.type = oqmlATOM_BOOL;
01920 }
01921
01922 oqmlFor::~oqmlFor()
01923 {
01924 free(ident);
01925 }
01926
01927 oqmlStatus *oqmlFor::compile(Database *db, oqmlContext *ctx)
01928 {
01929 oqmlStatus *s;
01930
01931 s = interval->compile(db, ctx);
01932 if (s) return s;
01933
01934 s = qcoll->compile(db, ctx);
01935 if (s) return s;
01936
01937 oqmlAtomType nodeType;
01938 ctx->pushSymbol(ident, &nodeType, 0, oqml_False);
01939 s = qpred->compile(db, ctx);
01940 ctx->popSymbol(ident, oqml_False);
01941
01942 if (s) return s;
01943
01944 return oqmlSuccess;
01945 }
01946
01947 oqmlStatus *oqmlFor::eval(Database *db, oqmlContext *ctx, oqmlAtomList **alist, oqmlComp *, oqmlAtom *)
01948 {
01949 oqmlStatus *s;
01950
01951 s = interval->evalNodes(db, ctx);
01952 if (s) return s;
01953
01954 oqmlAtomList *al;
01955 s = qcoll->eval(db, ctx, &al);
01956 if (s) return s;
01957
01958 oqmlAtomList *rlist = new oqmlAtomList();
01959 const Class *cls;
01960 s = oqml_coll_eval(this, db, ctx, al->first, rlist, cls);
01961 if (s) return s;
01962
01963 oqmlBool isAll = interval->isAll();
01964
01965 unsigned int count = 0;
01966 unsigned int max = rlist->cnt;
01967 oqmlAtom *a = rlist->first;
01968 while(a)
01969 {
01970 oqmlAtomList *predList;
01971 oqmlAtom *next = a->next;
01972
01973 ctx->pushSymbol(ident, &a->type, a, oqml_False);
01974 s = qpred->eval(db, ctx, &predList);
01975 ctx->popSymbol(ident, oqml_False);
01976 if (s) return s;
01977
01978 if (!predList->first)
01979 return new oqmlStatus(this,
01980 "condition: boolean expected, got nil");
01981
01982 if (!OQML_IS_BOOL(predList->first))
01983 return new oqmlStatus(this,
01984 "condition: boolean expected, got %s",
01985 predList->first->type.getString());
01986
01987 if (OQML_ATOM_BOOLVAL(predList->first))
01988 {
01989 oqml_Interval::Status is = interval->isIn(++count, max);
01990 if (is == oqml_Interval::Error)
01991 {
01992 *alist = new oqmlAtomList(new oqmlAtom_bool(oqml_False));
01993 return oqmlSuccess;
01994 }
01995
01996 if (is == oqml_Interval::Success)
01997 {
01998 *alist = new oqmlAtomList(new oqmlAtom_bool(oqml_True));
01999 return oqmlSuccess;
02000 }
02001 }
02002 else if (isAll)
02003 {
02004 *alist = new oqmlAtomList(new oqmlAtom_bool(oqml_False));
02005 return oqmlSuccess;
02006 }
02007
02008 a = next;
02009 }
02010
02011 if (isAll && count == max)
02012 {
02013 *alist = new oqmlAtomList(new oqmlAtom_bool(oqml_True));
02014 return oqmlSuccess;
02015 }
02016
02017 oqml_Interval::Status is = interval->isIn(count, oqml_INFINITE);
02018
02019 if (is == oqml_Interval::Success)
02020 *alist = new oqmlAtomList(new oqmlAtom_bool(oqml_True));
02021 else
02022 *alist = new oqmlAtomList(new oqmlAtom_bool(oqml_False));
02023
02024 return oqmlSuccess;
02025 }
02026
02027 void oqmlFor::evalType(Database *db, oqmlContext *ctx, oqmlAtomType *at)
02028 {
02029 *at = eval_type;
02030 }
02031
02032 oqmlBool oqmlFor::isConstant() const
02033 {
02034 return oqml_False;
02035 }
02036
02037 void
02038 oqmlFor::lock()
02039 {
02040 oqmlNode::lock();
02041 interval->lock();
02042 qcoll->lock();
02043 qpred->lock();
02044 }
02045
02046 void
02047 oqmlFor::unlock()
02048 {
02049 oqmlNode::unlock();
02050 interval->unlock();
02051 qcoll->unlock();
02052 qpred->unlock();
02053 }
02054
02055 std::string
02056 oqmlFor::toString(void) const
02057 {
02058 if (exists)
02059 {
02060 if (is_statement)
02061 return std::string("exists ") + ident + " in " +
02062 qcoll->toString() + ": " + qpred->toString() + "; ";
02063 return std::string("(exists ") + ident + " in " +
02064 qcoll->toString() + ": " + qpred->toString() + ")";
02065 }
02066
02067 if (is_statement)
02068 return std::string("for ") + interval->toString() + " " + ident + " in " +
02069 qcoll->toString() + ": " + qpred->toString() + "; ";
02070 return std::string("(for ") + interval->toString() + " " + ident + " in " +
02071 qcoll->toString() + ": " + qpred->toString() + ")";
02072 }
02073
02074
02075
02076
02077
02078
02079
02080 oqml_CollSpec::oqml_CollSpec(const char *_coll_type, const char *_type_spec, oqmlBool _isref, const char *_ident, oqmlBool _ishash, const char *_impl_hints)
02081 {
02082 coll_type = strdup(_coll_type);
02083 type_spec = strdup(_type_spec);
02084 isref = (_isref ? True : False);
02085 ishash = (_ishash ? True : False);
02086 ident = strdup(_ident);
02087 impl_hints = _impl_hints ? strdup(_impl_hints) : 0;
02088 coll_spec = NULL;
02089 }
02090
02091 oqml_CollSpec::oqml_CollSpec(const char *_coll_type, oqml_CollSpec *_coll_spec, oqmlBool _isref, const char *_ident, oqmlBool _ishash, const char *_impl_hints)
02092 {
02093 coll_type = strdup(_coll_type);
02094 isref = (_isref ? True : False);
02095 ishash = (_ishash ? True : False);
02096 ident = strdup(_ident);
02097 impl_hints = _impl_hints ? strdup(_impl_hints) : 0;
02098 type_spec = NULL;
02099 coll_spec = _coll_spec;
02100 }
02101
02102 std::string
02103 oqml_CollSpec::toString(void) const
02104 {
02105 return std::string(coll_type) + "<" + (type_spec ? type_spec : "??") +
02106 (isref ? "*" : "") +
02107 (ident ? std::string(", \"") + ident + "\"" : std::string(", \"\"")) +
02108 (ishash ? ", hash" : ", btree") +
02109 (impl_hints ? std::string(", \"") + impl_hints + "\"": std::string(", """)) +
02110 ">";
02111 }
02112
02113 oqml_CollSpec::~oqml_CollSpec()
02114 {
02115 free(coll_type);
02116 free(type_spec);
02117 free(ident);
02118 free(impl_hints);
02119 }
02120 }