Attribute_inv.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 /*
00026   TODO :
00027   One must update runtime pointers in the client side by giving back
00028   the oid modified ; so each time there is a dataWrite() one has to
00029   fill an object will the following information : oid modified, item offset, 
00030   value of the data (which is an oid!).
00031   The client side will get this information and will looksin its cache for
00032   the modified oids, then will modify their IDR en consequence!
00033 */
00034 
00035 //#define FRONT_END
00036 
00037 #include "eyedb_p.h"
00038 #include "Attribute_p.h"
00039 #include "CollectionBE.h"
00040 #include <eyedbsm/eyedbsm.h>
00041 #include "InvOidContext.h"
00042 
00043 #include <assert.h>
00044 
00045 #include "misc.h"
00046 
00047 #define CK(X) do { \
00048  Status __s__ = (X); \
00049  if (__s__) return __s__; \
00050 } while(0)
00051 
00052 //#define INVDBG
00053 
00054 namespace eyedb {
00055 
00056 #ifdef INVDBG
00057   static void
00058   get_object_class(Database *db, const Oid &oid)
00059   {
00060     if (!oid.isValid())
00061       return;
00062 
00063     Class *objcls = NULL;
00064     Status status = db->getObjectClass(oid, objcls);
00065 
00066     if (status)
00067       status->print();
00068 
00069     if (objcls)
00070       IDB_LOG(IDB_LOG_RELSHIP_DETAILS, ("OID %s -> %s\n", oid.toString(), objcls->getName()));
00071   }
00072 #else
00073 #define get_object_class(x, y)
00074 #endif
00075 
00076   static Status
00077   inverse_coll_realize(Collection *&coll)
00078   {
00079     coll->invalidateInverse();
00080     Status s = coll->realize();
00081     coll->validateInverse();
00082     coll->release(); coll = 0;
00083     return s;
00084   }
00085 
00086   static Status
00087   requalify(Database *db, const Oid &obj_oid,
00088             const Attribute *&inv_item)
00089   {
00090     if (!obj_oid.isValid())
00091       return Success;
00092 
00093     Class *objcls = 0;
00094     Status status = db->getObjectClass(obj_oid, objcls);
00095     if (status) return status;
00096 
00097     if (objcls->getOid() == inv_item->getClassOwner()->getOid())
00098       return Success;
00099 
00100     IDB_LOG(IDB_LOG_RELSHIP_DETAILS,
00101             ("Attribute::inverse_realize(requalifying inverse item "
00102              "%s::%s for %s\n",
00103              inv_item->getClassOwner()->getName(),
00104              inv_item->getName(), obj_oid.toString()));
00105     /*
00106       printf("Attribute::inverse_realize(requalifying inverse item "
00107       "%s::%s for %s\n",
00108       inv_item->getClassOwner()->getName(),
00109       inv_item->getName(), obj_oid.toString());
00110     */
00111 
00112     inv_item = objcls->getAttribute(inv_item->getName());
00113 
00114     assert(inv_item);
00115     return Success;
00116   }
00117 
00118   Status
00119   Attribute::checkInverse(const Attribute *item) const
00120   {
00121     if (!item)
00122       item = this;
00123 
00124     if (item->isVarDim())
00125       return Exception::make(IDB_ATTRIBUTE_INVERSE_ERROR,
00126                              "'%s' cannot make inverse on variable "
00127                              "dimension attribute", item->name);
00128 
00129     if (!item->cls->asCollectionClass() && !item->cls->asAgregatClass())
00130       return Exception::make(IDB_ATTRIBUTE_INVERSE_ERROR, 
00131                              "'%s' cannot make inverse on mateagregat "
00132                              "or collection_class attribute", item->name);
00133 
00134     if (item->typmod.pdims > 1)
00135       return Exception::make(IDB_ATTRIBUTE_INVERSE_ERROR,
00136                              "'%s' cannot make inverse on non "
00137                              "single dimension attribute", item->name);
00138 
00139     return Success;
00140   }
00141 
00142   void
00143   Attribute::getInverse(const char **cname, const char **fname,
00144                         const Attribute **item) const
00145   {
00146     if (cname)
00147       *cname = inv_spec.clsname;
00148     if (fname)
00149       *fname = inv_spec.fname;
00150     if (item)
00151       *item = inv_spec.item;
00152   }
00153 
00154   Bool Attribute::hasInverse() const
00155   {
00156     return inv_spec.item ? True : False;
00157   }
00158 
00159   Status Attribute::setInverse(const Attribute *item)
00160   {
00161     if (inv_spec.item || inv_spec.clsname)
00162       return Exception::make(IDB_ATTRIBUTE_INVERSE_ERROR,
00163                              "inverse is already set for '%s'", name);
00164 
00165     Status status = checkInverse();
00166     if (status)
00167       return status;
00168 
00169     status = checkInverse(item);
00170     if (status)
00171       return status;
00172 
00173     inv_spec.item = item;
00174     return Success;
00175   }
00176 
00177   Status Attribute::setInverse(const char *clsname, const char *fname)
00178   {
00179     if (inv_spec.item || inv_spec.clsname)
00180       return Exception::make(IDB_ATTRIBUTE_INVERSE_ERROR,
00181                              "inverse is already set for '%s'", name);
00182 
00183     Status status = checkInverse();
00184     if (status)
00185       return status;
00186 
00187     if (!clsname || !fname)
00188       return Exception::make(IDB_ATTRIBUTE_INVERSE_ERROR,
00189                              "'%s' setInverse : invalid null value", name);
00190 
00191     inv_spec.clsname = strdup(clsname);
00192     inv_spec.fname      = strdup(fname);
00193     return Success;
00194   }
00195 
00196   void
00197   Attribute::completeInverseItem(Schema *m)
00198   {
00199     if (!inv_spec.item->cls)
00200       ((Attribute *)inv_spec.item)->cls =
00201         m->getClass(inv_spec.item->oid_cl);
00202 
00203     if (!inv_spec.item->class_owner)
00204       ((Attribute *)inv_spec.item)->class_owner =
00205         m->getClass(inv_spec.item->oid_cl_own);
00206   }
00207 
00208   Status
00209   Attribute::completeInverse(Schema *m)
00210   {
00211     if (!inv_spec.clsname || inv_spec.item)
00212       return Success;
00213 
00214     Class *cl;
00215     cl = m->getClass(inv_spec.clsname);
00216 
00217     if (!cl)
00218       return Exception::make(IDB_ATTRIBUTE_INVERSE_ERROR,
00219                              "attribute '%s' in agregat class '%s': "
00220                              "cannot find agregat class '%s'",
00221                              name, class_owner->getName(),
00222                              inv_spec.clsname);
00223 
00224     if (!cl->asAgregatClass())
00225       return Exception::make(IDB_ATTRIBUTE_INVERSE_ERROR,
00226                              "attribute '%s' in agregat class '%s':"
00227                              "class '%s' is not a agregat class",
00228                              name, class_owner->getName(),
00229                              inv_spec.clsname);
00230 
00231     inv_spec.item = cl->getAttribute(inv_spec.fname);
00232 
00233     if (!inv_spec.item)
00234       return Exception::make(IDB_ATTRIBUTE_INVERSE_ERROR,
00235                              "attribute '%s' in agregat class '%s': "
00236                              "cannot find item '%s' in agregat class '%s'",
00237                              name, class_owner->getName(),
00238                              inv_spec.fname, inv_spec.clsname);
00239 
00240     completeInverseItem(m);
00241 
00242     return checkInverse(inv_spec.item);
00243   }
00244 
00245   Status Attribute::completeInverse(Database *db)
00246   {
00247     Class *cl;
00248     Schema *m = db->getSchema();
00249 
00250     Status s = completeInverse(m);
00251     if (s)
00252       return s;
00253 
00254     if (inv_spec.item) {
00255       completeInverseItem(m);
00256 
00257       inv_spec.num = inv_spec.item->num;
00258       cl = (Class *)inv_spec.item->class_owner;
00259 
00260       // added the 10/12/99
00261       if (!cl)
00262         return Success;
00263       // ...
00264 
00265       if (!cl->getOid().isValid()) {
00266         Status status = cl->create();
00267         if (status) return status;
00268       }
00269     
00270       inv_spec.oid_cl = cl->getOid();
00271     }
00272 
00273     return Success;
00274   }
00275 
00276   // ---------------------------------------------------------------------------
00277   //
00278   // Inverse computing
00279   // 
00280   // ---------------------------------------------------------------------------
00281 
00282   /* 
00283      obj_idr         : the IDR of the current object.
00284      obj_oid         : the oid of the current object.
00285      inv_obj_oid     : (obj_idr::this) the oid of the object (collection or not)
00286      pointed by 'this' attribute in the IDR.
00287      old_inv_obj_oid : (obj_oid::this) the oid of the object (collection or not)
00288      pointed by 'this' attribute in the DB.
00289      [no meaning if op == objInvCreate]
00290      relation 1:1
00291      cur_obj_oid  : (inv_obj_oid::inv_item) the oid of the object pointed by
00292      inv_obj_oid by 'this->inv_item' attribute in the DB.
00293      old_obj_oid  : (old_inv_obj_oid::inv_item) the oid of the object pointed
00294      by old_inv_obj_oid by 'this->inv_item' attribute
00295      in the DB.
00296   */
00297 
00298   static const char *
00299   get_op_name(Attribute::InvObjOp op)
00300   {
00301     if (op == Attribute::invObjCreate)
00302       return "ObjCreate";
00303 
00304     if (op == Attribute::invObjUpdate)
00305       return "ObjUpdate";
00306 
00307     if (op == Attribute::invObjRemove)
00308       return "ObjRemove";
00309 
00310     return "invObjUnknown";
00311   }
00312 
00313   Status
00314   Attribute::inverse_coll_perform(Database *db, InvObjOp op,
00315                                   const Oid &obj_oid,
00316                                   const Oid &inv_obj_oid) const
00317   {
00318     // WARNING: changed the 10/04/00 because of a manue's bug in genetpig
00319     if (!inv_spec.item)
00320       return Success;
00321 
00322     IDB_LOG(IDB_LOG_RELSHIP_DETAILS,
00323             ("inverse_coll_perform(%s, %s)\n", name, inv_spec.item->getName()));
00324 
00325     if (inv_spec.item->getClass()->asCollectionClass())
00326       return inverse_coll_perform_N_N(db, op, obj_oid, inv_obj_oid);
00327 
00328     return inverse_coll_perform_N_1(db, op, obj_oid, inv_obj_oid);
00329   }
00330 
00331   /*
00332     obj_oid         : the oid of the current object.
00333     x_obj_oid       : the oid of the object to insert (op == invObjUpdate) or
00334     remove (op == invObjRemove) from the collection.
00335   */
00336 
00337   // introduced the 15/12/99
00338   // because I do not understand why it is necessary to run all this code
00339   // when one adds an object!
00340 #define N_N_SIMPLE
00341 
00342   Status
00343   Attribute::inverse_coll_perform_N_N(Database *db, InvObjOp op,
00344                                       const Oid &obj_oid,
00345                                       const Oid &x_obj_oid) const
00346   {
00347     IDB_LOG(IDB_LOG_RELSHIP_DETAILS,
00348             ("inverse_coll_perform_N_N(%s, inv %s, op = %s, "
00349              "obj_oid = %s, x_obj_oid = %s)\n",
00350              name, inv_spec.item->getName(), get_op_name(op), obj_oid.toString(),
00351              x_obj_oid.toString()));
00352   
00353     const Attribute *inv_item = inv_spec.item;
00354     InvCtx inv_ctx;
00355     assert(inv_item);
00356 
00357     get_object_class(db, obj_oid);
00358     get_object_class(db, x_obj_oid);
00359 
00360     if (op == invObjUpdate) // i.e. inserting x_obj_oid
00361       {
00362         Oid old_obj_oid;
00363         CK(inverse_read_oid(db, inv_item, x_obj_oid, old_obj_oid));
00364 
00365         Collection *coll = 0;
00366         if (old_obj_oid.isValid())
00367           CK(inverse_get_collection(db, old_obj_oid, coll));
00368 
00369 #ifndef N_N_SIMPLE
00370         if (coll)
00371           {
00372             OidArray oid_arr;
00373             CK(coll->getElements(oid_arr));
00374 
00375             for (int i = 0; i < oid_arr.getCount(); i++)
00376               {
00377                 Oid coll_oid;
00378                 CK(inverse_read_oid(db, this, oid_arr[i], coll_oid));
00379                 if (coll_oid.isValid())
00380                   {
00381                     Collection *inv_coll;
00382                     CK(inverse_get_collection(db, coll_oid, inv_coll));
00383                     if (inv_coll)
00384                       {
00385                         IDB_LOG(IDB_LOG_RELSHIP_DETAILS,
00386                                 ("suppressing [1] %s from collection %s\n",
00387                                  x_obj_oid.toString(), 
00388                                  inv_coll->getOid().toString()));
00389                         CK(inv_coll->suppress(x_obj_oid, True));
00390                         CK(inverse_coll_realize(inv_coll));
00391                       }
00392                   }
00393               }
00394           }
00395 #endif
00396 
00397         if (!coll)
00398           {
00399             CK(inverse_create_collection(db, inv_item, x_obj_oid,
00400                                          True, x_obj_oid, coll));
00401               
00402             CK(inverse_write_oid(db, inv_item, x_obj_oid,
00403                                  coll->getOidC(), inv_ctx));
00404           }
00405 
00406 #ifndef N_N_SIMPLE
00407         Collection *obj_coll = 0;
00408         Oid coll_obj_oid;
00409         CK(inverse_read_oid(db, this, obj_oid, coll_obj_oid));
00410 
00411         CK(inverse_get_collection(db, coll_obj_oid, obj_coll));
00412 
00413         OidArray oid_arr;
00414 
00415         Iterator q(obj_coll);
00416         CK(q.getStatus());
00417         CK(q.scan(oid_arr));
00418       
00419         obj_coll->release(); obj_coll = 0;
00420 
00421         for (int i = 0; i < oid_arr.getCount(); i++)
00422           {
00423             Oid coll_oid;
00424             CK(inverse_read_oid(db, inv_item, oid_arr[i], coll_oid));
00425 
00426             if (coll_oid.isValid())
00427               {
00428                 Collection *inv_coll = 0;
00429                 CK(inverse_get_collection(db, coll_oid, inv_coll));
00430                 if (inv_coll)
00431                   {
00432                     OidArray inv_oid_arr;
00433                     CK(inv_coll->getElements(inv_oid_arr));
00434                     inv_coll->release(); inv_coll = 0;
00435 
00436                     for (int j = 0; j < inv_oid_arr.getCount(); j++)
00437                       {
00438                         Collection *rinv_coll = 0;
00439                         Oid rinv_coll_oid;
00440                         CK(inverse_read_oid(db, this, inv_oid_arr[j],
00441                                             rinv_coll_oid));
00442                         if (rinv_coll_oid.isValid())
00443                           {
00444                             CK(inverse_get_collection(db, rinv_coll_oid,
00445                                                       rinv_coll));
00446                       
00447                             if (rinv_coll)
00448                               {
00449                                 if (i == 0)
00450                                   {
00451                                     IDB_LOG(IDB_LOG_RELSHIP_DETAILS,
00452                                             ("inserting [1] %s to collection %s\n",
00453                                              inv_oid_arr[j].toString(), 
00454                                              coll->getOid().toString()));
00455                                     CK(coll->insert(inv_oid_arr[j], True));
00456                                   }
00457                                 IDB_LOG(IDB_LOG_RELSHIP_DETAILS,
00458                                         ("appending [2] %s to collection %s\n",
00459                                          x_obj_oid.toString(), 
00460                                          rinv_coll->getOid().toString()));
00461                                 CK(rinv_coll->insert(x_obj_oid, True));
00462                                 CK(inverse_coll_realize(rinv_coll));
00463                               }
00464                           }
00465                       }
00466                   }
00467               }
00468           }
00469 #endif
00470 
00471         IDB_LOG(IDB_LOG_RELSHIP_DETAILS,
00472                 ("appending [3] %s to collection %s\n",
00473                  obj_oid.toString(), coll->getOid().toString()));
00474         coll->insert(obj_oid, True);
00475         CK(inverse_coll_realize(coll));
00476 
00477         return Success;
00478       }
00479 
00480     if (op == invObjRemove) // removing x_obj_oid from collection
00481       {
00482         Oid old_obj_oid;
00483         CK(inverse_read_oid(db, inv_item, x_obj_oid, old_obj_oid));
00484 
00485         Collection *coll = 0;
00486         if (old_obj_oid.isValid())
00487           CK(inverse_get_collection(db, old_obj_oid, coll));
00488 
00489         Oid cur_coll_oid;
00490         CK(inverse_read_oid(db, this, obj_oid, cur_coll_oid));
00491 
00492         if (coll)
00493           {
00494             OidArray oid_arr;
00495             CK(coll->getElements(oid_arr));
00496 
00497             for (int i = 0; i < oid_arr.getCount(); i++)
00498               {
00499                 Oid coll_oid;
00500                 CK(inverse_read_oid(db, this, oid_arr[i], coll_oid));
00501                 if (coll_oid.isValid() && coll_oid != cur_coll_oid)
00502                   {
00503                     Collection *inv_coll;
00504                     CK(inverse_get_collection(db, coll_oid, inv_coll));
00505                     if (inv_coll)
00506                       {
00507                         IDB_LOG(IDB_LOG_RELSHIP_DETAILS,
00508                                 ("suppressing [2] %s from collection %s\n",
00509                                  x_obj_oid.toString(), 
00510                                  inv_coll->getOid().toString()));
00511                         CK(inv_coll->suppress(x_obj_oid, True));
00512                         CK(inverse_coll_realize(inv_coll));
00513                       }
00514                   }
00515               }
00516 
00517             IDB_LOG(IDB_LOG_RELSHIP_DETAILS,
00518                     ("suppressing [3] %s from collection %s\n",
00519                      obj_oid.toString(), 
00520                      coll->getOid().toString()));
00521             coll->suppress(obj_oid, True);
00522 
00523             CK(inverse_coll_realize(coll));
00524           }
00525 
00526         return Success;
00527       }
00528 
00529     abort();
00530     return Success;
00531   }
00532 
00533   /*
00534     obj_oid         : the oid of the current object.
00535     x_obj_oid       : the oid of the object to insert (op == invObjUpdate) pr
00536     remove (op == invObjRemove) from the collection.
00537   */
00538 
00539   Status
00540   Attribute::inverse_coll_perform_N_1(Database *db, InvObjOp op,
00541                                       const Oid &obj_oid,
00542                                       const Oid &x_obj_oid) const
00543   {
00544     IDB_LOG(IDB_LOG_RELSHIP_DETAILS, ("inverse_coll_perform_N_1(%s, inv %s, op = %s, "
00545                                       "obj_oid = %s, x_obj_oid = %s)\n",
00546                                       name, inv_spec.item->getName(), get_op_name(op), obj_oid.toString(),
00547                                       x_obj_oid.toString()));
00548 
00549     const Attribute *inv_item = inv_spec.item;
00550     InvCtx inv_ctx;
00551     assert(inv_item);
00552 
00553     get_object_class(db, obj_oid);
00554     get_object_class(db, x_obj_oid);
00555 
00556     if (op == invObjUpdate) // i.e. inserting x_obj_oid
00557       {
00558         Oid old_obj_oid;
00559         CK(inverse_read_oid(db, inv_item, x_obj_oid, old_obj_oid));
00560         if (old_obj_oid.isValid() && old_obj_oid != obj_oid)
00561           {
00562             Oid old_inv_obj_oid;
00563             CK(inverse_read_oid(db, this, old_obj_oid, old_inv_obj_oid));
00564             if (old_inv_obj_oid.isValid())
00565               {
00566                 Collection *old_coll;
00567                 CK(inverse_get_collection(db, old_inv_obj_oid, old_coll));
00568                 if (old_coll)
00569                   {
00570                     OidArray oid_arr;
00571                     CK(old_coll->getElements(oid_arr));
00572 
00573                     for (int i = 0; i < oid_arr.getCount(); i++)
00574                       {
00575                         CK(inverse_write_oid(db, inv_item, oid_arr[i],
00576                                              Oid::nullOid, inv_ctx));
00577                         IDB_LOG(IDB_LOG_RELSHIP_DETAILS,
00578                                 ("suppressing [4] %s from collection %s\n",
00579                                  oid_arr[i].toString(), 
00580                                  old_coll->getOid().toString()));
00581                         CK(old_coll->suppress(oid_arr[i], True));
00582                       }
00583 
00584                     CK(inverse_coll_realize(old_coll));
00585                   }
00586               }
00587           }
00588       
00589         return inverse_write_oid(db, inv_item, x_obj_oid, obj_oid, inv_ctx);
00590       }
00591 
00592     if (op == invObjRemove)
00593       return inverse_write_oid(db, inv_item, x_obj_oid, Oid::nullOid,
00594                                inv_ctx);
00595 
00596     abort();
00597     return Success;
00598   }
00599 
00600   static void
00601   _trace_(const char *mth, Attribute::InvObjOp op,
00602           const Attribute *item,
00603           const Attribute *inv_item,
00604           const Oid &obj_oid, 
00605           const Oid &inv_obj_oid)
00606   {
00607     if (!(IDB_LOG_RELSHIP_DETAILS & Log::getLogMask()))
00608       return;
00609 
00610     char buf[256];
00611     std::string str;
00612     sprintf(buf, "Attribute::%s\n", mth);
00613     str += buf;
00614     sprintf(buf, "\t\top = %s;\n", get_op_name(op));
00615     str += buf;
00616     sprintf(buf, "\t\titem = %s, %d;\n", item->getName(), item->getNum());
00617     str += buf;
00618     sprintf(buf, "\t\tinv_item = %s, %d;\n", inv_item->getName(), inv_item->getNum());
00619     str += buf;
00620     sprintf(buf, "\t\tobj_oid = %s;\n", obj_oid.toString());
00621     str += buf;
00622     sprintf(buf, "\t\tinv_obj_oid = %s;\n\n", inv_obj_oid.toString());
00623     str += buf;
00624 
00625     IDB_LOG(IDB_LOG_RELSHIP_DETAILS, (str.c_str()));
00626   }
00627 
00628   // ---------------------------------------------------------------------------
00629   //
00630   // inverse_1_1
00631   //
00632   // ---------------------------------------------------------------------------
00633 
00634   Status
00635   Attribute::inverse_1_1(Database *db, InvObjOp op,
00636                          const Attribute *inv_item,
00637                          const Oid &obj_oid, 
00638                          const Oid &inv_obj_oid,
00639                          const InvCtx &inv_ctx) const
00640   {
00641     _trace_("inverse_1_1", op, this, inv_item, obj_oid, inv_obj_oid);
00642 
00643     if (op == invObjCreate)
00644       {
00645         if (!inv_obj_oid.isValid())
00646           return Success;
00647         Oid cur_obj_oid;
00648         CK(inverse_read_oid(db, inv_item, inv_obj_oid, cur_obj_oid));
00649 
00650         IDB_LOG(IDB_LOG_RELSHIP_DETAILS,
00651                 ("inverse 1_1 create: cur_obj_oid %s\n",
00652                  cur_obj_oid.toString()));
00653 
00654         if (cur_obj_oid != obj_oid) // added the 30/8/99
00655           {
00656             if (cur_obj_oid.isValid())
00657               CK(inverse_write_oid(db, this, cur_obj_oid, Oid::nullOid,
00658                                    inv_ctx));
00659             return inverse_write_oid(db, inv_item, inv_obj_oid, obj_oid,
00660                                      inv_ctx);
00661           }
00662 
00663         return Success; // added the 10/9/99
00664       }
00665 
00666     if (op == invObjUpdate)
00667       {
00668         Oid old_inv_obj_oid;
00669         CK(inverse_read_oid(db, this, obj_oid, old_inv_obj_oid));
00670 
00671         IDB_LOG(IDB_LOG_RELSHIP_DETAILS,
00672                 ("inverse 1_1 update: obj_oid %s, "
00673                  "old_inv_obj_oid %s, inv_obj_oid %s\n",
00674                  obj_oid.toString(), old_inv_obj_oid.toString(),
00675                  inv_obj_oid.toString()));
00676 
00677         if (old_inv_obj_oid.isValid() && old_inv_obj_oid != inv_obj_oid)
00678           {
00679             Oid old_obj_oid;
00680             CK(inverse_read_oid(db, inv_item, old_inv_obj_oid, old_obj_oid));
00681 
00682             IDB_LOG(IDB_LOG_RELSHIP_DETAILS,
00683                     ("inverse 1_1 update: old_obj_oid %s\n", old_obj_oid.toString()));
00684             if (old_obj_oid == obj_oid)
00685               CK(inverse_write_oid(db, inv_item, old_inv_obj_oid,
00686                                    Oid::nullOid, inv_ctx));
00687           }
00688 
00689         if (!inv_obj_oid.isValid())
00690           return Success;
00691 
00692         Oid cur_obj_oid;
00693         CK(inverse_read_oid(db, inv_item, inv_obj_oid, cur_obj_oid));
00694 
00695         IDB_LOG(IDB_LOG_RELSHIP_DETAILS,
00696                 ("inverse 1_1 update: cur_obj_oid %s\n",
00697                  cur_obj_oid.toString()));
00698 
00699         // changed the 15/9/99
00700         //      if (cur_obj_oid.isValid())
00701         if (cur_obj_oid.isValid() && cur_obj_oid != obj_oid)
00702           CK(inverse_write_oid(db, this, cur_obj_oid, Oid::nullOid,
00703                                inv_ctx));
00704         return inverse_write_oid(db, inv_item, inv_obj_oid, obj_oid, inv_ctx);
00705       }
00706 
00707     if (op == invObjRemove)
00708       {
00709         if (!inv_obj_oid.isValid())
00710           return Success;
00711         return inverse_write_oid(db, inv_item, inv_obj_oid, Oid::nullOid,
00712                                  inv_ctx);
00713       }
00714 
00715     abort();
00716     return Success;
00717   }
00718   
00719   // ---------------------------------------------------------------------------
00720   //
00721   // inverse_1_N
00722   //
00723   // ---------------------------------------------------------------------------
00724 
00725   Status
00726   Attribute::inverse_1_N(Database *db, InvObjOp op,
00727                          const Attribute *inv_item,
00728                          const Oid &obj_oid,
00729                          const Oid &inv_obj_oid,
00730                          const InvCtx &inv_ctx) const
00731   {
00732     _trace_("inverse_1_N", op, this, inv_item, obj_oid, inv_obj_oid);
00733 
00734     if (op == invObjUpdate)
00735       {
00736         Oid old_inv_obj_oid;
00737         CK(inverse_read_oid(db, this, obj_oid, old_inv_obj_oid));
00738 
00739         if (old_inv_obj_oid.isValid() && old_inv_obj_oid != inv_obj_oid)
00740           {
00741             Oid old_obj_oid;
00742             CK(inverse_read_oid(db, inv_item, old_inv_obj_oid, old_obj_oid));
00743             if (old_obj_oid.isValid())
00744               {
00745                 Collection *coll;
00746                 CK(inverse_get_collection(db, old_obj_oid, coll));
00747 
00748                 if (coll)
00749                   {
00750                     IDB_LOG(IDB_LOG_RELSHIP_DETAILS,
00751                             ("suppressing [5] %s from collection %s\n",
00752                              obj_oid.toString(), 
00753                              coll->getOid().toString()));
00754                     CK(coll->suppress(obj_oid, True));
00755                     CK(inverse_coll_realize(coll));
00756                   }
00757               }
00758           }
00759       }
00760 
00761     if (op == invObjCreate || op == invObjUpdate)
00762       {
00763         if (!inv_obj_oid.isValid())
00764           return Success;
00765 
00766         Oid cur_obj_oid;
00767         CK(inverse_read_oid(db, inv_item, inv_obj_oid, cur_obj_oid));
00768 
00769         Collection *coll = 0;
00770         if (cur_obj_oid.isValid())
00771           CK(inverse_get_collection(db, cur_obj_oid, coll));
00772 
00773         if (!coll)
00774           {
00775             CK(inverse_create_collection(db, inv_item, Oid::nullOid,
00776                                          False, inv_obj_oid, coll));
00777             CK(inverse_write_oid(db, inv_item, inv_obj_oid, coll->getOidC(),
00778                                  inv_ctx));
00779           }
00780 
00781         if (coll)
00782           {
00783             IDB_LOG(IDB_LOG_RELSHIP_DETAILS,
00784                     ("appending [4] %s to collection %s\n",
00785                      obj_oid.toString(), coll->getOid().toString()));
00786             CK(coll->insert(obj_oid, True));
00787             CK(inverse_coll_realize(coll));
00788           }
00789 
00790         return Success;
00791       }
00792 
00793     if (op == invObjRemove)
00794       {
00795         if (!inv_obj_oid.isValid())
00796           return Success;
00797 
00798         Oid cur_obj_oid;
00799         CK(inverse_read_oid(db, inv_item, inv_obj_oid, cur_obj_oid));
00800 
00801         if (cur_obj_oid.isValid())
00802           {
00803             Collection *coll;
00804             CK(inverse_get_collection(db, cur_obj_oid, coll));
00805 
00806             if (!coll)
00807               return Success;
00808 
00809             IDB_LOG(IDB_LOG_RELSHIP_DETAILS,
00810                     ("suppressing [6] %s from collection %s\n",
00811                      obj_oid.toString(), 
00812                      coll->getOid().toString()));
00813             CK(coll->suppress(obj_oid, True));
00814             CK(inverse_coll_realize(coll));
00815             return Success;
00816           }
00817 
00818         return Success;
00819       }
00820 
00821     abort();
00822     return Success;
00823   }
00824   
00825   // ---------------------------------------------------------------------------
00826   //
00827   // inverse_N_1
00828   //
00829   // ---------------------------------------------------------------------------
00830 
00831   Status
00832   Attribute::inverse_N_1(Database *db, InvObjOp op,
00833                          const Attribute *inv_item,
00834                          const Oid &obj_oid,
00835                          const Oid &inv_obj_oid,
00836                          const InvCtx &inv_ctx) const
00837   {
00838     _trace_("inverse_N_1", op, this, inv_item, obj_oid, inv_obj_oid);
00839     Status status;
00840 
00841     if (op == invObjUpdate)
00842       {
00843         Oid old_inv_obj_oid;
00844         CK(inverse_read_oid(db, this, obj_oid, old_inv_obj_oid));
00845         if (old_inv_obj_oid.isValid() && old_inv_obj_oid != inv_obj_oid)
00846           {
00847             Collection *old_coll = 0;
00848             CK(inverse_get_collection(db, old_inv_obj_oid, old_coll));
00849             if (old_coll)
00850               {
00851                 OidArray oid_arr;
00852                 CK(old_coll->getElements(oid_arr));
00853 
00854                 old_coll->release(); old_coll = 0;
00855                 // visiblement, on a un BUG
00856                 for (int i = 0; i < oid_arr.getCount(); i++)
00857                   CK(inverse_write_oid(db, inv_item, oid_arr[i],
00858                                        Oid::nullOid, inv_ctx));
00859               }
00860           }
00861       }
00862 
00863     if (op == invObjCreate || op == invObjUpdate)
00864       {
00865         if (!inv_obj_oid.isValid()) return Success;
00866 
00867         Collection *coll = 0;
00868         CK(inverse_get_collection(db, inv_obj_oid, coll));
00869 
00870         if (coll)
00871           {
00872             OidArray oid_arr;
00873             CK(coll->getElements(oid_arr));
00874             coll->release(); coll = 0;
00875             for (int i = 0; i < oid_arr.getCount(); i++)
00876               {
00877                 Oid old_obj_oid;
00878                 CK(inverse_read_oid(db, inv_item, oid_arr[i], old_obj_oid));
00879                 if (old_obj_oid != obj_oid) // added the 30/8/99
00880                   {
00881                     if (old_obj_oid.isValid())
00882                       CK(inverse_write_oid(db, this, old_obj_oid,
00883                                            Oid::nullOid, inv_ctx));
00884                     CK(inverse_write_oid(db, inv_item, oid_arr[i], obj_oid,
00885                                          inv_ctx));
00886                   }
00887               }
00888           }
00889 
00890         return Success;
00891       }
00892 
00893     if (op == invObjRemove)
00894       {
00895         if (!inv_obj_oid.isValid()) return Success;
00896 
00897         Collection *coll;
00898 
00899         CK(inverse_get_collection(db, inv_obj_oid, coll));
00900         if (coll)
00901           {
00902             OidArray oid_arr;
00903             CK(coll->getElements(oid_arr));
00904             coll->release(); coll = 0;
00905 
00906             for (int i = 0; i < oid_arr.getCount(); i++)
00907               CK(inverse_write_oid(db, inv_item, oid_arr[i], Oid::nullOid,
00908                                    inv_ctx));
00909           }
00910 
00911         return Success;
00912       }
00913 
00914     abort();
00915     return Success;
00916 
00917     return Success;
00918   }
00919 
00920   // ---------------------------------------------------------------------------
00921   //
00922   // inverse_N_N
00923   //
00924   // ---------------------------------------------------------------------------
00925 
00926   Status
00927   Attribute::inverse_N_N(Database *db,
00928                          InvObjOp op,
00929                          const Attribute *inv_item,
00930                          const Oid &obj_oid,
00931                          const Oid &inv_obj_oid,
00932                          const InvCtx &inv_ctx) const
00933   {
00934     _trace_("inverse_N_N", op, this, inv_item, obj_oid, inv_obj_oid);
00935 
00936     if (op == invObjUpdate)
00937       {
00938         Oid old_inv_obj_oid;
00939         CK(inverse_read_oid(db, this, obj_oid, old_inv_obj_oid));
00940         if (old_inv_obj_oid.isValid() && old_inv_obj_oid != inv_obj_oid)
00941           {
00942             Collection *old_coll;
00943             CK(inverse_get_collection(db, old_inv_obj_oid, old_coll));
00944             if (old_coll)
00945               {
00946                 OidArray oid_arr;
00947                 CK(old_coll->getElements(oid_arr));
00948                 for (int i = 0; i < oid_arr.getCount(); i++)
00949                   {
00950                     IDB_LOG(IDB_LOG_RELSHIP_DETAILS,
00951                             ("suppressing [7] %s from collection %s\n",
00952                              oid_arr[i].toString(), 
00953                              old_coll->getOid().toString()));
00954                     CK(old_coll->suppress(oid_arr[i], True));
00955 
00956                     Oid coll_oid;
00957                     CK(inverse_read_oid(db, inv_item, oid_arr[i], coll_oid));
00958 
00959                     if (coll_oid.isValid())
00960                       {
00961                         Collection *inv_coll;
00962                         CK(inverse_get_collection(db, coll_oid, inv_coll));
00963                         if (inv_coll)
00964                           {
00965                             IDB_LOG(IDB_LOG_RELSHIP_DETAILS,
00966                                     ("suppressing [8] %s from collection %s\n",
00967                                      obj_oid.toString(), 
00968                                      inv_coll->getOid().toString()));
00969                             CK(inv_coll->suppress(obj_oid, True));
00970                             CK(inverse_coll_realize(inv_coll));
00971                           }
00972                       }
00973                   }
00974 
00975                 CK(inverse_coll_realize(old_coll));
00976               }
00977           }
00978 
00979         // optimisation added the 15/9/99
00980         if ((old_inv_obj_oid.isValid() && old_inv_obj_oid == inv_obj_oid) ||
00981             !inv_obj_oid.isValid())
00982           return Success;
00983       }
00984 
00985     // 15/9/99
00986     // je pense qu'en cas d'update, il n'y a rien a faire sauf
00987     // si la nouvelle collection est != de l'ancienne
00988     // (see above)
00989     if (op == invObjCreate || op == invObjUpdate)
00990       {
00991         if (!inv_obj_oid.isValid()) return Success;
00992 
00993         Collection *coll;
00994         CK(inverse_get_collection(db, inv_obj_oid, coll));
00995 
00996         if (!coll)
00997           return Success;
00998 
00999         OidArray oid_arr;
01000         CK(coll->getElements(oid_arr));
01001 
01002         for (int i = 0; i < oid_arr.getCount(); i++)
01003           {
01004             Oid coll_obj_oid;
01005             CK(inverse_read_oid(db, inv_item, oid_arr[i], coll_obj_oid));
01006             Collection *inv_coll = 0;
01007 
01008             if (coll_obj_oid.isValid())
01009               CK(inverse_get_collection(db, coll_obj_oid, inv_coll));
01010           
01011             if (!inv_coll)
01012               {
01013                 CK(inverse_create_collection(db, inv_item, oid_arr[i],
01014                                              True, oid_arr[i], inv_coll));
01015               
01016                 CK(inverse_write_oid(db, inv_item, oid_arr[i],
01017                                      inv_coll->getOidC(), inv_ctx));
01018               }
01019 
01020             // the following line is a gag, I think!
01021             // CK(coll->insert(oid_arr[i], True));
01022             IDB_LOG(IDB_LOG_RELSHIP_DETAILS, ("appending [5] %s to collection %s\n",
01023                                               obj_oid.toString(), 
01024                                               inv_coll->getOid().toString()));
01025             CK(inv_coll->insert(obj_oid, True));
01026             CK(inverse_coll_realize(inv_coll));
01027           }
01028 
01029         // no more necessary
01030         // CK(inverse_coll_realize(coll));
01031         coll->release(); coll = 0;
01032         return Success;
01033       }
01034 
01035     if (op == invObjRemove)
01036       {
01037         if (!inv_obj_oid.isValid()) return Success;
01038 
01039         Collection *coll;
01040         CK(inverse_get_collection(db, inv_obj_oid, coll));
01041 
01042         if (!coll)
01043           return Success;
01044 
01045         OidArray oid_arr;
01046         CK(coll->getElements(oid_arr));
01047 
01048         for (int i = 0; i < oid_arr.getCount(); i++)
01049           {
01050             Oid coll_oid;
01051             CK(inverse_read_oid(db, inv_item, oid_arr[i], coll_oid));
01052             if (coll_oid.isValid())
01053               {
01054                 Collection *inv_coll;
01055                 CK(inverse_get_collection(db, coll_oid, inv_coll));
01056                 IDB_LOG(IDB_LOG_RELSHIP_DETAILS,
01057                         ("suppressing [9] %s from collection %s\n",
01058                          oid_arr[i].toString(), 
01059                          coll->getOid().toString()));
01060                 CK(coll->suppress(oid_arr[i], True));
01061                 if (inv_coll)
01062                   {
01063                     IDB_LOG(IDB_LOG_RELSHIP_DETAILS,
01064                             ("suppressing [10] %s from collection %s\n",
01065                              obj_oid.toString(), 
01066                              inv_coll->getOid().toString()));
01067                     CK(inv_coll->suppress(obj_oid, True));
01068                     CK(inverse_coll_realize(inv_coll));
01069                   }
01070               }
01071           }
01072       
01073         CK(inverse_coll_realize(coll));
01074         return Success;
01075       }
01076 
01077     abort();
01078     return Success;
01079   }  
01080 
01081   // ---------------------------------------------------------------------------
01082   //
01083   // Main routing method: inverse_realize
01084   // 
01085   // ---------------------------------------------------------------------------
01086 
01087   Status
01088   Attribute::inverse_realize(Database *db, InvObjOp op, Data obj_idr,
01089                              const Oid &obj_oid) const
01090   {
01091     if (!inv_spec.item) return Success;
01092 
01093     InvCtx inv_ctx(obj_oid, obj_idr);
01094     const Attribute *inv_item = inv_spec.item;
01095     Oid inv_obj_oid = inverse_get_inv_obj_oid(obj_idr);
01096     Status status;
01097     Class *objcls = NULL;
01098 
01099     IDB_LOG(IDB_LOG_RELSHIP, ("Attribute::inverse_realize(name = \"%s::%s\", "
01100                               "invitem = \"%s::%s\", "
01101                               "op = %s. obj_oid = %s, inv_obj_oid = %s)\n", 
01102                               class_owner->getName(), name,
01103                               inv_item->getClassOwner()->getName(), inv_item->getName(),
01104                               get_op_name(op),
01105                               obj_oid.getString(), inv_obj_oid.getString()));
01106 
01107     get_object_class(db, obj_oid);
01108     get_object_class(db, inv_obj_oid);
01109 
01110     if (cls->asCollectionClass())
01111       {
01112         if (inv_item->cls->asCollectionClass())
01113           status = inverse_N_N(db, op, inv_item, obj_oid, inv_obj_oid, inv_ctx);
01114         else
01115           status = inverse_N_1(db, op, inv_item, obj_oid, inv_obj_oid, inv_ctx);
01116       }
01117     else
01118       {
01119         if (inv_item->cls->asCollectionClass())
01120           status = inverse_1_N(db, op, inv_item, obj_oid, inv_obj_oid, inv_ctx);
01121         else
01122           status = inverse_1_1(db, op, inv_item, obj_oid, inv_obj_oid, inv_ctx);
01123       }
01124 
01125     IDB_LOG(IDB_LOG_RELSHIP,
01126             ("Attribute::inverse_realize(name = \"%s::%s\") ending with "
01127              "status '%s'\n\n", class_owner->getName(), name,
01128              (!status ? "success" : status->getDesc())));
01129 
01130     return status;
01131   }
01132 
01133   // ---------------------------------------------------------------------------
01134   //
01135   // Public API Methods
01136   // 
01137   // ---------------------------------------------------------------------------
01138 
01139   Status
01140   Attribute::createInverse_realize(Database *db,
01141                                    Data obj_idr,
01142                                    const Oid *obj_oid) const
01143   {
01144     return inverse_realize(db, invObjCreate, obj_idr, *obj_oid);
01145   }
01146 
01147   Status
01148   Attribute::updateInverse_realize(Database *db,
01149                                    Data obj_idr,
01150                                    const Oid *obj_oid) const
01151   {
01152     return inverse_realize(db, invObjUpdate, obj_idr, *obj_oid);
01153   }
01154 
01155   Status
01156   Attribute::removeInverse_realize(Database *db,
01157                                    Data obj_idr,
01158                                    const Oid *obj_oid) const
01159   {
01160     return inverse_realize(db, invObjRemove, obj_idr, *obj_oid);
01161   }
01162 
01163   // ---------------------------------------------------------------------------
01164   //
01165   // Low level utilily methods.
01166   // 
01167   // ---------------------------------------------------------------------------
01168 
01169   Status
01170   Attribute::inverse_get_collection(Database *db,
01171                                     const Oid &inv_obj_oid,
01172                                     Collection*& coll) const
01173   {
01174     coll = 0;
01175 
01176     Object *o;
01177     Status status = db->loadObject(&inv_obj_oid, &o);
01178   
01179     if (status)
01180       return status;
01181   
01182     if (!o->asCollection())
01183       {
01184         o->release();
01185         return Exception::make(IDB_ATTRIBUTE_INVERSE_ERROR,
01186                                "%s::%s collection expected",
01187                                class_owner->getName(), name);
01188       }
01189   
01190     if (o->isRemoved())
01191       {
01192         o->release();
01193         return Success;
01194       }
01195 
01196     coll = o->asCollection();
01197 
01198     return Success;
01199   }
01200 
01201   extern std::string
01202   getAttrCollDefName(const Attribute *attr, const Oid &oid);
01203 
01204   Status
01205   Attribute::inverse_create_collection(Database *db,
01206                                        const Attribute *inv_item,
01207                                        const Oid &obj_oid,
01208                                        Bool is_N_N,
01209                                        const Oid &master_oid,
01210                                        Collection *&coll) const
01211   {
01212     Status status = requalify(db, master_oid, inv_item);
01213     if (status) return status;
01214 
01215     if (!inv_item->isIndirect())
01216       {
01217         IDB_LOG(IDB_LOG_RELSHIP_DETAILS,
01218                 ("creating literal collection '%s'\n", inv_item->getName()));
01219 
01220         Object *master_obj=0;
01221         coll = 0;
01222         status = db->loadObject(master_oid, master_obj);
01223         if (status) return status;
01224         assert(master_obj);
01225         status = inv_item->getValue(master_obj, (Data *)&coll, 1, 0);
01226         if (status) return status;
01227         assert(coll);
01228         if (!coll->getOidC().isValid())
01229           {
01230             status = coll->create_realize(RecMode::NoRecurs);
01231             if (status) return status;
01232             //printf("CREATING INV COLLECTION %s\n", coll->getOidC().toString());
01233             IDB_LOG(IDB_LOG_RELSHIP_DETAILS, 
01234                     ("have created literal collection %s for attribute %s::%s\n",
01235                      coll->getOidC().toString(),
01236                      inv_item->getClassOwner()->getName(),
01237                      inv_item->getName()));
01238           }
01239         else
01240           IDB_LOG(IDB_LOG_RELSHIP_DETAILS, 
01241                   ("literal collection %s was already created "
01242                    "for attribute %s::%s\n",
01243                    coll->getOidC().toString(),
01244                    inv_item->getClassOwner()->getName(),
01245                    inv_item->getName()));
01246 
01247         coll->incrRefCount();
01248         master_obj->release();
01249         return Success;
01250       }
01251 
01252     std::string collname = getAttrCollDefName(inv_item, obj_oid);
01253 
01254     Class *coll_class = const_cast<Class *>
01255       (inv_item->cls->asCollectionClass()->getCollClass());
01256 
01257     if (inv_item->cls->asCollSetClass())
01258       coll = new CollSet(db, collname.c_str(), coll_class);
01259 
01260     else if (inv_item->cls->asCollBagClass()) {
01261       //printf("inverse: creating bag collection\n");
01262       coll = new CollBag(db, collname.c_str(), coll_class);
01263     }
01264 
01265     else if (inv_item->cls->asCollArrayClass())
01266       coll = new CollArray(db, collname.c_str(), coll_class);
01267 
01268     else if (inv_item->cls->asCollListClass())
01269       coll = new CollList(db, collname.c_str(), coll_class);
01270 
01271     else {
01272       coll = 0;
01273       abort();
01274     }
01275 
01276     if (is_N_N)
01277       CollectionPeer::setInvOid(coll, obj_oid, inv_item->getNum());
01278 
01279     IDB_LOG(IDB_LOG_RELSHIP_DETAILS, ("creating collection '%s' "
01280                                       "-> magorder %u\n",
01281                                       inv_item->getName(),
01282                                       inv_item->getMagOrder()));
01283 
01284     //printf("WARNING: should set something about collection implementation\n");
01285     //coll->setMagOrder(inv_item->getMagOrder());
01286     
01287     status = coll->realize();
01288     //Status status = coll->create_realize(RecMode::NoRecurs);
01289 
01290     IDB_LOG(IDB_LOG_RELSHIP_DETAILS, ("have created collection %s for "
01291                                       "attribute %s::%s\n",
01292                                       coll->getOid().toString(),
01293                                       inv_item->getClassOwner()->getName(),
01294                                       inv_item->getName()));
01295 
01296     if (is_N_N)
01297       IDB_LOG(IDB_LOG_RELSHIP_DETAILS,
01298               ("setting inv_oid %s to collection %s\n",
01299                obj_oid.toString(), coll->getOidC().toString()));
01300 
01301     return status;
01302   }
01303 
01304   Oid
01305   Attribute::inverse_get_inv_obj_oid(Data obj_idr) const
01306   {
01307     Oid inv_obj_oid;
01308     eyedbsm::x2h_oid(inv_obj_oid.getOid(), obj_idr + idr_poff);
01309     return inv_obj_oid;
01310   }
01311 
01312   Status
01313   Attribute::inverse_read_oid(Database *db, const Attribute *item,
01314                               const Oid &obj_oid,
01315                               Oid &old_obj_oid)
01316   {
01317     if (obj_oid.getDbid() != db->getDbid())
01318       return Exception::make(IDB_ATTRIBUTE_INVERSE_ERROR,
01319                              "%s does not belong to database #%d: relationships cannot cross databases", obj_oid.toString(), db->getDbid());
01320 
01321     eyedbsm::Oid toid;
01322     Status s = StatusMake(dataRead(db->getDbHandle(), item->idr_poff,
01323                                    sizeof(eyedbsm::Oid),
01324                                    (Data)&toid, 0,
01325                                    obj_oid.getOid()));
01326     eyedbsm::x2h_oid(old_obj_oid.getOid(), &toid);
01327 
01328     IDB_LOG(IDB_LOG_RELSHIP_DETAILS, ("read oid -> item=%s, obj_oid=%s, "
01329                                       "old_obj_oid=%s\n",
01330                                       item->getName(), obj_oid.toString(),
01331                                       old_obj_oid.toString()));
01332     return s;
01333   }
01334 
01335 
01336   Status
01337   Attribute::inverse_write_oid(Database *db, const Attribute *item,
01338                                const Oid &obj_oid,
01339                                const Oid &new_obj_oid,
01340                                const InvCtx &inv_ctx)
01341   {
01342     // With new indexes, this test is no more useful, but it was an
01343     // interesting optimisation
01344     if (item->isIndirect()) {
01345       Status status = item->updateIndexForInverse(db, obj_oid, new_obj_oid);
01346       if (status)
01347         return status;
01348     }
01349 
01350     IDB_LOG(IDB_LOG_RELSHIP_DETAILS, ("write oid -> item=%s, obj_oid=%s, "
01351                                       "new_obj_oid=%s\n",
01352                                       item->getName(), obj_oid.toString(),
01353                                       new_obj_oid.toString()));
01354 
01355     InvOidContext::insert(obj_oid, item, new_obj_oid);
01356 
01357     eyedbsm::Oid toid;
01358     eyedbsm::h2x_oid(&toid, new_obj_oid.getOid());
01359 
01360     if (obj_oid == inv_ctx.oid) {
01361       //printf("writing in idr %p\n", inv_ctx.idr);
01362       //IDB_LOG(IDB_LOG_RELSHIP_DETAILS, ("writing oid on idr %p %p\n",
01363       //inv_ctx.idr, item->idr_poff));
01364       mcp(inv_ctx.idr+item->idr_poff, &toid, sizeof(Oid));
01365     }
01366 
01367     return StatusMake(dataWrite(db->getDbHandle(), item->idr_poff,
01368                                 sizeof(eyedbsm::Oid),
01369                                 (Data)&toid,
01370                                 obj_oid.getOid()));
01371   }
01372 }

Generated on Mon Dec 22 18:15:50 2008 for eyedb by  doxygen 1.5.3