syscls_impl.cc

00001 /* 
00002    EyeDB Object Database Management System
00003    Copyright (C) 1994-2008 SYSRA
00004    
00005    EyeDB is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Lesser General Public
00007    License as published by the Free Software Foundation; either
00008    version 2.1 of the License, or (at your option) any later version.
00009    
00010    EyeDB is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Lesser General Public License for more details.
00014    
00015    You should have received a copy of the GNU Lesser General Public
00016    License along with this library; if not, write to the Free Software
00017    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA 
00018 */
00019 
00020 /*
00021    Author: Eric Viara <viara@sysra.com>
00022 */
00023 
00024 
00025 //#define FRONT_END
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   // etcMake
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   // oqlctbMake
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   // utilsMake
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   // ClassComponent
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) // a 'not null' constraint should be better
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     // must update
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     //printf("ClassComponent::remove(%p, %s, %s)\n", this, oid.toString(), cl->getName());
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   // added the 5/3/00
00222   // BUG_ETC_UPDATE
00223   static inline const char *get_class_name(const Class *cls)
00224   {
00225     return cls->getAliasName() ? cls->getAliasName() : cls->getName();
00226   }
00227 
00228   //
00229   // ClassVariable
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   // Protection
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   // Trigger
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           //obj_arr[0]->release();
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   // CardinalityConstraint
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     // disconnected the 15/02/99
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   // AttributeComponent
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   // NotNullConstraint
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   // UniqueConstraint
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   // Classes for component propagation tests
01089   //
01090   // _Test suffix will disapear
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     //  printf("Index::userGarbage(%p)\n", this);
01232   }
01233 
01234   void AttributeComponent::userInitialize()
01235   {
01236     //printf("AttributeComponent::userInitialize(%p)\n", this);
01237   }
01238 
01239   void AttributeComponent::userCopy(const Object &)
01240   {
01241     //  printf("AttributeComponent::userCopy(%p)\n", this);
01242   }
01243 
01244   void AttributeComponent::userGarbage()
01245   {
01246     //  printf("AttributeComponent::userGarbage(%p)\n", this);
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); // prevent from reimplementing index
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     // warning: the idx oid could have been changed during
01313     // the store process because of a reimplementation, so we must reload
01314     // the object and get its idxoid !
01315 #ifdef NEW_INDEX_MOVE
01316     // not in this case 
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   //#define REIMPL_TRACE
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     // getClassOwner() must be called before the new invocation for idx because
01518     // of an obscure problem (bug?) with the C++ compiler:
01519     // as getClassOwner() calls the new operator, gbx package "thought"
01520     // that the created idx is on the stack, because the new operator 
01521     // for idx is called before the call of the method getClassOwner() !
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     // to inform backend that it is a reimplementation
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       printf("HashIndex::realize(%s, %s, key_count%d, hash_method=%p, backend_updating=%d)\n",
01591       getAttrpath(), getOid().toString(), getKeyCount(), getHashMethod(),
01592       backend_updating);
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     //printf("HashIndex:: -> index remove(%s)\n", oid.toString());
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     //printf("HashIndex:: -> REMOVE(%s)\n", oid.toString());
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       // if (val)
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       printf("realizing btreeindex %s %s creating=%d\n",
01924       getOid().toString(), getName(), creating);
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     //fprintf(fd, " on %s::%s", getClassOwner()->getName(), getAttrname());
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     //printf("making collattrimp %s '%s'\n", attrpath, hints);
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     //printf("realizing collattrimpl %s\n", getAttrpath());
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 }

Generated on Mon Dec 22 18:16:11 2008 for eyedb by  doxygen 1.5.3