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
00026 #include "eyedb_p.h"
00027 #include "oql_p.h"
00028 #include <assert.h>
00029 #include <eyedblib/butils.h>
00030 #include <eyedb/oqlctb.h>
00031
00032
00033 namespace eyedb {
00034
00035 extern char *attrcomp_delete_ud;
00036
00037
00038
00039
00040
00041 void
00042 sysclsMake(Object **o)
00043 {
00044 Object *etc_o = sysclsMakeObject(*o);
00045 if (etc_o)
00046 *o = etc_o;
00047 }
00048
00049
00050
00051
00052
00053 void
00054 oqlctbMake(Object **o)
00055 {
00056 Object *oqlctb_o = oqlctbMakeObject(*o);
00057 if (oqlctb_o)
00058 *o = oqlctb_o;
00059 }
00060
00061
00062
00063
00064
00065 void
00066 utilsMake(Object **o)
00067 {
00068 Object *utils_o = utilsMakeObject(*o);
00069 if (utils_o)
00070 *o = utils_o;
00071 }
00072
00073
00074
00075
00076
00077 static Status
00078 comp_exists(ClassComponent *comp, Bool &exists, Oid *comp_oid = 0)
00079 {
00080 OQL oql(comp->getDatabase(), "select class_component.name = \"%s\"",
00081 comp->getName().c_str());
00082 OidArray oid_arr;
00083 Status status = oql.execute(oid_arr);
00084 if (status) return status;
00085 exists = IDBBOOL(oid_arr.getCount());
00086 if (exists && comp_oid)
00087 *comp_oid = oid_arr[0];
00088 return Success;
00089 }
00090
00091 Status ClassComponent::realize(const RecMode *rcm)
00092 {
00093 Status status;
00094
00095 if (!oid.isValid())
00096 {
00097 Class* cl = getClassOwner();
00098
00099 if (!cl)
00100 return Exception::make(IDB_ERROR, "cannot create class component: attribute `class_owner' is not set");
00101
00102 if (!db)
00103 return Exception::make(IDB_ERROR, "no database associated with object");
00104
00105 if (status = check(cl))
00106 return status;
00107
00108 #if 0
00109 Bool exists;
00110 if (status = comp_exists(this, exists))
00111 return status;
00112
00113 if (exists)
00114 return Exception::make(IDB_UNIQUE_CONSTRAINT_ERROR,
00115 "component '%s' already exists "
00116 "in database", getName());
00117 #endif
00118
00119 if (status = Agregat::realize(rcm))
00120 return status;
00121
00122 if (status = cl->add(this, False)) {
00123 db->removeObject(&getOid());
00124 return status;
00125 }
00126
00127 return Success;
00128 }
00129
00130 if (status = Agregat::realize(rcm))
00131 return status;
00132
00133
00134 return Success;
00135 }
00136
00137 Status ClassComponent::make(Class *)
00138 {
00139 if (isRemoved())
00140 return Exception::make(IDB_ERROR, "index '%s' is removed",
00141 oid.toString());
00142 return Success;
00143 }
00144
00145 Status
00146 ClassComponent_realize_prologue(Database *db, const Class *&cl)
00147 {
00148 if (!cl->isRemoved())
00149 return Success;
00150
00151 ClassConversion::Context *conv_ctx = 0;
00152 ClassConversion::Context *cnvctx;
00153 Status s = ClassConversion::getClass_(db, cl->getOid(), cl, conv_ctx);
00154 if (s) return s;
00155 if (cl->isRemoved())
00156 return Exception::make(IDB_ERROR,
00157 "internal error in class component remove for update: "
00158 "class %s is removed",
00159 cl->getOid().toString());
00160 return Success;
00161 }
00162
00163 Status ClassComponent::remove(const RecMode *rcm)
00164 {
00165 if (isRemoved())
00166 return Exception::make(IDB_ERROR,
00167 "class component %s is removed",
00168 getOid().toString());
00169
00170 Class * cl = getClassOwner();
00171 Status s;
00172
00173
00174
00175 incrRefCount();
00176
00177 s = ClassComponent_realize_prologue(db, (const Class *&)cl);
00178 if (s) return s;
00179
00180 s = cl->suppress(this);
00181 if (s) return s;
00182
00183 s = Agregat::remove(rcm);
00184
00185 if (s)
00186 s = cl->add(this, False);
00187
00188 return s;
00189 }
00190
00191 Status ClassComponent::check(Class *cl) const
00192 {
00193 return Success;
00194 }
00195
00196 int ClassComponent::getInd() const
00197 {
00198 return 0;
00199 }
00200
00201 Bool ClassComponent::isInherit() const
00202 {
00203 return False;
00204 }
00205
00206 Status ClassComponent::m_trace(FILE *fd, int, unsigned int, const RecMode*) const
00207 {
00208 return Success;
00209 }
00210
00211 Status ClassComponent::realize_for_update()
00212 {
00213 return realize();
00214 }
00215
00216 Status ClassComponent::remove_for_update()
00217 {
00218 return remove();
00219 }
00220
00221
00222
00223 static inline const char *get_class_name(const Class *cls)
00224 {
00225 return cls->getAliasName() ? cls->getAliasName() : cls->getName();
00226 }
00227
00228
00229
00230
00231
00232 Status ClassVariable::check(Class *cl) const
00233 {
00234 if (!getVname()[0])
00235 return Exception::make(IDB_ERROR, "variable name must be set");
00236
00237 return Success;
00238 }
00239
00240 int ClassVariable::getInd() const
00241 {
00242 return Class::Variable_C;
00243 }
00244
00245 Bool ClassVariable::isInherit() const
00246 {
00247 return True;
00248 }
00249
00250 Status ClassVariable::m_trace(FILE *fd, int indent, unsigned int flags, const RecMode *rcm) const
00251 {
00252 Status s = Success;
00253 char *indent_str = make_indent(indent);
00254 const Object *v = getVal();
00255 if (v)
00256 fprintf(fd, "variable %s *%s::%s = ",
00257 v->getClass()->getName(),
00258 getClassOwner()->getName(), getVname().c_str());
00259 else
00260 fprintf(fd, "variable %s::%s = ",
00261 getClassOwner()->getName(), getVname().c_str());
00262
00263 Bool tr = False;
00264 if (v)
00265 {
00266 if (rcm->getType() == RecMode_FullRecurs)
00267 {
00268 fprintf(fd, "%s {%s} = ", v->getOid().getString(), v->getClass()->getName());
00269 s = ObjectPeer::trace_realize(v, fd, indent + INDENT_INC, flags, rcm);
00270 tr = True;
00271 }
00272 else
00273 fprintf(fd, "{%s}", v->getOid().getString());
00274 }
00275 else
00276 fprintf(fd, NullString);
00277
00278 fprintf(fd, "%s", (tr ? indent_str : ""));
00279 if ((flags & CompOidTrace) == CompOidTrace)
00280 fprintf(fd, " {%s}", oid.getString());
00281 delete_indent(indent_str);
00282 return s;
00283 }
00284
00285
00286
00287
00288
00289 Status Protection::realize(const RecMode *rcm)
00290 {
00291 return Agregat::realize(rcm);
00292 }
00293
00294 Status Protection::remove(const RecMode *rcm)
00295 {
00296 return Agregat::remove(rcm);
00297 }
00298
00299
00300
00301
00302
00303 const char *
00304 getTriggerName(TriggerType ttype)
00305 {
00306 if (ttype == TriggerCREATE_BEFORE)
00307 return "create_before";
00308 if (ttype == TriggerCREATE_AFTER)
00309 return "create_after";
00310 if (ttype == TriggerUPDATE_BEFORE)
00311 return "update_before";
00312 if (ttype == TriggerUPDATE_AFTER)
00313 return "update_after";
00314 if (ttype == TriggerLOAD_BEFORE)
00315 return "load_before";
00316 if (ttype == TriggerLOAD_AFTER)
00317 return "load_after";
00318 if (ttype == TriggerREMOVE_BEFORE)
00319 return "remove_before";
00320 if (ttype == TriggerREMOVE_AFTER)
00321 return "remove_after";
00322
00323 return 0;
00324 }
00325
00326 int Trigger::getInd() const
00327 {
00328 TriggerType _type = getType();
00329
00330 if (_type == TriggerCREATE_BEFORE)
00331 return Class::TrigCreateBefore_C;
00332 if (_type == TriggerCREATE_AFTER)
00333 return Class::TrigCreateAfter_C;
00334 if (_type == TriggerUPDATE_BEFORE)
00335 return Class::TrigUpdateBefore_C;
00336 if (_type == TriggerUPDATE_AFTER)
00337 return Class::TrigUpdateAfter_C;
00338 if (_type == TriggerLOAD_BEFORE)
00339 return Class::TrigLoadBefore_C;
00340 if (_type == TriggerLOAD_AFTER)
00341 return Class::TrigLoadAfter_C;
00342 if (_type == TriggerREMOVE_BEFORE)
00343 return Class::TrigRemoveBefore_C;
00344 if (_type == TriggerREMOVE_AFTER)
00345 return Class::TrigRemoveAfter_C;
00346 abort();
00347 }
00348
00349 Trigger::Trigger(Database *_db, Class *class_owner,
00350 TriggerType _type,
00351 ExecutableLang lang,
00352 Bool isSystem,
00353 const char *suffix,
00354 Bool light,
00355 const char *extref) :
00356 AgregatClassExecutable(_db, (const Dataspace *)0, 1)
00357 {
00358 initialize(_db);
00359 db = _db;
00360 Executable *ex = getEx();
00361 ex->initExec(suffix, lang, isSystem, BACKEND, 0, class_owner);
00362 setClassOwner(class_owner);
00363 setType(_type);
00364 setSuffix(suffix);
00365 setName(getCSym());
00366 setLight(light);
00367 ex->setExtrefBody(extref);
00368 }
00369
00370 Status Trigger::apply(const Oid &_oid, Object *o)
00371 {
00372 if (o->isApplyingTrigger())
00373 return Success;
00374
00375 if (getEx()->getLang() == OQL_LANG)
00376 {
00377 if (!isRTInitialized)
00378 return Exception::make(IDB_EXECUTABLE_ERROR,
00379 "cannot apply OQL 'trigger<%s> %s::%s'",
00380 getTriggerName(getType()),
00381 getClassOwner()->getName(), getName().c_str());
00382
00383 o->setApplyingTrigger(True);
00384 oqmlStatus *s = oqmlMethodCall::applyTrigger(db, this, o, &_oid);
00385 o->setApplyingTrigger(False);
00386
00387 if (s)
00388 return Exception::make("applying OQL 'trigger<%s> %s::%s', got: %s",
00389 getTriggerName(getType()),
00390 getClassOwner()->getName(), getName().c_str(),
00391 s->msg);
00392 return Success;
00393 }
00394
00395 if (!csym)
00396 return Exception::make(IDB_EXECUTABLE_ERROR,
00397 "cannot apply C++ 'trigger<%s> %s::%s: "
00398 "runtime pointer function is null",
00399 getTriggerName(getType()),
00400 getClassOwner()->getName(), getName().c_str());
00401
00402 o->setApplyingTrigger(True);
00403 Status s = csym(getType(), db, _oid, o);
00404 o->setApplyingTrigger(False);
00405
00406 return s;
00407 }
00408
00409 const char *Trigger::getCSym() const
00410 {
00411 static char str[256];
00412 if (db)
00413 db->transactionBegin();
00414
00415 if (!getClassOwner())
00416 return "";
00417
00418 sprintf(str, "%s_%s_%s",
00419 (getClassOwner()->getAliasName() ? getClassOwner()->getAliasName() :
00420 getClassOwner()->getName()),
00421 getStrTriggerType(getType()),
00422 getSuffix().c_str());
00423
00424 if (db)
00425 db->transactionCommit();
00426
00427 return str;
00428 }
00429
00430 const char *Trigger::getStrTriggerType(TriggerType _type)
00431 {
00432 if (_type == TriggerCREATE_BEFORE)
00433 return "create_before";
00434 if (_type == TriggerCREATE_AFTER)
00435 return "create_after";
00436 if (_type == TriggerUPDATE_BEFORE)
00437 return "update_before";
00438 if (_type == TriggerUPDATE_AFTER)
00439 return "update_after";
00440 if (_type == TriggerLOAD_BEFORE)
00441 return "load_before";
00442 if (_type == TriggerLOAD_AFTER)
00443 return "load_after";
00444 if (_type == TriggerREMOVE_BEFORE)
00445 return "remove_before";
00446 if (_type == TriggerREMOVE_AFTER)
00447 return "remove_after";
00448 abort();
00449 }
00450
00451 const char *
00452 Trigger::getPrototype(Bool scope) const
00453 {
00454 static char s[256];
00455 sprintf(s, "%strigger<%s> %s::%s()",
00456 (getLight() ? "light" : ""),
00457 getStrTriggerType(getType()),
00458 getClassOwner()->getName(), getSuffix().c_str());
00459 return s;
00460 }
00461
00462 Bool Trigger::isInherit() const
00463 {
00464 return True;
00465 }
00466
00467 void
00468 print_oqlexec(FILE *fd, const char *body)
00469 {
00470 int len = strlen(body);
00471 char *x = strdup(body);
00472 char c = body[len-1];
00473 x[len-1] = 0;
00474
00475 if (c == '}')
00476 fprintf(fd, " %%oql%s%%}", x);
00477 else
00478 {
00479 x[len-2] = 0;
00480 fprintf(fd, " %%oql%s%%)", x);
00481 }
00482
00483 free(x);
00484 }
00485
00486 Status Trigger::m_trace(FILE *fd, int indent, unsigned int flags,
00487 const RecMode *rcm) const
00488 {
00489 Status s = Success;
00490 Bool istrs;
00491 if (db && !db->isInTransaction())
00492 {
00493 db->transactionBegin();
00494 istrs = True;
00495 }
00496 else
00497 istrs = False;
00498
00499 fprintf(fd, "%strigger<%s> ",
00500 (getLight() ? "light" : ""),
00501 getStrTriggerType(getType()));
00502
00503 if (!(flags & NoScope))
00504 fprintf(fd, "%s::", getClassOwner()->getName());
00505
00506 fprintf(fd, "%s()", getSuffix().c_str());
00507
00508 if (flags & ExecBodyTrace)
00509 {
00510 const Executable *ex = getEx();
00511 if (ex->getLang() & C_LANG)
00512 fprintf(fd, " C++(\"%s\")", ex->getExtrefBody().c_str());
00513 else
00514 {
00515 ((Trigger *)this)->runtimeInit();
00516 if (body)
00517 print_oqlexec(fd, body);
00518 }
00519 }
00520
00521 if (rcm->getType() == RecMode_FullRecurs)
00522 {
00523 fprintf(fd, " ");
00524 s = ObjectPeer::trace_realize(this, fd, indent + INDENT_INC, flags, rcm);
00525 }
00526
00527 if ((flags & CompOidTrace) == CompOidTrace)
00528 fprintf(fd, " {%s}", oid.getString());
00529
00530 if (istrs)
00531 db->transactionCommit();
00532 return s;
00533 }
00534
00535 Status Trigger::realize(const RecMode *rcm)
00536 {
00537 if (!db)
00538 return Exception::make(IDB_ERROR, "no database associated with object");
00539
00540 if (!getSuffix().c_str() || !*getSuffix().c_str())
00541 return Exception::make(IDB_ERROR, "cannot realize unamed trigger");
00542
00543 if (!oid.isValid())
00544 {
00545 OQL q(db, "select trigger.name = \"%s\"", getCSym());
00546
00547 ObjectArray obj_arr(true);
00548 Status s = q.execute(obj_arr);
00549 if (s) return s;
00550
00551 if (obj_arr.getCount()) {
00552
00553 return Exception::make(IDB_UNIQUE_CONSTRAINT_ERROR,
00554 "trigger<%s> %s::%s() already exists "
00555 "in database '%s'",
00556 Trigger::getStrTriggerType(getType()),
00557 getClassOwner()->getName(),
00558 getName().c_str(),
00559 db->getName());
00560 }
00561 }
00562
00563 return ClassComponent::realize(rcm);
00564 }
00565
00566 Status Trigger::remove(const RecMode *rcm)
00567 {
00568 return ClassComponent::remove(rcm);
00569 }
00570
00571 std::string
00572 Trigger::makeExtrefBody(const Class *cls, const char *oql,
00573 const char *name,
00574 std::string &oqlConstruct)
00575 {
00576 std::string funcname = std::string("oql$") + cls->getAliasName() + "$" +
00577 name;
00578
00579 std::string s = funcname;
00580 s += ":";
00581
00582 oqlConstruct = std::string("function ") + funcname + "()" + oql;
00583
00584 return s + oql;
00585 }
00586
00587 Status
00588 Trigger::runtimeInit()
00589 {
00590 if (isRTInitialized)
00591 return Success;
00592
00593 const char *s = getEx()->getExtrefBody().c_str();
00594
00595 tmpbuf = strdup(s);
00596 char *q = strchr(tmpbuf, ':');
00597
00598 if (!q)
00599 return Exception::make(IDB_EXECUTABLE_ERROR,
00600 "invalid internal format '%s'", s);
00601 *q = 0;
00602 funcname = tmpbuf;
00603
00604 body = q+1;
00605 fullBody = strdup((std::string("function ") + funcname + "()" + body).c_str());
00606 isRTInitialized = True;
00607 return Success;
00608 }
00609
00610 void
00611 Trigger::userInitialize()
00612 {
00613 isRTInitialized = False;
00614 body = 0;
00615 fullBody = 0;
00616 funcname = 0;
00617 tmpbuf = 0;
00618 entry = 0;
00619 }
00620
00621 void
00622 Trigger::userCopy(const Object &o)
00623 {
00624 Trigger::userInitialize();
00625 }
00626
00627 void
00628 Trigger::userGarbage()
00629 {
00630 free(tmpbuf);
00631 free(fullBody);
00632 }
00633
00634 Status UnreadableObject::trace_realize(FILE*fd, int indent, unsigned int, const RecMode *) const
00635 {
00636 char *last_indent_str = make_indent(indent-INDENT_INC);
00637 char *indent_str = make_indent(indent);
00638
00639 fprintf(fd, "{\n");
00640 fprintf(fd, "%s<unreadable object>\n", indent_str);
00641 fprintf(fd, "%s};\n", last_indent_str);
00642
00643 delete_indent(last_indent_str);
00644 delete_indent(indent_str);
00645 return Success;
00646 }
00647
00648 Bool UnreadableObject::isUnreadableObject(const Class *cls)
00649 {
00650 if (cls && !strcmp(cls->getName(), "unreadable_object"))
00651 return True;
00652 return False;
00653 }
00654
00655 Bool UnreadableObject::isUnreadableObject(const Object *o)
00656 {
00657 return isUnreadableObject(o->getClass());
00658 }
00659
00660
00661
00662
00663
00664 int CardinalityConstraint::maxint = -1;
00665
00666 CardinalityConstraint::CardinalityConstraint(Database *_db,
00667 Class *class_owner,
00668 const char *atname,
00669 int bottom, int bottom_excl,
00670 int top, int top_excl)
00671 : AgregatClassComponent(_db, (const Dataspace *)0, 1)
00672 {
00673 initialize(_db);
00674 db = _db;
00675 setClassOwner(class_owner);
00676 setAttrname(atname);
00677 CardinalityDescription *card = getCardDesc();
00678 card->setBottom(bottom);
00679 card->setBottomExcl(bottom_excl);
00680 card->setTop(top);
00681 card->setTopExcl(top_excl);
00682 setName(genName());
00683 }
00684
00685 const char *CardinalityConstraint::genName() const
00686 {
00687 static char str[256];
00688 const CardinalityDescription *card = getCardDesc();
00689 sprintf(str, "card_%s::%s%s%d,%d%s",
00690 get_class_name(getClassOwner()),
00691 getAttrname().c_str(),
00692 (card->getBottomExcl() ? "]" : "["),
00693 card->getBottom(),
00694 card->getTop(),
00695 (card->getTopExcl() ? "[" : "]"));
00696 return str;
00697 }
00698
00699 Status CardinalityConstraint::make(Class *cl)
00700 {
00701 Attribute *item;
00702
00703 if (!(item = (Attribute *)cl->getAttribute(getAttrname().c_str())))
00704 return Exception::make(IDB_ERROR, "cardinality constraint: attribute '%s'"
00705 " does not exist in class '%s'",
00706 getAttrname().c_str(), cl->getName());
00707
00708
00709 #if 0
00710 if (item->getCardinalityConstraint() &&
00711 !item->getCardinalityConstraint()->getOid().compare(getOid()))
00712 return Exception::make(IDB_ERROR,
00713 "a cardinality constraint already exists for attribute '%s::%s'",
00714 cl->getName(), getAttrname());
00715 #endif
00716
00717 return item->setCardinalityConstraint(this);
00718 }
00719
00720 Status CardinalityConstraint::check(Class *cl) const
00721 {
00722 const char *atname = getAttrname().c_str();
00723 if (!atname || !*atname)
00724 return Exception::make(IDB_ERROR, "attribute name is not set for"
00725 " cardinality constraint in class '%s'",
00726 cl->getName());
00727 const Attribute *item;
00728 if (!(item = cl->getAttribute(atname)))
00729 return Exception::make(IDB_ERROR, "cardinality constraint: attribute '%s'"
00730 " does not exist in class '%s'",
00731 atname, cl->getName());
00732
00733 return Success;
00734 }
00735
00736 int CardinalityConstraint::getInd() const
00737 {
00738 return 0;
00739 }
00740
00741 Bool CardinalityConstraint::isInherit() const
00742 {
00743 return True;
00744 }
00745
00746 Status CardinalityConstraint::m_trace(FILE *fd, int indent, unsigned int flags, const RecMode* rcm) const
00747 {
00748 Status s = Success;
00749 char *indent_str = make_indent(indent);
00750 Bool tr = False;
00751
00752 if (db)
00753 db->transactionBegin();
00754 fprintf(fd, "card(");
00755 if (rcm->getType() == RecMode_FullRecurs)
00756 {
00757 s = ObjectPeer::trace_realize(this, fd, indent + INDENT_INC, flags, rcm);
00758 tr = True;
00759 }
00760 else
00761 fprintf(fd, "%s::%s", getClassOwner()->getName(), getAttrname().c_str());
00762
00763 if (db)
00764 db->transactionCommit();
00765
00766 const CardinalityDescription *card = getCardDesc();
00767 fprintf(fd, "%s", (tr ? indent_str : ""));
00768
00769 fprintf(fd, " %s)", card->getString(False));
00770
00771 if ((flags & CompOidTrace) == CompOidTrace)
00772 fprintf(fd, " {%s}", oid.getString());
00773
00774 delete_indent(indent_str);
00775 return s;
00776 }
00777
00778 const char *CardinalityDescription::getString(Bool isprefix) const
00779 {
00780 static char card_str[256];
00781
00782 int bottom = getBottom();
00783 int top = getTop();
00784 int bottom_excl = getBottomExcl();
00785 int top_excl = getTopExcl();
00786
00787 int maxint = CardinalityConstraint::maxint;
00788
00789 const char *prefix;
00790
00791 if (isprefix)
00792 prefix = "card ";
00793 else
00794 prefix = "";
00795
00796 if (bottom == top)
00797 sprintf(card_str, "%s= %d", prefix, bottom);
00798 else if (bottom && top != maxint)
00799 sprintf(card_str, "%sin %s%d,%d%s", prefix,
00800 bottom_excl ? "]" : "[",
00801 bottom,
00802 top,
00803 top_excl ? "[" : "]");
00804 else if (top == maxint)
00805 sprintf(card_str, "%s>%s %d", prefix, bottom_excl ? "" : "=", bottom);
00806 else if (!bottom)
00807 sprintf(card_str, "%s<%s %d", prefix, top_excl ? "" : "=", top);
00808
00809 return card_str;
00810 }
00811
00812 Bool
00813 CardinalityDescription::compare(CardinalityDescription *card)
00814 {
00815 if (!card)
00816 return False;
00817
00818 return getBottom() == card->getBottom() &&
00819 getBottomExcl() == card->getBottomExcl() &&
00820 getTop() == card->getTop() &&
00821 getTopExcl() == card->getTopExcl() ? True : False;
00822 }
00823
00824 Status
00825 post_etc_update(Database *db)
00826 {
00827 return Success;
00828 }
00829
00830
00831
00832
00833
00834 Status
00835 AttributeComponent::m_trace(FILE *, int, unsigned int, const RecMode *) const
00836 {
00837 return 0;
00838 }
00839
00840 Status
00841 AttributeComponent::checkUnique(const char *clsname, const char *msg)
00842 {
00843 OQL oql(db, "select %s.attrpath = \"%s\"", clsname, getAttrpath().c_str());
00844 OidArray oid_arr;
00845 Status s = oql.execute(oid_arr);
00846 if (s) return s;
00847 if (oid_arr.getCount())
00848 return Exception::make(IDB_ERROR, "%s '%s' already "
00849 "exist", msg, getAttrpath().c_str());
00850 return Success;
00851 }
00852
00853 std::string
00854 AttributeComponent::makeAttrpath(const Class *cls)
00855 {
00856 std::string attrpath = getAttrpath();
00857 const char *p = strchr(attrpath.c_str(), '.');
00858 assert(p);
00859 return std::string(cls->getName()) + "." + std::string(p+1);
00860 }
00861
00862 Status
00863 AttributeComponent::find(Database *db, const Class *cls,
00864 AttributeComponent *&cattr_comp)
00865 {
00866 std::string attrpath = makeAttrpath(cls);
00867 char *name = strdup(getName().c_str());
00868 char *p = strchr(name, ':');
00869 assert(p);
00870 *p = 0;
00871 std::string newname = std::string(name) + ":" + attrpath;
00872 free(name);
00873 cattr_comp = 0;
00874 Status s = cls->getAttrComp(newname.c_str(), cattr_comp);
00875 if (s) return s;
00876 return Success;
00877 }
00878
00879 AttributeComponent *
00880 AttributeComponent::xclone(Database *, const Class *)
00881 {
00882 abort();
00883 return 0;
00884 }
00885
00886
00887
00888
00889
00890 NotNullConstraint::NotNullConstraint(Database *_db, Class *cls,
00891 const char *attrpath,
00892 Bool propagate) :
00893 AttributeComponent(_db, (const Dataspace *)0, 1)
00894 {
00895 initialize(_db);
00896 db = _db;
00897 setClassOwner(cls);
00898 setAttrpath(attrpath);
00899 setName(genName());
00900 setPropagate(propagate);
00901 }
00902
00903 static const char *
00904 getPropagString(const AttributeComponent *comp)
00905 {
00906 static std::string s;
00907 s = ", propagate = ";
00908 s += comp->getPropagate() ? "on" : "off";
00909 return s.c_str();
00910 }
00911
00912 Status
00913 NotNullConstraint::m_trace(FILE *fd, int indent, unsigned int flags,
00914 const RecMode *rcm) const
00915 {
00916 Status s = Success;
00917 char *indent_str = make_indent(indent);
00918 Bool tr = False;
00919
00920 fprintf(fd, "constraint<notnull%s> on %s", getPropagString(this), getAttrpath().c_str());
00921
00922 if (rcm->getType() == RecMode_FullRecurs)
00923 {
00924 fprintf(fd, " ");
00925 s = ObjectPeer::trace_realize(this, fd, indent + INDENT_INC, flags, rcm);
00926 tr = True;
00927 }
00928
00929 fprintf(fd, "%s", (tr ? indent_str : ""));
00930 if ((flags & CompOidTrace) == CompOidTrace)
00931 fprintf(fd, " {%s}", oid.getString());
00932 delete_indent(indent_str);
00933 return s;
00934 }
00935
00936 const char *
00937 NotNullConstraint::genName() const
00938 {
00939 static std::string s;
00940 s = std::string("notnull") + ":" + getAttrpath();
00941 return s.c_str();
00942 }
00943
00944 Status
00945 NotNullConstraint::realize(const RecMode *rcm)
00946 {
00947 Status s;
00948
00949 Bool creating = IDBBOOL(!getOid().isValid());
00950 if (creating) {
00951 s = checkUnique("notnull_constraint", "notnull constraint");
00952 if (s) return s;
00953 }
00954
00955 s = AttributeComponent::realize(rcm);
00956 if (s) return s;
00957 if (creating)
00958 return StatusMake(constraintCreate(db->getDbHandle(),
00959 oid.getOid()));
00960 return Success;
00961 }
00962
00963 Status
00964 NotNullConstraint::remove(const RecMode *rcm)
00965 {
00966 RPCStatus rpc_status =
00967 constraintDelete(db->getDbHandle(), oid.getOid(),
00968 getUserData(attrcomp_delete_ud) ? 1 : 0);
00969
00970 if (rpc_status)
00971 return StatusMake(rpc_status);
00972 return AttributeComponent::remove(rcm);
00973 }
00974
00975 int
00976 NotNullConstraint::getInd() const
00977 {
00978 return Class::NotnullConstraint_C;
00979 }
00980
00981 AttributeComponent *
00982 NotNullConstraint::xclone(Database *db, const Class *cls)
00983 {
00984 std::string str = makeAttrpath(cls);
00985 return new NotNullConstraint(db, (Class *)cls, str.c_str(),
00986 getPropagate());
00987 }
00988
00989
00990
00991
00992
00993 UniqueConstraint::UniqueConstraint(Database *_db, Class *cls,
00994 const char *attrpath,
00995 Bool propagate) :
00996 AttributeComponent(_db, (const Dataspace *)0, 1)
00997 {
00998 initialize(_db);
00999 db = _db;
01000 setClassOwner(cls);
01001 setAttrpath(attrpath);
01002 setName(genName());
01003 setPropagate(propagate);
01004 }
01005
01006 Status
01007 UniqueConstraint::m_trace(FILE *fd, int indent, unsigned int flags, const RecMode* rcm) const
01008 {
01009 Status s = Success;
01010 char *indent_str = make_indent(indent);
01011 Bool tr = False;
01012
01013 if (db)
01014 db->transactionBegin();
01015 fprintf(fd, "constraint<unique%s> on %s", getPropagString(this), getAttrpath().c_str());
01016 if (rcm->getType() == RecMode_FullRecurs)
01017 {
01018 fprintf(fd, " ");
01019 s = ObjectPeer::trace_realize(this, fd, indent + INDENT_INC, flags, rcm);
01020 tr = True;
01021 }
01022
01023 if (db)
01024 db->transactionCommit();
01025
01026 fprintf(fd, "%s", (tr ? indent_str : ""));
01027 if ((flags & CompOidTrace) == CompOidTrace)
01028 fprintf(fd, "{%s}", oid.getString());
01029 delete_indent(indent_str);
01030 return s;
01031 }
01032
01033 const char *
01034 UniqueConstraint::genName() const
01035 {
01036 static std::string s;
01037 s = std::string("unique") + ":" + getAttrpath();
01038 return s.c_str();
01039 }
01040
01041 Status
01042 UniqueConstraint::realize(const RecMode *rcm)
01043 {
01044 Status s;
01045
01046 Bool creating = IDBBOOL(!getOid().isValid());
01047 if (creating) {
01048 s = checkUnique("unique_constraint", "unique constraint");
01049 if (s) return s;
01050 }
01051
01052 s = AttributeComponent::realize(rcm);
01053 if (s) return s;
01054 if (creating)
01055 return StatusMake(constraintCreate(db->getDbHandle(),
01056 oid.getOid()));
01057 return Success;
01058 }
01059
01060 Status
01061 UniqueConstraint::remove(const RecMode *rcm)
01062 {
01063 RPCStatus rpc_status =
01064 constraintDelete(db->getDbHandle(), oid.getOid(),
01065 getUserData(attrcomp_delete_ud) ? 1 : 0);
01066
01067 if (rpc_status)
01068 return StatusMake(rpc_status);
01069 return AttributeComponent::remove(rcm);
01070 }
01071
01072 AttributeComponent *
01073 UniqueConstraint::xclone(Database *db, const Class *cls)
01074 {
01075 std::string str = makeAttrpath(cls);
01076 return new UniqueConstraint(db, (Class *)cls, str.c_str(),
01077 getPropagate());
01078 }
01079
01080 int
01081 UniqueConstraint::getInd() const
01082 {
01083 return Class::UniqueConstraint_C;
01084 }
01085
01086
01087
01088
01089
01090
01091
01092
01093
01094
01095 CardinalityConstraint_Test::CardinalityConstraint_Test
01096 (Database *, Class *, const char *attrname, int, int, int, int)
01097 {
01098 }
01099
01100 const char *
01101 CardinalityConstraint_Test::genName() const
01102 {
01103 return 0;
01104 }
01105
01106 Status CardinalityConstraint_Test::m_trace(FILE *, int, unsigned int, const RecMode *) const
01107 {
01108 return 0;
01109 }
01110
01111 static int maxint;
01112
01113
01114 Index::Index(Database *, const char *, const char *)
01115 {
01116 }
01117
01118 Status Index::realize(const RecMode*)
01119 {
01120 return 0;
01121 }
01122
01123 Status
01124 Index::report(eyedbsm::DbHandle *sedbh, const Oid &idxoid)
01125 {
01126 abort();
01127 return Success;
01128 }
01129
01130 Status Index::remove(const RecMode*)
01131 {
01132 return 0;
01133 }
01134
01135 Status Index::s_trace(FILE *, Bool, unsigned int flags) const
01136 {
01137 return 0;
01138 }
01139
01140 void Index::userInitialize()
01141 {
01142 idx = 0;
01143 }
01144
01145 void Index::userCopy(const Object &)
01146 {
01147 idx = 0;
01148 }
01149
01150 Status
01151 Index::makeDataspace(Database *_db, const Dataspace *&dataspace) const
01152 {
01153 Bool isnull;
01154 short dspid = getDspid(&isnull);
01155 if (!isnull)
01156 return _db->getDataspace(dspid, dataspace);
01157 dataspace = 0;
01158 return Success;
01159 }
01160
01161 Status
01162 Index::getCount(unsigned int &count)
01163 {
01164 RPCStatus rpc_status =
01165 indexGetCount(db->getDbHandle(), oid.getOid(), (int *)&count);
01166
01167 return StatusMake(rpc_status);
01168 }
01169
01170 Status
01171 Index::getStats(IndexStats *&stats)
01172 {
01173 RPCStatus rpc_status =
01174 indexGetStats(db->getDbHandle(), oid.getOid(), (Data *)&stats);
01175 if (rpc_status)
01176 return StatusMake(rpc_status);
01177
01178 const Dataspace *dataspace;
01179 Status s = makeDataspace(db, dataspace);
01180 if (s) return s;
01181 if (dataspace)
01182 stats->idximpl->setDataspace(dataspace);
01183
01184 if (asHashIndex() && asHashIndex()->getHashMethod())
01185 stats->idximpl->setHashMethod(asHashIndex()->getHashMethod());
01186 return Success;
01187 }
01188
01189 Status
01190 Index::getStats(std::string &xstats, Bool dspImpl, Bool full,
01191 const char *indent)
01192 {
01193 IndexStats *stats = 0;
01194 RPCStatus rpc_status =
01195 indexGetStats(db->getDbHandle(), oid.getOid(), (Data *)&stats);
01196 if (rpc_status)
01197 return StatusMake(rpc_status);
01198 xstats = (stats ? stats->toString(dspImpl, full, indent) : std::string(""));
01199 delete stats;
01200 return Success;
01201 }
01202
01203 Status
01204 Index::simulate(const IndexImpl &idximpl, std::string &xstats,
01205 Bool dspImpl, Bool full, const char *indent)
01206 {
01207 IndexStats *stats = 0;
01208 Status s = simulate(idximpl, stats);
01209 if (s) return s;
01210 xstats = (stats ? stats->toString(dspImpl, full, indent) : std::string(""));
01211 return Success;
01212 }
01213
01214 Status
01215 Index::simulate(const IndexImpl &idximpl, IndexStats *&stats)
01216 {
01217 Data data;
01218 Offset offset = 0;
01219 Size size = 0;
01220 Status s = IndexImpl::code(data, offset, size, idximpl);
01221 if (s) return s;
01222
01223 RPCStatus rpc_status =
01224 indexSimulStats(db->getDbHandle(), oid.getOid(), data, size, (Data *)&stats);
01225 free(data);
01226 return StatusMake(rpc_status);
01227 }
01228
01229 void Index::userGarbage()
01230 {
01231
01232 }
01233
01234 void AttributeComponent::userInitialize()
01235 {
01236
01237 }
01238
01239 void AttributeComponent::userCopy(const Object &)
01240 {
01241
01242 }
01243
01244 void AttributeComponent::userGarbage()
01245 {
01246
01247 }
01248
01249 int
01250 Index::getInd() const
01251 {
01252 return Class::Index_C;
01253 }
01254
01255 short
01256 Index::get_dspid() const
01257 {
01258 Bool isnull;
01259 short dspid = getDspid(&isnull);
01260
01261 if (isnull)
01262 return Dataspace::DefaultDspid;
01263
01264 return dspid;
01265 }
01266
01267 inline int
01268 IDXTYPE(const Index *idx)
01269 {
01270 return idx->asHashIndex() ? 1 : 0;
01271 }
01272
01273 Status
01274 Index::getDefaultDataspace(const Dataspace *&dataspace) const
01275 {
01276 short dspid = get_dspid();
01277
01278 if (dspid == Dataspace::DefaultDspid) {
01279 dataspace = 0;
01280 return Success;
01281 }
01282
01283 return db->getDataspace(dspid, dataspace);
01284 }
01285
01286 #define NEW_INDEX_MOVE
01287
01288 static const char index_move[] = "eyedb:move";
01289 extern char index_backend[];
01290
01291 Status
01292 Index::setDefaultDataspace(const Dataspace *dataspace)
01293 {
01294 Status s = setDspid(dataspace->getId());
01295 if (s) return s;
01296
01297 #ifdef NEW_INDEX_MOVE
01298 void *ud;
01299 if (!getUserData(index_move))
01300 ud = setUserData(index_backend, AnyUserData);
01301 s = store();
01302 if (!getUserData(index_move))
01303 setUserData(index_backend, ud);
01304 #else
01305 s = store();
01306 #endif
01307 if (s) return s;
01308
01309 Oid idxoid = getIdxOid();
01310 if (!idxoid.isValid()) return Success;
01311
01312
01313
01314
01315 #ifdef NEW_INDEX_MOVE
01316
01317 #endif
01318
01319 Index *idx;
01320 s = db->reloadObject(oid, (Object *&)idx);
01321 if (s) return s;
01322 #ifdef NEW_INDEX_MOVE
01323 if (!getUserData(index_move))
01324 assert(idx->getIdxOid() == getIdxOid());
01325 #endif
01326 idxoid = idx->getIdxOid();
01327 idx->release();
01328
01329 RPCStatus rpc_status =
01330 setDefaultIndexDataspace(db->getDbHandle(), idxoid.getOid(),
01331 IDXTYPE(this), dataspace->getId());
01332
01333 return StatusMake(rpc_status);
01334 }
01335
01336 Status
01337 Index::getObjectLocations(ObjectLocationArray &locarr)
01338 {
01339 const Oid &idxoid = getIdxOid();
01340 if (!idxoid.isValid()) return Success;
01341
01342 RPCStatus rpc_status = getIndexLocations(db->getDbHandle(),
01343 idxoid.getOid(),
01344 IDXTYPE(this),
01345 (void *)&locarr);
01346 return StatusMake(rpc_status);
01347 }
01348
01349 Status
01350 Index::move(const Dataspace *dataspace) const
01351 {
01352 #ifdef NEW_INDEX_MOVE
01353 Index *mthis = const_cast<Index *>(this);
01354 void *ud = mthis->setUserData(index_move, AnyUserData);
01355 Status s = mthis->setDefaultDataspace(dataspace);
01356 mthis->setUserData(index_move, ud);
01357 return s;
01358 #else
01359 const Oid &idxoid = getIdxOid();
01360 if (!idxoid.isValid()) return Success;
01361 RPCStatus rpc_status = moveIndex(db->getDbHandle(), idxoid.getOid(),
01362 IDXTYPE(this),
01363 dataspace->getId());
01364 return StatusMake(rpc_status);
01365 #endif
01366 }
01367
01368 HashIndex::HashIndex(Database *_db, Class *cls,
01369 const char *pathattr,
01370 Bool propagate, Bool is_string,
01371 const Dataspace *dataspace,
01372 int key_count, BEMethod_C *mth,
01373 const int *impl_hints, int impl_hints_cnt)
01374 : Index(_db, (const Dataspace *)0, 1)
01375 {
01376 initialize(_db);
01377 db = _db;
01378 setClassOwner(cls);
01379 setAttrpath(pathattr);
01380 setKeyCount(key_count);
01381 setIsString((Bool)is_string);
01382 setPropagate(propagate);
01383 if (dataspace)
01384 setDspid(dataspace->getId());
01385 setHashMethod(mth);
01386 setName(genName());
01387 for (int i = 0; i < impl_hints_cnt; i++)
01388 setImplHints(i, impl_hints[i]);
01389 }
01390
01391 struct KeyValue {
01392 const char *key;
01393 const char *value;
01394 void set(const char *_key, const char *_value) {
01395 key = _key;
01396 value = _value;
01397 }
01398 };
01399
01400 struct KeyValueArray {
01401 int kalloc;
01402 int cnt;
01403 KeyValue *kvalues;
01404 KeyValueArray() {
01405 kalloc = cnt = 0;
01406 kvalues = 0;
01407 }
01408 void add(const char *k, const char *v) {
01409 if (cnt >= kalloc) {
01410 kalloc += 8;
01411 kvalues = (KeyValue *)realloc(kvalues, kalloc * sizeof(KeyValue));
01412 }
01413 kvalues[cnt++].set(k, v);
01414 }
01415 void trace() {
01416 for (int i = 0; i < cnt; i++)
01417 printf("'%s' <-> '%s'\n", kvalues[i].key, (kvalues[i].value ?
01418 kvalues[i].value : "NULL"));
01419 }
01420 ~KeyValueArray() {
01421 free(kvalues);
01422 }
01423 };
01424
01425 HashIndex::HashIndex(Database *_db,
01426 Class *cls, const char *attrpath,
01427 Bool propagate, Bool is_string,
01428 const IndexImpl *idximpl)
01429 : Index(_db, (const Dataspace *)0, 1)
01430 {
01431 initialize(_db);
01432 db = _db;
01433 setClassOwner(cls);
01434 setAttrpath(attrpath);
01435 setKeyCount(idximpl->getKeycount());
01436 setIsString((Bool)is_string);
01437 setPropagate(propagate);
01438 setHashMethod(idximpl->getHashMethod());
01439 if (idximpl->getDataspace())
01440 setDspid(idximpl->getDataspace()->getId());
01441 setName(genName());
01442
01443 unsigned int impl_hints_cnt;
01444 const int *impl_hints = idximpl->getImplHints(impl_hints_cnt);
01445
01446 for (int i = 0; i < impl_hints_cnt; i++)
01447 setImplHints(i, impl_hints[i]);
01448 }
01449
01450 Status
01451 HashIndex::make(Database *db, Class *cls, const char *attrpath,
01452 Bool propagate, Bool is_string,
01453 const char *hints, HashIndex *&idx)
01454 {
01455 idx = 0;
01456 IndexImpl *idximpl;
01457 Status s = IndexImpl::make(db, IndexImpl::Hash, hints, idximpl,
01458 is_string);
01459 if (s) return s;
01460
01461 idx = new HashIndex(db, cls, attrpath, propagate, is_string,
01462 idximpl);
01463 return Success;
01464 }
01465
01466 Status HashIndex::check(Class *) const
01467 {
01468 return 0;
01469 }
01470
01471 Status HashIndex::make(Class *)
01472 {
01473 return 0;
01474 }
01475
01476
01477
01478 Bool
01479 Index::compareHints(Index *idx)
01480 {
01481 unsigned int cnt1 = getImplHintsCount();
01482 unsigned int cnt2 = idx->getImplHintsCount();
01483 int cnt = cnt1 < cnt2 ? cnt1 : cnt2;
01484
01485 #ifdef REIMPL_TRACE
01486 printf("compareHints: cnt %d vs %d\n", cnt1, cnt2);
01487 #endif
01488 for (unsigned int i = 0; i < cnt; i++) {
01489 #ifdef REIMPL_TRACE
01490 printf("hints[%d] %d %d\n", i, getImplHints(i), idx->getImplHints(i));
01491 #endif
01492 int val = getImplHints(i);
01493 if (val && val != idx->getImplHints(i))
01494 return False;
01495 if (!val)
01496 setImplHints(i, idx->getImplHints(i));
01497 }
01498
01499 return True;
01500 }
01501
01502 Status
01503 Index::reimplement(const IndexImpl &idximpl, Index *&idx)
01504 {
01505 IndexImpl::Type idxtype = idximpl.getType();
01506
01507 if ((idxtype == IndexImpl::Hash && asHashIndex()) ||
01508 (idxtype == IndexImpl::BTree && asBTreeIndex())) {
01509 setImplementation(&idximpl);
01510 idx = this;
01511 return store();
01512 }
01513
01514 unsigned int impl_hints_cnt;
01515 const int *impl_hints = idximpl.getImplHints(impl_hints_cnt);
01516
01517
01518
01519
01520
01521
01522
01523 Class *clsown = getClassOwner();
01524 if (idxtype == IndexImpl::Hash) {
01525 BEMethod_C *mth = idximpl.getHashMethod();
01526 idx = new HashIndex(db, clsown, getAttrpath().c_str(),
01527 getPropagate(), getIsString(),
01528 idximpl.getDataspace(),
01529 idximpl.getKeycount(), mth,
01530 impl_hints, impl_hints_cnt);
01531 }
01532 else
01533 idx = new BTreeIndex(db, clsown, getAttrpath().c_str(),
01534 getPropagate(), getIsString(),
01535 idximpl.getDataspace(),
01536 idximpl.getDegree(),
01537 impl_hints, impl_hints_cnt);
01538
01539 Oid idxoid = getIdxOid();
01540 setIdxOid(Oid::nullOid);
01541 setPropagate(False);
01542
01543 setImplHints(IDB_IDX_MAGIC_HINTS, IDB_IDX_MAGIC_HINTS_VALUE);
01544 Status s = store();
01545
01546 if (!s)
01547 s = remove();
01548
01549 if (s) {
01550 idx->release();
01551 idx = 0;
01552 return s;
01553 }
01554
01555 idx->setIdxOid(idxoid);
01556 s = idx->store();
01557 if (s) {
01558 idx->release();
01559 idx = 0;
01560 return s;
01561 }
01562 return Success;
01563 }
01564
01565 Bool
01566 HashIndex::compareHashMethod(HashIndex *idx)
01567 {
01568 BEMethod_C *mth1 = getHashMethod();
01569 BEMethod_C *mth2 = idx->getHashMethod();
01570
01571 if ((!mth1 && mth2) || (mth1 && !mth2))
01572 return False;
01573
01574 if (mth1 && mth1->getOid() != mth2->getOid())
01575 return False;
01576
01577 return True;
01578 }
01579
01580 Status HashIndex::realize(const RecMode*rcm)
01581 {
01582 Status s;
01583
01584 Bool backend_updating = IDBBOOL(getUserData(index_backend));
01585 Bool creating = IDBBOOL(!backend_updating && !getOid().isValid());
01586 Bool updating = False;
01587 bool index_moving = (getUserData(index_move) != 0);
01588
01589
01590
01591
01592
01593
01594 if (creating) {
01595 #ifndef DUP_INDEX
01596 s = checkUnique("index", "index");
01597 if (s) return s;
01598 #endif
01599 }
01600 else if (!backend_updating) {
01601 HashIndex *idx;
01602 s = db->reloadObject(getOid(), (Object *&)idx);
01603 if (s) return s;
01604 if ((getKeyCount() && idx->getKeyCount() != getKeyCount()) ||
01605 idx->getDspid () != getDspid() ||
01606 !compareHints(idx) ||
01607 !compareHashMethod(idx)) {
01608 #ifdef REIMPL_TRACE
01609 printf("Hashindex: should reimplement: "
01610 "key_count: %d v.s %d "
01611 "dsp_id %d: v.s %d "
01612 "compareHints: %d "
01613 "compareHashMethod: %d\n",
01614 getKeyCount(), idx->getKeyCount(),
01615 getDspid(), idx->getDspid(),
01616 compareHints(idx),
01617 compareHashMethod(idx));
01618 #endif
01619 updating = True;
01620 }
01621 #ifdef REIMPL_TRACE
01622 else
01623 printf("Hashindex: should NOT reimplement\n");
01624 #endif
01625 if (!getKeyCount())
01626 setKeyCount(idx->getKeyCount());
01627 idx->release();
01628 }
01629
01630 BEMethod_C *mth = getHashMethod();
01631 if (mth)
01632 setHashMethod(mth);
01633 else
01634 setHashMethodOid(Oid::nullOid);
01635
01636 s = AttributeComponent::realize(rcm);
01637
01638 if (s) return s;
01639
01640 if (creating || updating)
01641 return StatusMake(indexCreate(db->getDbHandle(),
01642 index_moving,
01643 oid.getOid()));
01644
01645 return Success;
01646 }
01647
01648 Status HashIndex::report(eyedbsm::DbHandle *sedbh, const Oid &idxoid)
01649 {
01650 eyedbsm::HIdx hidx(sedbh, idxoid.getOid());
01651 if (hidx.status())
01652 return Exception::make(IDB_ERROR, eyedbsm::statusGet(hidx.status()));
01653
01654 const eyedbsm::HIdx::_Idx &xidx = hidx.getIdx();
01655 setKeyCount(xidx.key_count);
01656 setImplHintsCount(eyedbsm::HIdxImplHintsCount);
01657 for (int n = 0; n < eyedbsm::HIdxImplHintsCount; n++)
01658 setImplHints(n, xidx.impl_hints[n]);
01659 #ifdef REIMPL_TRACE
01660 printf("Hashindex::report\n");
01661 #endif
01662 return Success;
01663 }
01664
01665 Status HashIndex::remove(const RecMode*)
01666 {
01667
01668 RPCStatus rpc_status =
01669 indexRemove(db->getDbHandle(), oid.getOid(),
01670 getUserData(attrcomp_delete_ud) ? 1 : 0);
01671
01672 if (rpc_status)
01673 return StatusMake(rpc_status);
01674
01675
01676 return AttributeComponent::remove();
01677 }
01678
01679 #define PREF(FD, VAR) \
01680 if (!VAR) { \
01681 fprintf(FD, ", hints = \""); \
01682 VAR = True; \
01683 } \
01684 else \
01685 fprintf(FD, " ")
01686
01687 Status HashIndex::s_trace(FILE *fd, Bool is_string, unsigned int flags) const
01688 {
01689 if (!(flags & AttrCompDetailTrace)) {
01690 fprintf(fd, "index<hash> on %s", getAttrpath().c_str());
01691 return Success;
01692 }
01693
01694 fprintf(fd, "index<type = hash");
01695 Bool hints = False;
01696
01697 const Dataspace *dataspace;
01698 Status s = makeDataspace(db, dataspace);
01699 if (s) return s;
01700 if (dataspace) {
01701 PREF(fd, hints);
01702 fprintf(fd, "dataspace = %s;", dataspace->getName());
01703 }
01704
01705 const BEMethod_C *mth = getHashMethod();
01706 if (mth) {
01707 PREF(fd, hints);
01708 fprintf(fd, "key_function = %s::%s;", mth->getClassOwner()->getName(),
01709 mth->getEx()->getExname().c_str());
01710 }
01711
01712 if (getKeyCount()) {
01713 PREF(fd, hints);
01714 fprintf(fd, "key_count = %d;", getKeyCount());
01715 }
01716
01717 unsigned int cnt = getImplHintsCount();
01718
01719 #ifdef IDB_SKIP_HASH_XCOEF
01720 if (cnt > eyedbsm::HIdx::XCoef_Hints)
01721 cnt = eyedbsm::HIdx::XCoef_Hints;
01722 #endif
01723
01724 for (unsigned int i = 0; i < cnt; i++) {
01725 if (is_string) {
01726 if (i == eyedbsm::HIdx::IniObjCnt_Hints)
01727 continue;
01728 }
01729 else if ((i) == eyedbsm::HIdx::IniSize_Hints &&
01730 getImplHints(eyedbsm::HIdx::IniObjCnt_Hints))
01731 continue;
01732 int val = getImplHints(i);
01733
01734 if (IndexImpl::isHashHintImplemented(i)) {
01735 PREF(fd, hints);
01736 fprintf(fd, "%s = %d;", IndexImpl::hashHintToStr(i), val);
01737 }
01738 }
01739
01740 fprintf(fd, "%s%s> on %s", (hints ? "\"" : ""), getPropagString(this),
01741 getAttrpath().c_str());
01742
01743 return Success;
01744 }
01745
01746 Status HashIndex::m_trace(FILE *fd, int indent, unsigned int flags,
01747 const RecMode *rcm) const
01748 {
01749 Status s = Success;
01750 s = s_trace(fd, IDBBOOL(flags & IDB_ATTR_IS_STRING), flags);
01751 if (s) return s;
01752
01753 if ((flags & CompOidTrace) == CompOidTrace ||
01754 rcm->getType() == RecMode_FullRecurs)
01755 fprintf(fd, " {%s}", oid.getString());
01756
01757 if (rcm->getType() == RecMode_FullRecurs)
01758 {
01759 fprintf(fd, " ");
01760 s = ObjectPeer::trace_realize(this, fd, indent + INDENT_INC, flags, rcm);
01761 }
01762 return s;
01763 }
01764
01765 AttributeComponent *
01766 HashIndex::xclone(Database *db, const Class *cls)
01767 {
01768 int impl_hints[eyedbsm::HIdxImplHintsCount];
01769 memset(impl_hints, 0, sizeof(int) * eyedbsm::HIdxImplHintsCount);
01770 unsigned int impl_hints_cnt = getImplHintsCount();
01771 for (int i = 0; i < impl_hints_cnt; i++)
01772 impl_hints[i] = getImplHints(i);
01773 Bool isnull;
01774
01775 const Dataspace *dataspace;
01776 Status s = makeDataspace(db, dataspace);
01777 if (s) throw *s;
01778
01779 std::string str = makeAttrpath(cls);
01780 return new HashIndex(db, (Class *)cls, str.c_str(),
01781 getPropagate(), getIsString(),
01782 dataspace, getKeyCount(), getHashMethod(),
01783 impl_hints, impl_hints_cnt);
01784 }
01785
01786 Status
01787 HashIndex::setImplementation(const IndexImpl *idximpl)
01788 {
01789 if (idximpl->getType() == IndexImpl::BTree)
01790 return Exception::make(IDB_ERROR,
01791 "cannot change dynamically hash index "
01792 "implementation to btree index using the "
01793 "setImplementation() method: use the "
01794 "reimplement() method");
01795 setKeyCount(idximpl->getKeycount());
01796 if (idximpl->getHashMethod())
01797 setHashMethod(idximpl->getHashMethod());
01798 else
01799 setHashMethodOid(Oid::nullOid);
01800
01801 if (idximpl->getDataspace())
01802 setDspid(idximpl->getDataspace()->getId());
01803
01804 unsigned int impl_hints_cnt;
01805 const int *impl_hints = idximpl->getImplHints(impl_hints_cnt);
01806 setImplHintsCount(impl_hints_cnt);
01807 for (int i = 0; i < impl_hints_cnt; i++)
01808 setImplHints(i, impl_hints[i]);
01809
01810 return Success;
01811 }
01812
01813 Status
01814 HashIndex::getImplementation(IndexImpl *&idximpl, Bool remote) const
01815 {
01816 const Dataspace *dataspace;
01817 Status s = makeDataspace(db, dataspace);
01818 if (s) return s;
01819
01820 if (!remote) {
01821 unsigned int cnt = getImplHintsCount();
01822 int *impl_hints = (cnt ? new int [cnt] : 0);
01823 for (unsigned int i = 0; i < cnt; i++)
01824 impl_hints[i] = getImplHints(i);
01825 idximpl =
01826 new IndexImpl(IndexImpl::Hash, dataspace, getKeyCount(),
01827 (BEMethod_C *)getHashMethod(),
01828 impl_hints, cnt);
01829 delete [] impl_hints;
01830 return Success;
01831 }
01832
01833 RPCStatus rpc_status =
01834 indexGetImplementation(db->getDbHandle(),
01835 oid.getOid(), (Data *)&idximpl);
01836 if (rpc_status)
01837 return StatusMake(rpc_status);
01838
01839 idximpl->setHashMethod((BEMethod_C *)getHashMethod());
01840 idximpl->setDataspace(dataspace);
01841 return Success;
01842 }
01843
01844 const char *HashIndex::genName() const
01845 {
01846 static std::string s;
01847 s = std::string("index") + ":" + getAttrpath();
01848 return s.c_str();
01849 }
01850
01851 BTreeIndex::BTreeIndex(Database *_db, Class *cls,
01852 const char *pathattr,
01853 Bool propagate, Bool is_string,
01854 const Dataspace *dataspace, int degree,
01855 const int *impl_hints , int impl_hints_cnt) : Index(_db, (const Dataspace *)0, 1)
01856 {
01857 initialize(_db);
01858 db = _db;
01859 setClassOwner(cls);
01860 setAttrpath(pathattr);
01861 setIsString((Bool)is_string);
01862 setPropagate(propagate);
01863 setName(genName());
01864 if (dataspace)
01865 setDspid(dataspace->getId());
01866 setDegree(degree);
01867 }
01868
01869 BTreeIndex::BTreeIndex(Database *_db, Class *cls,
01870 const char *pathattr,
01871 Bool propagate, Bool is_string,
01872 const IndexImpl *idximpl) :
01873 Index(_db, (const Dataspace *)0, 1)
01874 {
01875 initialize(_db);
01876 db = _db;
01877 setClassOwner(cls);
01878 setAttrpath(pathattr);
01879 setIsString((Bool)is_string);
01880 setPropagate(propagate);
01881 setName(genName());
01882 setDegree(idximpl->getDegree());
01883 if (idximpl->getDataspace())
01884 setDspid(idximpl->getDataspace()->getId());
01885
01886 unsigned int impl_hints_cnt;
01887 const int *impl_hints = idximpl->getImplHints(impl_hints_cnt);
01888
01889 for (int i = 0; i < impl_hints_cnt; i++)
01890 setImplHints(i, impl_hints[i]);
01891 }
01892
01893 Status
01894 BTreeIndex::make(Database *db, Class *cls, const char *attrpath,
01895 Bool propagate, Bool is_string,
01896 const char *hints, BTreeIndex *&idx)
01897 {
01898 idx = 0;
01899 IndexImpl *idximpl;
01900 Status s = IndexImpl::make(db, IndexImpl::BTree, hints, idximpl,
01901 is_string);
01902 if (s) return s;
01903
01904 idx = new BTreeIndex(db, cls, attrpath, propagate, is_string, idximpl);
01905 return Success;
01906 }
01907
01908 Status BTreeIndex::check(Class *) const
01909 {
01910 return 0;
01911 }
01912
01913 Status BTreeIndex::realize(const RecMode *rcm)
01914 {
01915 Status s;
01916
01917 Bool backend_updating = IDBBOOL(getUserData(index_backend));
01918 Bool creating = IDBBOOL(!backend_updating && !getOid().isValid());
01919 Bool updating = False;
01920 bool index_moving = (getUserData(index_move) != 0);
01921
01922
01923
01924
01925
01926 if (creating) {
01927 #ifndef DUP_INDEX
01928 s = checkUnique("index", "index");
01929 if (s) return s;
01930 #endif
01931 }
01932 else if (!backend_updating) {
01933 BTreeIndex *idx;
01934 s = db->reloadObject(getOid(), (Object *&)idx);
01935 if (s) return s;
01936 if ((getDegree() && idx->getDegree() != getDegree()) ||
01937 idx->getDspid () != getDspid() ||
01938 !compareHints(idx)) {
01939 #ifdef REIMPL_TRACE
01940 printf("BTreeindex: should reimplement: "
01941 "degree: %d %d "
01942 "dspid: %d %d\n",
01943 getDegree(), idx->getDegree(),
01944 getDspid(), idx->getDspid());
01945 #endif
01946 updating = True;
01947 }
01948 #ifdef REIMPL_TRACE
01949 else
01950 printf("BTreeindex: should NOT reimplement\n");
01951 #endif
01952 if (!getDegree())
01953 setDegree(idx->getDegree());
01954 idx->release();
01955 }
01956
01957 s = AttributeComponent::realize(rcm);
01958 if (s) return s;
01959 if (creating || updating)
01960 return StatusMake(indexCreate(db->getDbHandle(),
01961 index_moving,
01962 oid.getOid()));
01963
01964 return Success;
01965 }
01966
01967 Status BTreeIndex::report(eyedbsm::DbHandle *sedbh, const Oid &idxoid)
01968 {
01969 eyedbsm::BIdx bidx(sedbh, *idxoid.getOid());
01970 if (bidx.status())
01971 return Exception::make(IDB_ERROR, eyedbsm::statusGet(bidx.status()));
01972
01973 setDegree(bidx.getDegree());
01974 #ifdef REIMPL_TRACE
01975 printf("Btreeindex::report ");
01976 trace();
01977 #endif
01978 return Success;
01979 }
01980
01981 Status BTreeIndex::remove(const RecMode* )
01982 {
01983 RPCStatus rpc_status =
01984 indexRemove(db->getDbHandle(), oid.getOid(),
01985 getUserData(attrcomp_delete_ud) ? 1 : 0);
01986
01987 if (rpc_status)
01988 return StatusMake(rpc_status);
01989
01990 return AttributeComponent::remove();
01991 }
01992
01993 Status BTreeIndex::s_trace(FILE *fd, Bool is_string, unsigned int flags) const
01994 {
01995 if (!(flags & AttrCompDetailTrace)) {
01996 fprintf(fd, "index<btree> on %s", getAttrpath().c_str());
01997 return Success;
01998 }
01999
02000 fprintf(fd, "index<type = btree");
02001 Bool hints = False;
02002
02003 const Dataspace *dataspace;
02004 Status s = makeDataspace(db, dataspace);
02005 if (s) return s;
02006
02007 if (dataspace) {
02008 PREF(fd, hints);
02009 fprintf(fd, "dataspace = %s;", dataspace->getName());
02010 }
02011
02012 if (getDegree()) {
02013 PREF(fd, hints);
02014 fprintf(fd, "degree = %d;", getDegree());
02015 }
02016
02017 fprintf(fd, "%s%s> on %s", (hints ? "\"" : ""), getPropagString(this),
02018 getAttrpath().c_str());
02019
02020 return Success;
02021 }
02022
02023 Status
02024 BTreeIndex::m_trace(FILE *fd, int indent, unsigned int flags,
02025 const RecMode *rcm) const
02026 {
02027 Status s = Success;
02028 s = s_trace(fd, False, flags);
02029 if (s) return s;
02030
02031
02032 if ((flags & CompOidTrace) == CompOidTrace ||
02033 rcm->getType() == RecMode_FullRecurs)
02034 fprintf(fd, " {%s}", oid.getString());
02035
02036 if (rcm->getType() == RecMode_FullRecurs)
02037 {
02038 fprintf(fd, " ");
02039 s = ObjectPeer::trace_realize(this, fd, indent + INDENT_INC, flags, rcm);
02040 }
02041 return s;
02042 }
02043
02044 AttributeComponent *
02045 BTreeIndex::xclone(Database *db, const Class *cls)
02046 {
02047 const Dataspace *dataspace;
02048 Status s = makeDataspace(db, dataspace);
02049 if (s) throw *s;
02050
02051 std::string str = makeAttrpath(cls);
02052 return new BTreeIndex(db, (Class *)cls, str.c_str(),
02053 getPropagate(), getIsString(),
02054 dataspace, getDegree(), 0, 0);
02055 }
02056
02057 Status
02058 BTreeIndex::setImplementation(const IndexImpl *idximpl)
02059 {
02060 if (idximpl->getType() == IndexImpl::Hash)
02061 return Exception::make(IDB_ERROR,
02062 "cannot change dynamically btree index "
02063 "implementation to hash index using the "
02064 "setImplementation() method: use the "
02065 "reimplement() method");
02066 setDegree(idximpl->getDegree());
02067 if (idximpl->getDataspace())
02068 setDspid(idximpl->getDataspace()->getId());
02069 unsigned int impl_hints_cnt;
02070 const int *impl_hints = idximpl->getImplHints(impl_hints_cnt);
02071 setImplHintsCount(impl_hints_cnt);
02072 for (int i = 0; i < impl_hints_cnt; i++)
02073 setImplHints(i, impl_hints[i]);
02074
02075 return Success;
02076 }
02077
02078 Status
02079 BTreeIndex::getImplementation(IndexImpl *&idximpl, Bool remote) const
02080 {
02081 const Dataspace *dataspace;
02082 Status s = makeDataspace(db, dataspace);
02083 if (s) return s;
02084
02085 if (!remote) {
02086 unsigned int cnt = getImplHintsCount();
02087 int *impl_hints = (cnt ? new int [cnt] : 0);
02088
02089 idximpl = new IndexImpl(IndexImpl::BTree, dataspace, getDegree(),
02090 0, impl_hints, cnt);
02091 delete [] impl_hints;
02092 return Success;
02093 }
02094
02095 RPCStatus rpc_status =
02096 indexGetImplementation(db->getDbHandle(),
02097 oid.getOid(), (Data *)&idximpl);
02098 if (rpc_status)
02099 return StatusMake(rpc_status);
02100
02101 idximpl->setDataspace(dataspace);
02102 return Success;
02103 }
02104
02105 const char *BTreeIndex::genName() const
02106 {
02107 static std::string s;
02108 s = std::string("index") + ":" + getAttrpath();
02109 return s.c_str();
02110 }
02111
02112
02113 Status
02114 CardinalityConstraint_Test::realize(const RecMode *rcm)
02115 {
02116 return 0;
02117 }
02118
02119 Status
02120 CardinalityConstraint_Test::remove(const RecMode *rcm)
02121 {
02122 return 0;
02123 }
02124
02125 int
02126 CardinalityConstraint_Test::getInd() const
02127 {
02128 return Class::CardinalityConstraint_C;
02129 }
02130
02131 int
02132 AttributeComponent::getInd() const
02133 {
02134 assert(0);
02135 return 0;
02136 }
02137
02138 CollAttrImpl::CollAttrImpl(Database *_db, Class *cls,
02139 const char *attrpath,
02140 Bool propagate,
02141 const Dataspace *dataspace,
02142 IndexImpl::Type idxtype,
02143 int key_count_or_degree,
02144 BEMethod_C *mth,
02145 const int *impl_hints,
02146 int impl_hints_cnt)
02147 : AttributeComponent(_db, (const Dataspace *)0, 1)
02148 {
02149 initialize(_db);
02150 db = _db;
02151 setClassOwner(cls);
02152 setAttrpath(attrpath);
02153 setIdxtype(idxtype);
02154 setKeyCountOrDegree(key_count_or_degree);
02155 setPropagate(propagate);
02156 if (dataspace)
02157 setDspid(dataspace->getId());
02158 setHashMethod(mth);
02159 setName(genName());
02160 for (int i = 0; i < impl_hints_cnt; i++)
02161 setImplHints(i, impl_hints[i]);
02162 }
02163
02164 CollAttrImpl::CollAttrImpl(Database *_db, Class *cls,
02165 const char *attrpath,
02166 Bool propagate,
02167 const IndexImpl *idximpl)
02168 : AttributeComponent(_db, (const Dataspace *)0, 1)
02169 {
02170 initialize(_db);
02171 db = _db;
02172 setClassOwner(cls);
02173 setAttrpath(attrpath);
02174 setIdxtype(idximpl->getType());
02175 setKeyCountOrDegree(idximpl->getKeycount());
02176 setPropagate(propagate);
02177 setHashMethod(idximpl->getHashMethod());
02178 if (idximpl->getDataspace())
02179 setDspid(idximpl->getDataspace()->getId());
02180 setName(genName());
02181
02182 unsigned int impl_hints_cnt;
02183 const int *impl_hints = idximpl->getImplHints(impl_hints_cnt);
02184
02185 for (int i = 0; i < impl_hints_cnt; i++)
02186 setImplHints(i, impl_hints[i]);
02187 }
02188
02189 Status
02190 CollAttrImpl::makeDataspace(Database *_db, const Dataspace *&dataspace) const
02191 {
02192 Bool isnull;
02193 short dspid = getDspid(&isnull);
02194 if (!isnull)
02195 return _db->getDataspace(dspid, dataspace);
02196 dataspace = 0;
02197 return Success;
02198 }
02199
02200 Status
02201 CollAttrImpl::make(Database *db, Class *cls, const char *attrpath,
02202 Bool propagate, IndexImpl::Type type,
02203 const char *hints, CollAttrImpl *&impl)
02204 {
02205 impl = 0;
02206 IndexImpl *idximpl;
02207
02208 Status s = IndexImpl::make(db, type, hints, idximpl);
02209 if (s) return s;
02210
02211 impl = new CollAttrImpl(db, cls, attrpath, propagate, idximpl);
02212 return Success;
02213 }
02214
02215 AttributeComponent *
02216 CollAttrImpl::xclone(Database *db, const Class *cls)
02217 {
02218 unsigned int impl_hints_cnt = getImplHintsCount();
02219 int impl_hints[eyedbsm::HIdxImplHintsCount];
02220 memset(impl_hints, 0, sizeof(int) * eyedbsm::HIdxImplHintsCount);
02221 for (int i = 0; i < impl_hints_cnt; i++)
02222 impl_hints[i] = getImplHints(i);
02223
02224 const Dataspace *dataspace;
02225 Status s = makeDataspace(db, dataspace);
02226 if (s) throw *s;
02227
02228 std::string str = makeAttrpath(cls);
02229 return new CollAttrImpl(db, (Class *)cls, str.c_str(),
02230 getPropagate(),
02231 dataspace, (IndexImpl::Type)getIdxtype(),
02232 getKeyCountOrDegree(),
02233 getHashMethod(), impl_hints, impl_hints_cnt);
02234 }
02235
02236 Status
02237 CollAttrImpl::realize(const RecMode *rcm)
02238 {
02239 Status s;
02240
02241 Bool creating = IDBBOOL(!getOid().isValid());
02242
02243 if (creating) {
02244 s = checkUnique("collection_attribute_implementation",
02245 "collection attribute implementation");
02246 if (s) return s;
02247 }
02248
02249 s = AttributeComponent::realize(rcm);
02250 if (s) return s;
02251 if (creating)
02252 return StatusMake(constraintCreate(db->getDbHandle(),
02253 oid.getOid()));
02254 return Success;
02255 }
02256
02257 Status
02258 CollAttrImpl::remove(const RecMode *rcm)
02259 {
02260 RPCStatus rpc_status =
02261 constraintDelete(db->getDbHandle(), oid.getOid(),
02262 getUserData(attrcomp_delete_ud) ? 1 : 0);
02263
02264 if (rpc_status)
02265 return StatusMake(rpc_status);
02266 return AttributeComponent::remove(rcm);
02267 }
02268
02269 Status
02270 CollAttrImpl::s_trace(FILE *fd, Bool, unsigned int flags) const
02271 {
02272 int idxtype = getIdxtype();
02273 fprintf(fd, "implementation<type = %s", idxtype == IndexImpl::Hash ?
02274 "hash" : "btree");
02275 Bool hints = False;
02276
02277 const Dataspace *dataspace;
02278 Status s = makeDataspace(db, dataspace);
02279 if (s) return s;
02280
02281 if (dataspace) {
02282 PREF(fd, hints);
02283 fprintf(fd, "dataspace = %s;", dataspace->getName());
02284 }
02285
02286 const BEMethod_C *mth = getHashMethod();
02287 if (mth) {
02288 PREF(fd, hints);
02289 fprintf(fd, "key_function = %s::%s;", mth->getClassOwner()->getName(),
02290 mth->getEx()->getExname().c_str());
02291 }
02292
02293 if (getKeyCountOrDegree()) {
02294 PREF(fd, hints);
02295 if (idxtype == IndexImpl::Hash)
02296 fprintf(fd, "key_count = %d;", getKeyCountOrDegree());
02297 else
02298 fprintf(fd, "degree = %d;", getKeyCountOrDegree());
02299 }
02300
02301 unsigned int cnt = getImplHintsCount();
02302 for (unsigned int i = 0; i < cnt; i++) {
02303 if ((i) == eyedbsm::HIdx::IniSize_Hints &&
02304 getImplHints(eyedbsm::HIdx::IniObjCnt_Hints))
02305 continue;
02306 int val = getImplHints(i);
02307 if (val) {
02308 PREF(fd, hints);
02309 fprintf(fd, "%s = %d;", IndexImpl::hashHintToStr(i), val);
02310 }
02311 }
02312
02313 fprintf(fd, "%s%s> on %s", (hints ? "\"" : ""), getPropagString(this),
02314 getAttrpath().c_str());
02315
02316 return Success;
02317 }
02318
02319 Status
02320 CollAttrImpl::m_trace(FILE *fd, int indent, unsigned int flags,
02321 const RecMode *rcm) const
02322 {
02323 Status s = Success;
02324 s = s_trace(fd, False);
02325 if (s) return s;
02326
02327 if ((flags & CompOidTrace) == CompOidTrace ||
02328 rcm->getType() == RecMode_FullRecurs)
02329 fprintf(fd, " {%s}", oid.getString());
02330
02331 if (rcm->getType() == RecMode_FullRecurs)
02332 {
02333 fprintf(fd, " ");
02334 s = ObjectPeer::trace_realize(this, fd, indent + INDENT_INC, flags, rcm);
02335 }
02336 return s;
02337 }
02338
02339 const char *
02340 CollAttrImpl::genName() const
02341 {
02342 static std::string s;
02343 s = std::string("implementation") + ":" + getAttrpath();
02344 return s.c_str();
02345 }
02346
02347 int
02348 CollAttrImpl::getInd() const
02349 {
02350 return Class::CollectionImpl_C;
02351 }
02352
02353 Status
02354 CollAttrImpl::getImplementation(Database *db,
02355 const IndexImpl *&_idximpl)
02356
02357 {
02358 if (!idximpl) {
02359 const Dataspace *dataspace;
02360 Status s = makeDataspace(db, dataspace);
02361 if (s) return s;
02362
02363 unsigned int impl_hints_cnt = getImplHintsCount();
02364 int impl_hints[eyedbsm::HIdxImplHintsCount];
02365 memset(impl_hints, 0, sizeof(int) * eyedbsm::HIdxImplHintsCount);
02366 for (int i = 0; i < impl_hints_cnt; i++)
02367 impl_hints[i] = getImplHints(i);
02368 idximpl = new IndexImpl((IndexImpl::Type)getIdxtype(),
02369 dataspace, getKeyCountOrDegree(),
02370 getHashMethod(), impl_hints,
02371 impl_hints_cnt);
02372 }
02373
02374 _idximpl = idximpl;
02375 return Success;
02376 }
02377
02378 void CollAttrImpl::userInitialize()
02379 {
02380 idximpl = 0;
02381 dsp = 0;
02382 }
02383
02384 void CollAttrImpl::userCopy(const Object &)
02385 {
02386 idximpl = 0;
02387 dsp = 0;
02388 }
02389
02390 void CollAttrImpl::userGarbage()
02391 {
02392 if (idximpl)
02393 idximpl->release();
02394 dsp = 0;
02395 }
02396 }