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 std::string str = getEx()->getExtrefBody();
00594 const char *s = str.c_str();
00595
00596 tmpbuf = strdup(s);
00597 char *q = strchr(tmpbuf, ':');
00598
00599 if (!q)
00600 return Exception::make(IDB_EXECUTABLE_ERROR,
00601 "invalid internal format '%s'", s);
00602 *q = 0;
00603 funcname = tmpbuf;
00604
00605 body = q+1;
00606 fullBody = strdup((std::string("function ") + funcname + "()" + body).c_str());
00607 isRTInitialized = True;
00608 return Success;
00609 }
00610
00611 void
00612 Trigger::userInitialize()
00613 {
00614 isRTInitialized = False;
00615 body = 0;
00616 fullBody = 0;
00617 funcname = 0;
00618 tmpbuf = 0;
00619 entry = 0;
00620 }
00621
00622 void
00623 Trigger::userCopy(const Object &o)
00624 {
00625 Trigger::userInitialize();
00626 }
00627
00628 void
00629 Trigger::userGarbage()
00630 {
00631 free(tmpbuf);
00632 free(fullBody);
00633 }
00634
00635 Status UnreadableObject::trace_realize(FILE*fd, int indent, unsigned int, const RecMode *) const
00636 {
00637 char *last_indent_str = make_indent(indent-INDENT_INC);
00638 char *indent_str = make_indent(indent);
00639
00640 fprintf(fd, "{\n");
00641 fprintf(fd, "%s<unreadable object>\n", indent_str);
00642 fprintf(fd, "%s};\n", last_indent_str);
00643
00644 delete_indent(last_indent_str);
00645 delete_indent(indent_str);
00646 return Success;
00647 }
00648
00649 Bool UnreadableObject::isUnreadableObject(const Class *cls)
00650 {
00651 if (cls && !strcmp(cls->getName(), "unreadable_object"))
00652 return True;
00653 return False;
00654 }
00655
00656 Bool UnreadableObject::isUnreadableObject(const Object *o)
00657 {
00658 return isUnreadableObject(o->getClass());
00659 }
00660
00661
00662
00663
00664
00665 int CardinalityConstraint::maxint = -1;
00666
00667 CardinalityConstraint::CardinalityConstraint(Database *_db,
00668 Class *class_owner,
00669 const char *atname,
00670 int bottom, int bottom_excl,
00671 int top, int top_excl)
00672 : AgregatClassComponent(_db, (const Dataspace *)0, 1)
00673 {
00674 initialize(_db);
00675 db = _db;
00676 setClassOwner(class_owner);
00677 setAttrname(atname);
00678 CardinalityDescription *card = getCardDesc();
00679 card->setBottom(bottom);
00680 card->setBottomExcl(bottom_excl);
00681 card->setTop(top);
00682 card->setTopExcl(top_excl);
00683 setName(genName());
00684 }
00685
00686 const char *CardinalityConstraint::genName() const
00687 {
00688 static char str[256];
00689 const CardinalityDescription *card = getCardDesc();
00690 sprintf(str, "card_%s::%s%s%d,%d%s",
00691 get_class_name(getClassOwner()),
00692 getAttrname().c_str(),
00693 (card->getBottomExcl() ? "]" : "["),
00694 card->getBottom(),
00695 card->getTop(),
00696 (card->getTopExcl() ? "[" : "]"));
00697 return str;
00698 }
00699
00700 Status CardinalityConstraint::make(Class *cl)
00701 {
00702 Attribute *item;
00703
00704 if (!(item = (Attribute *)cl->getAttribute(getAttrname().c_str())))
00705 return Exception::make(IDB_ERROR, "cardinality constraint: attribute '%s'"
00706 " does not exist in class '%s'",
00707 getAttrname().c_str(), cl->getName());
00708
00709
00710 #if 0
00711 if (item->getCardinalityConstraint() &&
00712 !item->getCardinalityConstraint()->getOid().compare(getOid()))
00713 return Exception::make(IDB_ERROR,
00714 "a cardinality constraint already exists for attribute '%s::%s'",
00715 cl->getName(), getAttrname());
00716 #endif
00717
00718 return item->setCardinalityConstraint(this);
00719 }
00720
00721 Status CardinalityConstraint::check(Class *cl) const
00722 {
00723 std::string atname_s = getAttrname();
00724 const char *atname = atname_s.c_str();
00725 if (!atname || !*atname)
00726 return Exception::make(IDB_ERROR, "attribute name is not set for"
00727 " cardinality constraint in class '%s'",
00728 cl->getName());
00729 const Attribute *item;
00730 if (!(item = cl->getAttribute(atname)))
00731 return Exception::make(IDB_ERROR, "cardinality constraint: attribute '%s'"
00732 " does not exist in class '%s'",
00733 atname, cl->getName());
00734
00735 return Success;
00736 }
00737
00738 int CardinalityConstraint::getInd() const
00739 {
00740 return 0;
00741 }
00742
00743 Bool CardinalityConstraint::isInherit() const
00744 {
00745 return True;
00746 }
00747
00748 Status CardinalityConstraint::m_trace(FILE *fd, int indent, unsigned int flags, const RecMode* rcm) const
00749 {
00750 Status s = Success;
00751 char *indent_str = make_indent(indent);
00752 Bool tr = False;
00753
00754 if (db)
00755 db->transactionBegin();
00756 fprintf(fd, "card(");
00757 if (rcm->getType() == RecMode_FullRecurs)
00758 {
00759 s = ObjectPeer::trace_realize(this, fd, indent + INDENT_INC, flags, rcm);
00760 tr = True;
00761 }
00762 else
00763 fprintf(fd, "%s::%s", getClassOwner()->getName(), getAttrname().c_str());
00764
00765 if (db)
00766 db->transactionCommit();
00767
00768 const CardinalityDescription *card = getCardDesc();
00769 fprintf(fd, "%s", (tr ? indent_str : ""));
00770
00771 fprintf(fd, " %s)", card->getString(False));
00772
00773 if ((flags & CompOidTrace) == CompOidTrace)
00774 fprintf(fd, " {%s}", oid.getString());
00775
00776 delete_indent(indent_str);
00777 return s;
00778 }
00779
00780 const char *CardinalityDescription::getString(Bool isprefix) const
00781 {
00782 static char card_str[256];
00783
00784 int bottom = getBottom();
00785 int top = getTop();
00786 int bottom_excl = getBottomExcl();
00787 int top_excl = getTopExcl();
00788
00789 int maxint = CardinalityConstraint::maxint;
00790
00791 const char *prefix;
00792
00793 if (isprefix)
00794 prefix = "card ";
00795 else
00796 prefix = "";
00797
00798 if (bottom == top)
00799 sprintf(card_str, "%s= %d", prefix, bottom);
00800 else if (bottom && top != maxint)
00801 sprintf(card_str, "%sin %s%d,%d%s", prefix,
00802 bottom_excl ? "]" : "[",
00803 bottom,
00804 top,
00805 top_excl ? "[" : "]");
00806 else if (top == maxint)
00807 sprintf(card_str, "%s>%s %d", prefix, bottom_excl ? "" : "=", bottom);
00808 else if (!bottom)
00809 sprintf(card_str, "%s<%s %d", prefix, top_excl ? "" : "=", top);
00810
00811 return card_str;
00812 }
00813
00814 Bool
00815 CardinalityDescription::compare(CardinalityDescription *card)
00816 {
00817 if (!card)
00818 return False;
00819
00820 return getBottom() == card->getBottom() &&
00821 getBottomExcl() == card->getBottomExcl() &&
00822 getTop() == card->getTop() &&
00823 getTopExcl() == card->getTopExcl() ? True : False;
00824 }
00825
00826 Status
00827 post_etc_update(Database *db)
00828 {
00829 return Success;
00830 }
00831
00832
00833
00834
00835
00836 Status
00837 AttributeComponent::m_trace(FILE *, int, unsigned int, const RecMode *) const
00838 {
00839 return 0;
00840 }
00841
00842 Status
00843 AttributeComponent::checkUnique(const char *clsname, const char *msg)
00844 {
00845 OQL oql(db, "select %s.attrpath = \"%s\"", clsname, getAttrpath().c_str());
00846 OidArray oid_arr;
00847 Status s = oql.execute(oid_arr);
00848 if (s) return s;
00849 if (oid_arr.getCount())
00850 return Exception::make(IDB_ERROR, "%s '%s' already "
00851 "exist", msg, getAttrpath().c_str());
00852 return Success;
00853 }
00854
00855 std::string
00856 AttributeComponent::makeAttrpath(const Class *cls)
00857 {
00858 std::string attrpath = getAttrpath();
00859 const char *p = strchr(attrpath.c_str(), '.');
00860 assert(p);
00861 return std::string(cls->getName()) + "." + std::string(p+1);
00862 }
00863
00864 Status
00865 AttributeComponent::find(Database *db, const Class *cls,
00866 AttributeComponent *&cattr_comp)
00867 {
00868 std::string attrpath = makeAttrpath(cls);
00869 char *name = strdup(getName().c_str());
00870 char *p = strchr(name, ':');
00871 assert(p);
00872 *p = 0;
00873 std::string newname = std::string(name) + ":" + attrpath;
00874 free(name);
00875 cattr_comp = 0;
00876 Status s = cls->getAttrComp(newname.c_str(), cattr_comp);
00877 if (s) return s;
00878 return Success;
00879 }
00880
00881 AttributeComponent *
00882 AttributeComponent::xclone(Database *, const Class *)
00883 {
00884 abort();
00885 return 0;
00886 }
00887
00888
00889
00890
00891
00892 NotNullConstraint::NotNullConstraint(Database *_db, Class *cls,
00893 const char *attrpath,
00894 Bool propagate) :
00895 AttributeComponent(_db, (const Dataspace *)0, 1)
00896 {
00897 initialize(_db);
00898 db = _db;
00899 setClassOwner(cls);
00900 setAttrpath(attrpath);
00901 setName(genName());
00902 setPropagate(propagate);
00903 }
00904
00905 static const char *
00906 getPropagString(const AttributeComponent *comp)
00907 {
00908 static std::string s;
00909 s = ", propagate = ";
00910 s += comp->getPropagate() ? "on" : "off";
00911 return s.c_str();
00912 }
00913
00914 Status
00915 NotNullConstraint::m_trace(FILE *fd, int indent, unsigned int flags,
00916 const RecMode *rcm) const
00917 {
00918 Status s = Success;
00919 char *indent_str = make_indent(indent);
00920 Bool tr = False;
00921
00922 fprintf(fd, "constraint<notnull%s> on %s", getPropagString(this), getAttrpath().c_str());
00923
00924 if (rcm->getType() == RecMode_FullRecurs)
00925 {
00926 fprintf(fd, " ");
00927 s = ObjectPeer::trace_realize(this, fd, indent + INDENT_INC, flags, rcm);
00928 tr = True;
00929 }
00930
00931 fprintf(fd, "%s", (tr ? indent_str : ""));
00932 if ((flags & CompOidTrace) == CompOidTrace)
00933 fprintf(fd, " {%s}", oid.getString());
00934 delete_indent(indent_str);
00935 return s;
00936 }
00937
00938 const char *
00939 NotNullConstraint::genName() const
00940 {
00941 static std::string s;
00942 s = std::string("notnull") + ":" + getAttrpath();
00943 return s.c_str();
00944 }
00945
00946 Status
00947 NotNullConstraint::realize(const RecMode *rcm)
00948 {
00949 Status s;
00950
00951 Bool creating = IDBBOOL(!getOid().isValid());
00952 if (creating) {
00953 s = checkUnique("notnull_constraint", "notnull constraint");
00954 if (s) return s;
00955 }
00956
00957 s = AttributeComponent::realize(rcm);
00958 if (s) return s;
00959 if (creating)
00960 return StatusMake(constraintCreate(db->getDbHandle(),
00961 oid.getOid()));
00962 return Success;
00963 }
00964
00965 Status
00966 NotNullConstraint::remove(const RecMode *rcm)
00967 {
00968 RPCStatus rpc_status =
00969 constraintDelete(db->getDbHandle(), oid.getOid(),
00970 getUserData(attrcomp_delete_ud) ? 1 : 0);
00971
00972 if (rpc_status)
00973 return StatusMake(rpc_status);
00974 return AttributeComponent::remove(rcm);
00975 }
00976
00977 int
00978 NotNullConstraint::getInd() const
00979 {
00980 return Class::NotnullConstraint_C;
00981 }
00982
00983 AttributeComponent *
00984 NotNullConstraint::xclone(Database *db, const Class *cls)
00985 {
00986 std::string str = makeAttrpath(cls);
00987 return new NotNullConstraint(db, (Class *)cls, str.c_str(),
00988 getPropagate());
00989 }
00990
00991
00992
00993
00994
00995 UniqueConstraint::UniqueConstraint(Database *_db, Class *cls,
00996 const char *attrpath,
00997 Bool propagate) :
00998 AttributeComponent(_db, (const Dataspace *)0, 1)
00999 {
01000 initialize(_db);
01001 db = _db;
01002 setClassOwner(cls);
01003 setAttrpath(attrpath);
01004 setName(genName());
01005 setPropagate(propagate);
01006 }
01007
01008 Status
01009 UniqueConstraint::m_trace(FILE *fd, int indent, unsigned int flags, const RecMode* rcm) const
01010 {
01011 Status s = Success;
01012 char *indent_str = make_indent(indent);
01013 Bool tr = False;
01014
01015 if (db)
01016 db->transactionBegin();
01017 fprintf(fd, "constraint<unique%s> on %s", getPropagString(this), getAttrpath().c_str());
01018 if (rcm->getType() == RecMode_FullRecurs)
01019 {
01020 fprintf(fd, " ");
01021 s = ObjectPeer::trace_realize(this, fd, indent + INDENT_INC, flags, rcm);
01022 tr = True;
01023 }
01024
01025 if (db)
01026 db->transactionCommit();
01027
01028 fprintf(fd, "%s", (tr ? indent_str : ""));
01029 if ((flags & CompOidTrace) == CompOidTrace)
01030 fprintf(fd, "{%s}", oid.getString());
01031 delete_indent(indent_str);
01032 return s;
01033 }
01034
01035 const char *
01036 UniqueConstraint::genName() const
01037 {
01038 static std::string s;
01039 s = std::string("unique") + ":" + getAttrpath();
01040 return s.c_str();
01041 }
01042
01043 Status
01044 UniqueConstraint::realize(const RecMode *rcm)
01045 {
01046 Status s;
01047
01048 Bool creating = IDBBOOL(!getOid().isValid());
01049 if (creating) {
01050 s = checkUnique("unique_constraint", "unique constraint");
01051 if (s) return s;
01052 }
01053
01054 s = AttributeComponent::realize(rcm);
01055 if (s) return s;
01056 if (creating)
01057 return StatusMake(constraintCreate(db->getDbHandle(),
01058 oid.getOid()));
01059 return Success;
01060 }
01061
01062 Status
01063 UniqueConstraint::remove(const RecMode *rcm)
01064 {
01065 RPCStatus rpc_status =
01066 constraintDelete(db->getDbHandle(), oid.getOid(),
01067 getUserData(attrcomp_delete_ud) ? 1 : 0);
01068
01069 if (rpc_status)
01070 return StatusMake(rpc_status);
01071 return AttributeComponent::remove(rcm);
01072 }
01073
01074 AttributeComponent *
01075 UniqueConstraint::xclone(Database *db, const Class *cls)
01076 {
01077 std::string str = makeAttrpath(cls);
01078 return new UniqueConstraint(db, (Class *)cls, str.c_str(),
01079 getPropagate());
01080 }
01081
01082 int
01083 UniqueConstraint::getInd() const
01084 {
01085 return Class::UniqueConstraint_C;
01086 }
01087
01088
01089
01090
01091
01092
01093
01094
01095
01096
01097 CardinalityConstraint_Test::CardinalityConstraint_Test
01098 (Database *, Class *, const char *attrname, int, int, int, int)
01099 {
01100 }
01101
01102 const char *
01103 CardinalityConstraint_Test::genName() const
01104 {
01105 return 0;
01106 }
01107
01108 Status CardinalityConstraint_Test::m_trace(FILE *, int, unsigned int, const RecMode *) const
01109 {
01110 return 0;
01111 }
01112
01113 static int maxint;
01114
01115
01116 Index::Index(Database *, const char *, const char *)
01117 {
01118 }
01119
01120 Status Index::realize(const RecMode*)
01121 {
01122 return 0;
01123 }
01124
01125 Status
01126 Index::report(eyedbsm::DbHandle *sedbh, const Oid &idxoid)
01127 {
01128 abort();
01129 return Success;
01130 }
01131
01132 Status Index::remove(const RecMode*)
01133 {
01134 return 0;
01135 }
01136
01137 Status Index::s_trace(FILE *, Bool, unsigned int flags) const
01138 {
01139 return 0;
01140 }
01141
01142 void Index::userInitialize()
01143 {
01144 idx = 0;
01145 }
01146
01147 void Index::userCopy(const Object &)
01148 {
01149 idx = 0;
01150 }
01151
01152 Status
01153 Index::makeDataspace(Database *_db, const Dataspace *&dataspace) const
01154 {
01155 Bool isnull;
01156 short dspid = getDspid(&isnull);
01157 if (!isnull)
01158 return _db->getDataspace(dspid, dataspace);
01159 dataspace = 0;
01160 return Success;
01161 }
01162
01163 Status
01164 Index::getCount(unsigned int &count)
01165 {
01166 RPCStatus rpc_status =
01167 indexGetCount(db->getDbHandle(), oid.getOid(), (int *)&count);
01168
01169 return StatusMake(rpc_status);
01170 }
01171
01172 Status
01173 Index::getStats(IndexStats *&stats)
01174 {
01175 RPCStatus rpc_status =
01176 indexGetStats(db->getDbHandle(), oid.getOid(), (Data *)&stats);
01177 if (rpc_status)
01178 return StatusMake(rpc_status);
01179
01180 const Dataspace *dataspace;
01181 Status s = makeDataspace(db, dataspace);
01182 if (s) return s;
01183 if (dataspace)
01184 stats->idximpl->setDataspace(dataspace);
01185
01186 if (asHashIndex() && asHashIndex()->getHashMethod())
01187 stats->idximpl->setHashMethod(asHashIndex()->getHashMethod());
01188 return Success;
01189 }
01190
01191 Status
01192 Index::getStats(std::string &xstats, Bool dspImpl, Bool full,
01193 const char *indent)
01194 {
01195 IndexStats *stats = 0;
01196 RPCStatus rpc_status =
01197 indexGetStats(db->getDbHandle(), oid.getOid(), (Data *)&stats);
01198 if (rpc_status)
01199 return StatusMake(rpc_status);
01200 xstats = (stats ? stats->toString(dspImpl, full, indent) : std::string(""));
01201 delete stats;
01202 return Success;
01203 }
01204
01205 Status
01206 Index::simulate(const IndexImpl &idximpl, std::string &xstats,
01207 Bool dspImpl, Bool full, const char *indent)
01208 {
01209 IndexStats *stats = 0;
01210 Status s = simulate(idximpl, stats);
01211 if (s) return s;
01212 xstats = (stats ? stats->toString(dspImpl, full, indent) : std::string(""));
01213 return Success;
01214 }
01215
01216 Status
01217 Index::simulate(const IndexImpl &idximpl, IndexStats *&stats)
01218 {
01219 Data data;
01220 Offset offset = 0;
01221 Size size = 0;
01222 Status s = IndexImpl::code(data, offset, size, &idximpl);
01223 if (s) return s;
01224
01225 RPCStatus rpc_status =
01226 indexSimulStats(db->getDbHandle(), oid.getOid(), data, size, (Data *)&stats);
01227 free(data);
01228 return StatusMake(rpc_status);
01229 }
01230
01231 void Index::userGarbage()
01232 {
01233
01234 }
01235
01236 void AttributeComponent::userInitialize()
01237 {
01238
01239 }
01240
01241 void AttributeComponent::userCopy(const Object &)
01242 {
01243
01244 }
01245
01246 void AttributeComponent::userGarbage()
01247 {
01248
01249 }
01250
01251 int
01252 Index::getInd() const
01253 {
01254 return Class::Index_C;
01255 }
01256
01257 short
01258 Index::get_dspid() const
01259 {
01260 Bool isnull;
01261 short dspid = getDspid(&isnull);
01262
01263 if (isnull)
01264 return Dataspace::DefaultDspid;
01265
01266 return dspid;
01267 }
01268
01269 inline int
01270 IDXTYPE(const Index *idx)
01271 {
01272 return idx->asHashIndex() ? 1 : 0;
01273 }
01274
01275 Status
01276 Index::getDefaultDataspace(const Dataspace *&dataspace) const
01277 {
01278 short dspid = get_dspid();
01279
01280 if (dspid == Dataspace::DefaultDspid) {
01281 dataspace = 0;
01282 return Success;
01283 }
01284
01285 return db->getDataspace(dspid, dataspace);
01286 }
01287
01288 #define NEW_INDEX_MOVE
01289
01290 static const char index_move[] = "eyedb:move";
01291 extern char index_backend[];
01292
01293 Status
01294 Index::setDefaultDataspace(const Dataspace *dataspace)
01295 {
01296 Status s = setDspid(dataspace->getId());
01297 if (s) return s;
01298
01299 #ifdef NEW_INDEX_MOVE
01300 void *ud;
01301 if (!getUserData(index_move))
01302 ud = setUserData(index_backend, AnyUserData);
01303 s = store();
01304 if (!getUserData(index_move))
01305 setUserData(index_backend, ud);
01306 #else
01307 s = store();
01308 #endif
01309 if (s) return s;
01310
01311 Oid idxoid = getIdxOid();
01312 if (!idxoid.isValid()) return Success;
01313
01314
01315
01316
01317 #ifdef NEW_INDEX_MOVE
01318
01319 #endif
01320
01321 Index *idx;
01322 s = db->reloadObject(oid, (Object *&)idx);
01323 if (s) return s;
01324 #ifdef NEW_INDEX_MOVE
01325 if (!getUserData(index_move))
01326 assert(idx->getIdxOid() == getIdxOid());
01327 #endif
01328 idxoid = idx->getIdxOid();
01329 idx->release();
01330
01331 RPCStatus rpc_status =
01332 setDefaultIndexDataspace(db->getDbHandle(), idxoid.getOid(),
01333 IDXTYPE(this), dataspace->getId());
01334
01335 return StatusMake(rpc_status);
01336 }
01337
01338 Status
01339 Index::getObjectLocations(ObjectLocationArray &locarr)
01340 {
01341 const Oid &idxoid = getIdxOid();
01342 if (!idxoid.isValid()) return Success;
01343
01344 RPCStatus rpc_status = getIndexLocations(db->getDbHandle(),
01345 idxoid.getOid(),
01346 IDXTYPE(this),
01347 (void *)&locarr);
01348 return StatusMake(rpc_status);
01349 }
01350
01351 Status
01352 Index::move(const Dataspace *dataspace) const
01353 {
01354 #ifdef NEW_INDEX_MOVE
01355 Index *mthis = const_cast<Index *>(this);
01356 void *ud = mthis->setUserData(index_move, AnyUserData);
01357 Status s = mthis->setDefaultDataspace(dataspace);
01358 mthis->setUserData(index_move, ud);
01359 return s;
01360 #else
01361 const Oid &idxoid = getIdxOid();
01362 if (!idxoid.isValid()) return Success;
01363 RPCStatus rpc_status = moveIndex(db->getDbHandle(), idxoid.getOid(),
01364 IDXTYPE(this),
01365 dataspace->getId());
01366 return StatusMake(rpc_status);
01367 #endif
01368 }
01369
01370 HashIndex::HashIndex(Database *_db, Class *cls,
01371 const char *pathattr,
01372 Bool propagate, Bool is_string,
01373 const Dataspace *dataspace,
01374 int key_count, BEMethod_C *mth,
01375 const int *impl_hints, int impl_hints_cnt)
01376 : Index(_db, (const Dataspace *)0, 1)
01377 {
01378 initialize(_db);
01379 db = _db;
01380 setClassOwner(cls);
01381 setAttrpath(pathattr);
01382 setKeyCount(key_count);
01383 setIsString((Bool)is_string);
01384 setPropagate(propagate);
01385 if (dataspace)
01386 setDspid(dataspace->getId());
01387 setHashMethod(mth);
01388 setName(genName());
01389 for (int i = 0; i < impl_hints_cnt; i++)
01390 setImplHints(i, impl_hints[i]);
01391 }
01392
01393 struct KeyValue {
01394 const char *key;
01395 const char *value;
01396 void set(const char *_key, const char *_value) {
01397 key = _key;
01398 value = _value;
01399 }
01400 };
01401
01402 struct KeyValueArray {
01403 int kalloc;
01404 int cnt;
01405 KeyValue *kvalues;
01406 KeyValueArray() {
01407 kalloc = cnt = 0;
01408 kvalues = 0;
01409 }
01410 void add(const char *k, const char *v) {
01411 if (cnt >= kalloc) {
01412 kalloc += 8;
01413 kvalues = (KeyValue *)realloc(kvalues, kalloc * sizeof(KeyValue));
01414 }
01415 kvalues[cnt++].set(k, v);
01416 }
01417 void trace() {
01418 for (int i = 0; i < cnt; i++)
01419 printf("'%s' <-> '%s'\n", kvalues[i].key, (kvalues[i].value ?
01420 kvalues[i].value : "NULL"));
01421 }
01422 ~KeyValueArray() {
01423 free(kvalues);
01424 }
01425 };
01426
01427 HashIndex::HashIndex(Database *_db,
01428 Class *cls, const char *attrpath,
01429 Bool propagate, Bool is_string,
01430 const IndexImpl *idximpl)
01431 : Index(_db, (const Dataspace *)0, 1)
01432 {
01433 initialize(_db);
01434 db = _db;
01435 setClassOwner(cls);
01436 setAttrpath(attrpath);
01437 setKeyCount(idximpl->getKeycount());
01438 setIsString((Bool)is_string);
01439 setPropagate(propagate);
01440 setHashMethod(idximpl->getHashMethod());
01441 if (idximpl->getDataspace())
01442 setDspid(idximpl->getDataspace()->getId());
01443 setName(genName());
01444
01445 unsigned int impl_hints_cnt;
01446 const int *impl_hints = idximpl->getImplHints(impl_hints_cnt);
01447
01448 for (int i = 0; i < impl_hints_cnt; i++)
01449 setImplHints(i, impl_hints[i]);
01450 }
01451
01452 Status
01453 HashIndex::make(Database *db, Class *cls, const char *attrpath,
01454 Bool propagate, Bool is_string,
01455 const char *hints, HashIndex *&idx)
01456 {
01457 idx = 0;
01458 IndexImpl *idximpl;
01459 Status s = IndexImpl::make(db, IndexImpl::Hash, hints, idximpl,
01460 is_string);
01461 if (s) return s;
01462
01463 idx = new HashIndex(db, cls, attrpath, propagate, is_string,
01464 idximpl);
01465 return Success;
01466 }
01467
01468 Status HashIndex::check(Class *) const
01469 {
01470 return 0;
01471 }
01472
01473 Status HashIndex::make(Class *)
01474 {
01475 return 0;
01476 }
01477
01478
01479
01480 Bool
01481 Index::compareHints(Index *idx)
01482 {
01483 unsigned int cnt1 = getImplHintsCount();
01484 unsigned int cnt2 = idx->getImplHintsCount();
01485 int cnt = cnt1 < cnt2 ? cnt1 : cnt2;
01486
01487 #ifdef REIMPL_TRACE
01488 printf("compareHints: cnt %d vs %d\n", cnt1, cnt2);
01489 #endif
01490 for (unsigned int i = 0; i < cnt; i++) {
01491 #ifdef REIMPL_TRACE
01492 printf("hints[%d] %d %d\n", i, getImplHints(i), idx->getImplHints(i));
01493 #endif
01494 int val = getImplHints(i);
01495 if (val && val != idx->getImplHints(i))
01496 return False;
01497 if (!val)
01498 setImplHints(i, idx->getImplHints(i));
01499 }
01500
01501 return True;
01502 }
01503
01504 Status
01505 Index::reimplement(const IndexImpl &idximpl, Index *&idx)
01506 {
01507 IndexImpl::Type idxtype = idximpl.getType();
01508
01509 if ((idxtype == IndexImpl::Hash && asHashIndex()) ||
01510 (idxtype == IndexImpl::BTree && asBTreeIndex())) {
01511 setImplementation(&idximpl);
01512 idx = this;
01513 return store();
01514 }
01515
01516 unsigned int impl_hints_cnt;
01517 const int *impl_hints = idximpl.getImplHints(impl_hints_cnt);
01518
01519
01520
01521
01522
01523
01524
01525 Class *clsown = getClassOwner();
01526 if (idxtype == IndexImpl::Hash) {
01527 BEMethod_C *mth = idximpl.getHashMethod();
01528 idx = new HashIndex(db, clsown, getAttrpath().c_str(),
01529 getPropagate(), getIsString(),
01530 idximpl.getDataspace(),
01531 idximpl.getKeycount(), mth,
01532 impl_hints, impl_hints_cnt);
01533 }
01534 else
01535 idx = new BTreeIndex(db, clsown, getAttrpath().c_str(),
01536 getPropagate(), getIsString(),
01537 idximpl.getDataspace(),
01538 idximpl.getDegree(),
01539 impl_hints, impl_hints_cnt);
01540
01541 Oid idxoid = getIdxOid();
01542 setIdxOid(Oid::nullOid);
01543 setPropagate(False);
01544
01545 setImplHints(IDB_IDX_MAGIC_HINTS, IDB_IDX_MAGIC_HINTS_VALUE);
01546 Status s = store();
01547
01548 if (!s)
01549 s = remove();
01550
01551 if (s) {
01552 idx->release();
01553 idx = 0;
01554 return s;
01555 }
01556
01557 idx->setIdxOid(idxoid);
01558 s = idx->store();
01559 if (s) {
01560 idx->release();
01561 idx = 0;
01562 return s;
01563 }
01564 return Success;
01565 }
01566
01567 Bool
01568 HashIndex::compareHashMethod(HashIndex *idx)
01569 {
01570 BEMethod_C *mth1 = getHashMethod();
01571 BEMethod_C *mth2 = idx->getHashMethod();
01572
01573 if ((!mth1 && mth2) || (mth1 && !mth2))
01574 return False;
01575
01576 if (mth1 && mth1->getOid() != mth2->getOid())
01577 return False;
01578
01579 return True;
01580 }
01581
01582 Status HashIndex::realize(const RecMode*rcm)
01583 {
01584 Status s;
01585
01586 Bool backend_updating = IDBBOOL(getUserData(index_backend));
01587 Bool creating = IDBBOOL(!backend_updating && !getOid().isValid());
01588 Bool updating = False;
01589 bool index_moving = (getUserData(index_move) != 0);
01590
01591
01592
01593
01594
01595
01596 if (creating) {
01597 #ifndef DUP_INDEX
01598 s = checkUnique("index", "index");
01599 if (s) return s;
01600 #endif
01601 }
01602 else if (!backend_updating) {
01603 HashIndex *idx;
01604 s = db->reloadObject(getOid(), (Object *&)idx);
01605 if (s) return s;
01606 if ((getKeyCount() && idx->getKeyCount() != getKeyCount()) ||
01607 idx->getDspid () != getDspid() ||
01608 !compareHints(idx) ||
01609 !compareHashMethod(idx)) {
01610 #ifdef REIMPL_TRACE
01611 printf("Hashindex: should reimplement: "
01612 "key_count: %d v.s %d "
01613 "dsp_id %d: v.s %d "
01614 "compareHints: %d "
01615 "compareHashMethod: %d\n",
01616 getKeyCount(), idx->getKeyCount(),
01617 getDspid(), idx->getDspid(),
01618 compareHints(idx),
01619 compareHashMethod(idx));
01620 #endif
01621 updating = True;
01622 }
01623 #ifdef REIMPL_TRACE
01624 else
01625 printf("Hashindex: should NOT reimplement\n");
01626 #endif
01627 if (!getKeyCount())
01628 setKeyCount(idx->getKeyCount());
01629 idx->release();
01630 }
01631
01632 BEMethod_C *mth = getHashMethod();
01633 if (mth)
01634 setHashMethod(mth);
01635 else
01636 setHashMethodOid(Oid::nullOid);
01637
01638 s = AttributeComponent::realize(rcm);
01639
01640 if (s) return s;
01641
01642 if (creating || updating)
01643 return StatusMake(indexCreate(db->getDbHandle(),
01644 index_moving,
01645 oid.getOid()));
01646
01647 return Success;
01648 }
01649
01650 Status HashIndex::report(eyedbsm::DbHandle *sedbh, const Oid &idxoid)
01651 {
01652 eyedbsm::HIdx hidx(sedbh, idxoid.getOid());
01653 if (hidx.status())
01654 return Exception::make(IDB_ERROR, eyedbsm::statusGet(hidx.status()));
01655
01656 const eyedbsm::HIdx::_Idx &xidx = hidx.getIdx();
01657 setKeyCount(xidx.key_count);
01658 setImplHintsCount(eyedbsm::HIdxImplHintsCount);
01659 for (int n = 0; n < eyedbsm::HIdxImplHintsCount; n++)
01660 setImplHints(n, xidx.impl_hints[n]);
01661 #ifdef REIMPL_TRACE
01662 printf("Hashindex::report\n");
01663 #endif
01664 return Success;
01665 }
01666
01667 Status HashIndex::remove(const RecMode*)
01668 {
01669
01670 RPCStatus rpc_status =
01671 indexRemove(db->getDbHandle(), oid.getOid(),
01672 getUserData(attrcomp_delete_ud) ? 1 : 0);
01673
01674 if (rpc_status)
01675 return StatusMake(rpc_status);
01676
01677
01678 return AttributeComponent::remove();
01679 }
01680
01681 #define PREF(FD, VAR) \
01682 if (!VAR) { \
01683 fprintf(FD, ", hints = \""); \
01684 VAR = True; \
01685 } \
01686 else \
01687 fprintf(FD, " ")
01688
01689 Status HashIndex::s_trace(FILE *fd, Bool is_string, unsigned int flags) const
01690 {
01691 if (!(flags & AttrCompDetailTrace)) {
01692 fprintf(fd, "index<hash> on %s", getAttrpath().c_str());
01693 return Success;
01694 }
01695
01696 fprintf(fd, "index<type = hash");
01697 Bool hints = False;
01698
01699 const Dataspace *dataspace;
01700 Status s = makeDataspace(db, dataspace);
01701 if (s) return s;
01702 if (dataspace) {
01703 PREF(fd, hints);
01704 fprintf(fd, "dataspace = %s;", dataspace->getName());
01705 }
01706
01707 const BEMethod_C *mth = getHashMethod();
01708 if (mth) {
01709 PREF(fd, hints);
01710 fprintf(fd, "key_function = %s::%s;", mth->getClassOwner()->getName(),
01711 mth->getEx()->getExname().c_str());
01712 }
01713
01714 if (getKeyCount()) {
01715 PREF(fd, hints);
01716 fprintf(fd, "key_count = %d;", getKeyCount());
01717 }
01718
01719 unsigned int cnt = getImplHintsCount();
01720
01721 #ifdef IDB_SKIP_HASH_XCOEF
01722 if (cnt > eyedbsm::HIdx::XCoef_Hints)
01723 cnt = eyedbsm::HIdx::XCoef_Hints;
01724 #endif
01725
01726 for (unsigned int i = 0; i < cnt; i++) {
01727 if (is_string) {
01728 if (i == eyedbsm::HIdx::IniObjCnt_Hints)
01729 continue;
01730 }
01731 else if ((i) == eyedbsm::HIdx::IniSize_Hints &&
01732 getImplHints(eyedbsm::HIdx::IniObjCnt_Hints))
01733 continue;
01734 int val = getImplHints(i);
01735
01736 if (IndexImpl::isHashHintImplemented(i)) {
01737 PREF(fd, hints);
01738 fprintf(fd, "%s = %d;", IndexImpl::hashHintToStr(i), val);
01739 }
01740 }
01741
01742 fprintf(fd, "%s%s> on %s", (hints ? "\"" : ""), getPropagString(this),
01743 getAttrpath().c_str());
01744
01745 return Success;
01746 }
01747
01748 Status HashIndex::m_trace(FILE *fd, int indent, unsigned int flags,
01749 const RecMode *rcm) const
01750 {
01751 Status s = Success;
01752 s = s_trace(fd, IDBBOOL(flags & IDB_ATTR_IS_STRING), flags);
01753 if (s) return s;
01754
01755 if ((flags & CompOidTrace) == CompOidTrace ||
01756 rcm->getType() == RecMode_FullRecurs)
01757 fprintf(fd, " {%s}", oid.getString());
01758
01759 if (rcm->getType() == RecMode_FullRecurs)
01760 {
01761 fprintf(fd, " ");
01762 s = ObjectPeer::trace_realize(this, fd, indent + INDENT_INC, flags, rcm);
01763 }
01764 return s;
01765 }
01766
01767 AttributeComponent *
01768 HashIndex::xclone(Database *db, const Class *cls)
01769 {
01770 int impl_hints[eyedbsm::HIdxImplHintsCount];
01771 memset(impl_hints, 0, sizeof(int) * eyedbsm::HIdxImplHintsCount);
01772 unsigned int impl_hints_cnt = getImplHintsCount();
01773 for (int i = 0; i < impl_hints_cnt; i++)
01774 impl_hints[i] = getImplHints(i);
01775 Bool isnull;
01776
01777 const Dataspace *dataspace;
01778 Status s = makeDataspace(db, dataspace);
01779 if (s) throw *s;
01780
01781 std::string str = makeAttrpath(cls);
01782 return new HashIndex(db, (Class *)cls, str.c_str(),
01783 getPropagate(), getIsString(),
01784 dataspace, getKeyCount(), getHashMethod(),
01785 impl_hints, impl_hints_cnt);
01786 }
01787
01788 Status
01789 HashIndex::setImplementation(const IndexImpl *idximpl)
01790 {
01791 if (idximpl->getType() == IndexImpl::BTree)
01792 return Exception::make(IDB_ERROR,
01793 "cannot change dynamically hash index "
01794 "implementation to btree index using the "
01795 "setImplementation() method: use the "
01796 "reimplement() method");
01797 setKeyCount(idximpl->getKeycount());
01798 if (idximpl->getHashMethod())
01799 setHashMethod(idximpl->getHashMethod());
01800 else
01801 setHashMethodOid(Oid::nullOid);
01802
01803 if (idximpl->getDataspace())
01804 setDspid(idximpl->getDataspace()->getId());
01805
01806 unsigned int impl_hints_cnt;
01807 const int *impl_hints = idximpl->getImplHints(impl_hints_cnt);
01808 setImplHintsCount(impl_hints_cnt);
01809 for (int i = 0; i < impl_hints_cnt; i++)
01810 setImplHints(i, impl_hints[i]);
01811
01812 return Success;
01813 }
01814
01815 Status
01816 HashIndex::getImplementation(IndexImpl *&idximpl, Bool remote) const
01817 {
01818 const Dataspace *dataspace;
01819 Status s = makeDataspace(db, dataspace);
01820 if (s) return s;
01821
01822 if (!remote) {
01823 unsigned int cnt = getImplHintsCount();
01824 int *impl_hints = (cnt ? new int [cnt] : 0);
01825 for (unsigned int i = 0; i < cnt; i++)
01826 impl_hints[i] = getImplHints(i);
01827 idximpl =
01828 new IndexImpl(IndexImpl::Hash, dataspace, getKeyCount(),
01829 (BEMethod_C *)getHashMethod(),
01830 impl_hints, cnt);
01831 delete [] impl_hints;
01832 return Success;
01833 }
01834
01835 RPCStatus rpc_status =
01836 indexGetImplementation(db->getDbHandle(),
01837 oid.getOid(), (Data *)&idximpl);
01838 if (rpc_status)
01839 return StatusMake(rpc_status);
01840
01841 idximpl->setHashMethod((BEMethod_C *)getHashMethod());
01842 idximpl->setDataspace(dataspace);
01843 return Success;
01844 }
01845
01846 const char *HashIndex::genName() const
01847 {
01848 static std::string s;
01849 s = std::string("index") + ":" + getAttrpath();
01850 return s.c_str();
01851 }
01852
01853 BTreeIndex::BTreeIndex(Database *_db, Class *cls,
01854 const char *pathattr,
01855 Bool propagate, Bool is_string,
01856 const Dataspace *dataspace, int degree,
01857 const int *impl_hints , int impl_hints_cnt) : Index(_db, (const Dataspace *)0, 1)
01858 {
01859 initialize(_db);
01860 db = _db;
01861 setClassOwner(cls);
01862 setAttrpath(pathattr);
01863 setIsString((Bool)is_string);
01864 setPropagate(propagate);
01865 setName(genName());
01866 if (dataspace)
01867 setDspid(dataspace->getId());
01868 setDegree(degree);
01869 }
01870
01871 BTreeIndex::BTreeIndex(Database *_db, Class *cls,
01872 const char *pathattr,
01873 Bool propagate, Bool is_string,
01874 const IndexImpl *idximpl) :
01875 Index(_db, (const Dataspace *)0, 1)
01876 {
01877 initialize(_db);
01878 db = _db;
01879 setClassOwner(cls);
01880 setAttrpath(pathattr);
01881 setIsString((Bool)is_string);
01882 setPropagate(propagate);
01883 setName(genName());
01884 setDegree(idximpl->getDegree());
01885 if (idximpl->getDataspace())
01886 setDspid(idximpl->getDataspace()->getId());
01887
01888 unsigned int impl_hints_cnt;
01889 const int *impl_hints = idximpl->getImplHints(impl_hints_cnt);
01890
01891 for (int i = 0; i < impl_hints_cnt; i++)
01892 setImplHints(i, impl_hints[i]);
01893 }
01894
01895 Status
01896 BTreeIndex::make(Database *db, Class *cls, const char *attrpath,
01897 Bool propagate, Bool is_string,
01898 const char *hints, BTreeIndex *&idx)
01899 {
01900 idx = 0;
01901 IndexImpl *idximpl;
01902 Status s = IndexImpl::make(db, IndexImpl::BTree, hints, idximpl,
01903 is_string);
01904 if (s) return s;
01905
01906 idx = new BTreeIndex(db, cls, attrpath, propagate, is_string, idximpl);
01907 return Success;
01908 }
01909
01910 Status BTreeIndex::check(Class *) const
01911 {
01912 return 0;
01913 }
01914
01915 Status BTreeIndex::realize(const RecMode *rcm)
01916 {
01917 Status s;
01918
01919 Bool backend_updating = IDBBOOL(getUserData(index_backend));
01920 Bool creating = IDBBOOL(!backend_updating && !getOid().isValid());
01921 Bool updating = False;
01922 bool index_moving = (getUserData(index_move) != 0);
01923
01924
01925
01926
01927
01928 if (creating) {
01929 #ifndef DUP_INDEX
01930 s = checkUnique("index", "index");
01931 if (s) return s;
01932 #endif
01933 }
01934 else if (!backend_updating) {
01935 BTreeIndex *idx;
01936 s = db->reloadObject(getOid(), (Object *&)idx);
01937 if (s) return s;
01938 if ((getDegree() && idx->getDegree() != getDegree()) ||
01939 idx->getDspid () != getDspid() ||
01940 !compareHints(idx)) {
01941 #ifdef REIMPL_TRACE
01942 printf("BTreeindex: should reimplement: "
01943 "degree: %d %d "
01944 "dspid: %d %d\n",
01945 getDegree(), idx->getDegree(),
01946 getDspid(), idx->getDspid());
01947 #endif
01948 updating = True;
01949 }
01950 #ifdef REIMPL_TRACE
01951 else
01952 printf("BTreeindex: should NOT reimplement\n");
01953 #endif
01954 if (!getDegree())
01955 setDegree(idx->getDegree());
01956 idx->release();
01957 }
01958
01959 s = AttributeComponent::realize(rcm);
01960 if (s) return s;
01961 if (creating || updating)
01962 return StatusMake(indexCreate(db->getDbHandle(),
01963 index_moving,
01964 oid.getOid()));
01965
01966 return Success;
01967 }
01968
01969 Status BTreeIndex::report(eyedbsm::DbHandle *sedbh, const Oid &idxoid)
01970 {
01971 eyedbsm::BIdx bidx(sedbh, *idxoid.getOid());
01972 if (bidx.status())
01973 return Exception::make(IDB_ERROR, eyedbsm::statusGet(bidx.status()));
01974
01975 setDegree(bidx.getDegree());
01976 #ifdef REIMPL_TRACE
01977 printf("Btreeindex::report ");
01978 trace();
01979 #endif
01980 return Success;
01981 }
01982
01983 Status BTreeIndex::remove(const RecMode* )
01984 {
01985 RPCStatus rpc_status =
01986 indexRemove(db->getDbHandle(), oid.getOid(),
01987 getUserData(attrcomp_delete_ud) ? 1 : 0);
01988
01989 if (rpc_status)
01990 return StatusMake(rpc_status);
01991
01992 return AttributeComponent::remove();
01993 }
01994
01995 Status BTreeIndex::s_trace(FILE *fd, Bool is_string, unsigned int flags) const
01996 {
01997 if (!(flags & AttrCompDetailTrace)) {
01998 fprintf(fd, "index<btree> on %s", getAttrpath().c_str());
01999 return Success;
02000 }
02001
02002 fprintf(fd, "index<type = btree");
02003 Bool hints = False;
02004
02005 const Dataspace *dataspace;
02006 Status s = makeDataspace(db, dataspace);
02007 if (s) return s;
02008
02009 if (dataspace) {
02010 PREF(fd, hints);
02011 fprintf(fd, "dataspace = %s;", dataspace->getName());
02012 }
02013
02014 if (getDegree()) {
02015 PREF(fd, hints);
02016 fprintf(fd, "degree = %d;", getDegree());
02017 }
02018
02019 fprintf(fd, "%s%s> on %s", (hints ? "\"" : ""), getPropagString(this),
02020 getAttrpath().c_str());
02021
02022 return Success;
02023 }
02024
02025 Status
02026 BTreeIndex::m_trace(FILE *fd, int indent, unsigned int flags,
02027 const RecMode *rcm) const
02028 {
02029 Status s = Success;
02030 s = s_trace(fd, False, flags);
02031 if (s) return s;
02032
02033
02034 if ((flags & CompOidTrace) == CompOidTrace ||
02035 rcm->getType() == RecMode_FullRecurs)
02036 fprintf(fd, " {%s}", oid.getString());
02037
02038 if (rcm->getType() == RecMode_FullRecurs)
02039 {
02040 fprintf(fd, " ");
02041 s = ObjectPeer::trace_realize(this, fd, indent + INDENT_INC, flags, rcm);
02042 }
02043 return s;
02044 }
02045
02046 AttributeComponent *
02047 BTreeIndex::xclone(Database *db, const Class *cls)
02048 {
02049 const Dataspace *dataspace;
02050 Status s = makeDataspace(db, dataspace);
02051 if (s) throw *s;
02052
02053 std::string str = makeAttrpath(cls);
02054 return new BTreeIndex(db, (Class *)cls, str.c_str(),
02055 getPropagate(), getIsString(),
02056 dataspace, getDegree(), 0, 0);
02057 }
02058
02059 Status
02060 BTreeIndex::setImplementation(const IndexImpl *idximpl)
02061 {
02062 if (idximpl->getType() == IndexImpl::Hash)
02063 return Exception::make(IDB_ERROR,
02064 "cannot change dynamically btree index "
02065 "implementation to hash index using the "
02066 "setImplementation() method: use the "
02067 "reimplement() method");
02068 setDegree(idximpl->getDegree());
02069 if (idximpl->getDataspace())
02070 setDspid(idximpl->getDataspace()->getId());
02071 unsigned int impl_hints_cnt;
02072 const int *impl_hints = idximpl->getImplHints(impl_hints_cnt);
02073 setImplHintsCount(impl_hints_cnt);
02074 for (int i = 0; i < impl_hints_cnt; i++)
02075 setImplHints(i, impl_hints[i]);
02076
02077 return Success;
02078 }
02079
02080 Status
02081 BTreeIndex::getImplementation(IndexImpl *&idximpl, Bool remote) const
02082 {
02083 const Dataspace *dataspace;
02084 Status s = makeDataspace(db, dataspace);
02085 if (s) return s;
02086
02087 if (!remote) {
02088 unsigned int cnt = getImplHintsCount();
02089 int *impl_hints = (cnt ? new int [cnt] : 0);
02090
02091 idximpl = new IndexImpl(IndexImpl::BTree, dataspace, getDegree(),
02092 0, impl_hints, cnt);
02093 delete [] impl_hints;
02094 return Success;
02095 }
02096
02097 RPCStatus rpc_status =
02098 indexGetImplementation(db->getDbHandle(),
02099 oid.getOid(), (Data *)&idximpl);
02100 if (rpc_status)
02101 return StatusMake(rpc_status);
02102
02103 idximpl->setDataspace(dataspace);
02104 return Success;
02105 }
02106
02107 const char *BTreeIndex::genName() const
02108 {
02109 static std::string s;
02110 s = std::string("index") + ":" + getAttrpath();
02111 return s.c_str();
02112 }
02113
02114
02115 Status
02116 CardinalityConstraint_Test::realize(const RecMode *rcm)
02117 {
02118 return 0;
02119 }
02120
02121 Status
02122 CardinalityConstraint_Test::remove(const RecMode *rcm)
02123 {
02124 return 0;
02125 }
02126
02127 int
02128 CardinalityConstraint_Test::getInd() const
02129 {
02130 return Class::CardinalityConstraint_C;
02131 }
02132
02133 int
02134 AttributeComponent::getInd() const
02135 {
02136 assert(0);
02137 return 0;
02138 }
02139
02140 CollAttrImpl::CollAttrImpl(Database *_db, Class *cls,
02141 const char *attrpath,
02142 Bool propagate,
02143 const Dataspace *dataspace,
02144 CollImpl::Type impl_type,
02145 int key_count_or_degree,
02146 BEMethod_C *mth,
02147 const int *impl_hints,
02148 int impl_hints_cnt)
02149 : AttributeComponent(_db, (const Dataspace *)0, 1)
02150 {
02151 initialize(_db);
02152 db = _db;
02153 setClassOwner(cls);
02154 setAttrpath(attrpath);
02155 setImplType(impl_type);
02156 setKeyCountOrDegree(key_count_or_degree);
02157 setPropagate(propagate);
02158 if (dataspace)
02159 setDspid(dataspace->getId());
02160 setHashMethod(mth);
02161 setName(genName());
02162 for (int i = 0; i < impl_hints_cnt; i++)
02163 setImplHints(i, impl_hints[i]);
02164 }
02165
02166 CollAttrImpl::CollAttrImpl(Database *_db, Class *cls,
02167 const char *attrpath,
02168 Bool propagate,
02169 const IndexImpl *idximpl)
02170 : AttributeComponent(_db, (const Dataspace *)0, 1)
02171 {
02172 initialize(_db);
02173 db = _db;
02174 setClassOwner(cls);
02175 setAttrpath(attrpath);
02176 if (idximpl) {
02177 setImplType(idximpl->getType());
02178 setKeyCountOrDegree(idximpl->getKeycount());
02179 setHashMethod(idximpl->getHashMethod());
02180 if (idximpl->getDataspace())
02181 setDspid(idximpl->getDataspace()->getId());
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 else {
02189 setImplType(CollImpl::NoIndex);
02190 }
02191
02192 setPropagate(propagate);
02193 setName(genName());
02194 }
02195
02196 Status
02197 CollAttrImpl::makeDataspace(Database *_db, const Dataspace *&dataspace) const
02198 {
02199 Bool isnull;
02200 short dspid = getDspid(&isnull);
02201 if (!isnull)
02202 return _db->getDataspace(dspid, dataspace);
02203 dataspace = 0;
02204 return Success;
02205 }
02206
02207 Status
02208 CollAttrImpl::make(Database *db, Class *cls, const char *attrpath,
02209 Bool propagate, CollImpl::Type impl_type,
02210 const char *hints, CollAttrImpl *&impl)
02211 {
02212 impl = 0;
02213 IndexImpl *idximpl;
02214 if (impl_type == CollImpl::HashIndex || impl_type == CollImpl::BTreeIndex) {
02215 Status s = IndexImpl::make(db, (IndexImpl::Type)impl_type, hints, idximpl);
02216 if (s) return s;
02217 }
02218 else {
02219 if (hints) {
02220 return Exception::make(IDB_ERROR, "no hints for no indexed collections");
02221 }
02222 idximpl = NULL;
02223 }
02224
02225 impl = new CollAttrImpl(db, cls, attrpath, propagate, idximpl);
02226 return Success;
02227 }
02228
02229 AttributeComponent *
02230 CollAttrImpl::xclone(Database *db, const Class *cls)
02231 {
02232 unsigned int impl_hints_cnt = getImplHintsCount();
02233 int impl_hints[eyedbsm::HIdxImplHintsCount];
02234 memset(impl_hints, 0, sizeof(int) * eyedbsm::HIdxImplHintsCount);
02235 for (int i = 0; i < impl_hints_cnt; i++)
02236 impl_hints[i] = getImplHints(i);
02237
02238 const Dataspace *dataspace;
02239 Status s = makeDataspace(db, dataspace);
02240 if (s) throw *s;
02241
02242 std::string str = makeAttrpath(cls);
02243 return new CollAttrImpl(db, (Class *)cls, str.c_str(),
02244 getPropagate(),
02245 dataspace, (CollImpl::Type)getImplType(),
02246 getKeyCountOrDegree(),
02247 getHashMethod(), impl_hints, impl_hints_cnt);
02248 }
02249
02250 Status
02251 CollAttrImpl::realize(const RecMode *rcm)
02252 {
02253 Status s;
02254
02255 Bool creating = IDBBOOL(!getOid().isValid());
02256
02257 if (creating) {
02258 s = checkUnique("collection_attribute_implementation",
02259 "collection attribute implementation");
02260 if (s) return s;
02261 }
02262
02263 s = AttributeComponent::realize(rcm);
02264 if (s) return s;
02265 if (creating)
02266 return StatusMake(constraintCreate(db->getDbHandle(),
02267 oid.getOid()));
02268 return Success;
02269 }
02270
02271 Status
02272 CollAttrImpl::remove(const RecMode *rcm)
02273 {
02274 RPCStatus rpc_status =
02275 constraintDelete(db->getDbHandle(), oid.getOid(),
02276 getUserData(attrcomp_delete_ud) ? 1 : 0);
02277
02278 if (rpc_status)
02279 return StatusMake(rpc_status);
02280 return AttributeComponent::remove(rcm);
02281 }
02282
02283 Status
02284 CollAttrImpl::s_trace(FILE *fd, Bool, unsigned int flags) const
02285 {
02286 int idxtype = getImplType();
02287 fprintf(fd, "implementation<type = %s", idxtype == IndexImpl::Hash ?
02288 "hash" : "btree");
02289 Bool hints = False;
02290
02291 const Dataspace *dataspace;
02292 Status s = makeDataspace(db, dataspace);
02293 if (s) return s;
02294
02295 if (dataspace) {
02296 PREF(fd, hints);
02297 fprintf(fd, "dataspace = %s;", dataspace->getName());
02298 }
02299
02300 const BEMethod_C *mth = getHashMethod();
02301 if (mth) {
02302 PREF(fd, hints);
02303 fprintf(fd, "key_function = %s::%s;", mth->getClassOwner()->getName(),
02304 mth->getEx()->getExname().c_str());
02305 }
02306
02307 if (getKeyCountOrDegree()) {
02308 PREF(fd, hints);
02309 if (idxtype == IndexImpl::Hash)
02310 fprintf(fd, "key_count = %d;", getKeyCountOrDegree());
02311 else
02312 fprintf(fd, "degree = %d;", getKeyCountOrDegree());
02313 }
02314
02315 unsigned int cnt = getImplHintsCount();
02316 for (unsigned int i = 0; i < cnt; i++) {
02317 if ((i) == eyedbsm::HIdx::IniSize_Hints &&
02318 getImplHints(eyedbsm::HIdx::IniObjCnt_Hints))
02319 continue;
02320 int val = getImplHints(i);
02321 if (val) {
02322 PREF(fd, hints);
02323 fprintf(fd, "%s = %d;", IndexImpl::hashHintToStr(i), val);
02324 }
02325 }
02326
02327 fprintf(fd, "%s%s> on %s", (hints ? "\"" : ""), getPropagString(this),
02328 getAttrpath().c_str());
02329
02330 return Success;
02331 }
02332
02333 Status
02334 CollAttrImpl::m_trace(FILE *fd, int indent, unsigned int flags,
02335 const RecMode *rcm) const
02336 {
02337 Status s = Success;
02338 s = s_trace(fd, False);
02339 if (s) return s;
02340
02341 if ((flags & CompOidTrace) == CompOidTrace ||
02342 rcm->getType() == RecMode_FullRecurs)
02343 fprintf(fd, " {%s}", oid.getString());
02344
02345 if (rcm->getType() == RecMode_FullRecurs)
02346 {
02347 fprintf(fd, " ");
02348 s = ObjectPeer::trace_realize(this, fd, indent + INDENT_INC, flags, rcm);
02349 }
02350 return s;
02351 }
02352
02353 const char *
02354 CollAttrImpl::genName() const
02355 {
02356 static std::string s;
02357 s = std::string("implementation") + ":" + getAttrpath();
02358 return s.c_str();
02359 }
02360
02361 int
02362 CollAttrImpl::getInd() const
02363 {
02364 return Class::CollectionImpl_C;
02365 }
02366
02367 Status
02368 CollAttrImpl::getImplementation(Database *db,
02369 const CollImpl *&_collimpl)
02370
02371 {
02372 CollImpl::Type impl_type = (CollImpl::Type)getImplType();
02373 const IndexImpl *idximpl = 0;
02374 if (!collimpl) {
02375 if (impl_type == CollImpl::HashIndex || impl_type == CollImpl::BTreeIndex) {
02376 const Dataspace *dataspace;
02377 Status s = makeDataspace(db, dataspace);
02378 if (s) return s;
02379
02380 unsigned int impl_hints_cnt = getImplHintsCount();
02381 int impl_hints[eyedbsm::HIdxImplHintsCount];
02382 memset(impl_hints, 0, sizeof(int) * eyedbsm::HIdxImplHintsCount);
02383 for (int i = 0; i < impl_hints_cnt; i++)
02384 impl_hints[i] = getImplHints(i);
02385 idximpl = new IndexImpl((IndexImpl::Type)impl_type,
02386 dataspace, getKeyCountOrDegree(),
02387 getHashMethod(), impl_hints,
02388 impl_hints_cnt);
02389 collimpl = new CollImpl(idximpl);
02390 }
02391 else {
02392 collimpl = new CollImpl(impl_type);
02393 }
02394 }
02395
02396 _collimpl = collimpl;
02397 return Success;
02398 }
02399
02400 void CollAttrImpl::userInitialize()
02401 {
02402 collimpl = 0;
02403 dsp = 0;
02404 }
02405
02406 void CollAttrImpl::userCopy(const Object &)
02407 {
02408 collimpl = 0;
02409 dsp = 0;
02410 }
02411
02412 void CollAttrImpl::userGarbage()
02413 {
02414 if (collimpl)
02415 collimpl->release();
02416 dsp = 0;
02417 }
02418 }