Attribute.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 #include "eyedb_p.h"
00026 #include "CollectionBE.h"
00027 #include "Attribute_p.h"
00028 #include "eyedb/gbxcyctx.h"
00029 #include "eyedblib/strutils.h"
00030 
00031 static void stop_imm2() { }
00032 
00033 //#define IDX_CTX_SHORTCUT
00034 
00035 #define ATTR_COMP_SET_OID_OFFSET 40
00036 #define CODE_ENDOFF
00037 //#define CODE_ENDOFF_TRACE
00038 #define NEW_RELEASE
00039 //#define TRACE_IDX
00040 
00041 //#define TRACK_BUG1
00042 
00043 #define _64BITS_PORTAGE
00044 
00045 #ifdef _64BITS_PORTAGE
00046 #define SIZEOFOBJECT 8
00047 #define SIZEOFDATA   8
00048 #else
00049 #define SIZEOFOBJECT sizeof(Object *)
00050 #define SIZEOFDATA sizeof(Data)
00051 #endif
00052 
00053 //#define MULTI_IDX_OPTIM1
00054 #define MULTI_IDX_CACHE_OPTIM
00055 #define MULTI_IDX_BAG
00056 #define MAGORDER_VERSION 20409
00057 
00058 #define VARS_INISZ 3
00059 #define VARS_SZ   24
00060 #define VARS_TSZ  (VARS_INISZ+VARS_SZ)
00061 
00062 static bool eyedb_support_stack = getenv("EYEDB_SUPPORT_STACK") ? true : false;
00063 
00064 //#define E_XDR_TRACE
00065 
00066 namespace eyedbsm {
00067   extern int hidx_gccnt;
00068 }
00069 
00070 
00071 namespace eyedb {
00072 
00073 #define E_XDR_1
00074 
00075 #define getDB(O) (Database *)(O)->getClass()->getDatabase()
00076 
00077 //#define VARS_COND(DB) IDBBOOL(isString())
00078 #define VARS_COND(DB) is_string
00079 #define VARS_OFFSET (sizeof(Size) + sizeof(Oid))
00080 #define VARS_DATA(IDR) ((IDR) + idr_poff + VARS_OFFSET)
00081 
00082 unsigned char Attribute::idxNull    = '0';
00083 unsigned char Attribute::idxNotNull = '1';
00084 
00085 int Attribute::composedMode = -1;
00086 static AttrIdxContext null_idx_ctx;
00087 
00088 #define CHECK_OBJ(O) \
00089 do { \
00090   CHK_OBJ(O); \
00091   if ((O)->isRemoved()) \
00092     return Exception::make(IDB_ERROR, "object '%s' is removed.", \
00093                             (O)->getOid().toString()); \
00094 } while(0)
00095 
00096 #define CHECK_OID(OID) \
00097 do { \
00098   Bool isremoved; \
00099   Status s = db->isRemoved(OID, isremoved); \
00100   if (!s && isremoved) \
00101    return Exception::make(IDB_ERROR, "object '%s' is removed.", \
00102                              OID.toString()); \
00103 } while(0)
00104 
00105 #define CHECK_RTTYPE(O) \
00106 do { \
00107   if (dyn_class_owner && \
00108       (O)->getClass()->getOid() != dyn_class_owner->getOid() && \
00109       dyn_class_owner->getOid().isValid() && (O)->getClass()->getOid().isValid()) \
00110     return Exception::make(IDB_ERROR, "runtime type error: object is of " \
00111                               "type '%s' not of type '%s'",  \
00112                               (O)->getClass()->getName(), \
00113                               dyn_class_owner->getName()); \
00114 } while(0)
00115 
00116 const char *Attribute::template_name = "<template>";
00117 
00118 const char *Attribute::log_item_entry_fmt = 
00119 "index=%s oid=%s, data='%s', index=%d (%s)\n";
00120 
00121 const char *Attribute::log_comp_entry_fmt = 
00122 "index=%s oid=%s, data='%s' (%s)\n";
00123 
00124 //#define FRONT_END
00125 #include "misc.h"
00126 #include <iostream>
00127 #include <assert.h>
00128 
00129 #define ATTR_COMPLETE() \
00130   if (!cls) \
00131      ((Attribute *)this)->cls = \
00132                       db->getSchema()->getClass(oid_cl); \
00133   if (!class_owner) \
00134      ((Attribute *)this)->class_owner = \
00135                       db->getSchema()->getClass(oid_cl_own)
00136 
00137 #define check_range(from, nb) \
00138 { \
00139     Status status = checkRange(from, nb); \
00140     if (status) return status; \
00141 }
00142 
00143 #define check_var_range(o, from, nb, psize) \
00144 { \
00145     Status status; \
00146     status = checkVarRange(o, from, nb, psize); \
00147     if (status != Success) \
00148                                 return status; \
00149 }
00150 
00151 #define IS_BASIC_ENUM(CL) ((CL)->asBasicClass() || (CL)->asEnumClass())
00152 #define IS_STRING(CL)     ((CL)->asCharClass() && !isIndirect() && \
00153                            typmod.ndims == 1 && typmod.dims[0])
00154 
00155 #define PRINT_NULL(FD) fprintf(FD, NullString)
00156 /*
00157 #define ATTRNAME(IDX) ((IDX) ? (IDX)->getAttrname() : \
00158      (const char *)(std::string(class_owner->getName()) + "::" + name))
00159 */
00160 
00161 #define ATTRPATH(IDX) ((IDX) ? (IDX)->getAttrpath().c_str() : \
00162      (std::string(class_owner->getName()) + "::" + name).c_str())
00163 
00164 static int inline iniSize(int sz)
00165 {
00166   if (!sz)
00167     return 0;
00168   return ((sz-1) >> 3) + 1;
00169 }
00170 
00171 static int inline revSize(int sz)
00172 {
00173   return (sz << 3)/9;
00174 }
00175 
00176 #define SHIFT(X) ((X) >> 3)
00177 #define UNSHIFT(X) ((X) << 3)
00178 #define MASK(FROM, SFROM) (1 << (7 - (FROM - (UNSHIFT(SFROM)))))
00179 #define SMASK(FROM, SFROM) (0xff >> (FROM - (UNSHIFT(SFROM))))
00180 #define EMASK(TO, STO)     (0xff << (7 - (TO - (UNSHIFT(STO)))))
00181 
00182 #define fpos(P, OFF) ((char const *)(P) + (OFF))
00183 
00184 //#define NEW_NOTNULL_TRACE
00185 
00186 static eyedbsm::Boolean
00187 idx_precmp(void const * p, void const * q, eyedbsm::Idx::KeyType const * type,
00188            int & r)
00189 {
00190   if (type->offset > 0) {
00191 #ifdef NEW_NOTNULL_TRACE
00192     printf("comparing null char %d vs. %d\n", *(unsigned char *)p,
00193            *(unsigned char *)q);
00194 #endif
00195     r = (*(unsigned char *)p - *(unsigned char *)q);
00196     if (r)
00197       return eyedbsm::True;
00198   }
00199   
00200   if (type->offset == (1 + sizeof(eyedblib::int32))) {
00201     int pind, qind;
00202     eyedblib_mcp(&pind, fpos(p, 1), sizeof(eyedblib::int32));
00203     eyedblib_mcp(&qind, fpos(q, 1), sizeof(eyedblib::int32));
00204 #ifdef NEW_NOTNULL_TRACE
00205     printf("comparing index %d vs. %d\n", pind, qind);
00206 #endif
00207     r = pind - qind;
00208     if (r)
00209       return eyedbsm::True;
00210   }
00211 
00212   return eyedbsm::False;
00213 }
00214 
00215 Bool
00216 Attribute::isNull(Data inidata, int nb, int from)
00217 {
00218   if (!nb)
00219     return True;
00220 
00221   int sfrom = SHIFT(from);
00222   if (nb == 1)
00223     {
00224       unsigned char *s = inidata + sfrom;
00225       unsigned mask = MASK(from, sfrom);
00226       if (*s & mask)
00227         return False;
00228       return True;
00229     }
00230 
00231   int to = from+nb-1;
00232   int sto = SHIFT(to);
00233 
00234   unsigned char *s = inidata + sfrom;
00235   unsigned char *e = inidata + sto;
00236 
00237   unsigned int smask = SMASK(from, sfrom);
00238   unsigned int emask = EMASK(to, sto);
00239 
00240   if (*s & smask)
00241     return False;
00242 
00243   if (*e & emask)
00244     return False;
00245 
00246   for (unsigned char *p = s+1; p < e; p++)
00247     if (*p)
00248       return False;
00249 
00250   return True;
00251 }
00252 
00253 Bool
00254 Attribute::isNull(Data inidata, const TypeModifier *tmod)
00255 {
00256   return isNull(inidata, tmod->pdims, 0);
00257 }
00258 
00259 static inline void
00260 setInit(Data inidata, int nb, int from, int val)
00261 {
00262   if (!nb)
00263     return;
00264 
00265   int sfrom = SHIFT(from);
00266   if (nb == 1)
00267     {
00268       unsigned char *s = inidata + sfrom;
00269       unsigned mask = MASK(from, sfrom);
00270       if (val)
00271         *s |= mask;
00272       else
00273         *s &= ~mask;
00274       return;
00275     }
00276   int to = from+nb-1;
00277   int sto = SHIFT(to);
00278 
00279   unsigned char *s = inidata + sfrom;
00280   unsigned char *e = inidata + sto;
00281 
00282   unsigned int smask = SMASK(from, sfrom);
00283   unsigned int emask = EMASK(to, sto);
00284 
00285   if (val)
00286     {
00287       *s |= smask;
00288       *e |= emask;
00289 
00290       for (unsigned char *p = s+1; p < e; p++)
00291         *p = 0xff;
00292     }
00293   else
00294     {
00295       *s &= ~smask;
00296       *e &= ~emask;
00297 
00298       for (unsigned char *p = s+1; p < e; p++)
00299         *p = 0;
00300     }
00301 }
00302 
00303 int Attribute::iniCompute(const Database *, int sz, Data &pdata, Data &inidata) const
00304 {
00305   if (isIndirect())
00306     {
00307       inidata = 0;
00308       return 0;
00309     }
00310 
00311   inidata = pdata;
00312   pdata += idr_inisize;
00313   return idr_inisize;
00314 }
00315 
00316 int AttrVarDim::iniCompute(const Database *db, int sz, Data &pdata, Data &inidata) const
00317 {
00318   if (is_basic_enum)
00319     {
00320       int size = iniSize(sz);
00321       inidata = pdata;
00322       pdata += size;
00323       return size;
00324     }
00325 
00326   inidata = 0;
00327   return 0;
00328 }
00329 
00330 #define IS_LOADED_MASK        (unsigned int)0x40000000
00331 #define SZ_MASK               (unsigned int)0x80000000
00332 
00333 #define IS_LOADED(X)          (((X) & IS_LOADED_MASK) ? True : False)
00334 #define SET_IS_LOADED(X, B)   ((B) ? (((X) | IS_LOADED_MASK)) : ((X) & ~IS_LOADED_MASK))
00335 
00336 #define IS_SIZE_CHANGED(X)     (((X) & SZ_MASK) ? True : False)
00337 #define SET_SIZE_CHANGED(X, B) ((B) ? (((X) | SZ_MASK)) : ((X) & ~SZ_MASK))
00338 
00339 #define CLEAN_SIZE(X)          ((X) & ~(SZ_MASK|IS_LOADED_MASK))
00340 
00341 static inline int
00342 set_oid_realize(Data pdata, const Oid *oid, int nb, int from)
00343 {
00344   // needs XDR ? yes !
00345 #ifdef E_XDR_1
00346   for (int n = 0; n < nb; n++) {
00347     if (eyedbsm::cmp_oid(pdata + ((from+n) * sizeof(Oid)), oid[n].getOid())) {
00348       for (int m = 0; m < nb; m++)
00349         eyedbsm::h2x_oid(pdata + ((from+m) * sizeof(Oid)), oid[m].getOid());
00350       return 1;
00351     }
00352   }
00353 #else
00354   if (memcmp(pdata + (from * sizeof(Oid)), oid,  nb * sizeof(Oid))) {
00355     memcpy(pdata + (from * sizeof(Oid)), oid,  nb * sizeof(Oid));
00356     return 1;
00357   }
00358 #endif
00359 
00360   return 0;
00361 }
00362 
00363 static const char incomp_fmt[] = "incomplete type '%s' for attribute '%s' #%d in agregat class '%s'";
00364 
00365 inline static Class *
00366 get_class(Schema *sch, const Class *cls)
00367 {
00368   if (!cls)
00369     return 0;
00370   return sch->getClass(cls->getOid());
00371 }
00372 
00373 Attribute *makeAttribute(const Attribute *agreg)
00374 {
00375   return makeAttribute(agreg, agreg->getClass(), agreg->getClassOwner(),
00376                           agreg->getDynClassOwner(), agreg->getNum());
00377 }
00378 
00379 Attribute *makeAttribute(const Attribute *agreg,
00380                                const Class *_cls,
00381                                const Class *_class_owner,
00382                                const Class *_dyn_class_owner,
00383                                int num)
00384 {
00385   if (agreg->isNative())
00386     return new AttrNative((AttrNative *)agreg, _cls, _class_owner,
00387                              _dyn_class_owner, num);
00388 
00389   Bool is_vardim = agreg->isVarDim(), is_indirect = agreg->isIndirect();
00390 
00391   if (!is_vardim && !is_indirect)
00392     return new AttrDirect(agreg, _cls, _class_owner, _dyn_class_owner, num);
00393 
00394   if (!is_vardim && is_indirect)
00395     return new AttrIndirect(agreg, _cls, _class_owner, _dyn_class_owner, num);
00396 
00397   if (is_vardim && !is_indirect)
00398     return new AttrVarDim(agreg, _cls, _class_owner, _dyn_class_owner, num);
00399 
00400   if (is_vardim && is_indirect)
00401     return new AttrIndirectVarDim(agreg, _cls, _class_owner, _dyn_class_owner, num);
00402 
00403   return 0;
00404 }
00405 
00406 Attribute *Attribute::clone(Database *db) const
00407 {
00408   if (!db)
00409     return eyedb::makeAttribute(this);
00410 
00411   Schema *sch = db->getSchema();
00412   return makeAttribute(this,
00413                           get_class(sch, getClass()),
00414                           get_class(sch, getClassOwner()),
00415                           get_class(sch, getDynClassOwner()),
00416                           num);
00417 }
00418 
00419 Attribute *makeAttribute(Database *db,
00420                                Data data, Offset *offset,
00421                                const Class *_dyn_class_owner,
00422                                int num)
00423 {
00424   eyedblib::int16 code;
00425 
00426 #ifdef CODE_ENDOFF
00427   eyedblib::int32 endoff;
00428   int32_decode(data, offset, &endoff);
00429 #endif
00430   int16_decode(data, offset, &code);
00431 
00432   *offset -= sizeof(eyedblib::int16);
00433 #ifdef CODE_ENDOFF
00434   *offset -= sizeof(eyedblib::int32);
00435 #endif
00436 
00437   switch(code)
00438     {
00439     case AttrDirect_Code:
00440       return new AttrDirect(db, data, offset, _dyn_class_owner, num);
00441 
00442     case AttrIndirect_Code:
00443       return new AttrIndirect(db, data, offset, _dyn_class_owner, num);
00444 
00445     case AttrVarDim_Code:
00446       return new AttrVarDim(db, data, offset, _dyn_class_owner, num);
00447 
00448     case AttrIndirectVarDim_Code:
00449       return new AttrIndirectVarDim(db, data, offset, _dyn_class_owner, num);
00450 
00451     default:
00452       fprintf(stderr, "unknown attribute code %d\n", code);
00453       assert(0);
00454       return 0;
00455     }
00456 }
00457 
00458 TypeModifier::TypeModifier()
00459 {
00460   ndims = 0;
00461   maxdims = 0;
00462   pdims = 0;
00463   mode = (TypeModifier::_mode)0;
00464   dims = NULL;
00465 }
00466 
00467 TypeModifier::TypeModifier(const TypeModifier &typmod)
00468 {
00469   *this = typmod;
00470 }
00471 
00472 TypeModifier& TypeModifier::operator=(const TypeModifier &typmod)
00473 {
00474   ndims = typmod.ndims;
00475   pdims = typmod.pdims;
00476   maxdims = typmod.maxdims;
00477   mode = typmod.mode;
00478 
00479   if (ndims) {
00480     dims = (int *)malloc(sizeof(int) * ndims);
00481     memcpy(dims, typmod.dims, sizeof(int) * ndims);
00482   }
00483   else
00484     dims = NULL;
00485 
00486   return *this;
00487 }
00488 
00489 TypeModifier TypeModifier::make(Bool isRef, int ndims, int *dims)
00490 {
00491   TypeModifier typmod;
00492 
00493   unsigned short md = (isRef ? TypeModifier::_Indirect : 0);
00494 
00495   if (ndims)
00496     {
00497       typmod.ndims   = ndims;
00498       typmod.dims    = (int *)malloc(sizeof(int) * ndims);
00499 
00500       memcpy(typmod.dims, dims, sizeof(int)*ndims);
00501 
00502       typmod.pdims = 1;
00503       typmod.maxdims = 1;
00504 
00505       for (int i = 0; i < ndims; i++)
00506         {
00507           if (dims[i] < 0)
00508             {
00509               md |= TypeModifier::_VarDim;
00510               typmod.maxdims *= -dims[i];
00511             }
00512           else
00513             {
00514               typmod.pdims *= dims[i];
00515               typmod.maxdims *= dims[i];
00516             }
00517         }
00518     }
00519   else
00520     {
00521       typmod.ndims   = 0;
00522       typmod.dims    = 0;
00523       typmod.pdims   = 1;
00524       typmod.maxdims = 1;
00525     }
00526 
00527   typmod.mode = (TypeModifier::_mode)md;
00528 
00529   return typmod;
00530 }
00531 
00532 Status TypeModifier::codeIDR(Data* data, Offset *offset,
00533                               Size *alloc_size)
00534 {
00535   //  : mode
00536   eyedblib::int16 k = (eyedblib::int16)mode;
00537   int16_code(data, offset, alloc_size, &k);
00538   //  : pdims
00539   int32_code(data, offset, alloc_size, &pdims);
00540   //  : maxdims
00541   int32_code(data, offset, alloc_size, &maxdims);
00542   //  : ndims
00543   int16_code(data, offset, alloc_size, &ndims);
00544 
00545   //  : dims[]
00546   for (int i = 0; i < ndims; i++)
00547     int32_code(data, offset, alloc_size, &dims[i]);
00548 
00549   return Success;
00550 }
00551 
00552 Status TypeModifier::decodeIDR(Data data, Offset *offset)
00553 {
00554   memset(&ndims, 0, sizeof(eyedblib::int32)); // strange, isn't it?
00555 
00556   //  : mode
00557   eyedblib::int16 k;
00558 
00559   int16_decode(data, offset, &k);
00560   mode = (enum _mode)k;
00561   //  : pdims
00562   int32_decode(data, offset, &pdims);
00563   //  : maxdims
00564   int32_decode(data, offset, &maxdims);
00565   //  : ndims
00566   int16_decode(data, offset, &ndims);
00567 
00568   dims = (int *)malloc(sizeof(int) * ndims);
00569 
00570   for (int i = 0; i < ndims; i++)
00571     int32_decode(data, offset,  &dims[i]);
00572   return Success;
00573 }
00574 
00575 Bool
00576 TypeModifier::compare(const TypeModifier *tmod) const
00577 {
00578   if (ndims != tmod->ndims)
00579     return False;
00580 
00581   if (pdims != tmod->pdims)
00582     return False;
00583 
00584   if (maxdims != tmod->maxdims)
00585     return False;
00586 
00587   if (mode != tmod->mode)
00588     return False;
00589 
00590   for (int i = 0; i < ndims; i++)
00591     if (dims[i] != tmod->dims[i])
00592       return False;
00593 
00594   return True;
00595 }
00596 
00597 TypeModifier::~TypeModifier()
00598 {
00599   free(dims);
00600 }
00601 
00602 //
00603 // Attribute methods
00604 //
00605 
00606 Status Attribute::setCardinalityConstraint(CardinalityConstraint *_card)
00607 {
00608 #ifdef CARD_TRACE
00609   printf("Attribute::setCardinalityConstraint %s\n", name);
00610 #endif
00611   if (cls && !cls->asCollectionClass())
00612     return Exception::make(IDB_ERROR,
00613                               "cannot set a cardinality constraint on item %s::%s (not a collection)", class_owner->getName(), name);
00614 
00615   card = _card;
00616   return Success;
00617 }
00618 
00619 Status
00620 Attribute::getClassOid(Database *db, const Class *ocls,
00621                           const Oid &cls_oid, Oid &oid)
00622 {
00623   oid = ocls->getOid();
00624   if (oid.isValid())
00625     return Success;
00626 
00627   if (cls_oid.isValid()) {
00628     oid = cls_oid;
00629     return Success;
00630   }
00631 
00632   Class *xcls = db->getSchema()->getClass(ocls->getName());
00633   if (!xcls)
00634     return Success;
00635     /*
00636     return Exception::make(IDB_ATTRIBUTE_ERROR,
00637                               "attribute %s::%s: class %s is unknown",
00638                               class_owner->getName(), name, ocls->getName());
00639     */
00640 
00641   oid = xcls->getOid();
00642 
00643   /*
00644   if (!oid.isValid())
00645     return Exception::make(IDB_ATTRIBUTE_ERROR,
00646                               "attribute %s::%s: class %s has no valid oid",
00647                               class_owner->getName(), name, ocls->getName());
00648   */
00649 
00650   return Success;
00651 }
00652 
00653 Status Attribute::codeIDR(Database *db, Data* data,
00654                                 Offset *offset, Size *alloc_size)
00655 {
00656   if (isNative())
00657     return Success;
00658 
00659 #ifdef CODE_ENDOFF
00660   Offset soffset = *offset;
00661   int32_code(data, offset, alloc_size, (eyedblib::int32 *)&endoff);
00662 #endif
00663   // code
00664   int16_code(data, offset, alloc_size, &code);
00665 
00666   Oid oid;
00667   Status s = getClassOid(db, cls, oid_cl, oid);
00668   if (s) return s;
00669   oid_code(data, offset, alloc_size, oid.getOid());
00670 
00671   /*
00672   printf("coding classowner %p %s::%s -> %s vs. %s\n", this,
00673          (class_owner ? class_owner->getName() : "<unknown>"), name,
00674          oid_cl_own.getString(), class_owner->getOid().toString());
00675   */
00676 
00677   // oid de la cls owner
00678   s = getClassOid(db, class_owner, oid_cl_own, oid);
00679   if (s) return s;
00680   oid_code(data, offset, alloc_size, oid.getOid());
00681 
00682   int32_code(data, offset, alloc_size, (eyedblib::int32 *)&magorder);
00683 
00684   // this has been added the 15/02/99 for class actual update.
00685   if (!inv_spec.oid_cl.isValid() && inv_spec.item)
00686     {
00687       inv_spec.oid_cl = inv_spec.item->getClassOwner()->getOid();
00688       inv_spec.num    = inv_spec.item->getNum();
00689     }
00690 
00691   // oid de la cls inverse
00692   oid_code(data, offset, alloc_size, inv_spec.oid_cl.getOid());
00693   // num de l'attribute inverse
00694   int16_code(data, offset, alloc_size, &inv_spec.num);
00695   // is_basic_enum
00696   char_code(data, offset, alloc_size, &is_basic_enum);
00697   // is_string
00698   char_code(data, offset, alloc_size, &is_string);
00699   // dspid
00700   int16_code(data, offset, alloc_size, &dspid);
00701 
00702   /*
00703   printf("coding component set %p %s::%s -> %s\n", this,
00704          (class_owner ? class_owner->getName() : "<unknown>"), name,
00705          attr_comp_set_oid.getString());
00706   */
00707 
00708 #ifdef CODE_ENDOFF_TRACE
00709   printf("ATTRIBUTE OFFSET %d [%d]\n", *offset, *offset - soffset);
00710 #endif
00711   assert(*offset - soffset == ATTR_COMP_SET_OID_OFFSET);
00712   oid_code(data, offset, alloc_size, attr_comp_set_oid.getOid());
00713 
00714   // name
00715   string_code(data, offset, alloc_size, name);
00716 
00717   // idr_inisize
00718   int32_code(data, offset, alloc_size, (eyedblib::int32 *)&idr_inisize);
00719   // idr_poff
00720   int32_code(data, offset, alloc_size, (eyedblib::int32 *)&idr_poff);
00721   // idr_item_psize
00722   int32_code(data, offset, alloc_size, (eyedblib::int32 *)&idr_item_psize);
00723   // idr_psize
00724   int32_code(data, offset, alloc_size, (eyedblib::int32 *)&idr_psize);
00725   // idr_voff
00726   int32_code(data, offset, alloc_size, (eyedblib::int32 *)&idr_voff);
00727   // idr_item_vsize
00728   int32_code(data, offset, alloc_size, (eyedblib::int32 *)&idr_item_vsize);
00729   // idr_vsize
00730   int32_code(data, offset, alloc_size, (eyedblib::int32 *)&idr_vsize);
00731 
00732   typmod.codeIDR(data, offset, alloc_size);
00733 
00734   endoff = *offset;
00735 #ifdef CODE_ENDOFF
00736   int32_code(data, &soffset, alloc_size, (eyedblib::int32 *)&endoff);
00737 #ifdef CODE_ENDOFF_TRACE
00738   printf("NAME %s -> endof %d\n", name, endoff);
00739 #endif
00740 #endif
00741 
00742   return Success;
00743 }
00744 
00745 void Attribute::reportAttrCompSetOid(Offset *offset, Data idr) const
00746 {
00747   Data oidr = idr;
00748   Offset endo;
00749   Offset soffset = *offset;
00750   int32_decode(idr, &soffset, (eyedblib::int32 *)&endo);
00751 #ifdef CODE_ENDOFF_TRACE
00752   printf("reportAttrCompSetOid(%d, %p, %s, %s)\n", endo, idr, attr_comp_set_oid.toString(), name);
00753 #endif
00754   soffset = *offset + ATTR_COMP_SET_OID_OFFSET;
00755   Size alloc_size = soffset + sizeof(eyedbsm::Oid);
00756   oid_code(&idr, &soffset, &alloc_size, attr_comp_set_oid.getOid());
00757   assert(idr == oidr);
00758   *offset = endo;
00759 }
00760 
00761 void Attribute::codeClassOid(Data data, Offset *offset)
00762 {
00763   *offset += sizeof(eyedblib::int16);
00764   Size alloc_size = endoff; //  *offset + 2 * sizeof(Oid);
00765   oid_code(&data, offset, &alloc_size, cls->getOid().getOid());
00766   oid_code(&data, offset, &alloc_size, class_owner->getOid().getOid());
00767 
00768   /*
00769   printf("have coded oid %s::%s -> %s %s class_owner=%p\n",
00770          class_owner->getName(), name,
00771          class_owner->getOid().toString(), cls->getOid().toString(),
00772          class_owner);
00773   */
00774 
00775   *offset = endoff;
00776 }
00777 
00778 Attribute::Attribute(Database *db, Data data, Offset *offset,
00779                            const Class *_dyn_class_owner, int n)
00780 {
00781   // MIND: must decode class_owner!!
00782   // must decode code
00783 #ifdef CODE_ENDOFF
00784   int32_decode(data, offset, (eyedblib::int32 *)&endoff);
00785 #endif
00786   int16_decode(data, offset, &code);
00787 
00788   // oid de la class
00789   cls = 0;
00790   eyedbsm::Oid _oid;
00791   oid_decode(data, offset, &_oid);
00792   oid_cl.setOid(_oid);
00793   class_owner = 0;
00794   dyn_class_owner = _dyn_class_owner;
00795   oid_decode(data, offset, &_oid);
00796   oid_cl_own.setOid(_oid);
00797 
00798   int32_decode(data, offset, (int *)&magorder);
00799 
00800   // oid de la cls inverse
00801   //  mset(&inv_spec, 0, sizeof(inv_spec));
00802   oid_decode(data, offset, &_oid);
00803   inv_spec.oid_cl.setOid(_oid);
00804   // num de l'attribute inverse
00805   int16_decode(data, offset, &inv_spec.num);
00806   // is_basic_enum
00807   char_decode(data, offset, &is_basic_enum);
00808   // is_string
00809   char_decode(data, offset, &is_string);
00810   // dspid
00811   int16_decode(data, offset, &dspid);
00812     
00813   oid_decode(data, offset, &_oid);
00814   attr_comp_set_oid.setOid(_oid);
00815 
00816   // name
00817   char *s;
00818   string_decode(data, offset, &s);
00819   name = strdup(s);
00820 
00821 #ifdef CODE_ENDOFF_TRACE
00822   printf("Decoding endof = %d %s\n", endoff, name);
00823 #endif
00824   /*
00825   printf("CLASS %s %p class=%s class_owner=%s\n",
00826          name, dyn_class_owner, oid_cl.toString(),
00827          oid_cl_own.toString());
00828   */
00829 
00830   /*
00831   printf("decoding component set %p %s::%s -> %s\n", this,
00832          (class_owner ? class_owner->getName() : "<unknown>"), name,
00833          attr_comp_set_oid.getString());
00834   */
00835   // idr_inisize
00836   int32_decode(data, offset, (eyedblib::int32 *)&idr_inisize);
00837   // idr_poff
00838   int32_decode(data, offset, (eyedblib::int32 *)&idr_poff);
00839   // idr_item_psize
00840   int32_decode(data, offset, (eyedblib::int32 *)&idr_item_psize);
00841   // idr_psize
00842   int32_decode(data, offset, (eyedblib::int32 *)&idr_psize);
00843   // idr_voff
00844   int32_decode(data, offset, (eyedblib::int32 *)&idr_voff);
00845   // idr_item_vsize
00846   int32_decode(data, offset, (eyedblib::int32 *)&idr_item_vsize);
00847   // idr_vsize
00848   int32_decode(data, offset, (eyedblib::int32 *)&idr_vsize);
00849 
00850   typmod.decodeIDR(data, offset);
00851 
00852   num = n;
00853   attr_comp_set = 0;
00854 
00855   card = NULL;
00856   user_data = 0;
00857   dataspace = 0;
00858 }
00859 
00860 void Attribute::setItem(Class *tp, const char *s,
00861                            Bool isRef, int ndims, int *dims,
00862                            char _is_basic_enum,
00863                            char _is_string)
00864 {
00865   //mset(&inv_spec, 0, sizeof(inv_spec));
00866   cls = tp;
00867   assert(cls || _is_basic_enum >= 0);
00868   if (cls)
00869     is_basic_enum = IS_BASIC_ENUM(cls);
00870   else
00871     is_basic_enum = _is_basic_enum;
00872 
00873   name = strdup(s);
00874 
00875   typmod = TypeModifier::make(isRef, ndims, dims);
00876   assert(cls || _is_string >= 0);
00877   if (cls)
00878     is_string = IS_STRING(cls);
00879   else
00880     is_string = _is_string;
00881 
00882   attr_comp_set = 0;
00883   attr_comp_set_oid.invalidate();
00884 
00885   magorder = 0;
00886   oid_cl.invalidate();
00887   oid_cl_own.invalidate();
00888   card = NULL;
00889   user_data = 0;
00890   dataspace = 0;
00891   dspid = Dataspace::DefaultDspid;
00892 }
00893 
00894 void
00895 Attribute::revert(Bool)
00896 {
00897 }
00898 
00899 Bool
00900 Attribute::isVarDim() const
00901 {
00902   return (typmod.mode == TypeModifier::VarDim ||
00903           typmod.mode == TypeModifier::IndirectVarDim) ? True : False;
00904 }
00905 
00906 Bool
00907 Attribute::isIndirect() const
00908 {
00909   return (typmod.mode == TypeModifier::Indirect ||
00910           typmod.mode == TypeModifier::IndirectVarDim) ? True : False;
00911 }
00912 
00913 /*
00914 int
00915 Attribute::isString() const
00916 {
00917   if (!getClass()->asCharClass() || isIndirect())
00918     return 0;
00919 
00920   if (typmod.ndims != 1)
00921     return 0;
00922 
00923   return typmod.dims[0];
00924 }
00925 */
00926 
00927 const TypeModifier &Attribute::getTypeModifier() const
00928 {
00929   return typmod;
00930 }
00931 
00932 Bool
00933 Attribute::compare(Database *db, const Attribute *item) const
00934 {
00935   if (num != item->num)
00936     return False;
00937 
00938   if (strcmp(name, item->name))
00939     return False;
00940 
00941   if (!typmod.compare(&item->typmod))
00942     return False;
00943   
00944   ATTR_COMPLETE();
00945 
00946   if (!cls || !item->cls)
00947     return False; // should raise an exception ??
00948 
00949   if (!cls->compare(item->cls))
00950     return False;
00951 
00952   return True;
00953 }
00954 
00955 Bool
00956 Attribute::compare(Database *db, const Attribute *item,
00957                    Bool compClassOwner,
00958                    Bool compNum,
00959                    Bool compName,
00960                    Bool inDepth) const
00961 {
00962   if (compNum && num != item->num)
00963     return False;
00964 
00965   if (compName && strcmp(name, item->name))
00966     return False;
00967 
00968   if (!typmod.compare(&item->typmod))
00969     return False;
00970   
00971   ATTR_COMPLETE();
00972 
00973   if (!inDepth && isIndirect()) {
00974     if (!cls->compare_l(item->cls))
00975       return False;
00976   }
00977   else {
00978     if (!cls->compare(item->cls, compClassOwner, compNum, compName, inDepth))
00979       return False;
00980   }
00981 
00982   if (compClassOwner) {
00983     if (!inDepth) {
00984       if (!class_owner->compare_l(item->class_owner))
00985         return False;
00986     }
00987     else {
00988       if (!class_owner->compare(item->class_owner, compClassOwner, compNum,
00989                                 compName, inDepth))
00990         return False;
00991     }
00992   }
00993 
00994   return True;
00995 }
00996 
00997 Attribute::Attribute(Class *tp, const char *s,
00998                            Bool isRef, int ndims, int *dims)
00999 {
01000   setItem(tp, s, isRef, ndims, dims);
01001 }
01002 
01003 Attribute::Attribute(Class *tp, const char *s, int dim)
01004 {
01005   setItem(tp, s, False, (dim ? 1 : 0), &dim);
01006 }
01007 
01008 const char *Attribute::getName() const
01009 {
01010   return name;
01011 }
01012 
01013 Attribute::Attribute(const Attribute *attr,
01014                            const Class *_cls,
01015                            const Class *_class_owner,
01016                            const Class *_dyn_class_owner,
01017                            int n)
01018 {
01019   // 10/10/00
01020   // l'appel à setItem est-il vraiment indispensable ???
01021   // je ne pense pas!!
01022 #if 1
01023   name = strdup(attr->name);
01024   typmod = TypeModifier::make(attr->isIndirect(), attr->typmod.ndims,
01025                                  attr->typmod.dims);
01026   cls = (Class *)(_cls ? _cls : attr->cls);
01027 #else
01028   setItem((Class *)(_cls ? _cls : attr->cls),
01029           attr->name, attr->isIndirect(),
01030           attr->typmod.ndims, attr->typmod.dims,
01031           attr->mode,
01032           attr->is_basic_enum,
01033           attr->is_string);
01034 #endif
01035   num = n;
01036   class_owner = _class_owner;
01037   dyn_class_owner = _dyn_class_owner;
01038 
01039   oid_cl       = attr->oid_cl;
01040   oid_cl_own   = attr->oid_cl_own;
01041 
01042   attr_comp_set    = attr->attr_comp_set;
01043   attr_comp_set_oid = attr->attr_comp_set_oid;
01044 
01045   is_basic_enum  = attr->is_basic_enum;
01046   is_string      = attr->is_string;
01047   idr_poff       = attr->idr_poff;
01048   idr_item_psize = attr->idr_item_psize;
01049   idr_psize      = attr->idr_psize;
01050   idr_inisize    = attr->idr_inisize;
01051   idr_voff       = attr->idr_voff;
01052   idr_item_vsize = attr->idr_item_vsize;
01053   idr_vsize      = attr->idr_vsize;
01054 
01055   inv_spec      = attr->inv_spec;
01056   card          = attr->card;
01057   magorder      = attr->magorder;
01058   user_data     = attr->user_data;
01059   dataspace     = attr->dataspace;
01060   dspid         = attr->dspid;
01061 }
01062 
01063 Status
01064 Attribute::clean_realize(Schema *m, const Class *&xcls)
01065 {
01066   if (xcls && !m->checkClass(xcls)) {
01067     std::string str = xcls->getName();
01068     xcls = m->getClass(xcls->getName());
01069     if (!xcls)
01070       return Exception::make(IDB_ATTRIBUTE_ERROR, "clean() error for "
01071                              "attribute %s::%s (%s)",
01072                              (class_owner ? class_owner->getName() :
01073                               "<unknown>"),
01074                              name,
01075                              str.c_str());
01076   }
01077 
01078   return Success;
01079 }
01080 
01081 Status
01082 Attribute::clean(Database *db)
01083 {
01084   ATTR_COMPLETE();
01085   Schema *m = db->getSchema();
01086   Status s = clean_realize(m, cls);
01087   if (s) return s;
01088   s = clean_realize(m, class_owner);
01089   if (s) return s;
01090   return clean_realize(m, dyn_class_owner);
01091 }
01092 
01093 Status
01094 Attribute::checkAttrPath(Schema *m, const Class *&rcls,
01095                             const Attribute *&attr,
01096                             const char *attrpath, AttrIdxContext *idx_ctx,
01097                             Bool just_check_attr)
01098 
01099 {
01100   char *s = strdup(attrpath);
01101   char *q = strchr(s, '.');
01102 
01103   if (!q) {
01104     free(s);
01105     return Exception::make("attribute path '%s' should be under the form "
01106                               "'class.attrname[.attrname]'", attrpath);
01107   }
01108 
01109   *q = 0;
01110   const Class *cls = m->getClass(s);
01111 
01112   Status status;
01113   if (!cls) {
01114     status = Exception::make("class '%s' not found", s);
01115     free(s);
01116     return status;
01117   }
01118 
01119   rcls = cls;
01120   if (idx_ctx)
01121     idx_ctx->set(cls, (Attribute *)0);
01122 
01123   char *p = q+1;
01124   for (;;) {
01125     char *x = strchr(p, '.');
01126     if (x)
01127       *x = 0;
01128     attr = cls->getAttribute(p);
01129 
01130     if (!attr) {
01131       //      if (just_check_attr && !x) {
01132       if (just_check_attr) {
01133         free(s);
01134         return Success;
01135       }
01136 
01137       status = Exception::make("attribute '%s' not found in class '%s'",
01138                                   p, cls->getName());
01139       free(s);
01140       return status;
01141     }
01142 
01143     if (idx_ctx)
01144       idx_ctx->push(attr);
01145 
01146     if (!x)
01147       break;
01148 
01149     if (attr->isIndirect()) {
01150       status = Exception::make("attribute '%s' in class '%s' is not "
01151                                   "litteral", p, cls->getName());
01152       free(s);
01153       return status;
01154     }
01155 
01156     p = x+1;
01157     cls = attr->getClass();
01158   }
01159 
01160   free(s);
01161   return Success;
01162 }
01163 
01164 Status Attribute::checkTypes(Data data, Size item_size, int nb) const
01165 {
01166   return Success;
01167 }
01168 
01169 static void
01170 compile_update(const AgregatClass *ma, int isz, int *offset, int *size)
01171 {
01172   if (ma->asUnionClass())
01173     {
01174       if (isz > *size)
01175         *size = isz;
01176     }
01177   else
01178     {
01179       *offset += isz;
01180       *size = isz;
01181     }
01182 }
01183 
01184 void
01185 get_prefix(const Object *agr, const Class *class_owner,
01186                char prefix[], int len)
01187 {
01188   const char *name = class_owner->getName();
01189   if (strcmp(agr->getClass()->getName(), name))
01190     {
01191       if (strlen(name) < len - 3)
01192         sprintf(prefix, "%s::", name);
01193       else
01194         {
01195           strncpy(prefix, name, len - 4);
01196           prefix[len-3] = 0;
01197           strcat(prefix, "::");
01198         }
01199     }
01200   else
01201     prefix[0] = 0;
01202 }
01203 
01204 Status Attribute::checkRange(int from, int &nb) const
01205 {
01206   const TypeModifier *tmod = &typmod;
01207 
01208   if (from < 0)
01209     return Exception::make(IDB_ATTRIBUTE_ERROR, "invalid negative offset [%d] for attribute '%s' in agregat class '%s'", from, name, class_owner->getName());
01210 
01211   if (from >= tmod->pdims)
01212     return Exception::make(IDB_OUT_OF_RANGE_ATTRIBUTE_ERROR, "offset [%d] too large for attribute '%s' in agregat class '%s'", from, name, class_owner->getName());
01213 
01214   if (nb == defaultSize)
01215     nb = tmod->pdims - from;
01216   else if (nb != directAccess && from + nb > tmod->pdims)
01217     return Exception::make(IDB_OUT_OF_RANGE_ATTRIBUTE_ERROR, "range [%d, %d[ too large for attribute '%s' in agregat class '%s'", from, from+nb, name, class_owner->getName());
01218 
01219   /* todo : blindage sur nb >= 0 && nb != directAccess si !cls->asBasicClass() */
01220   return Success;
01221 }
01222 
01223 Status
01224 Attribute::checkVarRange(const Object *agr, int from, int &nb,
01225                             Size *psize) const
01226 {
01227   const TypeModifier *tmod = &typmod;
01228   Size size;
01229 
01230   getSize(agr, size);
01231 
01232   if (psize)
01233     *psize = size;
01234 
01235   if (from < 0)
01236     return Exception::make(IDB_ATTRIBUTE_ERROR, "invalid negative offset [%d] for attribute '%s' in agregat class '%s'", from, name, class_owner->getName());
01237 
01238   if (nb != directAccess && size < (from+nb)/tmod->pdims)
01239     return Exception::make(IDB_OUT_OF_RANGE_ATTRIBUTE_ERROR, "range [%d, %d[ too large for attribute '%s' in agregat class '%s'", from, from+nb, name, class_owner->getName());
01240 
01241   return Success;
01242 }
01243 
01244 Status
01245 Attribute::checkVarRange(int from, int nb, Size size) const
01246 {
01247   if (from < 0)
01248     return Exception::make(IDB_ATTRIBUTE_ERROR, "invalid negative offset [%d] for attribute '%s' in agregat class '%s'", from, name, class_owner->getName());
01249 
01250   if (nb != wholeData && size < (from+nb)/typmod.pdims)
01251     return Exception::make(IDB_OUT_OF_RANGE_ATTRIBUTE_ERROR, "range [%d, %d[ too large for attribute '%s' in agregat class '%s'", from, from+nb, name,
01252                               class_owner->getName());
01253 
01254   return Success;
01255 }
01256 
01257 static Status
01258 check_type(const Class *cls, Object *o)
01259 {
01260   Bool is;
01261   Status status;
01262 
01263   status = cls->isObjectOfClass(o, &is, True);
01264 
01265   if (status)
01266     return status;
01267 
01268   if (!is)
01269     return Exception::make(IDB_ATTRIBUTE_ERROR, 
01270                               "waiting for object of class '%s', got object of class '%s'",
01271                               cls->getName(), (o->getClass() ?
01272                                                   o->getClass()->getName() : 
01273                                                   "<unknown>"));
01274 
01275   return Success;
01276 }
01277 
01278 void
01279 Attribute::setCollHints(Object *o, const Oid& oid,
01280                            CardinalityConstraint *card_to_set) const
01281 {
01282   if (!o || !o->asCollection())
01283     return;
01284 
01285 #ifdef CARD_TRACE
01286   printf("setCollHints(%s) card_to_set %p\n", name, card_to_set);
01287 #endif
01288   //if (card_to_set)
01289   o->asCollection()->setCardinalityConstraint(card_to_set);
01290 
01291   o->asCollection()->setInverse(oid, num); 
01292   //  o->asCollection()->setMagOrder(magorder);
01293 }
01294 
01295 Status
01296 Attribute::setCollImpl(Database *db, Object *o,
01297                           const AttrIdxContext &idx_ctx) const
01298 {
01299   if (!o || !o->asCollection() || !o->asCollection()->isLiteral())
01300     return Success;
01301 
01302   if (o->asCollection()->getOidC().isValid()) {
01303     /*
01304     printf("setCollImpl: %s => does not changed implementation\n",
01305            o->asCollection()->getOidC().toString());
01306     */
01307     return Success;
01308   }
01309 
01310   CollAttrImpl *collimpl;
01311   Status s = collimplPrologue(db, idx_ctx, collimpl);
01312   /*
01313   printf("setCollImplementation(%s, collimpl=%p, %s)\n", name, collimpl,
01314          o->asCollection()->getOidC().toString());
01315   */
01316   if (s || !collimpl) return s;
01317   const IndexImpl *idximpl = 0;
01318   s = collimpl->getImplementation(db, idximpl);
01319   if (s) return s;
01320 
01321   /*
01322   printf("setCollImplementation(%s, setting implementation %s)\n",
01323          name, (const char *)idximpl->getHintsString());
01324   */
01325   o->asCollection()->setImplementation(idximpl);
01326 
01327   // 3/10/05
01328   /*
01329   if (idximpl)
01330     const_cast<IndexImpl *>(idximpl)->release();
01331   */
01332 
01333   return Success;
01334 }
01335 
01336 Status
01337 Attribute::convert(Database *db, ClassConversion *,
01338                       Data in_idr, Size in_size) const
01339 {
01340   return Exception::make(IDB_ERROR, "attribute %s::%s conversion error",
01341                             class_owner->getName(), name);
01342 }
01343 
01344 static Oid getOid(Object *o)
01345 {
01346   if (!o)
01347     return Oid::nullOid;
01348 
01349   if (o->getOid().isValid())
01350     return o->getOid();
01351 
01352   Collection *coll = dynamic_cast<Collection *>(o);
01353   if (!coll)
01354     return Oid::nullOid;
01355 
01356   return coll->getLiteralOid();
01357 }
01358 
01359 static bool isAutoAffect(Object *old_o, Object *o)
01360 {
01361   if (old_o && o && old_o == o)
01362     return true;
01363 
01364   Oid o_oid = eyedb::getOid(o);
01365   Oid old_o_oid = eyedb::getOid(old_o);
01366   return o_oid.isValid() && o_oid == old_o_oid;
01367 }
01368 
01369 static bool is_persistent(Object *o)
01370 {
01371   return (bool)getOid(o).isValid();
01372 }
01373 
01374 Status
01375 Attribute::setValue(Object *agr,
01376                        Data pvdata, // pdata or vdata
01377                        Data data, Size incsize,
01378                        Size,
01379                        int nb, int from, Data inidata,
01380                        Bool is_indirect, Data vdata,
01381                        Bool check_class) const
01382 {
01383   Status status;
01384 
01385   CHECK_OBJ(agr);
01386 
01387   // EV 26/01/07: just for test
01388   assert(isIndirect() == is_indirect);
01389 
01390   if (!is_indirect) {
01391     // pvdata is pdata
01392     if (!pvdata) {
01393       setInit(inidata, nb, from, 0);
01394       return Success;
01395     }
01396 
01397     if (cls->asBasicClass()) {
01398 #ifdef E_XDR_TRACE
01399       printf("%s: Attribute::setValue() -> XDR\n", name);
01400 #endif
01401 #ifdef E_XDR
01402       if (cls->cmp((char *)(pvdata + (from * incsize)),
01403                    (const char *)data, incsize, nb) ||
01404           isNull(inidata, nb, from)) {
01405         cls->encode((char *)(pvdata + (from * incsize)),
01406                     (const char *)data, incsize, nb);
01407         agr->touch();
01408       }
01409 #else
01410       if (memcmp((char *)(pvdata + (from * incsize)),
01411                  (const char *)data, nb * incsize) ||
01412           isNull(inidata, nb, from)) {
01413         memcpy((char *)(pvdata + (from * incsize)),
01414                (const char *)data, nb * incsize);
01415         agr->touch();
01416       }
01417 #endif
01418 
01419       setInit(inidata, nb, from, 1);
01420       return Success;
01421     }
01422 
01423     else if (cls->asEnumClass()) {
01424       Bool modify;
01425 
01426       status = ((EnumClass *)cls)->setRawData
01427         ((Data)(pvdata + (from * incsize)), (Data)data, nb,
01428          modify, check_class);
01429       
01430       if (!status && (modify || isNull(inidata, nb, from)))
01431         agr->touch();
01432 
01433       if (!status)
01434         setInit(inidata, nb, from, 1);
01435       return status;
01436     }
01437   }
01438 
01439   for (int n = 0; n < nb; n++, data += sizeof(Object *)) {
01440     Object *o = 0;
01441     Object *old_o = 0;
01442 
01443     if (is_indirect) {
01444       // pvdata is vdata
01445       mcp(&old_o, pvdata + ((from+n) * SIZEOFOBJECT), sizeof(Object *));
01446 
01447       mcp(&o, data, sizeof(Object *));
01448 
01449       if (old_o == o)
01450         continue;
01451 
01452       if (o && o->isOnStack()) {
01453         if (!eyedb_support_stack)
01454           return Exception::make(IDB_ERROR,
01455                                  "setting attribute '%s::%s': "
01456                                  "cannot set a stack allocated object",
01457                                  class_owner->getName(), name);
01458       }
01459 
01460       setCollHints(old_o, Oid::nullOid, NULL);
01461       
01462       if (old_o)
01463         old_o->release();
01464 
01465       if (o) {
01466         if (check_class) {
01467           status = check_type(cls, o);
01468           if (status) {
01469             if (old_o)
01470               ObjectPeer::incrRefCount(old_o);
01471             return status;
01472           }
01473         }
01474 
01475         o->gbxObject::incrRefCount();
01476 
01477         Oid oid = o->getOid();
01478 
01479         if (oid.isValid()) {
01480           if (isVarDim())
01481             setOid(agr, &oid, 1, from+n);
01482           else {
01483 #ifdef E_XDR_TRACE
01484             printf("%s: setValue -> set_oid_realize\n", name);
01485 #endif
01486             set_oid_realize(agr->getIDR() + idr_poff, &oid, 1, from+n);
01487           }
01488         }
01489 
01490         setCollHints(o, agr->getOid(), card);
01491       }
01492       
01493       agr->touch();
01494       // no XDR
01495 #ifdef _64BITS_PORTAGE
01496       memcpy(pvdata + ((from+n) * SIZEOFOBJECT), data, sizeof(Object *));
01497 #else
01498       memcpy(pvdata + ((from+n) * SIZEOFOBJECT), data, incsize);
01499 #endif
01500     }
01501     else {
01502       // pvdata is pdata
01503 
01504       memcpy(&o, data, sizeof(Object *)); // no XDR
01505 
01506       bool should_release_masterobj = false;
01507 
01508       bool auto_affect = false;
01509 
01510       if (vdata) {
01511         // no XDR
01512         memcpy(&old_o, vdata + (from+n) * SIZEOFOBJECT, sizeof(Object *));
01513 
01514         auto_affect = isAutoAffect(old_o, o);
01515         if (!auto_affect) {
01516             
01517 #define SUPPORT_SET_LITERAL
01518 #ifdef SUPPORT_SET_LITERAL
01519           bool has_index = false;
01520           std::string idx_str;
01521 
01522           status = hasIndex(getDB(agr), has_index, idx_str);
01523           if (status)
01524             return status;
01525             
01526           if (has_index) {
01527             //if (is_persistent(old_o) && is_persistent(o) && has_index) {
01528             return Exception::make
01529               (IDB_ATTRIBUTE_ERROR,
01530                "setting attribute value '%s': "
01531                "cannot replace an indexed literal attribute '%s', must remove indexes first: %s",
01532                name, old_o->getClass()->getName(), idx_str.c_str());
01533           }
01534             
01535           should_release_masterobj = true;
01536 #else
01537           if (old_o != o && is_persistent(old_o))
01538             return Exception::make
01539               (IDB_ATTRIBUTE_ERROR,
01540                "setting attribute value '%s': "
01541                "cannot replace already stored literal attribute '%s'",
01542                name, old_o->getClass()->getName());
01543 #endif
01544         }
01545       }
01546 
01547       if (o) {
01548         if (check_class) {
01549           status = check_type(cls, o);
01550           if (status)
01551             return status;
01552         }
01553 
01554         // needs XDR ? no...
01555 #ifdef E_XDR_TRACE
01556         printf("%s: Attribute::setValue : cmp\n", name);
01557 #endif
01558         if (!o->getIDR()) {
01559           return Exception::make
01560             ("setting attribute value '%s': object of class '%s' "
01561              "invalid null IDR", name, o->getClass()->getName());
01562         }
01563 
01564         // 28/01/00: put the following code outside the 'if' statement
01565         // WARNING: the true test must be:
01566         /*
01567           if (o->getMasterObject() && (o->getMasterObject() != agr ||
01568           o->getMasterObjectAttribute() != this))
01569         */
01570         if (o->getMasterObject(false) && o->getMasterObject(false) != agr) {
01571           return Exception::make
01572             (IDB_ATTRIBUTE_ERROR,
01573              "setting attribute value '%s': object of class '%s' "
01574              "cannot be shared between several objects.", name,
01575              o->getClass()->getName());
01576         }
01577                       
01578         /*if (!auto_affect)*/ {
01579           status = o->setMasterObject(agr);
01580           if (status)
01581             return status;
01582         }
01583 
01584         if (memcmp(pvdata + ((from+n) * incsize),
01585                    o->getIDR() + IDB_OBJ_HEAD_SIZE, incsize)) {
01586 #ifdef E_XDR_TRACE
01587           printf("%s: Attribute::setValue -> needs XDR ? no\n", name);
01588 #endif
01589           memcpy(pvdata + ((from+n) * incsize),
01590                  o->getIDR() + IDB_OBJ_HEAD_SIZE, incsize);
01591 
01592           agr->touch();
01593         }
01594 
01595         /* WARNING: should be also:
01596            o->setMasterObjectAttribute(agr, this);
01597         */
01598       }
01599       else
01600         memset(pvdata + ((from+n) * incsize), 0, incsize);
01601 
01602       if (old_o) {
01603         if (should_release_masterobj) {
01604           status = old_o->releaseMasterObject();
01605           if (status)
01606             return status;
01607         }
01608         if (o != old_o)
01609           old_o->release_r();
01610       }
01611 
01612       if (old_o == o)
01613         continue;
01614 
01615       if (o)
01616         o->gbxObject::incrRefCount();
01617 
01618       agr->touch();
01619       // no XDR
01620       memcpy(vdata + ((from+n) * SIZEOFOBJECT), &o, sizeof(Object *));
01621     }
01622   }
01623 
01624   return Success;
01625 }
01626 
01627 Status Attribute::getValue(Database *db,
01628                            Data pvdata, // pdata or vdata
01629                            Data *data, Size incsize,
01630                            int nb, int from, Data inidata, Bool *isnull) const
01631 {
01632   if (isnull)
01633     *isnull = False;
01634 
01635   if (cls->asBasicClass()) {
01636     // pvdata is pdata
01637 #ifdef E_XDR_TRACE
01638     printf("%s: Attribute::getValue() -> XDR\n", name);
01639 #endif
01640     if (nb == directAccess)
01641       *data = (pvdata ? pvdata + (from * incsize) : 0);
01642 #ifdef E_XDR
01643     else
01644       cls->decode(data, pvdata + (from * incsize), incsize, nb);
01645 #else
01646     else
01647       memcpy(data, pvdata + (from * incsize), nb * incsize);
01648 #endif
01649 
01650     if (isnull) {
01651       if (inidata)
01652         *isnull = isNull(inidata, (nb == directAccess ?
01653                                    typmod.pdims - from : nb), from);
01654       else
01655         *isnull = True;
01656     }
01657   }
01658   else if (cls->asEnumClass()) {
01659     // pvdata is pdata
01660     if (isnull) {
01661       if (inidata)
01662         *isnull = isNull(inidata, nb, from);
01663       else
01664         *isnull = True;
01665     }
01666     
01667     return ((EnumClass *)cls)->getRawData
01668       ((Data)data, pvdata + (from * incsize), nb);
01669   }
01670   else {
01671     // pvdata is vdata
01672     // no XDR
01673     for (int n = 0; n < nb; n++, data += SIZEOFOBJECT) // was incsize
01674       memcpy(data, pvdata + (from+n) * SIZEOFOBJECT,
01675              sizeof(Object *));
01676   }
01677 
01678   return Success;
01679 }
01680 
01681 Status Attribute::incrRefCount(Object *agr, Data _idr, int n) const
01682 {
01683   for (int i = 0; i < n; i++, _idr += SIZEOFOBJECT) {
01684     Object *o;
01685     mcp(&o, _idr, sizeof(Object *));
01686     if (o) {
01687       o->incrRefCount();
01688       if (!isIndirect()) {
01689         Status s = o->setMasterObject(agr);
01690         if (s)
01691           return s;
01692       }
01693     }
01694   }
01695 
01696   return Success;
01697 }
01698 
01699 void Attribute::manageCycle(Object *mo, Data _idr, int n,
01700                                gbxCycleContext &r) const
01701 {
01702   //printf("BEGIN Attribute::manageCycle(o=%p, %s, %p, count=%d)\n", mo, name, _idr, n);
01703 
01704   if (r.isCycle()) {
01705 #ifdef MANAGE_CYCLE_TRACE
01706     printf("found #2 premature cycle in %s\n", name);
01707 #endif
01708     return;
01709   }
01710 
01711   for (int i = 0; i < n; i++, _idr += SIZEOFOBJECT) {
01712     Object *o;
01713     mcp(&o, _idr, sizeof(Object *));
01714 
01715     if (o && !gbxAutoGarb::isObjectDeleted(o)) {
01716       o->manageCycle(r);
01717       if (r.mustClean(o)) {
01718         if (Object::getReleaseCycleDetection()) {
01719           throw *Exception::make
01720             (IDB_ERROR,
01721              "attribute %s::%s in object %p: attempt to release "
01722              "object %p of class %s",
01723              (getClassOwner() ? getClassOwner()->getName() :
01724               "<unknown class>"), name, mo, o, o->getClass()->getName());
01725         }
01726 
01727         //printf("%s: mustclean %p in object %p at #%d\n", name, o, mo, i);
01728         mset(_idr, 0, sizeof(Object *));
01729         /*
01730         printf("%s::%s %s setting damaged %p\n", getClassOwner()->getName(),
01731                name, (isIndirect() ? "indirect" : "direct"), mo);
01732         */
01733 
01734         // EV : 04/01/07: as cycle are not managed correctly, I disconnect this code:
01735 #if 0
01736         if (!isIndirect())
01737           mo->setDamaged(this);
01738 #endif
01739       }
01740 
01741       if (r.isCycle()) {
01742         //#ifdef MANAGE_CYCLE_TRACE
01743         //printf("found #3 premature cycle in %s\n", name);
01744         //#endif
01745         return;
01746       }
01747     }
01748   }
01749   //printf("END Attribute::manageCycle(o=%p, %s, %p, count=%d)\n", mo, name, _idr, n);
01750 }
01751 
01752 Status Attribute::setValue(Object*, unsigned char*, int, int,
01753                                  Bool) const
01754 {
01755   return Success;
01756 }
01757 
01758 Status Attribute::getOid(const Object*, Oid*, int nb, int from) const
01759 {
01760   return Success;
01761 }
01762 
01763 Status Attribute::getValue(const Object*, unsigned char**, int, int,
01764                                  Bool *) const
01765 {
01766   return Success;
01767 }
01768 
01769 Status Attribute::trace(const Object*, FILE*, int*, unsigned int flags, const RecMode *rcm) const
01770 {
01771   return Success;
01772 }
01773 
01774 Status Attribute::compile_volat(const AgregatClass*, int*, int*)
01775 {
01776   return Success;
01777 }
01778 
01779 Status Attribute::setOid(Object*, const Oid*, int, int, Bool) const
01780 {
01781   return Success;
01782 }
01783 
01784 Status Attribute::compile_perst(const AgregatClass*, int*, int*, int *)
01785 {
01786   return Success;
01787 }
01788 
01789 Status Attribute::setSize(Object *agr, Size size) const
01790 {
01791   return Exception::make(IDB_ATTRIBUTE_ERROR, "cannot set size of non vardim item '%s' in agregat class '%s'", name, class_owner->getName());
01792 }
01793 
01794 Status Attribute::getSize(Data, Size&) const
01795 {
01796   return Exception::make(IDB_ATTRIBUTE_ERROR, "cannot get size of non vardim item '%s' in agregat class '%s'", name, class_owner->getName());
01797 }
01798 
01799 Status Attribute::getSize(const Object *agr, Size& size) const
01800 {
01801   return Exception::make(IDB_ATTRIBUTE_ERROR, "cannot get size of non vardim item '%s' in agregat class '%s'", name, class_owner->getName());
01802 }
01803 
01804 Status Attribute::getSize(Database *db, const Oid *data_oid,
01805                                 Size& size) const
01806 {
01807   return Exception::make(IDB_ATTRIBUTE_ERROR, "cannot get size of non vardim item '%s' in agregat class '%s'", name, class_owner->getName());
01808 }
01809 
01810 Status Attribute::update(Database *db,
01811                                const Oid& cloid,
01812                                const Oid& objoid,
01813                                Object *agr,
01814                                AttrIdxContext &idx_ctx) const
01815 {
01816   return Success;
01817 }
01818 
01819 Status
01820 Attribute::load(Database *db,
01821                    Object *agr,
01822                    const Oid &cloid,
01823                    LockMode lockmode,
01824                    AttrIdxContext &idx_ctx,
01825                    const RecMode *rcm, Bool force) const
01826 {
01827   return Success;
01828 }
01829 
01830 Status Attribute::realize(Database *db, Object *agr,
01831                                 const Oid& cloid,
01832                                 const Oid& objoid,
01833                                 AttrIdxContext &idx_ctx,
01834                                 const RecMode *rcm) const
01835 {
01836   return Success;
01837 }
01838 
01839 Status Attribute::remove(Database *db, Object *agr,
01840                                const Oid& cloid,
01841                                const Oid& objoid,
01842                                AttrIdxContext &idx_ctx,
01843                                const RecMode *rcm) const
01844 {
01845   return Success;
01846 }
01847 
01848 void Attribute::getPersistentIDR(Offset& p_off, Size& item_p_sz,
01849                                  Size& p_sz, Size& item_ini_sz) const
01850 {
01851   p_off = idr_poff;
01852   item_p_sz = idr_item_psize;
01853   p_sz = idr_psize;
01854   item_ini_sz = idr_inisize;
01855 }
01856 
01857 void Attribute::getVolatileIDR(Offset& v_off, Size& item_v_sz,
01858                                   Size& v_sz) const
01859 {
01860   v_off = idr_voff;
01861   item_v_sz = idr_item_vsize;
01862   v_sz = idr_vsize;
01863 }
01864 
01865 static Bool
01866 check_name(const ClassComponent *comp, void *xname)
01867 {
01868   return False;
01869 }
01870 
01871 CardinalityConstraint *Attribute::getCardinalityConstraint() const
01872 {
01873   return card;
01874 }
01875 
01876 #define mutable_attr const_cast<Attribute *>(this)
01877 
01878 Status
01879 Attribute::getIdx(Database *db, int ind, int& maxind, Size &sz,
01880                      const AttrIdxContext &idx_ctx, Index *&idx,
01881                      eyedbsm::Idx *&se_idx) const
01882 {
01883   ATTR_COMPLETE();
01884   Status s;
01885 
01886   idx = 0;
01887   se_idx = 0;
01888 
01889   if (s = const_cast<Attribute *>(this)->indexPrologue
01890       (const_cast<Database *>(cls->getDatabase()), idx_ctx, idx, False))
01891     return s;
01892 
01893   if (ind == Attribute::composedMode)
01894     {
01895       maxind = Attribute::composedMode;
01896       sz = idr_item_psize * typmod.maxdims;
01897 
01898       /*
01899       if (s = getMultiIndex(cls->getDatabase(), idx_ctx, idx, False))
01900         return s;
01901       */
01902       se_idx = (idx ? idx->idx : 0);
01903       return Success;
01904     }
01905 
01906   maxind = typmod.maxdims;
01907   sz = idr_item_psize;
01908 
01909   /*
01910   if ((mode & indexItemMode) != indexItemMode)
01911     return Success;
01912 
01913   if (s = getMultiIndex(cls->getDatabase(), idx_ctx, idx, False))
01914     return s;
01915   */
01916   se_idx = (idx ? idx->idx : 0);
01917   return Success;
01918 }
01919 
01920 
01921 #define NEW_ARGARR
01922 // FE
01923 eyedbsm::Status
01924 hash_key(const void *key, unsigned int len, void *hash_data, unsigned int &x)
01925 {
01926   BEMethod_C *mth = (BEMethod_C *)hash_data;
01927 #ifdef NEW_ARGARR
01928   static ArgArray *array = new ArgArray(2, Argument::NoGarbage);
01929 
01930   Argument retarg;
01931 
01932   (*array)[0]->set((const unsigned char *)key, len);
01933   (*array)[1]->set((int)len);
01934 
01935   Status s = mth->applyTo(mth->getDatabase(), (Object *)0, *array,
01936                              retarg, False);
01937 #else
01938   ArgArray array(2, Argument::NoGarbage);
01939   Argument retarg;
01940 
01941   array[0]->set((const unsigned char *)key, len);
01942   array[1]->set((int)len);
01943 
01944   Status s = mth->applyTo(mth->getDatabase(), (Object *)0, array,
01945                              retarg, False);
01946   array[0]->release();
01947   array[1]->release();
01948 #endif
01949 
01950   if (s)
01951     return eyedbsm::statusMake(eyedbsm::ERROR, "while applying hash function %s: %s",
01952                          mth->getName().c_str(), s->getString());
01953   x = retarg.getInteger();
01954   return eyedbsm::Success;
01955 }
01956 
01957 //#define INDEX_PRINT_STATS
01958 
01959 Status
01960 Attribute::openMultiIndexRealize(Database *db, Index *idx)
01961 {
01962   static const char fmt_error[] = "storage manager error '%s' "
01963     "reported when opening index '%s' of class '%s'";
01964 
01965   if (idx->idx)
01966     return Success;
01967 
01968   eyedbsm::Idx *se_idx = 0;
01969   const eyedbsm::Oid *idx_oid = idx->getIdxOid().getOid();
01970 
01971   eyedbsm::HIdx::hash_key_t hash_key = 0;
01972   void *hash_data = 0;
01973 
01974   if (idx->asHashIndex() &&
01975       idx->asHashIndex()->getHashMethod())
01976     {
01977       hash_key = hash_key;
01978       hash_data = idx->asHashIndex()->getHashMethod();
01979     }
01980 
01981   if (idx->asBTreeIndex() && !idx->getIsString())
01982     {
01983       se_idx = new eyedbsm::BIdx(get_eyedbsm_DbHandle((DbHandle *)db->getDbHandle()->u.dbh), *idx_oid, idx_precmp);
01984 
01985       if (se_idx->status() != eyedbsm::Success)
01986         return Exception::make(IDB_INDEX_ERROR, fmt_error,
01987                                   eyedbsm::statusGet(se_idx->status()),
01988                                   idx->getAttrpath().c_str(),
01989                                   idx->getClassOwner()->getName());
01990     }
01991 
01992   if (idx->asHashIndex() && !idx->getIsString())
01993     {
01994 
01995       se_idx = new eyedbsm::HIdx(get_eyedbsm_DbHandle((DbHandle *)db->getDbHandle()->u.dbh), idx_oid, hash_key, hash_data, idx_precmp);
01996 
01997       if (se_idx->status() != eyedbsm::Success)
01998         return Exception::make(IDB_INDEX_ERROR, fmt_error,
01999                                   eyedbsm::statusGet(se_idx->status()),
02000                                   idx->getAttrpath().c_str(),
02001                                   idx->getClassOwner()->getName());
02002     }
02003 
02004   if (idx->asBTreeIndex() && idx->getIsString())
02005     {
02006       se_idx = new eyedbsm::BIdx(get_eyedbsm_DbHandle((DbHandle *)db->getDbHandle()->u.dbh), *idx_oid, idx_precmp);
02007 
02008       if (se_idx->status() != eyedbsm::Success)
02009         return Exception::make(IDB_INDEX_ERROR, fmt_error,
02010                                   eyedbsm::statusGet(se_idx->status()),
02011                                   idx->getAttrpath().c_str(),
02012                                   idx->getClassOwner()->getName());
02013     }
02014 
02015   if (idx->asHashIndex() && idx->getIsString())
02016     {
02017       se_idx = new eyedbsm::HIdx(get_eyedbsm_DbHandle((DbHandle *)db->getDbHandle()->u.dbh), idx_oid, hash_key, hash_data, idx_precmp);
02018 
02019       if (se_idx->status() != eyedbsm::Success)
02020         return Exception::make(IDB_INDEX_ERROR, fmt_error,
02021                                   eyedbsm::statusGet(se_idx->status()),
02022                                   idx->getAttrpath().c_str(),
02023                                   idx->getClassOwner()->getName());
02024     }
02025 
02026   idx->idx = se_idx;
02027   return Success;
02028 }
02029 
02030 ClassComponent *
02031 Attribute::getComp(Class::CompIdx idx,
02032                       Bool (*pred)(const ClassComponent *, void *),
02033                       void *client_data) const
02034 {
02035   const Class *cl = getClassOwner();
02036   if (!cl)
02037     return NULL;
02038 
02039   const LinkedList *complist = cl->getCompList(idx);
02040 
02041   if (!complist)
02042     {
02043       Status s = ((Class *)cl)->setup(True);
02044       if (s)
02045         return NULL;
02046 
02047       if (!(complist = cl->getCompList(idx)))
02048         return NULL;
02049     }
02050 
02051   LinkedListCursor c(complist);
02052 
02053   ClassComponent *comp;
02054   while (c.getNext((void *&)comp))
02055     if (pred(comp, client_data))
02056       return comp;
02057 
02058   return NULL;
02059 }
02060 
02061 #define NEWIDXTYPE2
02062 #define NEWIDXTYPE3
02063 
02064 #ifdef NEWIDXTYPE3
02065 
02066 static void
02067 ktypes_dump(const Attribute *attr, eyedbsm::Idx::KeyType &ktypes, unsigned int count)
02068 {
02069   printf("Attribute %s::%s\n", attr->getClassOwner() ?
02070          attr->getClassOwner()->getName() : "<unknown>", attr->getName());
02071   printf("\tktypes.type = %d\n", ktypes.type);
02072   printf("\tktypes.count = %d\n", ktypes.count);
02073   printf("\tktypes.offset = %d\n", ktypes.offset);
02074   printf("\toldcount = %d\n\n", count);
02075 }
02076 
02077 static Status
02078 get_index_type(const Attribute *attr, Bool isComp,
02079                eyedbsm::Idx::KeyType &ktypes, Bool isHash,
02080                Bool isCollLit = False)
02081 {
02082   if (isHash && isComp && attr->isString()) {
02083     ktypes.type = eyedbsm::Idx::tString;
02084     if (attr->isVarDim()) {
02085       ktypes.count = eyedbsm::HIdx::VarSize;
02086       ktypes.offset = 0;
02087     }
02088     else {
02089       /*
02090       ktypes.count = sizeof(char) + attr->getTypeModifier().pdims;
02091       ktypes.offset = 0;
02092       */
02093       ktypes.count = attr->getTypeModifier().pdims;
02094       ktypes.offset = 1;
02095     }
02096     return Success;
02097   }
02098 
02099   const Class *cls = attr->getClass();
02100 
02101   if (isCollLit || attr->isIndirect() || cls->asOidClass())
02102     ktypes.type = eyedbsm::Idx::tOid;
02103   else if (cls->asCharClass())
02104     ktypes.type = eyedbsm::Idx::tChar;
02105   else if (cls->asInt16Class())
02106     ktypes.type = eyedbsm::Idx::tInt16;
02107   else if (cls->asInt32Class() || cls->asEnumClass())
02108     ktypes.type = eyedbsm::Idx::tInt32;
02109   else if (cls->asInt64Class())
02110     ktypes.type = eyedbsm::Idx::tInt64;
02111   else if (cls->asFloatClass())
02112     ktypes.type = eyedbsm::Idx::tFloat64;
02113   else if (cls->asByteClass())
02114     ktypes.type = eyedbsm::Idx::tUnsignedChar;
02115   else
02116     return Exception::make(IDB_ATTRIBUTE_ERROR,
02117                               "cannot create btree index on %s::%s of type %s",
02118                               attr->getClassOwner()->getName(), attr->getName(),
02119                               cls->getName());
02120   if (isComp) {
02121     if (attr->isVarDim())
02122       ktypes.count = eyedbsm::HIdx::VarSize; // should be eyedbsm::Idx::varSize
02123     else
02124       ktypes.count = attr->getTypeModifier().pdims;
02125 
02126     ktypes.offset = sizeof(char);
02127 
02128     assert(!isHash);
02129   }
02130   else {
02131     ktypes.count = 1;
02132     ktypes.offset = (isCollLit ? 0 : (sizeof(char) + sizeof(eyedblib::int32)));
02133 #ifdef IDB_UNDEF_ENUM_HINT
02134     if (cls->asEnumClass())
02135       ktypes.offset += sizeof(char);
02136 #endif
02137   }
02138 
02139   return Success;
02140 }
02141 #else
02142 static Status
02143 get_index_type(const Attribute *attr, eyedbsm::Idx::Type &type,
02144                unsigned int &count, Bool isCollLit = False)
02145 {
02146 #ifdef NEWIDXTYPE2
02147   if (isCollLit || attr->isIndirect()) {
02148     count = 1;
02149     type = eyedbsm::Idx::tOid;
02150     return Success;
02151   }
02152 
02153   /*
02154   if (attr->isString()) {
02155     count = 1;
02156     type = eyedbsm::Idx::tString;
02157     return Success;
02158   }
02159   */
02160 #else
02161   if (isCollLit) {
02162     count = sizeof(eyedbsm::Oid);
02163     type = eyedbsm::Idx::tUnsignedChar;
02164     assert(0);
02165     return Success;
02166   }
02167 
02168   if (attr->isIndirect()) {
02169     count = sizeof(eyedbsm::Oid);
02170     type = eyedbsm::Idx::tUnsignedChar;
02171     assert(0);
02172     return Success;
02173   }
02174 #endif
02175 
02176   // IN FACT, I THINK THAT INDEX ON ARRAY ARE NOT WELL SUPPORTED!
02177   count = (isComp ? attr->getTypeModifier().pdims : 1);
02178   ntypes = (isComp ? 1 : attr->getTypeModifier().pdims);
02179 
02180   const Class *cls = attr->getClass();
02181   if (cls->asCharClass()) {
02182     type = eyedbsm::Idx::tChar;
02183     return Success;
02184   }
02185 
02186   if (cls->asInt16Class()) {
02187     type = eyedbsm::Idx::tInt16;
02188     return Success;
02189   }
02190 
02191   if (cls->asInt32Class() || cls->asEnumClass()) {
02192     type = eyedbsm::Idx::tInt32;
02193     return Success;
02194   }
02195 
02196   if (cls->asInt64Class()) {
02197     type = eyedbsm::Idx::tInt64;
02198     return Success;
02199   }
02200 
02201   if (cls->asFloatClass()) {
02202     type = eyedbsm::Idx::tFloat64;
02203     return Success;
02204   }
02205 
02206   if (cls->asOidClass()) {
02207     count = sizeof(eyedbsm::Oid);
02208     type = eyedbsm::Idx::tUnsignedChar;
02209     assert(0);
02210     return Success;
02211   }
02212 
02213   if (cls->asByteClass()) {
02214     type = eyedbsm::Idx::tUnsignedChar;
02215     return Success;
02216   }
02217 
02218 #ifdef NEWIDXTYPE2
02219   if (cls->asOidClass()) {
02220     type = eyedbsm::Idx::tOid;
02221     return Success;
02222   }
02223 #endif
02224   return Exception::make(IDB_ATTRIBUTE_ERROR,
02225                             "cannot create btree index on %s::%s of type %s",
02226                             attr->getClassOwner()->getName(), attr->getName(),
02227                             cls->getName());
02228 }
02229 #endif
02230 
02231 static void
02232 display(const eyedbsm::Idx::KeyType &ktypes)
02233 {
02234   printf("ktypes.type %d\n", ktypes.type);
02235   printf("ktypes.count %d\n", ktypes.count);
02236   printf("ktypes.offset %d\n", ktypes.offset);
02237 }
02238 
02239 
02240 void
02241 resynchronize_indexes(Database *db, Index *idx)
02242 {
02243   idx->trace();
02244   idx->idx = 0;
02245   Index *new_idx = 0;
02246   if (!db->reloadObject(idx->getOid(), (Object *&)new_idx))
02247     {
02248       IDB_LOG(IDB_LOG_IDX_CREATE,
02249               ("resynchronize indexes %s %s\n",
02250                idx->getIdxOid().toString(),
02251                new_idx->getIdxOid().toString()));
02252       idx->setIdxOid(new_idx->getIdxOid());
02253       new_idx->release();
02254       return;
02255     }
02256   
02257   idx->setIdxOid(Oid::nullOid);
02258 }
02259 
02260 void
02261 idx_purge_test(void *xidx)
02262 {
02263   Index *idx = (Index *)xidx;
02264   idx->setIdxOid(Oid::nullOid);
02265   idx->idx = 0;
02266 }
02267 
02268 static void
02269 make_hash_hints(HashIndex *idx, int impl_hints[])
02270 {
02271   memset(impl_hints, 0, sizeof(int) * eyedbsm::HIdxImplHintsCount);
02272   int cnt = idx->getImplHintsCount();
02273   for (int i = 0; i < cnt; i++)
02274     impl_hints[i] = idx->getImplHints(i);
02275 }
02276 
02277 char index_backend[] = "eyedb:index:backend";
02278 
02279 Status
02280 Attribute::createDeferredIndex_realize(Database *db,
02281                                           const AttrIdxContext &idx_ctx,
02282                                           Index *idx)
02283 {
02284   // ATTENTION à l'aspect concurrence lors de cette creation différé
02285   static const char fmt_error[] = "storage manager error '%s' "
02286     "reported when opening index in attribute '%s' of class '%s'";
02287   //int hash_entries = 0;
02288   Oid idx_oid;
02289   //int mag_order = IDB_CLEAN_MAGORDER(idx_ctx.getMagOrder());
02290   Status status;
02291 
02292   /*
02293   if (!mag_order)
02294     return Exception::make(IDB_ATTRIBUTE_ERROR,
02295                               "invalid null magorder in %s::%s",
02296                               class_owner->getName(), name);
02297   */
02298 
02299   IDB_LOG(IDB_LOG_IDX_CREATE,
02300           ("Attribute::createDeferredIndex_realize(%s)\n",
02301            idx->getAttrpath().c_str()));
02302 
02303 #ifdef TRACE_IDX
02304   printf("creating deferred index this=%p, name=%s, attrname=%s\n",
02305          this, name, idx_ctx.getAttrName().c_str());
02306 #endif
02307 
02308   /*
02309   if (idx->asHashIndex())
02310     hash_entries = idx->asHashIndex()->getKeyCount();
02311   */
02312 
02313   eyedbsm::HIdx::hash_key_t hash_key = 0;
02314   void *hash_data = 0;
02315 
02316   if (idx->asHashIndex() &&
02317       idx->asHashIndex()->getHashMethod())
02318     {
02319       hash_key = hash_key;
02320       hash_data = idx->asHashIndex()->getHashMethod();
02321     }
02322 
02323   idx_oid = idx->getIdxOid();
02324 
02325   if (idx_oid.isValid())
02326     return Success;
02327 
02328   eyedbsm::Idx::KeyType ktypes;
02329   Idx *se_idx = 0;
02330 
02331   Bool isCollLit = IDBBOOL(!isIndirect() && cls->asCollectionClass());
02332   if (idx->asBTreeIndex() && !is_string)
02333     {
02334       /*
02335       printf("CREATING BTREE #3 %s::%s\n", class_owner->getName(), name);
02336       display(ktypes);
02337       */
02338 #ifdef NEWIDXTYPE3
02339       Status s = get_index_type(this, False, ktypes, False, isCollLit);
02340       if (s) return s;
02341 
02342 #elif defined(NEWIDXTYPE)
02343       Status s = get_index_type(this, ktypes.type, ktypes.count, isCollLit);
02344       if (s) return s;
02345       if (isCollLit)
02346         ktypes.offset = 0;
02347       else
02348         ktypes.offset = sizeof(char) + sizeof(eyedblib::int32);
02349 
02350 #endif
02351       se_idx = new eyedbsm::BIdx
02352         (get_eyedbsm_DbHandle((DbHandle *)db->getDbHandle()->u.dbh),
02353          sizeof(Oid), // was 2*sizeof(Oid),
02354          &ktypes,
02355          idx->get_dspid(),
02356          idx->asBTreeIndex()->getDegree());
02357 
02358       if (se_idx->status() != eyedbsm::Success)
02359         return Exception::make(IDB_INDEX_ERROR, fmt_error,
02360                                   eyedbsm::statusGet(se_idx->status()),
02361                                   idx_ctx.getAttrName().c_str(),
02362                                   class_owner->getName());
02363 
02364       se_idx->asBIdx()->open(idx_precmp);
02365       idx->report(get_eyedbsm_DbHandle((DbHandle *)db->getDbHandle()->u.dbh),
02366                   Oid(se_idx->oid()));
02367     }
02368 
02369   int impl_hints[eyedbsm::HIdxImplHintsCount];
02370   if (idx->asHashIndex())
02371     make_hash_hints(idx->asHashIndex(), impl_hints);
02372 
02373   if (idx->asHashIndex() && !is_string)
02374     {
02375       int count;
02376       if (isCollLit) count = idr_item_psize;
02377       else           count = sizeof(char) + sizeof(eyedblib::int32) + idr_item_psize;
02378 
02379       Status s = get_index_type(this, False, ktypes, True, isCollLit);
02380       if (s) return s;
02381 
02382 #ifdef NEW_NOTNULL_TRACE
02383       ktypes_dump(this, ktypes, count);
02384 #endif
02385 
02386       /*
02387       printf("MAGORDER %s -> %d %s -> %d\n",
02388              class_owner->getName(),
02389              class_owner->getMagorder(),
02390              dyn_class_owner->getName(),
02391              dyn_class_owner->getMagorder());
02392       */
02393       se_idx = new eyedbsm::HIdx
02394         (get_eyedbsm_DbHandle((DbHandle *)db->getDbHandle()->u.dbh),
02395          ktypes,
02396          sizeof(Oid),
02397          idx->get_dspid(),
02398          dyn_class_owner->getMagorder(),
02399          idx->asHashIndex()->getKeyCount(),
02400          impl_hints, eyedbsm::HIdxImplHintsCount);
02401 
02402       if (se_idx->status() != eyedbsm::Success)
02403         return Exception::make(IDB_INDEX_ERROR, fmt_error,
02404                                   eyedbsm::statusGet(se_idx->status()),
02405                                   idx_ctx.getAttrName().c_str(),
02406                                   class_owner->getName());
02407       se_idx->asHIdx()->open(hash_key, hash_data, idx_precmp);
02408 
02409       idx->report(get_eyedbsm_DbHandle((DbHandle *)db->getDbHandle()->u.dbh),
02410                   Oid(se_idx->oid()));
02411     }
02412 
02413   if (idx->asBTreeIndex() && is_string)
02414     {
02415       /*
02416       printf("CREATING BTREE #4 %s::%s\n", class_owner->getName(), name);
02417       display(ktypes);
02418       */
02419 #ifdef NEWIDXTYPE3
02420       Status s = get_index_type(this, True, ktypes, False);
02421       if (s) return s;
02422 #else
02423       Status s = get_index_type(this, ktypes.type, ktypes.count);
02424       if (s) return s;
02425       ktypes.offset = sizeof(char);
02426 #endif
02427       se_idx = new eyedbsm::BIdx
02428         (get_eyedbsm_DbHandle((DbHandle *)db->getDbHandle()->u.dbh),
02429          sizeof(Oid), // was 2*sizeof(Oid)
02430          &ktypes,
02431          idx->get_dspid(),
02432          idx->asBTreeIndex()->getDegree());
02433 
02434       if (se_idx->status())
02435         return Exception::make(IDB_INDEX_ERROR, fmt_error,
02436                                   eyedbsm::statusGet(se_idx->status()),
02437                                   idx_ctx.getAttrName().c_str(),
02438                                   class_owner->getName());
02439       se_idx->asBIdx()->open(idx_precmp);
02440       idx->report(get_eyedbsm_DbHandle((DbHandle *)db->getDbHandle()->u.dbh),
02441                   Oid(se_idx->oid()));
02442     }
02443 
02444   if (idx->asHashIndex() && is_string)
02445     {
02446       Status s = get_index_type(this, True, ktypes, True);
02447       if (s) return s;
02448 #ifdef NEW_NOTNULL_TRACE
02449       ktypes_dump(this, ktypes,
02450                   (isVarDim() ? eyedbsm::HIdx::varSize : sizeof(char) + idr_item_psize * typmod.maxdims));
02451 #endif
02452       /*
02453       printf("MAGORDER %s -> %d %s -> %d\n",
02454              class_owner->getName(),
02455              class_owner->getMagorder(),
02456              dyn_class_owner->getName(),
02457              dyn_class_owner->getMagorder());
02458 
02459       */
02460       se_idx = new eyedbsm::HIdx
02461         (get_eyedbsm_DbHandle((DbHandle *)db->getDbHandle()->u.dbh),
02462          ktypes,
02463          sizeof(Oid), // was 2*sizeof(Oid)
02464          idx->get_dspid(),
02465          dyn_class_owner->getMagorder(),
02466          idx->asHashIndex()->getKeyCount(),
02467          impl_hints, eyedbsm::HIdxImplHintsCount);
02468 
02469       if (se_idx->status())
02470         return Exception::make(IDB_INDEX_ERROR, fmt_error,
02471                                   eyedbsm::statusGet(se_idx->status()),
02472                                   idx_ctx.getAttrName().c_str(),
02473                                   class_owner->getName());
02474       se_idx->asHIdx()->open(hash_key, hash_data, idx_precmp);
02475 
02476       idx->report(get_eyedbsm_DbHandle((DbHandle *)db->getDbHandle()->u.dbh),
02477                   Oid(se_idx->oid()));
02478     }
02479 
02480   if (se_idx) {
02481     idx->idx = se_idx;
02482     idx->setIdxOid(se_idx->oid());
02483     void *ud = idx->setUserData(index_backend, AnyUserData);
02484     status = idx->store();
02485     idx->setUserData(index_backend, ud);
02486     db->addPurgeActionOnAbort(idx_purge_test, idx);
02487     if (status) {
02488       resynchronize_indexes(db, idx);
02489       return status;
02490     }
02491   }
02492 
02493   return Success;
02494 }
02495 
02496 int Attribute::getBound(Database *db, Data _idr)
02497 {
02498   return typmod.pdims;
02499 }
02500 
02501 static inline
02502 Bool checkNull(Data data, unsigned int size)
02503 {
02504   unsigned char *p = data;
02505 
02506   for (int i = 0; i < size; i++, p++)
02507     if (*p)
02508       return False;
02509 
02510   return True;
02511 }
02512 
02513 static void
02514 check_notnull(const char *msg, const char *name,
02515               Data pdata, Data inidata, int count, Bool indirect,
02516               const TypeModifier &typmod, unsigned int incsize)
02517 {
02518   Bool isnull;
02519 
02520   // 1) check not null for the whole data
02521   if (indirect)
02522     isnull = checkNull(pdata, sizeof(eyedbsm::Oid) * count);
02523   else
02524     isnull = Attribute::isNull(inidata, &typmod);
02525 
02526   Data xdata = pdata;
02527   for (int j = 0; j < count; j++, xdata += incsize)
02528     {
02529       if (indirect)
02530         isnull = checkNull(xdata, sizeof(eyedbsm::Oid));
02531       else
02532         isnull = Attribute::isNull(inidata, 1, j);
02533     }
02534 }
02535 
02536 static Bool
02537 check_notnull_comp(Data pdata, Data inidata, int count, Bool indirect,
02538                    const TypeModifier &typmod, unsigned int incsize)
02539 {
02540 
02541   if (indirect)
02542     return checkNull(pdata, sizeof(eyedbsm::Oid) * count);
02543 
02544   // added the 21/01/00 to correct a bug of notnull check when
02545   // vardim attribute has no index!
02546   if (!count) // means that there is no data!
02547     return True;
02548   // ....
02549   return Attribute::isNull(inidata, &typmod);
02550 }
02551 
02552 static Bool
02553 check_notnull(Data pdata, Data inidata, int count, Bool indirect,
02554               const TypeModifier &typmod, unsigned int incsize)
02555 {
02556   if (indirect)
02557     {
02558       for (int j = 0; j < count; j++, pdata += incsize)
02559         if (checkNull(pdata, sizeof(eyedbsm::Oid)))
02560           return True;
02561       return False;
02562     }
02563 
02564   for (int j = 0; j < count; j++, pdata += incsize)
02565     if (Attribute::isNull(inidata, 1, j))
02566       return True;
02567 
02568   return False;
02569 }
02570 
02571 Status Attribute::check() const
02572 {
02573   return Success;
02574 }
02575 #define CHECK_NOTNULL_BASE(comp, COMP) \
02576 if (notnull##comp) \
02577 { \
02578   if (check_notnull##comp(pdata, inidata, count, isIndirect(), \
02579                           typmod, idr_item_psize)) \
02580     return Exception::make(IDB_NOTNULL##COMP##_CONSTRAINT_ERROR, \
02581                               const_error, idx_ctx.getAttrName().c_str()); \
02582 } 
02583 
02584 #define CHECK_NOTNULL() CHECK_NOTNULL_BASE(, )
02585 
02586 #define CHECK_NOTNULL_COMP() CHECK_NOTNULL_BASE(_comp, _COMP)
02587 
02588 #define NULL_STR(X) ((X) ? "null data" : "not null data")
02589 
02590 /*
02591 #define IS_NULL(ISNULL, DATA, INIDATA) \
02592 Bool ISNULL; \
02593 if (notnull) \
02594   ISNULL = False; \
02595 else if (indirect) \
02596   ISNULL = checkNull(DATA, sizeof(eyedbsm::Oid)); \
02597 else \
02598   ISNULL = isNull(INIDATA, 1, n)
02599 */
02600 
02601 #define IS_NULL(ISNULL, DATA, INIDATA) \
02602 Bool ISNULL; \
02603 if (indirect) \
02604   ISNULL = checkNull(DATA, sizeof(eyedbsm::Oid)); \
02605 else \
02606   ISNULL = isNull(INIDATA, 1, n)
02607 
02608 #define NEW_NOTNULL
02609 #define NEW_NOTNULL2
02610 
02611 // MIND: 12/12/01
02612 // added ISNULL_2 macro:
02613 
02614 #ifdef NEW_NOTNULL
02615 /*
02616 #define IS_NULL_2(ISNULL, DATA) \
02617 Bool ISNULL; \
02618 if (notnull) \
02619   ISNULL = False; \
02620 else if (indirect) \
02621   ISNULL = checkNull(DATA, sizeof(eyedbsm::Oid)); \
02622 else \
02623   ISNULL = checkNull(DATA, idr_item_psize)
02624 */
02625 #define IS_NULL_2(ISNULL, DATA) \
02626 Bool ISNULL; \
02627 if (indirect) \
02628   ISNULL = checkNull(DATA, sizeof(eyedbsm::Oid)); \
02629 else \
02630   ISNULL = checkNull(DATA, idr_item_psize)
02631 #endif
02632 
02633 /*
02634 #define IS_COMP_NULL(ISNULL, PDATA, INIDATA) \
02635 Bool ISNULL; \
02636 if (notnull_comp) \
02637   ISNULL = False; \
02638 else \
02639   ISNULL = check_notnull_comp(PDATA, INIDATA, count, isIndirect(), \
02640                               typmod, idr_item_psize)
02641 */
02642 #define IS_COMP_NULL(ISNULL, PDATA, INIDATA) \
02643 Bool ISNULL; \
02644   ISNULL = check_notnull_comp(PDATA, INIDATA, count, isIndirect(), \
02645                               typmod, idr_item_psize)
02646 
02647 #define CHECK_UNIQUE(ISNULL, F1, F2) \
02648 do { \
02649  if (unique) \
02650  {  \
02651    if (!ISNULL) \
02652     { \
02653       eyedbsm::Boolean found; \
02654       if (status = idx_item->searchAny(e, &found)) \
02655         { \
02656           free(F1); free(F2); \
02657           return Exception::make(IDB_INDEX_ERROR, fmt_error, \
02658                                     eyedbsm::statusGet(status), \
02659                                     idx_ctx.getAttrName().c_str(), \
02660                                     class_owner->getName()); \
02661         } \
02662       if (found) \
02663         { \
02664           free(F1); free(F2); \
02665           return Exception::make(IDB_UNIQUE_CONSTRAINT_ERROR, \
02666                                     const_error, \
02667                                     idx_ctx.getAttrName().c_str()); \
02668         } \
02669     } \
02670  } \
02671 } while(0)
02672 
02673 #define CHECK_UNIQUE_COMP(ISNULL, F1, F2) \
02674 do { \
02675  if (unique_comp) \
02676  { \
02677    if (!ISNULL) \
02678     { \
02679       eyedbsm::Boolean found; \
02680       if (status = idx_comp->searchAny(data, &found)) \
02681         { \
02682           free(F1); free(F2); \
02683           return Exception::make(IDB_INDEX_ERROR, fmt_error, \
02684                                   eyedbsm::statusGet(status), \
02685                                  idx_ctx.getAttrName().c_str(), \
02686                                  class_owner->getName()); \
02687         } \
02688       if (found) \
02689         { \
02690           free(F1); free(F2); \
02691           return Exception::make(IDB_UNIQUE_COMP_CONSTRAINT_ERROR, \
02692                                   const_error, \
02693                                   idx_ctx.getAttrName().c_str()); \
02694         } \
02695     } \
02696  } \
02697 } while(0)
02698 
02699 static const char const_error[] = "attribute path '%s'";
02700 
02701 static void
02702 dump_data(unsigned char *e, int sz)
02703 {
02704   printf("IDX insert ->\n");
02705   for (int i = 0; i < sz; i++)
02706     printf("%03o ", e[i]);
02707   printf("\n");
02708 }
02709 
02710 // backend method
02711 
02712 Bool
02713 Attribute::indexPrologue(Database *db, Data _idr, Bool novd,
02714                             int &count, Data &pdata, Size &varsize,
02715                             Bool create)
02716 {
02717   varsize = 0;
02718   if (isVarDim() && novd)
02719     {
02720       if (!VARS_COND(db))
02721         return True;
02722 
02723       getSize(_idr, varsize);
02724 
02725       // ATTENTION: ce varsize est la nouvelle taille
02726       count = varsize;
02727       pdata = _idr + idr_poff + VARS_OFFSET;
02728       if (create && varsize > VARS_SZ)
02729         return True;
02730       return False;
02731     }
02732 
02733   if (isVarDim())
02734     {
02735       pdata = _idr;
02736       return False;
02737     }
02738 
02739   Data vdata;
02740   getData(db, _idr, pdata, vdata);
02741   count = typmod.pdims;
02742   return False;
02743 }
02744 
02745 Status
02746 Attribute::createIndexEntry_realize(Database *db,
02747                                        Data _idr,
02748                                        const Oid *_oid,
02749                                        const Oid *cloid,
02750                                        int offset,
02751                                        Bool novd,
02752                                        AttrIdxContext &idx_ctx,
02753                                        int count,
02754                                        int size)
02755 {
02756   // all should be factorize
02757   Data pdata;
02758   Size varsize;
02759 
02760   if (indexPrologue(db, _idr, novd, count, pdata, varsize, True))
02761     return Success;
02762 
02763   Status status;
02764   idx_ctx.push(db, *cloid, this);
02765   status = createIndexEntry(db, pdata, _oid, cloid, offset, count, size,
02766                             varsize, novd, idx_ctx);
02767   idx_ctx.pop();
02768   return status;
02769 }
02770 
02771 Status
02772 Attribute::collimplPrologue(Database *db,
02773                                const AttrIdxContext &idx_ctx,
02774                                CollAttrImpl *&collimpl) const
02775 {
02776 #ifdef IDX_CTX_SHORTCUT
02777   collimpl = 0;
02778 #else
02779   std::string attrpath = idx_ctx.getAttrName();
02780   Status s = loadComponentSet(db, False);
02781   if (s) return s;
02782 
02783   if (attr_comp_set) {
02784     s = attr_comp_set->find(attrpath.c_str(), collimpl);
02785     if (s) return s;
02786   }
02787   else
02788     collimpl = 0;
02789 #endif
02790 
02791   return Success;
02792 }
02793 
02794 Status
02795 Attribute::constraintPrologue(Database *db,
02796                                  const AttrIdxContext &idx_ctx,
02797                                  Bool &notnull_comp, Bool &notnull,
02798                                  Bool &unique_comp, Bool &unique) const
02799 {
02800 #ifdef IDX_CTX_SHORTCUT
02801   notnull_comp = notnull = False;
02802   unique_comp = unique = False;
02803 #else
02804   std::string attrpath = idx_ctx.getAttrName();
02805   Status s = loadComponentSet(db, False);
02806   if (s) return s;
02807 
02808   NotNullConstraint *notnull_component = 0;
02809   UniqueConstraint *unique_component = 0;
02810   if (attr_comp_set) {
02811     s = attr_comp_set->find(attrpath.c_str(), notnull_component);
02812     if (s) return s;
02813     s = attr_comp_set->find(attrpath.c_str(), unique_component);
02814     if (s) return s;
02815 
02816 #ifdef TRACE_IDX
02817     if (notnull_component)
02818       printf("found a notnull for %s\n", attrpath.c_str());
02819     if (unique_component)
02820       printf("found a unique for %s\n", attrpath.c_str());
02821 #endif
02822   }
02823 
02824   if (notnull_component) {
02825     if (is_string) {
02826       notnull_comp = True;
02827       notnull = False;
02828     }
02829     else {
02830       notnull = True;
02831       notnull_comp = False;
02832     }
02833   }
02834   else
02835     notnull_comp = notnull = False;
02836 
02837   if (unique_component) {
02838     if (is_string) {
02839       unique_comp = True;
02840       unique = False;
02841     }
02842     else {
02843       unique = True;
02844       unique_comp = False;
02845     }
02846   }
02847   else
02848     unique_comp = unique = False;
02849 
02850 #endif
02851   return Success;
02852 }
02853 
02854 Status
02855 Attribute::getAttrComponents(Database *db, const Class *xcls,
02856                                 LinkedList &list)
02857 {
02858   if (!cls) {
02859     //printf("WARNING getAttrComponents %s -> cls is null\n", xcls->getName());
02860     return Success;
02861   }
02862     
02863   if (!isIndirect() && !is_basic_enum && !cls->asCollectionClass()) {
02864     ATTR_COMPLETE();
02865     unsigned int attr_cnt;
02866     const Attribute **attrs = cls->getAttributes(attr_cnt);
02867     for (int i = 0; i < attr_cnt; i++) {
02868       Status s = const_cast<Attribute *>(attrs[i])->getAttrComponents
02869         (db, xcls, list);
02870       if (s) return s;
02871     }
02872 
02873     return Success;
02874   }
02875 
02876   Status s = loadComponentSet(db, False);
02877   if (s) return s;
02878   if (attr_comp_set)
02879     return attr_comp_set->getAttrComponents(xcls, list);
02880 
02881   return Success;
02882 }
02883 
02884 Status
02885 Attribute::indexPrologue(Database *db,
02886                             const AttrIdxContext &idx_ctx,
02887                             Index *&idx, Bool create)
02888 {
02889 #ifdef IDX_CTX_SHORTCUT
02890   idx = 0;
02891 #else
02892   std::string attrpath = idx_ctx.getAttrName();
02893   Status s = loadComponentSet(db, False);
02894   if (s) return s;
02895 
02896   if (attr_comp_set) {
02897     s = attr_comp_set->find(attrpath.c_str(), idx);
02898     if (s) return s;
02899     
02900     if (idx) {
02901       Idx *se_idx = idx->idx; // volatile idx
02902 
02903       if (!se_idx) {
02904         if (!idx->getIdxOid().isValid()) {
02905           if (!create)
02906             return Success;
02907 
02908           s = createDeferredIndex_realize(db, idx_ctx, idx);
02909           if (s) return s;
02910           assert(idx->idx);
02911           delete idx->idx;
02912           idx->idx = 0;
02913         }
02914       }
02915 
02916       s = openMultiIndexRealize(db, idx);
02917       if (s) return s;
02918     }
02919   }
02920   else
02921     idx = 0;
02922 #endif
02923 
02924   return Success;
02925 }
02926 
02927 Status
02928 Attribute::createIndexEntry(Database *db, Data pdata,
02929                                const Oid *_oid,
02930                                const Oid *cloid,
02931                                int offset, int count, int,
02932                                Size, Bool,
02933                                AttrIdxContext &idx_ctx) 
02934 {
02935   ATTR_COMPLETE();
02936   eyedbsm::Status status;
02937   static const char fmt_error[] = "storage manager error '%s' reported "
02938     "when creating index entry in attribute '%s' in agregat class '%s'";
02939 
02940   Oid xoid;
02941   Data inidata;
02942   int inisize = iniCompute(db, count, pdata, inidata);
02943 
02944 #ifdef TRACE_IDX
02945   printf("creating index entry this=%p, name=%s, attrname=%s\n",
02946          this, name,  idx_ctx.getAttrName().c_str());
02947 #endif
02948   IDB_LOG(IDB_LOG_IDX_CREATE,
02949           ("Attribute::createIndexEntry(%s)\n",
02950            idx_ctx.getAttrName().c_str()));
02951 
02952   Bool notnull, notnull_comp, unique, unique_comp;
02953   Status s = constraintPrologue(db, idx_ctx, notnull_comp, notnull,
02954                                    unique_comp, unique);
02955   if (s) return s;
02956 
02957   Index *idx_test;
02958   s = indexPrologue(db, idx_ctx, idx_test, True);
02959   if (s) return s;
02960 
02961   CHECK_NOTNULL();
02962 
02963   Oid soid[2];
02964   soid[0] = *_oid;
02965   soid[1] = *cloid;
02966 
02967   Idx *idx_item = 0, *idx_comp = 0;
02968   if (idx_test && !is_string)
02969     {
02970       // should be in a variable!
02971       if (cls && cls->asCollectionClass() && !isIndirect())
02972         return Success;
02973 
02974       idx_item = idx_test->idx;
02975 
02976       unsigned int size_of_e = sizeof(char) + sizeof(eyedblib::int32) +
02977         idr_item_psize;
02978       unsigned char *e = (unsigned char *)malloc(size_of_e);
02979       Data data = pdata;
02980       Bool indirect = isIndirect();
02981       for (int n = 0; n < count; n++, data += idr_item_psize) {
02982         IS_NULL(isnull, data, inidata);
02983         e[0] = (isnull ? idxNull : idxNotNull);
02984 
02985         h2x_32_cpy(e+sizeof(char), &n); // must code n because the index does not perform the swap
02986         if (indirect) {
02987           eyedbsm::Oid toid;
02988           eyedbsm::x2h_oid(&toid, data); // 8/09/06: data contains XDR oid : must be decoded to put in index because index perform the swap
02989           mcp(e+sizeof(char)+sizeof(eyedblib::int32), &toid, sizeof(eyedbsm::Oid));
02990         }
02991         else
02992           cls->decode(e+sizeof(char)+sizeof(eyedblib::int32), data, idr_item_psize);
02993 
02994         CHECK_UNIQUE(isnull, e, 0);
02995 
02996           IDB_LOG(IDB_LOG_IDX_INSERT,
02997                   (log_item_entry_fmt,
02998                    ATTRPATH(idx_test), soid[0].toString(),
02999                    dumpData(data), n, NULL_STR(isnull)));
03000 
03001           idx_ctx.addIdxOP(this, AttrIdxContext::IdxInsert,
03002                            idx_test, idx_item, e, size_of_e, soid);
03003         }
03004       free(e);
03005     }
03006   else if (unique)
03007     return Exception::make(IDB_UNIQUE_CONSTRAINT_ERROR,
03008                               "when creating index entry on '%s' : "
03009                               "unique constraint missing index",
03010                               idx_ctx.getAttrName().c_str());
03011 
03012   CHECK_NOTNULL_COMP();
03013 
03014   if (idx_test && is_string)
03015     {
03016       idx_comp = idx_test->idx;
03017 
03018       IS_COMP_NULL(isnull, pdata, inidata);
03019 
03020       int sz;
03021       if (isVarDim())
03022         sz = count;
03023       else
03024         sz = typmod.pdims * idr_item_psize;
03025 
03026       unsigned int size_of_data = sizeof(char) + sz;
03027       Data data = (unsigned char *)malloc(size_of_data);
03028       data[0] = (isnull ? idxNull : idxNotNull);
03029       memcpy(&data[1], pdata, sz);
03030 
03031       CHECK_UNIQUE_COMP(isnull, data, 0);
03032 
03033       IDB_LOG(IDB_LOG_IDX_INSERT,
03034               (log_comp_entry_fmt,
03035                ATTRPATH(idx_test), soid[0].toString(), pdata,
03036                NULL_STR(isnull)));
03037 
03038       idx_ctx.addIdxOP(this, AttrIdxContext::IdxInsert,
03039                        idx_test, idx_comp, data, size_of_data, soid);
03040       free(data);
03041     }
03042   else if (unique_comp)
03043     return Exception::make(IDB_UNIQUE_COMP_CONSTRAINT_ERROR,
03044                               "when creating index entry on '%s' : "
03045                               "unique constraint missing index",
03046                               idx_ctx.getAttrName().c_str());
03047 
03048   if (cls && cls->asAgregatClass() && !isIndirect() && count)
03049     {
03050       Status status;
03051 
03052       offset += idr_poff - IDB_OBJ_HEAD_SIZE;
03053 
03054       Data data = pdata;
03055 
03056       GBX_SUSPEND();
03057 
03058       for (int j = 0; j < count; j++, data += idr_item_psize)
03059         {
03060           Object *o = cls->newObj(data);
03061                                                                           
03062           status = ((AgregatClass *)cls)->
03063             createIndexEntries_realize(db, o->getIDR(), _oid, idx_ctx, cloid,
03064                                        offset + (j * idr_item_psize),
03065                                        True);
03066           o->release();
03067           if (status)
03068             return status;
03069         }
03070     }
03071 
03072   return Success;
03073 }
03074 
03075 #define SK() \
03076 (skipRemove ? "true" : "false"), (skipInsert ? "true" : "false")
03077 
03078 // backend method
03079 Status
03080 Attribute::sizesCompute(Database *db, const char fmt_error[],
03081                            const Oid *data_oid, int &offset,
03082                            Size varsize, Bool novd, int &osz,
03083                            int inisize, int &oinisize, Bool &skipRemove,
03084                            Bool &skipInsert)
03085 {
03086   skipRemove = False;
03087   skipInsert = False;
03088 
03089   if (isVarDim())
03090     {
03091       if (novd)
03092         {
03093           assert(VARS_COND(db));
03094 
03095           if (varsize > VARS_SZ) // was: '>= VARS_SZ' 6/02/01
03096             skipInsert = True;
03097 
03098           eyedbsm::Status status;
03099           char buf[sizeof(Size)+sizeof(Oid)];
03100 
03101           if ((status = eyedbsm::objectRead(get_eyedbsm_DbHandle
03102                                       ((DbHandle *)db->getDbHandle()->
03103                                        u.dbh),
03104                                       idr_poff + offset,
03105                                       sizeof buf,
03106                                       buf,
03107                                       eyedbsm::DefaultLock,
03108                                       0, 0,
03109                                       data_oid->getOid())))
03110             return Exception::make(IDB_INDEX_ERROR, fmt_error,
03111                                       eyedbsm::statusGet(status),
03112                                       name,
03113                                       class_owner->getName());
03114           
03115           Oid varoid;
03116           // needs XDR ?
03117 #ifdef E_XDR_TRACE
03118           printf("%s: sizesCompute -> XDR\n", name);
03119 #endif
03120 #ifdef E_XDR
03121           eyedbsm::x2h_oid(varoid.getOid(), buf+sizeof(Size));
03122 #else
03123           mcp(&varoid, buf+sizeof(Size), sizeof(varoid));
03124 #endif
03125           if (!varoid.isValid()) {
03126             offset += VARS_OFFSET;
03127 #ifdef E_XDR
03128             x2h_32_cpy(&osz, buf);
03129 #else
03130             mcp(&osz, buf, sizeof(osz));
03131 #endif
03132             osz = CLEAN_SIZE(osz);
03133             oinisize = iniSize(osz);
03134             return Success;
03135           }
03136 
03137           skipRemove = True;
03138           osz = 0;
03139           oinisize = 0;
03140           return Success;
03141         }
03142 
03143       unsigned int xsz;
03144       eyedbsm::objectSizeGet(get_eyedbsm_DbHandle((DbHandle *)db->
03145                                        getDbHandle()->u.dbh),
03146                        &xsz, eyedbsm::DefaultLock, data_oid->getOid());
03147       osz = revSize(xsz);
03148       oinisize = xsz - osz;
03149       return Success;
03150     }
03151 
03152   osz = idr_item_psize * typmod.maxdims;
03153   oinisize = inisize;
03154   return Success;
03155 }
03156 
03157 Status
03158 Attribute::updateIndexEntry(Database *db, Data pdata,
03159                             const Oid *_oid,
03160                             const Oid *cloid,
03161                             int offset, const Oid *data_oid,
03162                             int count,
03163                             Size varsize, Bool novd,
03164                             AttrIdxContext &idx_ctx)
03165 {
03166   ATTR_COMPLETE();
03167   eyedbsm::Status status;
03168   static const char fmt_error[] = "storage manager error '%s' reported when updating index entry in attribute '%s' in agregat class '%s'";
03169 
03170   if (!data_oid)
03171     data_oid = _oid;
03172 
03173 #ifdef TRACE_IDX
03174   printf("updating index entry this=%p, name=%s, attrname=%s\n",
03175          this, name,  idx_ctx.getAttrName().c_str());
03176 #endif
03177 
03178   Data inidata;
03179   int inisize = iniCompute(db, count, pdata, inidata);
03180 
03181   Bool notnull, notnull_comp, unique, unique_comp;
03182   Status s = constraintPrologue(db, idx_ctx, notnull_comp, notnull,
03183                                 unique_comp, unique);
03184   if (s) return s;
03185 
03186   Index *idx_test;
03187   s = indexPrologue(db, idx_ctx, idx_test, True);
03188   if (s) return s;
03189 
03190   CHECK_NOTNULL();
03191 
03192   Oid soid[2];
03193   soid[0] = *_oid;
03194   soid[1] = *cloid;
03195 
03196   //Index *idx = 0;
03197   Idx *idx_item = 0, *idx_comp = 0;
03198 
03199   if (idx_test && !is_string)
03200     {
03201       if (cls && cls->asCollectionClass() && !isIndirect())
03202         return Success;
03203 
03204       idx_item = idx_test->idx;
03205 
03206       Data data = pdata;
03207       eyedbsm::DbHandle *se_dbh = get_eyedbsm_DbHandle((DbHandle *)db->getDbHandle()->u.dbh);
03208       unsigned char *sinidata = 0;
03209       if (inisize) {
03210         sinidata = (unsigned char *)malloc(inisize);
03211         if ((status = eyedbsm::objectRead(se_dbh,
03212                                           idr_poff + offset,
03213                                           inisize,
03214                                           sinidata,
03215                                           eyedbsm::DefaultLock,
03216                                           0, 0,
03217                                           data_oid->getOid()))) {
03218           free(sinidata);
03219           return Exception::make(IDB_INDEX_ERROR, fmt_error,
03220                                  eyedbsm::statusGet(status),
03221                                  idx_ctx.getAttrName().c_str(),
03222                                  class_owner->getName());
03223         }
03224       }
03225 
03226       unsigned char *s = (unsigned char *)malloc((idr_item_psize + inisize)
03227                                                  * sizeof(unsigned char));
03228       unsigned int size_of_e = sizeof(char) + sizeof(eyedblib::int32) +
03229         idr_item_psize;
03230       unsigned char *e = (unsigned char *)malloc(size_of_e);
03231 
03232       unsigned char *sx = s;
03233       Bool indirect = isIndirect();
03234       for (int n = 0; n < count; n++, data += idr_item_psize)
03235         {
03236           if ((status = eyedbsm::objectRead(se_dbh,
03237                                             idr_poff + n * idr_item_psize + offset + inisize,
03238                                             idr_item_psize, s,
03239                                             eyedbsm::DefaultLock,
03240                                             0, 0,
03241                                             data_oid->getOid()))) {
03242             free(s);
03243             free(e);
03244             free(sinidata);
03245             return Exception::make(IDB_INDEX_ERROR, fmt_error,
03246                                       eyedbsm::statusGet(status),
03247                                       idx_ctx.getAttrName().c_str(),
03248                                       class_owner->getName());
03249           }
03250           
03251           IS_NULL(isnull_s, s, sinidata);
03252           IS_NULL(isnull_data, data, inidata);
03253 
03254           if (isnull_s != isnull_data ||
03255               memcmp(data, sx, idr_item_psize))
03256             {
03257               if (unique) {
03258                 e[0] = (isnull_data ? idxNull : idxNotNull);
03259                 h2x_32_cpy(e+sizeof(char), &n);
03260                 if (indirect) {
03261                   eyedbsm::Oid toid;
03262                   eyedbsm::x2h_oid(&toid, data);
03263                   mcp(e+sizeof(char)+sizeof(eyedblib::int32), &toid, sizeof(eyedbsm::Oid));
03264                 }
03265                 else
03266                   cls->decode(e+sizeof(char)+sizeof(eyedblib::int32), data, idr_item_psize);
03267 
03268                 CHECK_UNIQUE(isnull_data, e, s);
03269               }
03270 
03271               e[0] = (isnull_s ? idxNull : idxNotNull);
03272               h2x_32_cpy(e+sizeof(char), &n);
03273               if (indirect) {
03274                 eyedbsm::Oid toid;
03275                 eyedbsm::x2h_oid(&toid, sx);
03276                 mcp(e+sizeof(char)+sizeof(eyedblib::int32), &toid, sizeof(eyedbsm::Oid));
03277               }
03278               else
03279                 cls->decode(e+sizeof(char)+sizeof(eyedblib::int32), sx, idr_item_psize);
03280 
03281               eyedbsm::Boolean found;
03282               
03283               IDB_LOG(IDB_LOG_IDX_SUPPRESS,
03284                       (log_item_entry_fmt,
03285                        ATTRPATH(idx_test), soid[0].toString(),
03286                        dumpData(sx), n, NULL_STR(isnull_s)));
03287 
03288               idx_ctx.addIdxOP(this, AttrIdxContext::IdxRemove,
03289                                idx_test, idx_item, e, size_of_e, soid);
03290               
03291               e[0] = (isnull_data ? idxNull : idxNotNull);
03292               h2x_32_cpy(e+sizeof(char), &n);
03293               if (indirect) {
03294                 eyedbsm::Oid toid;
03295                 eyedbsm::x2h_oid(&toid, data);
03296                 mcp(e+sizeof(char)+sizeof(eyedblib::int32), &toid, sizeof(eyedbsm::Oid));
03297               }
03298               else
03299                 cls->decode(e+sizeof(char)+sizeof(eyedblib::int32), data, idr_item_psize);
03300 
03301               IDB_LOG(IDB_LOG_IDX_INSERT,
03302                       (log_item_entry_fmt,
03303                        ATTRPATH(idx_test), soid[0].toString(),
03304                        dumpData(data), n, NULL_STR(isnull_data)));
03305               
03306               idx_ctx.addIdxOP(this, AttrIdxContext::IdxInsert,
03307                                idx_test, idx_item, e, size_of_e, soid);
03308             }
03309         }
03310 
03311       free(sinidata);
03312       free(e);
03313       free(s);
03314     }
03315   else if (unique)
03316     return Exception::make(IDB_UNIQUE_CONSTRAINT_ERROR,
03317                               "when updating index entry on '%s' : "
03318                               "unique constraint missing index",
03319                               idx_ctx.getAttrName().c_str());
03320  
03321   CHECK_NOTNULL_COMP();
03322 
03323   if (idx_test && is_string)
03324     {
03325       idx_comp = idx_test->idx;
03326 
03327       int osz, oinisize;
03328 
03329       Bool skipRemove, skipInsert;
03330 
03331       s = sizesCompute(db, fmt_error, data_oid, offset, varsize, novd, osz,
03332                        inisize, oinisize, skipRemove, skipInsert);
03333       if (s) return s;
03334 
03335       if (skipInsert && skipRemove)
03336         return Success;
03337 
03338       int nsz;
03339       if (isVarDim())
03340         nsz = count;
03341       else
03342         nsz = typmod.pdims * idr_item_psize;
03343 
03344       Data data = pdata;
03345       unsigned char *s;
03346       Bool isnull_s, isnull_data;
03347 
03348       if (!skipRemove) {
03349         if (osz + oinisize) {
03350           s = (unsigned char *)malloc((osz + oinisize));
03351         
03352           if ((status = eyedbsm::objectRead(get_eyedbsm_DbHandle
03353                                       ((DbHandle *)db->getDbHandle()->u.dbh),
03354                                       idr_poff + offset, osz + oinisize, s,
03355                                       eyedbsm::DefaultLock,
03356                                       0, 0,
03357                                       data_oid->getOid()))) {
03358             free(s);
03359             return Exception::make(IDB_INDEX_ERROR, fmt_error,
03360                                       eyedbsm::statusGet(status),
03361                                       idx_ctx.getAttrName().c_str(),
03362                                       class_owner->getName());
03363           }
03364           
03365           IS_COMP_NULL(isnull_sx, s+oinisize, s);
03366           isnull_s = isnull_sx;
03367         }
03368         else {
03369           s = (unsigned char *)malloc(1);
03370           s[0] = 0;
03371           isnull_s = True;
03372         }
03373       }
03374       else {
03375         s = 0;
03376           isnull_s = False;
03377         }
03378 
03379       if (!skipInsert)
03380         {
03381           IS_COMP_NULL(isnull_data_x, data, inidata);
03382           isnull_data = isnull_data_x;
03383         }
03384       else
03385         isnull_data = False;
03386 
03387       // 29/01/01: suppressed 'novd' in the following test, because
03388       // I think that this test does not make any sense!
03389       if (/*novd || */ isnull_s != isnull_data || nsz != osz ||
03390           memcmp(data, s+oinisize, osz)) {
03391         if (!skipInsert)
03392           CHECK_UNIQUE_COMP(isnull_data, 0, 0);
03393 
03394         unsigned char *e = 0;
03395         unsigned int size_of_e = sizeof(char) + osz;
03396         if (!skipRemove) {
03397           e = (unsigned char *)malloc(size_of_e);
03398 
03399           eyedbsm::Boolean found;
03400 
03401           e[0] = (isnull_s ? idxNull : idxNotNull);
03402               
03403           memcpy(e+sizeof(char), s+oinisize, osz);
03404               
03405           IDB_LOG(IDB_LOG_IDX_SUPPRESS, 
03406                   (log_comp_entry_fmt,
03407                    ATTRPATH(idx_test), soid[0].toString(),
03408                    s+oinisize, NULL_STR(isnull_s)));
03409               
03410           idx_ctx.addIdxOP(this, AttrIdxContext::IdxRemove,
03411                            idx_test, idx_comp, e, size_of_e, soid);
03412         }
03413 
03414         if (!skipInsert) {
03415           if (!e || nsz > osz) {
03416             free(e);
03417             size_of_e = sizeof(char) + nsz;
03418             e = (unsigned char *)malloc(size_of_e);
03419           }
03420 
03421           e[0] = (isnull_data ? idxNull : idxNotNull);
03422           memcpy(e+sizeof(char), data, nsz);
03423               
03424           IDB_LOG(IDB_LOG_IDX_INSERT, 
03425                   (log_comp_entry_fmt,
03426                    ATTRPATH(idx_test), soid[0].toString(), data,
03427                    NULL_STR(isnull_data)));
03428               
03429           idx_ctx.addIdxOP(this, AttrIdxContext::IdxInsert,
03430                            idx_test, idx_comp, e, size_of_e, soid);
03431         }
03432 
03433         free(e);
03434       }
03435       free(s);
03436     }
03437   else if (unique_comp)
03438     return Exception::make(IDB_UNIQUE_COMP_CONSTRAINT_ERROR,
03439                               "when updating index entry on '%s' : "
03440                               "unique constraint missing index",
03441                               idx_ctx.getAttrName().c_str());
03442 
03443   if (cls->asAgregatClass() && !isIndirect() && count)
03444     {
03445       Status status;
03446 
03447       offset += idr_poff - IDB_OBJ_HEAD_SIZE;
03448 
03449       Data data = pdata;
03450 
03451       GBX_SUSPEND();
03452 
03453       for (int j = 0; j < count; j++, data += idr_item_psize)
03454         {
03455           Object *o = cls->newObj(data);
03456           Status status = ((AgregatClass *)cls)->
03457             updateIndexEntries_realize(db, o->getIDR(), _oid, idx_ctx, cloid,
03458                                        offset + (j * idr_item_psize),
03459                                        True, data_oid);
03460           o->release();
03461           if (status)
03462             return status;
03463         }
03464     }
03465 
03466   return Success;
03467 }
03468 
03469 Status Attribute::updateIndexEntry_realize(Database *db,
03470                                                  Data _idr,
03471                                                  const Oid *_oid,
03472                                                  const Oid *cloid,
03473                                                  int offset,
03474                                                  Bool novd,
03475                                                  const Oid *data_oid,
03476                                                  AttrIdxContext &idx_ctx,
03477                                                  int count)
03478 {
03479   Data pdata;
03480   Size varsize;
03481 
03482   if (indexPrologue(db, _idr, novd, count, pdata, varsize, False))
03483     return Success;
03484 
03485   Status status;
03486   idx_ctx.push(db, *cloid, this);
03487   status = updateIndexEntry(db, pdata, _oid, cloid, offset, data_oid, count,
03488                             varsize, novd, idx_ctx);
03489   idx_ctx.pop();
03490   return status;
03491 }
03492 
03493 Status Attribute::removeIndexEntry_realize(Database *db,
03494                                                  Data _idr,
03495                                                  const Oid *_oid,
03496                                                  const Oid *cloid,
03497                                                  int offset,
03498                                                  Bool novd,
03499                                                  const Oid *data_oid,
03500                                                  AttrIdxContext &idx_ctx,
03501                                                  int count)
03502 
03503 {
03504   Data pdata;
03505   Size varsize;
03506 
03507   if (indexPrologue(db, _idr, novd, count, pdata, varsize, False))
03508     return Success;
03509 
03510   Status status;
03511   idx_ctx.push(db, *cloid, this);
03512   status = removeIndexEntry(db, pdata, _oid, cloid, offset, data_oid,
03513                             count, varsize, novd, idx_ctx);
03514   idx_ctx.pop();
03515   return status;
03516 }
03517 
03518 Status Attribute::removeIndexEntry(Database *db, Data pdata,
03519                                          const Oid *_oid,
03520                                          const Oid *cloid,
03521                                          int offset, const Oid *data_oid,
03522                                          int count,
03523                                          Size varsize, Bool novd,
03524                                          AttrIdxContext &idx_ctx)
03525 {
03526   ATTR_COMPLETE();
03527   eyedbsm::Status status;
03528   static const char fmt_error[] = "storage manager error '%s' reported when removing index entry in attribute '%s' in agregat class '%s'";
03529 
03530   if (!data_oid)
03531     data_oid = _oid;
03532 
03533   Data inidata;
03534   int inisize = iniCompute(db, count, pdata, inidata);
03535 
03536   Oid soid[2];
03537   soid[0] = *_oid;
03538   soid[1] = *cloid;
03539 
03540   Status s = Success;
03541   //Index *idx = 0;
03542 
03543   Index *idx_test;
03544   s = indexPrologue(db, idx_ctx, idx_test, True);
03545   if (s) return s;
03546 
03547   Idx *idx_item = 0, *idx_comp = 0;
03548 
03549   if (idx_test && !is_string)
03550     //if ((mode & indexItemMode) == indexItemMode)
03551     {
03552       if (cls && cls->asCollectionClass() && !isIndirect())
03553         return Success;
03554 
03555       /*
03556       s = getMultiIndex(db, idx_ctx, idx);
03557       if (s) return s;
03558       if (!idx)
03559         return Exception::make(IDB_ATTRIBUTE_ERROR,
03560                                   "cannot open index '%s'",
03561                                   (const char *)idx_ctx.getAttrName());
03562       idx_item = idx->idx;
03563       */
03564       idx_item = idx_test->idx;
03565 
03566       eyedbsm::DbHandle *se_dbh = get_eyedbsm_DbHandle((DbHandle *)db->getDbHandle()->u.dbh);
03567       unsigned char *sinidata = 0;
03568       if (inisize) {
03569         sinidata = (unsigned char *)malloc(inisize);
03570         if ((status = eyedbsm::objectRead(se_dbh,
03571                                     idr_poff + offset,
03572                                     inisize,
03573                                     sinidata,
03574                                     eyedbsm::DefaultLock,
03575                                     0, 0,
03576                                     data_oid->getOid()))) {
03577           free(sinidata);
03578           return Exception::make(IDB_INDEX_ERROR, fmt_error,
03579                                     eyedbsm::statusGet(status),
03580                                     idx_ctx.getAttrName().c_str(),
03581                                     class_owner->getName());
03582         }
03583       }
03584 
03585       unsigned char *s = (unsigned char *)malloc(idr_item_psize + inisize);
03586       unsigned int size_of_e = sizeof(char) + sizeof(eyedblib::int32) +
03587         idr_item_psize;
03588       unsigned char *e = (unsigned char *)malloc(size_of_e);
03589       unsigned char *sx = s;
03590       Data data = pdata;
03591 
03592       Bool indirect = isIndirect();
03593       for (int n = 0; n < count; n++, data += idr_item_psize)
03594         {
03595           if ((status = eyedbsm::objectRead(se_dbh,
03596                                       idr_poff + n * idr_item_psize + offset + inisize,
03597                                       idr_item_psize,
03598                                       s, eyedbsm::DefaultLock, 0, 0, data_oid->getOid())))
03599             return Exception::make(IDB_INDEX_ERROR, fmt_error,
03600                                       eyedbsm::statusGet(status),
03601                                       idx_ctx.getAttrName().c_str(),
03602                                       class_owner->getName());
03603 
03604           IS_NULL(isnull_s, s, sinidata);
03605           e[0] = (isnull_s ? idxNull : idxNotNull);
03606           h2x_32_cpy(e+sizeof(char), &n);
03607           if (indirect) {
03608             eyedbsm::Oid toid;
03609             eyedbsm::x2h_oid(&toid, sx);
03610             mcp(e+sizeof(char)+sizeof(eyedblib::int32), &toid, sizeof(eyedbsm::Oid));
03611           }
03612           else
03613             cls->decode(e+sizeof(char)+sizeof(eyedblib::int32), sx, idr_item_psize);
03614 
03615           IDB_LOG(IDB_LOG_IDX_SUPPRESS,
03616                   (log_item_entry_fmt,
03617                    ATTRPATH(idx_test), soid[0].toString(),
03618                    dumpData(sx), n, NULL_STR(isnull_s)));
03619 
03620           idx_ctx.addIdxOP(this, AttrIdxContext::IdxRemove,
03621                            idx_test, idx_item, e, size_of_e, soid);
03622         }
03623 
03624       free(sinidata);
03625       free(e);
03626       free(s);
03627     }
03628 
03629   if (idx_test && is_string)
03630     //if ((mode & indexCompMode) == indexCompMode)
03631     {
03632       /*
03633       s = getMultiIndex(db, idx_ctx, idx);
03634       if (s) return s;
03635       if (!idx)
03636         return Exception::make(IDB_ATTRIBUTE_ERROR,
03637                                   "cannot open index '%s'",
03638                                   (const char *)idx_ctx.getAttrName());
03639       idx_comp = idx->idx;
03640       */
03641       idx_comp = idx_test->idx;
03642 
03643       int osz, oinisize;
03644 
03645       Bool skipRemove, dummy;
03646 
03647       s = sizesCompute(db, fmt_error, data_oid, offset, varsize, novd, osz,
03648                        inisize, oinisize, skipRemove, dummy);
03649       if (s) return s;
03650 
03651       if (skipRemove)
03652         return Success;
03653 
03654       unsigned char *s;
03655       Bool isnull_s;
03656       if (osz + oinisize) { // test added the 16/03/02
03657         s =  (unsigned char *)malloc(osz + oinisize);
03658       
03659         if ((status = eyedbsm::objectRead(get_eyedbsm_DbHandle
03660                                     ((DbHandle *)db->getDbHandle()->u.dbh),
03661                                     idr_poff + offset, osz + oinisize, s,
03662                                     eyedbsm::DefaultLock, 0, 0,
03663                                     data_oid->getOid())))
03664           {
03665             free(s);
03666             return Exception::make(IDB_INDEX_ERROR, fmt_error,
03667                                       eyedbsm::statusGet(status),
03668                                       idx_ctx.getAttrName().c_str(),
03669                                       class_owner->getName());
03670           }
03671         
03672         IS_COMP_NULL(isnull_sx, s+oinisize, s);
03673         isnull_s = isnull_sx;
03674       }
03675       else {
03676         s = (unsigned char *)malloc(1);
03677         s[0] = 0;
03678         isnull_s = True;
03679       }
03680 
03681       eyedbsm::Boolean found;
03682       unsigned int size_of_e = sizeof(char) + osz;
03683       unsigned char *e = (unsigned char *)malloc(size_of_e);
03684       e[0] = (isnull_s ? idxNull : idxNotNull);
03685       memcpy(e+sizeof(char), s+oinisize, osz);
03686       
03687       IDB_LOG(IDB_LOG_IDX_SUPPRESS, 
03688               (log_comp_entry_fmt,
03689                ATTRPATH(idx_test), soid[0].toString(), s+oinisize,
03690                NULL_STR(isnull_s)));
03691 
03692       idx_ctx.addIdxOP(this, AttrIdxContext::IdxRemove,
03693                        idx_test, idx_comp, e, size_of_e, soid);
03694       free(e);
03695       free(s);
03696     }
03697 
03698   if (cls->asAgregatClass() && !isIndirect() && count)
03699     {
03700       Status status;
03701 
03702       offset += idr_poff - IDB_OBJ_HEAD_SIZE;
03703 
03704       GBX_SUSPEND();
03705 
03706       Data data = pdata;
03707       for (int j = 0; j < count; j++, data += idr_item_psize)
03708         {
03709           Object *o = (Object *)cls->newObj(data);
03710           Status status = ((AgregatClass *)cls)->
03711             removeIndexEntries_realize(db, o->getIDR(), _oid, idx_ctx, cloid,
03712                                        offset + (j * idr_item_psize),
03713                                        True, data_oid);
03714           o->release();
03715           if (status)
03716             return status;
03717         }
03718     }
03719 
03720   return Success;
03721 }
03722 
03723 Status
03724 Attribute::updateIndexForInverse(Database *db, const Oid &_oid,
03725                                     const Oid &new_oid) const
03726 {
03727   Status status;
03728   static const char fmt_error[] = "storage manager error '%s' reported when updating index inverse entry in attribute '%s' in agregat class '%s'";
03729 
03730   assert(isIndirect());
03731 
03732   static const eyedblib::int32 zero = 0;
03733   Class *obj_cls;
03734   status = db->getObjectClass(_oid, obj_cls);
03735   if (status) return status;
03736 
03737   AttrIdxContext idx_ctx(obj_cls, this);
03738 
03739   Idx *se_idx;
03740 
03741   // ?? Hope that there is no problem with polymorphism ??
03742   //printf("UpdateIndexForInverse(%s::%s)\n", obj_cls->getName(), name);
03743   Index *idx = 0;
03744   status = const_cast<Attribute *>(this)->
03745     indexPrologue(db, idx_ctx, idx, True);
03746   if (!idx) return Success;
03747 
03748   if (status) return status;
03749   if (!idx)
03750     return Exception::make(IDB_ATTRIBUTE_ERROR,
03751                               "cannot open index '%s'",
03752                               idx_ctx.getAttrName().c_str());
03753   se_idx = idx->idx;
03754 
03755   Oid soid[2];
03756   soid[0] = _oid;
03757   soid[1] = obj_cls->getOid();
03758     
03759   eyedbsm::Oid toid;
03760   RPCStatus rpc_status =
03761     dataRead(db->getDbHandle(), idr_poff, sizeof(eyedbsm::Oid),
03762                  (Data)&toid, 0, _oid.getOid());
03763   Oid old_oid;
03764   eyedbsm::x2h_oid(old_oid.getOid(), &toid);
03765 
03766   if (rpc_status)
03767     return StatusMake(rpc_status);
03768 
03769   if (old_oid == new_oid)
03770     return Success;
03771 
03772   //printf("creating inverse index entry\n");
03773   unsigned char s[1+sizeof(eyedblib::int32)+sizeof(eyedbsm::Oid)];
03774 
03775   s[0] = old_oid.isValid() ? idxNotNull : idxNull;
03776   mcp(s+1, &zero, sizeof(eyedblib::int32));
03777   mcp(s+1+sizeof(eyedblib::int32), old_oid.getOid(), sizeof(eyedbsm::Oid));
03778 
03779   eyedbsm::Boolean found;
03780   eyedbsm::Status se_status;
03781 
03782   IDB_LOG(IDB_LOG_IDX_SUPPRESS,
03783           (log_item_entry_fmt,
03784            ATTRPATH(idx), soid[0].toString(),
03785            old_oid.toString(), 0, NULL_STR(!old_oid.isValid())));
03786 
03787   if ((se_status = se_idx->remove(s, soid, &found)))
03788     return Exception::make(IDB_INDEX_ERROR, fmt_error,
03789                               eyedbsm::statusGet(se_status),
03790                               idx_ctx.getAttrName().c_str(),
03791                               class_owner->getName());
03792 
03793   if (!found)
03794     return Exception::make(IDB_INDEX_ERROR, fmt_error,
03795                               "index entry not found",
03796                               idx_ctx.getAttrName().c_str(),
03797                               class_owner->getName());
03798 
03799 
03800 
03801   s[0] = new_oid.isValid() ? idxNotNull : idxNull;
03802   mcp(s+1, &zero, sizeof(eyedblib::int32));
03803   mcp(s+1+sizeof(eyedblib::int32), new_oid.getOid(), sizeof(eyedbsm::Oid));
03804 
03805   IDB_LOG(IDB_LOG_IDX_INSERT,
03806           (log_item_entry_fmt,
03807            ATTRPATH(idx), soid[0].toString(),
03808            new_oid.toString(), 0, NULL_STR(!new_oid.isValid())));
03809 
03810   if ((se_status = se_idx->insert(s, soid)))
03811     return Exception::make(IDB_INDEX_ERROR, fmt_error,
03812                               eyedbsm::statusGet(se_status),
03813                               idx_ctx.getAttrName().c_str(),
03814                               class_owner->getName());
03815 
03816   return Success;
03817 }
03818 
03819 void
03820 Attribute::newObjRealize(Object *) const
03821 {
03822 }
03823 
03824 void Attribute::getData(const Database *, Data _idr, Data& pdata, Data& vdata) const
03825 {
03826   pdata = _idr + idr_poff;
03827   vdata = _idr + idr_voff;
03828 }
03829 
03830 void Attribute::getData(const Object *agr, Data& pdata,
03831                            Data& vdata) const
03832 {
03833   getData(getDB(agr), agr->getIDR(), pdata, vdata);
03834 }
03835 
03836 void Attribute::getVarDimOid(Data _idr, Oid *oid) const
03837 {
03838   oid->invalidate();
03839 }
03840 
03841 void Attribute::getVarDimOid(const Object *, Oid *oid) const
03842 {
03843   oid->invalidate();
03844 }
03845 
03846 /*
03847 Status Attribute::getField(Database *db, const Oid *data_oid,
03848                                  Oid *doid, int *roffset, int offset,
03849                                  int from) const
03850 {
03851   return Success;
03852 }
03853 */
03854 
03855 Status Attribute::getVal(Database *db, const Oid *data_oid,
03856                                Data data, int offset,
03857                                int nb, int from, Bool *) const
03858 {
03859   return Success;
03860 }
03861 
03862 Status
03863 Attribute::getTValue(Database *db, const Oid &objoid,
03864                         Data *data, int nb, int from,
03865                         Bool *isnull, Size *rnb, Offset poffset) const
03866 {
03867   return Success;
03868 }
03869 
03870 Status Attribute::copy(Object *agr, Bool share) const
03871 {
03872   Data _idr = agr->getIDR();
03873   assert(_idr);
03874   if (!isIndirect() && is_basic_enum)
03875     return Success;
03876 
03877   return Attribute::incrRefCount(agr, _idr + idr_voff, typmod.pdims);
03878 }
03879 
03880 #ifdef GBX_NEW_CYCLE
03881 void Attribute::decrRefCountPropag(Object *, int) const
03882 {
03883 }
03884 #endif
03885 
03886 void Attribute::garbage(Object *, int) const
03887 {
03888 }
03889 
03890 void Attribute::manageCycle(Database *db, Object *o, gbxCycleContext &) const
03891 {
03892 }
03893 
03894 Status
03895 Attribute::add(Database *db, ClassConversion *conv,
03896                   Data in_idr, Size in_size) const
03897 {
03898   assert(0);
03899   Offset offset = conv->getOffsetN();
03900   Data start = in_idr + offset;
03901   Size size = conv->getSizeN();
03902   printf("add %s::%s idr_poff=%d offsetN=%d idr_psize=%d sizeN=%d "
03903          "in_size=%d sizemoved=%d %s==%s?\n",
03904          class_owner->getName(), name, idr_poff, offset, idr_psize, size,
03905          in_size, in_size - size - offset, name, conv->getAttrname().c_str());
03906   assert(idr_poff == offset);
03907   assert(idr_psize == size);
03908 
03909   memmove(start + size, start, in_size - size - offset);
03910   memset(start, 0, size);
03911   return Success;
03912 }
03913 
03914 #ifdef GBX_NEW_CYCLE
03915 void Attribute::decrRefCountPropag(Data vdata, int nb) const
03916 {
03917   Data data = vdata;
03918 
03919   for (int n = 0; n < nb; n++, data += SIZEOFOBJECT) {
03920     Object *o;
03921     mcp(&o, data, sizeof(Object *));
03922     if (o)
03923       o->decrRefCount();
03924   }
03925 }
03926 #endif
03927 
03928 inline void Attribute::garbage(Data vdata, int nb) const
03929 {
03930   Data data = vdata;
03931 
03932   for (int n = 0; n < nb; n++, data += SIZEOFOBJECT)
03933     {
03934       Object *o;
03935       mcp(&o, data, sizeof(Object *));
03936       if (o && !gbxAutoGarb::isObjectDeleted(o))
03937         {
03938           unsigned int refcnt = o->getRefCount();
03939           o->release_r();
03940           if (!refcnt)
03941             mset(data, 0, sizeof(Object *));
03942         }
03943     }
03944 }
03945 
03946 //
03947 // AttrDirect methods
03948 //
03949 
03950 AttrDirect::AttrDirect(const Attribute *attr,
03951                              const Class *_cls,
03952                              const Class *_class_owner,
03953                              const Class *_dyn_class_owner, int n) :
03954   Attribute(attr, _cls, _class_owner, _dyn_class_owner, n)
03955 {
03956   code = AttrDirect_Code;
03957 }
03958 
03959 AttrDirect::AttrDirect(Database *db,
03960                              Data data, Offset *offset,
03961                              const Class *_dyn_class_owner,
03962                              int n) :
03963   Attribute(db, data, offset, _dyn_class_owner, n)
03964 {
03965   code = AttrDirect_Code;
03966 }
03967 
03968 static char *TADDR;
03969 
03970 static void get_o1()
03971 {
03972   if (!TADDR) return;
03973   Object *o;
03974   memcpy(&o, TADDR, sizeof(Object *));
03975   printf("o = %p\n", o);
03976 }
03977 
03978 void
03979 AttrDirect::newObjRealize(Object *o) const
03980 {
03981   if (is_basic_enum)
03982     return;
03983 
03984   Data pdata = o->getIDR() + idr_poff;
03985   Data vdata = o->getIDR() + idr_voff;
03986 
03987   GBX_SUSPEND();
03988 
03989   for (int j = 0; j < typmod.pdims; j++) {
03990     Object *oo;
03991     // no XDR
03992     memcpy(&oo, vdata + (j * idr_item_vsize), sizeof(Object *));
03993     if (!oo) {
03994       oo = (Object *)cls->newObj(pdata + (j * idr_item_psize));
03995       oo->setMustRelease(false); // SMART_PTR
03996       memcpy(vdata + (j * idr_item_vsize), &oo, sizeof(Object *));
03997     }
03998     // added the 5/11/99
03999     Status s = oo->setMasterObject(o);
04000     if (s)
04001       throw *s;
04002   }
04003 }
04004 
04005 Status
04006 AttrDirect::load(Database *db,
04007                     Object *agr,
04008                     const Oid &cloid,
04009                     LockMode lockmode,
04010                     AttrIdxContext &idx_ctx,
04011                     const RecMode *rcm,
04012                     Bool force) const
04013 {
04014   if (is_basic_enum)
04015     return Success;
04016 
04017   Data pdata = agr->getIDR() + idr_poff;
04018 
04019   idx_ctx.push(db, cloid, this);
04020 
04021   pdata += idr_inisize;
04022   for (int j = 0; j < typmod.pdims; j++) {
04023     Status status;
04024     Object *o;
04025 
04026     memcpy(&o, agr->getIDR() + idr_voff + (j * idr_item_vsize),
04027            sizeof(Object *));
04028     
04029     // needs XDR ? no...
04030 #ifdef E_XDR_TRACE
04031     printf("%s: AttrDirect::load -> needs XDR ? no\n", name);
04032 #endif
04033     memcpy(o->getIDR() + IDB_OBJ_HEAD_SIZE,
04034            pdata +  (j * idr_item_psize), idr_item_psize);
04035 
04036     status = o->setDatabase(db);
04037 
04038     if (status != Success)
04039       return status;
04040 
04041     status = o->loadPerform(cloid, lockmode, idx_ctx, rcm);
04042 
04043     if (status != Success)
04044       return status;
04045 
04046     // needs XDR ? no
04047     memcpy(pdata +  (j * idr_item_psize),
04048            o->getIDR() + IDB_OBJ_HEAD_SIZE, idr_item_psize);
04049   }
04050 
04051   idx_ctx.pop();
04052   return Success;
04053 }
04054 
04055 Status AttrDirect::realize(Database *db, Object *agr,
04056                            const Oid& cloid,
04057                            const Oid& objoid,
04058                            AttrIdxContext &idx_ctx,
04059                            const RecMode *rcm) const
04060 {
04061   if (is_basic_enum)
04062     return Success;
04063 
04064   /*
04065     printf("AttrDirect::realize(%s);\n", name);
04066   */
04067 
04068   idx_ctx.push(db, cloid, this);
04069 
04070   for (int j = 0; j < typmod.pdims; j++) {
04071     Object *o;
04072 
04073     // no XDR
04074     memcpy(&o, agr->getIDR() + idr_voff + (j * idr_item_vsize),
04075            sizeof(Object *));
04076 
04077     if (o) {
04078       Status status;
04079 
04080       status = o->setDatabase(db);
04081       if (status) return status;
04082 
04083       setCollHints(o, objoid, card);
04084       status = setCollImpl(db, o, idx_ctx);
04085       if (status) return status;
04086 
04087       idx_ctx.pushOff(idr_poff +  (j * idr_item_psize));
04088       /*
04089       printf("%s: null_vd_oid: (null) %s %d\n", name,
04090              o->getClass()->getName(), IDB_OBJ_HEAD_SIZE);
04091 
04092       */
04093       status = o->realizePerform(cloid, objoid, idx_ctx, rcm);
04094 
04095       if (status)
04096         return status;
04097 
04098       // needs XDR ? no...
04099 #ifdef E_XDR_TRACE
04100       printf("%s: AttrDirect::realize : cmp\n", name);
04101 #endif
04102       /*
04103       printf("comparing: %s.%s[%d] %d agroid %s objoid %s [idr_size %d]\n",
04104              agr->getClass()->getName(), name, j, idr_poff,
04105              agr->getOid().toString(), objoid.toString(),
04106              agr->getIDRSize());
04107       */
04108       if (memcmp(agr->getIDR() + idr_poff +  (j * idr_item_psize),
04109                  o->getIDR() + IDB_OBJ_HEAD_SIZE, idr_item_psize)) {
04110 #ifdef E_XDR_TRACE
04111         printf("%s: AttrDirect::realize : needs XDR ? no\n", name);
04112 #endif
04113         memcpy(agr->getIDR() + idr_poff +  (j * idr_item_psize),
04114                o->getIDR() + IDB_OBJ_HEAD_SIZE, idr_item_psize);
04115 
04116         // 27/05/06: suppressed test
04117         //if (!o->asCollection()) // changed the 9/11/99
04118         agr->touch();
04119           
04120         Bool mustTouch;
04121         status = o->postRealizePerform(cloid, objoid,
04122                                        idx_ctx, mustTouch, rcm);
04123         if (status)
04124           return status;
04125 
04126         if (mustTouch)
04127           agr->touch();
04128       }
04129 
04130       idx_ctx.popOff();
04131     }
04132   }
04133 
04134   idx_ctx.pop();
04135   return Success;
04136 }
04137 
04138 Status AttrDirect::remove(Database *db, Object *agr,
04139                                 const Oid& cloid,
04140                                 const Oid& objoid,
04141                                 AttrIdxContext &idx_ctx,
04142                                 const RecMode *rcm) const
04143 {
04144   if (is_basic_enum)
04145     return Success;
04146 
04147   idx_ctx.push(db, cloid, this);
04148   for (int j = 0; j < typmod.pdims; j++)
04149     {
04150       Object *o;
04151 
04152       // no XDR
04153       memcpy(&o, agr->getIDR() + idr_voff + (j * idr_item_vsize),
04154              sizeof(Object *));
04155 
04156       if (o)
04157         {
04158           Status status;
04159 
04160           status = o->setDatabase(db);
04161           if (status != Success)
04162             return status;
04163 
04164           status = o->removePerform(cloid, objoid, idx_ctx, rcm);
04165 
04166           if (status != Success)
04167             return status;
04168 
04169           // needs XDR ?
04170 #ifdef E_XDR_TRACE
04171           printf("%s: AttrDirect::remove\n", name);
04172 #endif
04173           memcpy(agr->getIDR() + idr_poff +  (j * idr_item_psize),
04174                  o->getIDR() + IDB_OBJ_HEAD_SIZE, idr_item_psize);
04175         }
04176     }
04177 
04178   idx_ctx.pop();
04179   return Success;
04180 }
04181 
04182 Status AttrDirect::check() const
04183 {
04184   return Attribute::check();
04185 }
04186 
04187 Status AttrDirect::compile_perst(const AgregatClass *ma, int *offset, int *size, int *inisize)
04188 {
04189   Status status;
04190   const TypeModifier *tmod = &typmod;
04191 
04192   if (status = check())
04193     return status;
04194 
04195   idr_poff = *offset;
04196   if (is_basic_enum)
04197     idr_inisize = iniSize(tmod->pdims);
04198   else
04199     idr_inisize = 0;
04200 
04201   if (!cls->getIDRObjectSize(&idr_item_psize))
04202     return Exception::make(IDB_ATTRIBUTE_ERROR, incomp_fmt, cls->getName(), name, num, class_owner->getName());
04203 
04204   idr_item_psize -= IDB_OBJ_HEAD_SIZE;
04205   idr_psize = idr_item_psize * tmod->pdims + idr_inisize;
04206   *inisize = idr_inisize;
04207   
04208   compile_update(ma, idr_psize, offset, size);
04209 
04210   return Success;
04211 }
04212 
04213 Status AttrDirect::compile_volat(const AgregatClass *ma, int *offset, int *size)
04214 {
04215   Status status;
04216   const TypeModifier *tmod = &typmod;
04217 
04218   idr_voff = *offset;
04219 
04220   if (!is_basic_enum)
04221     {
04222       idr_item_vsize = SIZEOFOBJECT;
04223       idr_vsize = idr_item_vsize * tmod->pdims;
04224     }
04225   else
04226     {
04227       idr_item_vsize = 0;
04228       idr_vsize = 0;
04229     }
04230 
04231   compile_update(ma, idr_vsize, offset, size);
04232 
04233   return Success;
04234 }
04235 
04236 Status AttrDirect::setOid(Object *, const Oid *, int, int, Bool) const
04237 {
04238   return Exception::make(IDB_ATTRIBUTE_ERROR, "cannot set oid for direct attribute '%s' in agregat class '%s'", name, class_owner->getName());
04239 }
04240 
04241 Status AttrDirect::getOid(const Object *agr, Oid *oid, int nb, int from) const
04242 {
04243   return Exception::make(IDB_ATTRIBUTE_ERROR, "cannot get oid for direct attribute '%s' in agregat class '%s'", name, class_owner->getName());
04244 }
04245 
04246 Status AttrDirect::setValue(Object *agr, Data data,
04247                                    int nb, int from, Bool check_class) const
04248 {
04249   CHECK_OBJ(agr);
04250   CHECK_RTTYPE(agr);
04251   Status status;
04252 
04253   check_range(from, nb);
04254 
04255   Data pdata = agr->getIDR() + idr_poff;
04256   Data vdata;
04257 
04258   Data inidata;
04259   if (is_basic_enum) {
04260     vdata = 0;
04261     inidata = pdata;
04262     pdata += idr_inisize;
04263   }
04264   else {
04265     vdata = agr->getIDR() + idr_voff;
04266     inidata = 0;
04267   }
04268 
04269   return Attribute::setValue(agr, pdata, data, idr_item_psize,
04270                                 idr_item_psize + IDB_OBJ_HEAD_SIZE, nb,
04271                                 from, inidata, False, vdata, check_class);
04272 }
04273 
04274 Status AttrDirect::getValue(const Object *agr, Data *data, int nb, int from, Bool *isnull) const
04275 {
04276   CHECK_OBJ(agr);
04277   CHECK_RTTYPE(agr);
04278 
04279   check_range(from, nb);
04280 
04281   Data vdata;
04282 
04283   Data inidata;
04284   if (is_basic_enum) {
04285     inidata = agr->getIDR() + idr_poff;
04286     vdata = inidata + idr_inisize;
04287   }
04288   else {
04289     vdata = agr->getIDR() + idr_voff;
04290     inidata = 0;
04291   }
04292 
04293   return Attribute::getValue((Database *)agr->getDatabase(), vdata, data,
04294                                 idr_item_psize, nb, from, inidata, isnull);
04295 }
04296 
04297 /*
04298 Status AttrDirect::getField(Database *db, const Oid *data_oid,
04299                                    Oid *doid, int *roffset, int offset,
04300                                    int from) const
04301 {
04302   int nb = 1;
04303   check_range(from, nb);
04304 
04305   *roffset = idr_poff + (from * idr_item_psize) + idr_inisize;
04306   *doid = *data_oid;
04307 
04308   return Success;
04309 }
04310 */
04311 
04312 Status AttrDirect::getVal(Database *db, const Oid *data_oid,
04313                                  Data data, int offset,
04314                                  int nb, int from, Bool *isnull) const
04315 {
04316   check_range(from, nb);
04317 
04318   if (idr_inisize && isnull)
04319     {
04320       RPCStatus rpc_status;
04321 
04322       if (!from)
04323         {
04324           int size = idr_inisize + nb * idr_item_psize;
04325           Data inidata = (unsigned char *)malloc(size);
04326 
04327           rpc_status = dataRead(db->getDbHandle(),
04328                                     idr_poff + offset,
04329                                     size, inidata, 0,
04330                                     data_oid->getOid());
04331 
04332 
04333           // needs XDR ?
04334 #ifdef E_XDR_TRACE
04335           printf("%s: AttrDirect::getVal -> needs XDR\n", name);
04336 #endif
04337           memcpy(data, inidata+idr_inisize, size - idr_inisize);
04338           *isnull = isNull(inidata, nb, from);
04339           free(inidata);
04340           return StatusMake(rpc_status);
04341         }
04342       else
04343         {
04344           rpc_status = dataRead(db->getDbHandle(),
04345                                     idr_inisize + idr_poff +
04346                                     (from * idr_item_psize) + offset,
04347                                     nb * idr_item_psize, data, 0,
04348                                     data_oid->getOid());
04349 
04350           if (rpc_status)
04351             return StatusMake(rpc_status);
04352 
04353           Data inidata = (unsigned char *)malloc(idr_inisize);
04354 
04355           rpc_status = dataRead(db->getDbHandle(),
04356                                     idr_poff + offset, idr_inisize, inidata,
04357                                     0, data_oid->getOid());
04358           
04359           
04360           *isnull = isNull(inidata, nb, from);
04361           free(inidata);
04362           return StatusMake(rpc_status);
04363         }
04364     }
04365   else
04366     return StatusMake(dataRead(db->getDbHandle(),
04367                                       idr_inisize + idr_poff +
04368                                       (from * idr_item_psize) + offset,
04369                                       nb * idr_item_psize, data,
04370                                       0, data_oid->getOid()));
04371 }
04372 
04373 static const char tvalue_fmt[] = "cannot use the method "
04374 "Attribute::getTValue() for the non-basic type attribute '%s::%s'";
04375 
04376 static Status
04377 tvalue_prologue(Database *&db, const Oid &objoid)
04378 {
04379   if (objoid.getDbid() != db->getDbid()) {
04380     Database *xdb;
04381     Status status = Database::getOpenedDB(objoid.getDbid(), db, xdb);
04382     if (status) return status;
04383     if (!xdb) 
04384       return Exception::make(IDB_ERROR,
04385                                 "cannot get any value of object %s: "
04386                                 "database ID #%d must be manually "
04387                                 "opened by the client",
04388                                 objoid.toString(), objoid.getDbid());
04389     db = xdb;
04390   }
04391 
04392   // object conversion
04393   ObjectHeader hdr;
04394   RPCStatus rpc_status =
04395     objectHeaderRead(db->getDbHandle(), objoid.getOid(), &hdr);
04396   if (rpc_status) return StatusMake(rpc_status);
04397 
04398   if (!db->getSchema()->getClass(hdr.oid_cl)) {
04399     if (!db->writeBackConvertedObjects())
04400       return Exception::make(IDB_ERROR, "object %s cannot be converted "
04401                                 "on the fly", objoid.toString());
04402     /*
04403     printf("getTValue:: object %s needs a conversion\n",
04404            objoid.toString());
04405     */
04406     Data idr = 0;
04407     rpc_status = objectRead(db->getDbHandle(), 0, &idr, 0, objoid.getOid(),
04408                                 0, DefaultLock, 0);
04409     if (rpc_status) return StatusMake(rpc_status);
04410     free(idr);
04411   }
04412   return Success;
04413 }
04414 
04415 Status
04416 AttrDirect::getTValue(Database *db, const Oid &objoid,
04417                          Data *data, int nb, int from,
04418                          Bool *isnull, Size *rnb, Offset poffset) const
04419 {
04420   if (!is_basic_enum)
04421     return Exception::make(IDB_ERROR, tvalue_fmt,
04422                               getClassOwner()->getName(), name);
04423 
04424   check_range(from, nb);
04425 
04426   Status status = tvalue_prologue(db, objoid);
04427   if (status) return status;
04428 
04429   if (rnb)
04430     *rnb = nb;
04431 
04432   if (!idr_inisize || !isnull) {
04433     status = StatusMake(dataRead(db->getDbHandle(),
04434                                         poffset + idr_inisize + idr_poff +
04435                                         (from * idr_item_psize),
04436                                         nb * idr_item_psize, (Data)data,
04437                                         0, objoid.getOid()));
04438     if (status)
04439       CHECK_OID(objoid);
04440     return status;
04441   }
04442 
04443   RPCStatus rpc_status;
04444 
04445   if (!from) {
04446     int size = idr_inisize + nb * idr_item_psize;
04447     Data inidata = (unsigned char *)malloc(size);
04448     
04449     rpc_status = dataRead(db->getDbHandle(), poffset + idr_poff, size,
04450                               inidata, 0, objoid.getOid());
04451 
04452 
04453     if (rpc_status) {
04454       CHECK_OID(objoid);
04455       return StatusMake(rpc_status);
04456     }
04457 
04458     *isnull = isNull(inidata, nb, from);
04459 
04460 #ifdef E_XDR_TRACE
04461     printf("%s: AttrDirect::getTValue -> XDR\n", name);
04462 #endif
04463     if (cls->asEnumClass()) // needs XDR !
04464       cls->asEnumClass()->getRawData((Data)data, inidata+idr_inisize, nb);
04465 #ifdef E_XDR
04466     else
04467       //      cls->decode(data, inidata+idr_inisize, size-idr_inisize);
04468       cls->decode(data, inidata+idr_inisize, idr_item_psize, nb);
04469 #else
04470     else
04471       memcpy(data, inidata+idr_inisize, size-idr_inisize);
04472 #endif
04473 
04474     free(inidata);
04475     return Success;
04476   }
04477 
04478   Data xdata = (unsigned char *)malloc(nb * idr_item_psize);
04479 
04480   rpc_status = dataRead(db->getDbHandle(),
04481                             poffset + idr_inisize + idr_poff +
04482                             (from * idr_item_psize),
04483                             nb * idr_item_psize, xdata,
04484                             0, objoid.getOid());
04485 
04486   if (rpc_status) {
04487     free(xdata);
04488     CHECK_OID(objoid);
04489     return StatusMake(rpc_status);
04490   }
04491 
04492   if (cls->asEnumClass()) {
04493     cls->asEnumClass()->getRawData((Data)data, xdata, nb);
04494   }
04495   else {
04496     cls->decode(data, xdata, idr_item_psize, nb);
04497   }
04498 
04499   free(xdata);
04500 
04501   Data inidata = (unsigned char *)malloc(idr_inisize);
04502 
04503   rpc_status = dataRead(db->getDbHandle(),
04504                             poffset + idr_poff, idr_inisize, inidata,
04505                             0, objoid.getOid());
04506           
04507   *isnull = isNull(inidata, nb, from);
04508   free(inidata);
04509 
04510   if (rpc_status) {
04511     CHECK_OID(objoid);
04512     return StatusMake(rpc_status);
04513   }
04514 
04515   return Success;
04516 }
04517 
04518 #ifdef GBX_NEW_CYCLE
04519 void AttrDirect::decrRefCountPropag(Object *agr, int) const
04520 {
04521   if (is_basic_enum)
04522     return;
04523 
04524   Attribute::decrRefCountPropag(agr->getIDR() + idr_voff, typmod.maxdims);
04525 }
04526 #endif
04527 
04528 void AttrDirect::garbage(Object *agr, int) const
04529 {
04530   if (is_basic_enum)
04531     return;
04532 
04533   Attribute::garbage(agr->getIDR() + idr_voff, typmod.maxdims);
04534 }
04535 
04536 void AttrDirect::manageCycle(Database *db, Object *o, gbxCycleContext &r) const
04537 {
04538   if (is_basic_enum)
04539     return;
04540 
04541   Attribute::manageCycle(o, o->getIDR() + idr_voff, typmod.maxdims, r);
04542 }
04543 
04544 Status
04545 AttrDirect::convert(Database *db, ClassConversion *conv,
04546                        Data in_idr, Size in_size) const
04547 {
04548   if (conv->getUpdtype() == ADD_ATTR)
04549     return add(db, conv, in_idr, in_size);
04550 
04551   return Exception::make(IDB_ERROR, "attribute %s::%s conversion not yet "
04552                             "implemented", class_owner->getName(), name);
04553 }
04554 
04555 Status AttrDirect::trace(const Object *agr, FILE *fd, int *indent, unsigned int flags, const RecMode *rcm) const
04556 {
04557   IDB_CHECK_INTR();
04558 
04559   char *indent_str = make_indent(*indent);
04560   TypeModifier tmod = typmod;
04561   Data pdata = agr->getIDR() + idr_poff;
04562   char prefix[64];
04563   Status status = Success;
04564 
04565   get_prefix(agr, class_owner, prefix, sizeof(prefix));
04566 
04567   Data inidata = pdata;
04568   pdata += idr_inisize;
04569 
04570   if (is_basic_enum)
04571     {
04572       fprintf(fd, "%s%s%s = ", indent_str, prefix, name);
04573 
04574       //int len = strlen(indent_str) + strlen(prefix) + strlen(name) + 3;
04575       int len = *indent + INDENT_INC;
04576       if (cls->asBasicClass())
04577         {
04578           if (isNull(inidata, &tmod))
04579             PRINT_NULL(fd);
04580           else
04581             status = ((BasicClass *)cls)->traceData(fd, len, inidata, pdata, &tmod);
04582         }
04583       else
04584         {
04585           if (isNull(inidata, &tmod))
04586             PRINT_NULL(fd);
04587           else
04588             status = ((EnumClass *)cls)->traceData(fd, len, inidata, pdata, &tmod);
04589         }
04590       
04591       if (status)
04592         goto error;
04593       fprintf(fd, ";\n");
04594     }
04595   else
04596     for (int j = 0; j < typmod.pdims; j++)
04597       {
04598         Object *o;
04599 
04600         // no XDR
04601         memcpy(&o, agr->getIDR() + idr_voff + (j * idr_item_vsize),
04602                sizeof(Object *));
04603 
04604         if (!tmod.ndims)
04605           fprintf(fd, "%s%s%s %s = ", indent_str, prefix, name,
04606                   cls->getName());
04607         else
04608           fprintf(fd, "%s%s%s[%d] %s = ", indent_str, prefix, name, j,
04609                   cls->getName());
04610         status = ObjectPeer::trace_realize(o, fd, *indent + INDENT_INC, flags, rcm);
04611         if (status)
04612           goto error;
04613       }
04614 
04615  error:
04616   delete_indent(indent_str);
04617   return status;
04618 }
04619 
04620 //
04621 // AttrIndirect methods
04622 //
04623 
04624 AttrIndirect::AttrIndirect(const Attribute *agreg,
04625                                  const Class *_cls,
04626                                  const Class *_class_owner,
04627                                  const Class *_dyn_class_owner,
04628                                  int n) :
04629   Attribute(agreg, _cls, _class_owner, _dyn_class_owner, n)
04630 {
04631   code = AttrIndirect_Code;
04632   idr_inisize = 0;
04633 }
04634 
04635 AttrIndirect::AttrIndirect(Database *db,
04636                                  Data data, Offset *offset,
04637                                  const Class *_dyn_class_owner,
04638                                  int n) :
04639   Attribute(db, data, offset, _dyn_class_owner, n)
04640 {
04641   code = AttrIndirect_Code;
04642   idr_inisize = 0;
04643 }
04644 
04645 Status AttrIndirect::check() const
04646 {
04647   return Attribute::check();
04648 }
04649 
04650 Status
04651 AttrIndirect::load(Database *db,
04652                       Object *agr,
04653                       const Oid &cloid,
04654                       LockMode lockmode,
04655                       AttrIdxContext &idx_ctx,
04656                       const RecMode *rcm, Bool force) const
04657 {
04658   Data vdata = agr->getIDR() + idr_voff;
04659 
04660   for (int j = 0; j < typmod.pdims; j++)
04661     if (rcm->isAgregRecurs(this, j))
04662       {
04663         Oid oid;
04664         
04665         getOid(agr, &oid, 1, j);
04666         
04667         if (oid.isValid())
04668           {
04669             Status status;
04670             Object *o;
04671 
04672             status = db->loadObject_realize(&oid, &o, lockmode, rcm);
04673         
04674             if (status != Success)
04675               return status;
04676 
04677             o->setMustRelease(false); // SMART_PTR
04678             status = setValue(agr, (Data)&o, 1, j, False);
04679 
04680             if (status != Success)
04681               return status;
04682           }
04683       }
04684 
04685   return Success;
04686 }
04687 
04688 Status
04689 Attribute::cardManage(Database *db, Object *agr, int j) const
04690 {
04691   Object *o;
04692   Status status;
04693 
04694   Oid colloid;
04695   status = ((Agregat *)agr)->getItemOid(this, &colloid, 1, j);
04696 
04697   if (status)
04698     return status;
04699 
04700 #ifdef CARD_TRACE
04701   printf("Attribute::cardManage(%s -> %s)\n", name, colloid.toString());
04702 #endif
04703   if (!colloid.isValid())
04704     return Success;
04705 
04706   status = db->loadObject(&colloid, &o);
04707 
04708   if (status)
04709     return status;
04710 
04711   Collection *coll = (Collection *)o;
04712 
04713   if (!card->getCardDesc()->compare(coll->getCardinalityConstraint()))
04714     {
04715       coll->setCardinalityConstraint(card);
04716 
04717       status = coll->checkCardinality();
04718       if (status)
04719         {
04720           o->release();
04721           return status;
04722         }
04723 
04724       status = coll->realizeCardinality();
04725       if (status)
04726         {
04727           o->release();
04728           return status;
04729         }
04730     }
04731 
04732   o->release();
04733   return Success;
04734 }
04735 
04736 Status
04737 Attribute::inverseManage(Database *db, Object *agr, int j) const
04738 {
04739   if (!cls->asCollectionClass())
04740     return Success;
04741 
04742   Object *o;
04743   Status status;
04744 
04745   Oid colloid;
04746 
04747   if (status = agr->asAgregat()->getItemOid(this, &colloid, 1, j))
04748     return status;
04749 
04750   if (!colloid.isValid())
04751     return Success;
04752 
04753   if (status = db->loadObject(&colloid, &o))
04754     return status;
04755 
04756   Collection *coll = (Collection *)o;
04757 
04758   if (status = coll->realizeInverse(agr->getOid(), num))
04759     {
04760       o->release();
04761       return status;
04762     }
04763   
04764   o->release();
04765   return Success;
04766 }
04767 
04768 Status
04769 Attribute::inverseManage(Database *db, Object *agr,
04770                             Object *coll) const
04771 {
04772   if (!cls->asCollectionClass())
04773     return Success;
04774 
04775   return coll->asCollection()->realizeInverse(agr->getOid(), num);
04776 }
04777 
04778 std::string
04779 getAttrCollDefName(const Attribute *attr, const Oid &oid)
04780 {
04781   return std::string(attr->getClassOwner()->getName()) + "::" +
04782     attr->getName() + "[" + oid.toString() + "]";
04783 }
04784                              
04785 static void
04786 attrCollManage(const Attribute *attr, Collection *coll, Object *o)
04787 {
04788   if (!coll->getName() || !*coll->getName())
04789     coll->setName(getAttrCollDefName(attr, o->getOid()).c_str());
04790 }
04791 
04792 Status AttrIndirect::realize(Database *db, Object *_o,
04793                                    const Oid& cloid,
04794                                    const Oid& objoid,
04795                                    AttrIdxContext &idx_ctx,
04796                                    const RecMode *rcm) const
04797 {
04798   Agregat *agr = (Agregat *)_o;
04799   Data vdata = agr->getIDR() + idr_voff;
04800 
04801   for (int j = 0; j < typmod.pdims; j++)
04802     {
04803       Status status;
04804       Object *o;
04805 
04806       mcp(&o, vdata + (j * idr_item_vsize), sizeof(Object *));
04807 
04808 #ifdef CARD_TRACE
04809       Oid old_oid;
04810       status = agr->getItemOid(this, &old_oid, 1, j);
04811       if (status)
04812         return status;
04813       printf("AttrIndirect::realize(%s, %s, new_o=%s)\n",
04814              name, old_oid.toString(), o ? o->getOid().toString() : "NULL");
04815 #endif
04816       if (o && rcm->isAgregRecurs(this, j, o))
04817         {
04818           if (!o->getRefCount())
04819             abort(); // added the 23/08/99
04820           status = o->setDatabase(db);
04821           if (status != Success)
04822             return status;
04823 
04824           // ----- adding collection name?? -> 1/07/99 ----
04825           if (o->asCollection())
04826             attrCollManage(this, o->asCollection(), _o);
04827           // ----------------------------------------------
04828 
04829           status = o->realize(rcm);
04830           
04831           if (status == Success)
04832             status = agr->setItemOid(this, &o->getOid(), 1, j);
04833 
04834           if (status)
04835             return status;
04836 
04837           if (inv_spec.oid_cl.isValid())
04838             {
04839               status = inverseManage(db, agr, o);
04840               if (status)
04841                 return status;
04842             }
04843         }
04844       else if (!o)
04845         {
04846           if (card)
04847             {
04848               status = cardManage(db, agr, j);
04849               if (status)
04850                 return status;
04851             }
04852 
04853           if (inv_spec.oid_cl.isValid())
04854             {
04855               status = inverseManage(db, agr, j);
04856               if (status)
04857                 return status;
04858             }
04859         }
04860     }
04861 
04862   return Success;
04863 }
04864 
04865 Status AttrIndirect::remove(Database *db, Object *_o,
04866                                   const Oid& cloid,
04867                                   const Oid& objoid,
04868                                   AttrIdxContext &idx_ctx,
04869                                   const RecMode *rcm) const
04870 {
04871   Agregat *agr = (Agregat *)_o;
04872   Data vdata = agr->getIDR() + idr_voff;
04873 
04874   for (int j = 0; j < typmod.pdims; j++)
04875     {
04876       Status status;
04877       Object *o;
04878 
04879       // no XDR
04880       memcpy(&o, vdata + (j * idr_item_vsize), sizeof(Object *));
04881 
04882       if (o && rcm->isAgregRecurs(this, j, o))
04883         {
04884           status = o->setDatabase(db);
04885           if (status != Success)
04886             return status;
04887           status = o->remove(rcm);
04888 
04889           if (status == Success ||
04890               status->getStatus() == IDB_OBJECT_NOT_CREATED)
04891             status = agr->setItemOid(this, &Oid::nullOid, 1, j);
04892 
04893           if (status)
04894             return status;
04895         }
04896     }
04897 
04898   return Success;
04899 }
04900 
04901 Status AttrIndirect::compile_perst(const AgregatClass *ma, int *offset, int *size, int *inisize)
04902 {
04903   Status status;
04904   const TypeModifier *tmod = &typmod;
04905 
04906   if (status = check())
04907     return status;
04908 
04909   idr_inisize = 0;
04910   idr_poff = *offset;
04911 
04912   idr_item_psize = sizeof(Oid);
04913   idr_psize = idr_item_psize * tmod->pdims;
04914   *inisize = idr_inisize;
04915 
04916   compile_update(ma, idr_psize, offset, size);
04917 
04918   return Success;
04919 }
04920 
04921 Status AttrIndirect::compile_volat(const AgregatClass *ma, int *offset, int *size)
04922 {
04923   Status status;
04924   const TypeModifier *tmod = &typmod;
04925 
04926   idr_voff = *offset;
04927 
04928   idr_item_vsize = SIZEOFOBJECT;
04929   idr_vsize = idr_item_vsize * tmod->pdims;
04930 
04931   compile_update(ma, idr_vsize, offset, size);
04932 
04933   return Success;
04934 }
04935 
04936 Status AttrIndirect::setOid(Object *agr, const Oid *oid, int nb, int from, Bool check_class) const
04937 {
04938   CHECK_OBJ(agr);
04939   check_range(from, nb);
04940 
04941   if (oid->isValid() && check_class) {
04942     Class *o_class;
04943     Status status;
04944     Bool is;
04945     
04946     status = cls->isObjectOfClass(oid, &is, True, &o_class);
04947       
04948     if (status)
04949       return status;
04950       
04951     if (!is)
04952       return Exception::make(IDB_ATTRIBUTE_ERROR,
04953                                 "waiting for object of class '%s', got object of class '%s'",
04954                                 cls->getName(), o_class->getName());
04955   }
04956     
04957 #ifdef CARD_TRACE
04958   printf("AttributeIndirect::setValue(%s, %s, is %sa collection class)\n",
04959          name, oid->toString(), cls->asCollectionClass() ? "" : "NOT ");
04960   Oid old_oid;
04961   Status status = getOid(agr, &old_oid, nb, from);
04962   if (status) return status;
04963   printf("setOid(%s -> old_oid = %s\n", name, old_oid.toString());
04964 #endif
04965 
04966 #ifdef E_XDR_TRACE
04967   printf("%s: setOid -> set_oid_realize\n", name);
04968 #endif
04969   if (set_oid_realize(agr->getIDR() + idr_poff, oid, nb, from))
04970     agr->touch();
04971 
04972   return Success;
04973 }
04974 
04975 Status AttrIndirect::getOid(const Object *agr, Oid *oid, int nb, int from) const
04976 {
04977   CHECK_OBJ(agr);
04978   check_range(from, nb);
04979 
04980 #ifdef E_XDR_TRACE
04981   printf("%s: AttrIndirect::getOid() -> XDR\n", name);
04982 #endif
04983 #ifdef E_XDR_1
04984   for (int n = 0; n < nb; n++)
04985     eyedbsm::x2h_oid(oid[n].getOid(), agr->getIDR() + idr_poff +
04986                ((from+n) * sizeof(Oid)));
04987 #else
04988   memcpy(oid, agr->getIDR() + idr_poff + (from * sizeof(Oid)),
04989          nb * sizeof(Oid));
04990 #endif
04991   return Success;
04992 }
04993 
04994 Status AttrIndirect::setValue(Object *agr, Data data, int nb,
04995                                     int from, Bool check_class) const
04996 {
04997   CHECK_OBJ(agr);
04998   CHECK_RTTYPE(agr);
04999   Status status;
05000   Data vdata = agr->getIDR() + idr_voff;
05001 
05002   check_range(from, nb);
05003 
05004   return Attribute::setValue(agr, vdata, data,
05005                                 SIZEOFOBJECT, sizeof(Object *),
05006                                 nb, from, 0, True, 0, check_class);
05007 }
05008 
05009 Status AttrIndirect::getValue(const Object *agr, Data *data, int nb, int from, Bool *) const
05010 {
05011   CHECK_OBJ(agr);
05012   CHECK_RTTYPE(agr);
05013 
05014   Data vdata = agr->getIDR() + idr_voff;
05015 
05016   check_range(from, nb);
05017 
05018   mcp(data, vdata + from * SIZEOFOBJECT, nb * sizeof(Object *));
05019   return Success;
05020 }
05021 
05022 /*
05023 Status AttrIndirect::getField(Database *db, const Oid *data_oid,
05024                                      Oid *doid, int *roffset, int offset,
05025                                      int from) const
05026 {
05027   int nb = 1;
05028   check_range(from, nb);
05029 
05030   *roffset = 0;
05031   return StatusMake
05032     (dataRead(db->getDbHandle(),
05033                   idr_poff + (from * idr_item_psize) + offset,
05034                   idr_item_psize, (Data)doid, 0, data_oid->getOid()));
05035 }
05036 */
05037 
05038 Status AttrIndirect::getVal(Database *db, const Oid *data_oid,
05039                                    Data data, int offset,
05040                                    int nb, int from, Bool *) const
05041 {
05042   check_range(from, nb);
05043 
05044   assert(0);
05045   return StatusMake
05046     (dataRead(db->getDbHandle(),
05047                   idr_poff + (from * idr_item_psize) + offset,
05048                   nb * idr_item_psize, data, 0, data_oid->getOid()));
05049 }
05050 
05051 Status
05052 AttrIndirect::getTValue(Database *db, const Oid &objoid,
05053                            Data *data, int nb, int from,
05054                            Bool *isnull, Size *rnb, Offset poffset) const
05055 {
05056   check_range(from, nb);
05057 
05058   Status status = tvalue_prologue(db, objoid);
05059   if (status) return status;
05060 
05061   status = StatusMake
05062     (dataRead(db->getDbHandle(),
05063                   poffset + idr_poff + (from * idr_item_psize),
05064                   nb * idr_item_psize, (Data)data, 0, objoid.getOid()));
05065 
05066   if (rnb)
05067     *rnb = nb;
05068 
05069   if (status)
05070     CHECK_OID(objoid);
05071 
05072   if (status)
05073     return status;
05074 
05075 #ifdef E_XDR_1
05076   for (int i = 0; i < nb; i++) {
05077     Oid tmp_oid;
05078     eyedbsm::x2h_oid(tmp_oid.getOid(), data+i*sizeof(Oid));
05079     memcpy(data+i*sizeof(Oid), tmp_oid.getOid(), sizeof(Oid));
05080   }
05081 #endif
05082 
05083   if (!isnull) return status;
05084 
05085   *isnull = True;
05086 
05087   for (int i = 0; i < nb; i++) {
05088     Oid tmp_oid;
05089     mcp(&tmp_oid, data+i*sizeof(Oid), sizeof(Oid));
05090     if (tmp_oid.isValid()) {
05091       *isnull = False;
05092       break;
05093     }
05094   }
05095 
05096   return Success;
05097 }
05098 
05099 #ifdef GBX_NEW_CYCLE
05100 void AttrIndirect::decrRefCountPropag(Object *agr, int) const
05101 {
05102   Attribute::decrRefCountPropag(agr->getIDR() + idr_voff, typmod.maxdims);
05103 }
05104 #endif
05105 
05106 void AttrIndirect::garbage(Object *agr, int) const
05107 {
05108   Attribute::garbage(agr->getIDR() + idr_voff, typmod.maxdims);
05109 }
05110 
05111 void AttrIndirect::manageCycle(Database *db, Object *o, gbxCycleContext &r) const
05112 {
05113   Attribute::manageCycle(o, o->getIDR() + idr_voff, typmod.maxdims, r);
05114 }
05115 
05116 Status
05117 AttrIndirect::convert(Database *db, ClassConversion *conv,
05118                          Data in_idr, Size in_size) const
05119 {
05120   return Exception::make(IDB_ERROR, "attribute %s::%s conversion error",
05121                             class_owner->getName(), name);
05122 }
05123 
05124 Status AttrIndirect::trace(const Object *agr, FILE *fd, int *indent, unsigned int flags, const RecMode *rcm) const
05125 {
05126   IDB_CHECK_INTR();
05127 
05128   char *indent_str = make_indent(*indent);
05129   TypeModifier tmod = typmod;
05130   Data vdata = agr->getIDR() + idr_voff;
05131   char prefix[64];
05132   Status status = Success;
05133 
05134   get_prefix(agr, class_owner, prefix, sizeof(prefix));
05135 
05136   for (int j = 0; j < typmod.pdims; j++)
05137     {
05138       Object *o;
05139       Oid oid;
05140 
05141       // no XDR
05142       memcpy(&o, vdata + (j * idr_item_vsize), sizeof(Object *));
05143       getOid(agr, &oid, 1, j);
05144 
05145       if (o)
05146         {
05147           if (!tmod.ndims)
05148             fprintf(fd, "%s*%s%s %s {%s} = ", indent_str, prefix, name,
05149                     o->getClass()->getName(), oid.getString());
05150           else
05151             fprintf(fd, "%s*%s%s[%d] %s {%s} = ", indent_str, prefix, name, j,
05152                     o->getClass()->getName(), oid.getString());
05153           status = ObjectPeer::trace_realize(o, fd, *indent + INDENT_INC, flags, rcm);
05154           if (status) break;
05155         }
05156       else
05157         {
05158           if (!tmod.ndims)
05159             fprintf(fd, "%s*%s%s = {%s};\n", indent_str, prefix, name,
05160                     oid.getString());
05161           else
05162             fprintf(fd, "%s*%s%s[%d] = {%s};\n", indent_str, prefix, name, j,
05163                     oid.getString());
05164         }
05165     }
05166 
05167   delete_indent(indent_str);
05168 
05169   return status;
05170 }
05171 
05172 //
05173 // AttrVD methods
05174 //
05175 
05176 AttrVD::AttrVD(const Attribute *agreg,
05177                      const Class *_cls,
05178                      const Class *_class_owner,
05179                      const Class *_dyn_class_owner,
05180                      int n) :
05181   Attribute(agreg, _cls, _class_owner, _dyn_class_owner, n)
05182 {
05183 }
05184 
05185 AttrVD::AttrVD(Database *db, Data data, Offset *offset,
05186                      const Class *_dyn_class_owner,
05187                      int n):
05188   Attribute(db, data, offset, _dyn_class_owner, n)
05189 {
05190 }
05191 
05192 Status
05193 AttrVD::getDefaultDataspace(const Dataspace *&_dataspace) const
05194 {
05195   if (dataspace) {
05196     _dataspace = dataspace;
05197     return Success;
05198   }
05199 
05200   if (dspid == Dataspace::DefaultDspid) {
05201     _dataspace = 0;
05202     return Success;
05203   }
05204 
05205   if (!cls) return Exception::make(IDB_ERROR, "attribute %s is not completed", name);
05206   Status s = const_cast<Database *>(cls->getDatabase())->getDataspace(dspid, _dataspace);
05207   if (s) return s;
05208   const_cast<AttrVD *>(this)->dataspace = _dataspace;
05209   return Success;
05210 }
05211 
05212 Status
05213 AttrVD::setDefaultDataspace(const Dataspace *_dataspace)
05214 {
05215   if (!dataspace && dspid != Dataspace::DefaultDspid) {
05216     if (!cls) return Exception::make(IDB_ERROR, "attribute %s is not completed", name);
05217     Status s = const_cast<Database *>(cls->getDatabase())->getDataspace(dspid, dataspace);
05218     if (s) return s;
05219   }
05220 
05221   if (dataspace != _dataspace) {
05222     if (!dyn_class_owner) return Exception::make(IDB_ERROR, "attribute %s is not completed", name);
05223     dataspace = _dataspace;
05224     dspid = (dataspace ? dataspace->getId() : Dataspace::DefaultDspid);
05225     const_cast<Class *>(dyn_class_owner)->touch();
05226     return const_cast<Class *>(dyn_class_owner)->store();
05227   }
05228 
05229   return Success;
05230 }
05231 
05232 Status
05233 Attribute::move(Dataspace const *)
05234 {
05235   return Success;
05236 }
05237 
05238 Status
05239 Attribute::getLocations(ObjectLocationArray &)
05240 {
05241   return Success;
05242 }
05243 
05244 Status
05245 AttrVD::getLocations(ObjectLocationArray &)
05246 {
05247   return Success;
05248 }
05249 
05250 Status
05251 AttrVD::move(Dataspace const *)
05252 {
05253   return Success;
05254 }
05255 
05256 /*
05257 Status AttrVD::getField(Database *db, const Oid *data_oid,
05258                                Oid *doid, int *roffset, int offset,
05259                                int from) const
05260 {
05261   int nb = 1;
05262   check_range(from, nb);
05263 
05264   *roffset = from * idr_item_psize;
05265 
05266   return StatusMake
05267     (dataRead(db->getDbHandle(),
05268                   idr_poff + sizeof(Size),
05269                   sizeof(eyedbsm::Oid), (Data)doid, 0, data_oid->getOid()));
05270 }
05271 */
05272 
05273 Status AttrVD::getVal(Database *db, const Oid *data_oid,
05274                              Data data, int offset,
05275                              int nb, int from, Bool *) const
05276 {
05277   check_range(from, nb);
05278 
05279   return StatusMake
05280     (dataRead(db->getDbHandle(),
05281                   idr_poff + (from * idr_item_psize) +
05282                   offset, nb * idr_item_psize,
05283                   data, 0, data_oid->getOid()));
05284 }
05285 
05286 Status AttrVD::getSize(Data _idr, Size& size) const
05287 {
05288 #ifdef E_XDR_TRACE
05289   printf("%s: AttrVD::getSize -> XDR\n", name);
05290 #endif
05291 
05292 #ifdef E_XDR
05293   x2h_32_cpy(&size, _idr + idr_poff);
05294 #else
05295   mcp(&size, _idr + idr_poff, sizeof(Size));
05296 #endif
05297   size = CLEAN_SIZE(size);
05298   return Success;
05299 }
05300 
05301 Status AttrVD::getSize(const Object *agr, Size& size) const
05302 {
05303   return getSize(agr->getIDR(), size);
05304 }
05305 
05306 Status
05307 AttrVD::getSize(Database *db, const Oid *data_oid,
05308                    Size& size) const
05309 {
05310   RPCStatus rpc_status;
05311 
05312   rpc_status = dataRead(db->getDbHandle(),
05313                             idr_poff, sizeof(Size), (Data)&size,
05314                             0, data_oid->getOid());
05315 #ifdef E_XDR
05316   Size hsize;
05317   x2h_32_cpy(&hsize, &size);
05318   size = CLEAN_SIZE(hsize);
05319 #else
05320   size = CLEAN_SIZE(size);
05321 #endif
05322   return Success;
05323 }
05324 
05325 //
05326 // AttrVarDim methods
05327 //
05328 
05329 AttrVarDim::AttrVarDim(const Attribute *agreg,
05330                              const Class *_cls,
05331                              const Class *_class_owner,
05332                              const Class *_dyn_class_owner,
05333                              int n) :
05334   AttrVD(agreg, _cls, _class_owner, _dyn_class_owner, n)
05335 {
05336   code = AttrVarDim_Code;
05337   idr_inisize = 0;
05338 }
05339 
05340 AttrVarDim::AttrVarDim(Database *db, Data data, Offset *offset,
05341                              const Class *_dyn_class_owner,
05342                              int n) :
05343   AttrVD(db, data, offset, _dyn_class_owner, n)
05344 {
05345   code = AttrVarDim_Code;
05346   idr_inisize = 0;
05347 }
05348 
05349 Status AttrVarDim::check() const
05350 {
05351   Status s = Attribute::check();
05352   if (s) return s;
05353   const TypeModifier *tmod = &typmod;
05354 
05355   for (int i = 0; i < tmod->ndims; i++)
05356     if (tmod->dims[i] < 0 && i != 0)
05357       return Exception::make(IDB_ATTRIBUTE_ERROR, "only left dimension is allowed to be variable for attribute '%s' in agregat class '%s'", name, class_owner->getName());
05358 
05359   return Success;
05360 }
05361 
05362 int AttrVarDim::getBound(Database *db, Data _idr)
05363 {
05364   if (!is_basic_enum)
05365     {
05366       Size size;
05367 #ifdef E_XDR_TRACE
05368       printf("%s: AttrVD::getBound -> XDR\n", name);
05369 #endif
05370 #ifdef E_XDR
05371       x2h_32_cpy(&size, _idr + idr_poff);
05372 #else
05373       mcp(&size, _idr + idr_poff, sizeof(Size));
05374 #endif
05375       size = CLEAN_SIZE(size);
05376       return (int)size;
05377     }
05378   return 0;
05379 }
05380 
05381 Status AttrVarDim::compile_perst(const AgregatClass *ma, int *offset, int *size, int *inisize)
05382 {
05383   Status status;
05384   const TypeModifier *tmod = &typmod;
05385 
05386   if (status = check())
05387     return status;
05388 
05389   idr_poff = *offset;
05390   idr_inisize = 0;
05391 
05392   if (!cls->getIDRObjectSize(&idr_item_psize))
05393     return Exception::make(IDB_ATTRIBUTE_ERROR, incomp_fmt, cls->getName(), name, num, class_owner->getName());
05394 
05395   idr_item_psize -= IDB_OBJ_HEAD_SIZE;
05396 
05397   if (VARS_COND(ma->getDatabase()))
05398     idr_psize = VARS_OFFSET + VARS_TSZ;
05399   else
05400     idr_psize = sizeof(Size) + sizeof(Oid);
05401 
05402   *inisize = idr_inisize;
05403   
05404   compile_update(ma, idr_psize, offset, size);
05405 
05406   return Success;
05407 }
05408 
05409 Status AttrVarDim::compile_volat(const AgregatClass *ma, int *offset, int *size)
05410 {
05411   Status status;
05412   const TypeModifier *tmod = &typmod;
05413 
05414   idr_voff = *offset;
05415 
05416   if (!is_basic_enum)
05417     {
05418       idr_item_vsize = SIZEOFOBJECT;
05419       idr_vsize = SIZEOFDATA + SIZEOFDATA;
05420     }
05421   else
05422     {
05423       idr_item_vsize = 0;
05424       idr_vsize = SIZEOFDATA;
05425     }
05426 
05427   compile_update(ma, idr_vsize, offset, size);
05428 
05429   return Success;
05430 }
05431 
05432 Status AttrVarDim::setOid(Object *, const Oid *, int, int, Bool) const
05433 {
05434   return Exception::make(IDB_ATTRIBUTE_ERROR, "cannot set oid for direct attribute '%s' in agregat class '%s'", name, class_owner->getName());
05435 }
05436 
05437 Status AttrVarDim::getOid(const Object *agr, Oid *oid, int nb, int from) const
05438 {
05439   return Exception::make(IDB_ATTRIBUTE_ERROR, "cannot get oid for direct attribute '%s' in agregat class '%s'", name, class_owner->getName());
05440 }
05441 
05442 void AttrVarDim::setVarDimOid(Object *agr, const Oid *oid) const
05443 {
05444 #ifdef E_XDR_TRACE
05445   printf("%s: AttrVarDim::setVarDimOid() -> XDR\n", name);
05446 #endif
05447 #ifdef E_XDR
05448   if (eyedbsm::cmp_oid(agr->getIDR() + idr_poff + sizeof(Size), oid->getOid())) {
05449     eyedbsm::h2x_oid(agr->getIDR() + idr_poff + sizeof(Size), oid->getOid());
05450     agr->touch();
05451   }
05452 #else
05453   if (memcmp(agr->getIDR() + idr_poff + sizeof(Size), oid,
05454              sizeof(Oid))) {
05455     memcpy(agr->getIDR() + idr_poff + sizeof(Size), oid, sizeof(Oid));
05456     agr->touch();
05457   }
05458 #endif
05459 }
05460 
05461 void AttrVarDim::getVarDimOid(Data _idr, Oid *oid) const
05462 {
05463 #ifdef E_XDR_TRACE
05464   printf("%s: AttrVarDim::getVarDimOid() -> XDR\n", name);
05465 #endif
05466 #ifdef E_XDR
05467   eyedbsm::x2h_oid(oid->getOid(), _idr + idr_poff + sizeof(Size));
05468 #else
05469   mcp(oid, _idr + idr_poff + sizeof(Size), sizeof(Oid));
05470 #endif
05471 }
05472 
05473 void AttrVarDim::getVarDimOid(const Object *agr, Oid *oid) const
05474 {
05475   getVarDimOid(agr->getIDR(), oid);
05476 }
05477 
05478 void AttrVarDim::setSizeChanged(Object *agr, Bool changed) const
05479 {
05480   Size size;
05481 #ifdef E_XDR_TRACE
05482   printf("%s: AttrVarDim::setSizeChanged -> XDR\n", name);
05483 #endif
05484 #ifdef E_XDR
05485   x2h_32_cpy(&size, agr->getIDR() + idr_poff);
05486   size = SET_SIZE_CHANGED(size, changed);
05487   h2x_32_cpy(agr->getIDR() + idr_poff, &size);
05488 #else
05489   mcp(&size, agr->getIDR() + idr_poff, sizeof(Size));
05490   size = SET_SIZE_CHANGED(size, changed);
05491   mcp(agr->getIDR() + idr_poff, &size, sizeof(Size));
05492 #endif
05493 }
05494 
05495 Bool AttrVarDim::isSizeChanged(const Object *agr) const
05496 {
05497   Size size;
05498 #ifdef E_XDR_TRACE
05499   printf("%s: AttrVarDim::isSizeChanged -> XDR\n", name);
05500 #endif
05501 #ifdef E_XDR
05502   x2h_32_cpy(&size, agr->getIDR() + idr_poff);
05503 #else
05504   mcp(&size, agr->getIDR() + idr_poff, sizeof(Size));
05505 #endif
05506   return IS_SIZE_CHANGED(size);
05507 }
05508 
05509 void AttrVarDim::getData(const Database *db, Data _idr, Data& pdata,
05510                             Data& vdata) const
05511 {
05512   if (VARS_COND(db))
05513     {
05514       Size size;
05515       getSize(_idr, size);
05516       if (size <= VARS_SZ)
05517         {
05518           pdata = VARS_DATA(_idr);
05519           vdata = 0;
05520           return;
05521         }
05522     }
05523 
05524   // needs XDR ? guess no because vdata !
05525 #ifdef E_XDR_TRACE
05526   printf("%s: AttrVarDim::getData -> needs XDR ? no\n", name);
05527 #endif
05528   mcp(&pdata, _idr + idr_voff, sizeof(Data));
05529 
05530   if (is_basic_enum)
05531     vdata = 0;
05532   else
05533     mcp(&vdata, _idr + idr_voff + SIZEOFDATA, sizeof(Data));
05534 }
05535 
05536 Bool AttrVarDim::getIsLoaded(Data _idr) const
05537 {
05538   Size size;
05539 #ifdef E_XDR_TRACE
05540   printf("%s: AttrVarDim::getIsLoaded -> XDR\n", name);
05541 #endif
05542 #ifdef E_XDR
05543   x2h_32_cpy(&size, _idr + idr_poff);
05544 #else
05545   mcp(&size, _idr + idr_poff, sizeof(Size));
05546 #endif
05547 #ifdef TRACK_BUG1
05548   printf("%s::getIsLoaded() %d %p\n", name, size, size);
05549 #endif
05550   if (VARS_COND(cls->getDatabase()) && size <= VARS_SZ)
05551     return True;
05552   return IS_LOADED(size);
05553 }
05554 
05555 void AttrVarDim::setIsLoaded(Data _idr, Bool changed) const
05556 {
05557   Size size;
05558 #ifdef E_XDR_TRACE
05559   printf("%s: AttrVarDim::setIsLoaded -> XDR\n", name);
05560 #endif
05561 
05562 #ifdef E_XDR
05563   x2h_32_cpy(&size, _idr + idr_poff);
05564 #else
05565   mcp(&size, _idr + idr_poff, sizeof(Size));
05566 #endif
05567 
05568   if (VARS_COND(cls->getDatabase()) && size <= VARS_SZ)
05569     return;
05570 
05571   size = SET_IS_LOADED(size, changed);
05572 #ifdef E_XDR
05573   h2x_32_cpy(_idr + idr_poff, &size);
05574 #else
05575   mcp(_idr + idr_poff, &size, sizeof(Size));
05576 #endif
05577 }
05578 
05579 Bool AttrVarDim::getIsLoaded(const Object *agr) const
05580 {
05581   return getIsLoaded(agr->getIDR());
05582 }
05583 
05584 void AttrVarDim::setIsLoaded(const Object *agr, Bool changed) const
05585 {
05586   setIsLoaded(agr->getIDR(), changed);
05587 }
05588 
05589 void AttrVarDim::getData(const Object *agr, Data& pdata,
05590                             Data& vdata) const
05591 {
05592   getData(getDB(agr), agr->getIDR(), pdata, vdata);
05593 }
05594 
05595 void AttrVarDim::setData(const Database *db, Data _idr, Data pdata,
05596                             Data vdata) const
05597 {
05598 #ifdef TRACK_BUG1
05599   printf("%s: setting data pdata = %p vdata = %p\n", name, pdata, vdata);
05600 #endif
05601   Size size;
05602   getSize(_idr, size);
05603 
05604   //printf("%s: setting string '%s' size=%d pdata=%p\n",
05605   //name, (pdata ? (char *)pdata : "NULL"), size, pdata);
05606 
05607   // needs XDR ? guess no because vdata !
05608 #ifdef E_XDR_TRACE
05609   printf("%s: AttrVarDim::setData -> needs XDR ? no\n", name);
05610 #endif
05611   mcp(_idr + idr_voff, &pdata, sizeof(Data));
05612 
05613   if (!is_basic_enum)
05614     mcp(_idr + idr_voff + SIZEOFDATA, &vdata, sizeof(Data));
05615 }
05616 
05617 void AttrVarDim::setData(const Object *agr, Data pdata,
05618                             Data vdata) const
05619 {
05620   setData(agr->getDatabase(), agr->getIDR(), pdata, vdata);
05621 }
05622 
05623 void AttrVarDim::getInfo(const Object *agr, Data& pdata,
05624                              Data& vdata, Size& wpsize,
05625                              Size& wvsize, Oid &oid) const
05626 {
05627   Size size;
05628 
05629   getSize(agr, size);
05630   getVarDimOid(agr, &oid);
05631   //printf("getInfo(%s)\n", name);
05632   getData(agr, pdata, vdata);
05633 
05634   wpsize = size * idr_item_psize * typmod.pdims;
05635   wvsize = size * idr_item_vsize * typmod.pdims;
05636 }
05637 
05638 Status
05639 AttrVarDim::setSize_realize(Object *agr, Data _idr, Size nsize,
05640                                Bool make, Bool noGarbage) const
05641 {
05642   Database *db = getDB(agr);
05643   if (VARS_COND(db) && nsize <= VARS_SZ) {
05644     Data opdata, ovdata;
05645     getData(db, _idr, opdata, ovdata);
05646     if (opdata != VARS_DATA(_idr))
05647       free(opdata);
05648 
05649 #ifdef E_XDR_TRACE
05650     printf("%s: AttrVarDim::setSize_realize #1 -> XDR\n", name);
05651 #endif
05652 #ifdef E_XDR
05653     h2x_32_cpy(_idr + idr_poff, &nsize);
05654 #else
05655     mcp(_idr + idr_poff, &nsize, sizeof(Size));
05656 #endif
05657     return Success;
05658   }
05659 
05660   Size rsize;
05661   Data opdata, ovdata, npdata, nvdata;
05662 
05663   int wpsize;
05664   Size osize;
05665   int oinisize, rinisize, ninisize;
05666       
05667   rinisize = oinisize = ninisize = 0;
05668 
05669   Bool isLoaded = getIsLoaded(_idr);
05670 
05671   if (make) {
05672 #ifdef E_XDR_TRACE
05673     printf("%s: AttrVarDim::setSize_realize #2 -> XDR\n", name);
05674 #endif
05675 #ifdef E_XDR
05676     x2h_32_cpy(&osize, _idr + idr_poff);
05677 #else
05678     mcp(&osize, _idr + idr_poff, sizeof(Size));
05679 #endif
05680     osize = CLEAN_SIZE(osize);
05681     rsize = ((osize < nsize) ? osize : nsize);
05682   }
05683   else
05684     osize = 0;
05685 
05686   getData(db, _idr, opdata, ovdata);
05687 
05688   if (is_basic_enum) {
05689     oinisize = iniSize(osize);
05690     ninisize = iniSize(nsize);
05691     rinisize = ((oinisize < ninisize) ? oinisize : ninisize);
05692   }
05693 
05694 #ifdef E_XDR_TRACE
05695   printf("%s: AttrVarDim::setSize_realize #3 -> XDR\n", name);
05696 #endif
05697 #ifdef E_XDR
05698   h2x_32_cpy(_idr + idr_poff, &nsize);
05699 #else
05700   mcp(_idr + idr_poff, &nsize, sizeof(Size));
05701 #endif
05702   
05703   setIsLoaded(_idr, isLoaded);
05704 
05705   if (nsize == 0) {
05706     setData(db, _idr, 0, 0);
05707     if (opdata != VARS_DATA(_idr))
05708       free(opdata);
05709     if (is_basic_enum) // added this test the 3/09/01
05710       free(ovdata);
05711   }
05712   else {
05713     wpsize = idr_item_psize * nsize * typmod.pdims;
05714     npdata = (unsigned char *)malloc(wpsize + ninisize);
05715 
05716     if (make) {
05717       Size wrsize = idr_item_psize * rsize * typmod.pdims;
05718 
05719       mcp(npdata, opdata, rinisize);
05720       mset(npdata + rinisize, 0, ninisize - rinisize);
05721 
05722       // needs XDR ? no...
05723 #ifdef E_XDR_TRACE
05724       printf("%s: AttrVarDim::setSize_realize #4 -> needs XDR ? no\n", name);
05725 #endif
05726       memcpy(npdata + ninisize, opdata + oinisize, wrsize);
05727       memset(npdata + ninisize + wrsize, 0, wpsize - wrsize);
05728     }
05729     else
05730       memset(npdata, 0, wpsize + ninisize);
05731   
05732     if (opdata != VARS_DATA(_idr))
05733       free(opdata);
05734     
05735     if (idr_item_vsize) {
05736       int wvsize = idr_item_vsize * nsize * typmod.pdims;
05737       nvdata = (unsigned char *)malloc(wvsize);
05738       
05739       if (make) {
05740         // needs XDR ? no...
05741 #ifdef E_XDR_TRACE
05742         printf("%s: AttrVarDim::setSize_realize #5 -> needs XDR ? no\n", name);
05743 #endif
05744         Size wrsize = idr_item_vsize * rsize * typmod.pdims;
05745         memcpy(nvdata, ovdata, wrsize);
05746         memset(nvdata + wrsize, 0, wvsize - wrsize);
05747       }
05748       else
05749         memset(nvdata, 0, wvsize);
05750       
05751       if (is_basic_enum) // added this test the 3/09/01
05752         free(ovdata);
05753     }
05754     else
05755       nvdata = 0;
05756     
05757     setData(db, _idr, npdata, nvdata);
05758   }
05759   
05760   if (is_basic_enum)
05761     return Success;
05762 
05763   GBX_SUSPEND();
05764 
05765   if (!noGarbage)
05766     for (int j = nsize; j < osize; j++) {
05767       Object *oo;
05768       // no XDR
05769       memcpy(&oo, ovdata + (j * idr_item_vsize), sizeof(Object *));
05770       
05771       if (oo)
05772         oo->release();
05773     }
05774 
05775   free(ovdata);
05776 
05777   for (int j = osize; j < nsize; j++) // 20/09/01: was for (int j = 0; 
05778     {
05779       Object *oo;
05780       // no XDR
05781       memcpy(&oo, nvdata + (j * idr_item_vsize), sizeof(Object *));
05782 
05783       if (!oo) {
05784         oo = (Object *)cls->newObj(npdata + (j * idr_item_psize));
05785         oo->setMustRelease(false); // SMART_PTR
05786         // no XDR
05787         memcpy(nvdata + (j * idr_item_vsize), &oo, sizeof(Object *));
05788       }
05789 
05790       // added the 5/11/99
05791       Status s = oo->setMasterObject(agr);
05792       if (s)
05793         return s;
05794     }
05795 
05796   return Success;
05797 }
05798 
05799 #define AUTOLOAD(DB, AGR) \
05800 do { \
05801   if ((DB) && !getIsLoaded(AGR)) \
05802     { \
05803       Status status = load(DB, AGR, (AGR)->getClass()->getOid(), DefaultLock, \
05804                               null_idx_ctx, NoRecurs, True); \
05805       if (status) return status; \
05806    }\
05807 } while(0)
05808 
05809 Status AttrVarDim::setSize(Object *agr, Size nsize) const
05810 {
05811   Size osize;
05812   Status status;
05813 
05814   getSize(agr, osize);
05815 
05816   if (nsize == osize)
05817     return Success;
05818 
05819   AUTOLOAD(agr->getDatabase(), agr);
05820 
05821   status = setSize_realize(agr, agr->getIDR(), nsize, True);
05822 
05823   if (!status) {
05824     agr->touch();
05825     setSizeChanged(agr, True);
05826   }
05827 
05828   return status;
05829 }
05830 
05831 Status AttrVarDim::setValue(Object *agr, Data data, int nb, int from, Bool check_class) const
05832 {
05833   CHECK_OBJ(agr);
05834   CHECK_RTTYPE(agr);
05835   Size size;
05836   check_var_range(agr, from, nb, &size);
05837 
05838   if (from != 0 || nb != size)
05839     AUTOLOAD(agr->getDatabase(), agr);
05840 
05841   setIsLoaded(agr, True);
05842 
05843   Data pdata, vdata, inidata;
05844 
05845   //printf("setValue(%s)\n", name);
05846   getData(agr, pdata, vdata);
05847 
05848   if (is_basic_enum)
05849     iniCompute(agr->getDatabase(), size, pdata, inidata);
05850   else
05851     inidata = 0;
05852 
05853   Status s = Attribute::setValue(agr, pdata, data, idr_item_psize, 0, nb, from,
05854                                        inidata, False, vdata, True);
05855   //printf("%s: setValue -> %s pdata=%p, inidata=%p\n",
05856   //name, data, pdata, inidata);
05857   /*
05858   if (VARS_COND(agr->getDatabase()))
05859     {
05860       Data zdata = 0;
05861       getValue(agr, &zdata, directAccess, 0, 0);
05862       printf("----> getvalue returns %s\n", zdata);
05863     }
05864     */
05865 
05866   return s;
05867 }
05868 
05869 Status AttrVarDim::getValue(const Object *agr, Data *data, int nb, int from, Bool *isnull) const
05870 {
05871   CHECK_OBJ(agr);
05872   CHECK_RTTYPE(agr);
05873 
05874   Size sz;
05875   check_var_range(agr, from, nb, &sz);
05876 
05877   AUTOLOAD((Database *)agr->getDatabase(), (Object *)agr);
05878 
05879   Data pdata, vdata, xdata, inidata;
05880   //printf("getValue(%s)\n", name);
05881   getData(agr, pdata, vdata);
05882 
05883   Size size;
05884 
05885   if (is_basic_enum) {
05886     xdata = pdata;
05887     size = idr_item_psize;
05888     iniCompute(agr->getDatabase(), sz, xdata, inidata);
05889   }
05890   else {
05891     xdata = vdata;
05892     size = SIZEOFOBJECT;
05893     inidata = 0;
05894   }
05895 
05896   return Attribute::getValue((Database *)agr->getDatabase(), xdata,
05897                                 data, size, nb, from, inidata, isnull);
05898 }
05899 
05900 Status
05901 AttrVarDim::getTValue(Database *db, const Oid &objoid,
05902                          Data *data, int nb, int from,
05903                          Bool *isnull, Size *rnb, Offset poffset) const
05904 {
05905   if (!is_basic_enum)
05906     return Exception::make(IDB_ERROR, tvalue_fmt,
05907                               getClassOwner()->getName(), name);
05908 
05909   if (cls->asEnumClass())
05910     return Exception::make(IDB_ERROR,
05911                               "variable dimension array for enums is "
05912                               "not yet implemented for getTValue()");
05913 
05914   Status status = tvalue_prologue(db, objoid);
05915   if (status) return status;
05916 
05917   unsigned char infodata[sizeof(Size)+sizeof(Oid)];
05918   if (status = StatusMake
05919       (dataRead(db->getDbHandle(),
05920                     poffset + idr_poff,
05921                     sizeof(Size)+sizeof(Oid), infodata,
05922                     0, objoid.getOid()))) {
05923     CHECK_OID(objoid);
05924     return status;
05925   }
05926 
05927   Size size;
05928 #ifdef E_XDR_TRACE
05929   printf("%s: AttrVarDim::getTValue #1 -> XDR\n", name);
05930 #endif
05931 
05932 #ifdef E_XDR
05933   x2h_32_cpy(&size, infodata);
05934 #else
05935   mcp(&size, infodata, sizeof(Size));
05936 #endif
05937   size = CLEAN_SIZE(size);
05938 
05939   if (status = checkVarRange(from, nb, size))
05940     return status;
05941 
05942   if (rnb)
05943     *rnb = size;
05944 
05945   Oid data_oid;
05946   Size inisize;
05947   Offset offset;
05948   if (VARS_COND(db) && size <= VARS_SZ) {
05949     data_oid = objoid;
05950     offset = poffset + idr_poff + VARS_OFFSET;
05951   }
05952   else {
05953 #ifdef E_XDR_TRACE
05954     printf("%s: AttrVarDim::getTValue #2 -> XDR", name);
05955 #endif
05956 #ifdef E_XDR
05957     eyedbsm::x2h_oid(data_oid.getOid(), infodata+sizeof(Size));
05958 #else
05959     mcp(&data_oid, infodata+sizeof(Size), sizeof(Oid));
05960 #endif
05961     if (!data_oid.isValid()) {
05962       if (isnull)
05963         *isnull = True;
05964       return Success;
05965     }
05966     offset = 0;
05967   }
05968   
05969   inisize = iniSize(size);
05970   Bool toAlloc;
05971   Data pdata;
05972 
05973   if (nb == wholeData) {
05974     pdata = 0;
05975     toAlloc = True;
05976     nb = size;
05977   }
05978   else {
05979     pdata = (Data)data;
05980     toAlloc = False;
05981   }
05982 
05983   // added the 15/05/00
05984   if (!nb && !from) {
05985     if (toAlloc)
05986       *data = pdata = (unsigned char *)malloc(1);
05987     *pdata = 0;
05988     
05989     if (isnull)
05990       *isnull = True;
05991     return Success;
05992   }
05993   // ...
05994 
05995   if (!inisize || !isnull) {
05996     if (toAlloc)
05997       *data = pdata = (unsigned char *)malloc(nb * idr_item_psize);
05998     if (status = StatusMake
05999         (dataRead(db->getDbHandle(),
06000                       inisize + (from * idr_item_psize) + offset,
06001                       nb * idr_item_psize, pdata, 0, data_oid.getOid()))) {
06002       if (toAlloc)
06003         free(*data);
06004       CHECK_OID(objoid);
06005       return status;
06006     }
06007 
06008     return Success;
06009   }
06010 
06011   // 17/09/04: this seems to be thought as an optimisation !?
06012   // I think, this is not needed !
06013 #ifdef E_XDR
06014   if (0) {
06015 #else
06016   if (!from) {
06017 #endif
06018     unsigned char *xdata = (unsigned char *)malloc(nb * idr_item_psize +
06019                                                    inisize);
06020     if (status = StatusMake
06021         (dataRead(db->getDbHandle(),
06022                       offset,
06023                       inisize + nb * idr_item_psize, xdata,
06024                       0, data_oid.getOid()))) {
06025       free(xdata);
06026       CHECK_OID(objoid);
06027       return status;
06028     }
06029 
06030     *isnull = isNull(xdata, nb, from);
06031     if (toAlloc)
06032       *data = pdata = (unsigned char *)malloc(nb * idr_item_psize);
06033 #ifdef E_XDR_TRACE
06034     printf("%s: AttrVarDim::getTValue -> XDR [nb=%d]\n", name, nb);
06035 #endif
06036 #ifdef E_XDR
06037     cls->decode(pdata, xdata+inisize, idr_item_psize, nb);
06038 #else
06039     memcpy(pdata, xdata+inisize, nb * idr_item_psize);
06040 #endif
06041     
06042     free(xdata);
06043     return Success;
06044   }
06045 
06046   unsigned char *inidata = (unsigned char *)malloc(inisize);
06047   if (status = StatusMake
06048       (dataRead(db->getDbHandle(),
06049                     offset,
06050                     inisize, inidata, 0, data_oid.getOid()))) {
06051     free(inidata);
06052     CHECK_OID(objoid);
06053     return status;
06054   }
06055   
06056   *isnull = isNull(inidata, nb, from);
06057   if (toAlloc)
06058     *data = pdata = new unsigned char[nb * idr_item_psize];
06059 #ifdef E_XDR
06060   unsigned char *xdata = (unsigned char *)malloc(nb * idr_item_psize);
06061 #endif
06062 
06063   if (status = StatusMake
06064       (dataRead(db->getDbHandle(),
06065                     inisize + (from * idr_item_psize) + offset,
06066                     nb * idr_item_psize,
06067 #ifdef E_XDR
06068                     xdata,
06069 #else
06070                     pdata,
06071 #endif
06072                     0, data_oid.getOid()))) {
06073     if (toAlloc)
06074       free(*data);
06075 #ifdef E_XDR
06076     free(xdata);
06077 #endif
06078     CHECK_OID(objoid);
06079     return status;
06080   }
06081 
06082 #ifdef E_XDR
06083 #ifdef E_XDR_TRACE
06084   printf("%s: AttrVarDim::getTValue -> XDR [nb=%d]\n", name, nb);
06085 #endif
06086   cls->decode(pdata, xdata, idr_item_psize, nb);
06087   free(xdata);
06088 #endif
06089   return Success;
06090 }
06091 
06092 #ifdef GBX_NEW_CYCLE
06093 void AttrVarDim::decrRefCountPropag(Object *agr, int) const
06094 {
06095   if (!is_basic_enum) {
06096     Data pdata, vdata;
06097     Size size;
06098 
06099     getData(agr, pdata, vdata);
06100 
06101     if (vdata) {
06102       getSize(agr, size);
06103       Attribute::decrRefCountPropag(vdata, size);
06104     }
06105   }
06106 }
06107 #endif
06108 
06109 void AttrVarDim::garbage(Object *agr, int refcnt) const
06110 {
06111   if (!is_basic_enum)
06112     {
06113       Data pdata, vdata;
06114       Size size;
06115 
06116       getData(agr, pdata, vdata);
06117 
06118       if (vdata)
06119         {
06120           getSize(agr, size);
06121           Attribute::garbage(vdata, size);
06122         }
06123     }
06124 
06125   if (refcnt <= 1) // was refcnt == 1 12/10/00
06126     {
06127       // changed the 16/05/00
06128 #if 1
06129       //setSize_realize(agr, agr->getIDR(), 0, False);
06130       // changed the 12/10/00
06131       setSize_realize(agr, agr->getIDR(), 0, True, True); // added last argument the 3/09/01
06132 #else
06133       setIsLoaded(agr, True);
06134       setSize(agr, 0);
06135 #endif
06136     }
06137 }
06138 
06139 void AttrVarDim::manageCycle(Database *db, Object *o, gbxCycleContext &r) const
06140 {
06141   if (is_basic_enum)
06142     return;
06143 
06144   Data pdata, vdata;
06145   Size size;
06146 
06147   //printf("ManageCycle(%s)\n", name);
06148   getData(o, pdata, vdata);
06149 
06150   if (vdata)
06151     {
06152       getSize(o, size);
06153       Attribute::manageCycle(o, vdata, size, r);
06154     }
06155 }
06156 
06157 void
06158 AttrVarDim::newObjRealize(Object *o) const
06159 {
06160   if (is_basic_enum)
06161     {
06162       Data _idr = o->getIDR();
06163       Size size;
06164       getSize(_idr, size);
06165 
06166       //      printf("%s: newObjRealize(size=%d)\n", name, size);
06167       // QUESTION:
06168       // pourquoi faire un setSize_realize() dans la base is_basic_enum
06169       // et pas dans l'autre cas?
06170       // (voir aussi ref ##1):
06171 
06172       // 13/2/2: ATTENTION ce test a disparu avec le nouveau système
06173       // d'index: mais est-il toujours utile du fait que ce qui est
06174       // signalé plus bas ("Special case: data is NULL and ...") 
06175       // semblent impliquer les varstring NULL uniquement: ce qui
06176       // n'est plus un problème puisque les varstring NULL ont
06177       // de toute façon une longueur <= VARS_SZ et donc il n'est
06178       // pas nécessaire de créer une VDATA
06179 
06180       if (VARS_COND(o->getDatabase()) && size <= VARS_SZ)
06181         return;
06182       else if (size)
06183         {
06184           Data pdata, vdata;
06185           getData(o->getDatabase(), _idr, pdata, vdata);
06186           if (!pdata) // not that this test is new!
06187             setSize_realize(o, _idr, size, False);
06188         }
06189     }
06190 
06191   setIsLoaded(o, True);
06192 }
06193 
06194 Status AttrVarDim::copy(Object *agr, Bool share) const
06195 {
06196   Data _idr = agr->getIDR();
06197   Size size;
06198   getSize(_idr, size);
06199 
06200   if (size)
06201     {
06202       AUTOLOAD(agr->getDatabase(), agr);
06203       Data pdata, vdata;
06204       //printf("copy(%s)\n", name);
06205       getData(getDB(agr), _idr, pdata, vdata);
06206 
06207       if (!share)
06208         {
06209           Data npdata, nvdata;
06210           int wpsize = size * idr_item_psize * typmod.pdims +
06211             (is_basic_enum ? iniSize(size) : 0);
06212 
06213           // needs XDR ?
06214 #ifdef E_XDR_TRACE
06215           printf("%s: AttrVarDim::copy -> needs XDR ? no\n", name);
06216 #endif
06217 
06218           // added this test 12/10/00 because of memory leaks
06219           if (pdata == VARS_DATA(_idr))
06220             npdata = pdata;
06221           else
06222             {
06223               npdata = (unsigned char *)malloc(wpsize);
06224               // needs XDR ? no
06225               memcpy(npdata, pdata, wpsize);
06226             }     
06227 
06228           if (vdata)
06229             {
06230               int wvsize = size * idr_item_vsize * typmod.pdims;
06231               nvdata = (unsigned char *)malloc(wvsize);
06232               // needs XDR ? no
06233               memcpy(nvdata, vdata, wvsize);
06234               Status s = Attribute::incrRefCount(agr, nvdata, size);
06235               if (s)
06236                 return s;
06237             }
06238           else
06239             nvdata = 0;
06240 
06241           setData(agr->getDatabase(), _idr, npdata, nvdata);
06242         }
06243       else if (vdata) {
06244         Status s = Attribute::incrRefCount(agr, vdata, size);
06245         if (s)
06246           return s;
06247       }
06248     }
06249 
06250   return Success;
06251 }
06252 
06253 Status AttrVD::update_realize(Database *db, Object *agr,
06254                               const Oid& cloid,
06255                               const Oid& objoid,
06256                               int count, Size wpsize, Data pdata,
06257                               Oid &oid,
06258                               AttrIdxContext &idx_ctx) const
06259 {
06260   // added the 23/01/00
06261   // before this patch, notnull constraints on vardim with no index did
06262   // not work at all
06263   Bool notnull, notnull_comp, unique, unique_comp;
06264   Status s = constraintPrologue(db, idx_ctx, notnull_comp, notnull,
06265                                    unique_comp, unique);
06266   if (!wpsize && (notnull || notnull_comp))
06267     return Exception::make
06268       ((notnull ? IDB_NOTNULL_CONSTRAINT_ERROR :
06269         IDB_NOTNULL_COMP_CONSTRAINT_ERROR),
06270        const_error, idx_ctx.getAttrName().c_str());
06271 
06272   //printf("wpsize(%s) = %d\n", name, wpsize);
06273   if (oid.isValid() || wpsize)
06274     {
06275       RPCStatus rpc_status;
06276       const eyedbsm::Oid *cl_oid = agr->getClass()->getOid().getOid();
06277       const eyedbsm::Oid *actual_cl_oid = cloid.getOid();
06278       const eyedbsm::Oid *agr_oid = objoid.getOid();
06279 
06280       //      if (isSizeChanged(agr))
06281       // changed the 17/05/99 because of a bug found!
06282       if (isSizeChanged(agr) || !oid.isValid())
06283         {
06284           Size idx_size;
06285           Data idx_data = idx_ctx.code(idx_size);
06286           if (oid.isValid())
06287             {
06288               rpc_status = VDdataDelete(db->getDbHandle(), actual_cl_oid,
06289                                             cl_oid, num,
06290                                             agr_oid, oid.getOid(),
06291                                             idx_data, idx_size);
06292 
06293               if (rpc_status)
06294                 {
06295                   free(idx_data);
06296                   return StatusMake(rpc_status);
06297                 }
06298 
06299               agr->setDirty(True);
06300               setVarDimOid(agr, &Oid::nullOid);
06301             }
06302 
06303           if (wpsize && !(VARS_COND(db) && wpsize <= VARS_TSZ))
06304             {
06305               if ((rpc_status = VDdataCreate(db->getDbHandle(),
06306                                                  dspid,
06307                                                  actual_cl_oid,
06308                                                  cl_oid, num, count,
06309                                                  wpsize, pdata,
06310                                                  agr_oid, oid.getOid(),
06311                                                  idx_data, idx_size)) ==
06312                   RPCSuccess)
06313                 {
06314                   setVarDimOid(agr, &oid);
06315                   agr->setDirty(True);
06316                 }
06317               
06318               if (rpc_status)
06319                 {
06320                   setVarDimOid(agr, &Oid::nullOid);
06321                   free(idx_data);
06322                   return StatusMake(rpc_status);
06323                 }
06324             }
06325           else if (!VARS_COND(db))
06326             setVarDimOid(agr, &Oid::nullOid);
06327 
06328           setSizeChanged(agr, False);
06329           free(idx_data);
06330           return Success;
06331         }
06332       else if (agr->isModify() && !(VARS_COND(db) && wpsize <= VARS_TSZ))
06333         {
06334           Size idx_size;
06335           Data idx_data = idx_ctx.code(idx_size);
06336           rpc_status = VDdataWrite(db->getDbHandle(),
06337                                        actual_cl_oid,
06338                                        cl_oid, num, count,
06339                                        wpsize, pdata, agr_oid, oid.getOid(),
06340                                        idx_data, idx_size);
06341           
06342           free(idx_data);
06343 
06344           if (rpc_status)
06345             return StatusMake(rpc_status);
06346 
06347           agr->setDirty(True);
06348           return Success;
06349         }
06350     }
06351 
06352   agr->setDirty(True);
06353   return Success;
06354 }
06355 
06356 Status AttrVD::remove_realize(Database *db,
06357                                     const Oid& actual_cl_oid,
06358                                     const Oid& objoid,
06359                                     Object *agr,
06360                                     AttrIdxContext &idx_ctx) const
06361 {
06362   Oid oid;
06363 
06364   getVarDimOid(agr, &oid);
06365 
06366   if (oid.isValid())
06367     {
06368       RPCStatus rpc_status;
06369       const eyedbsm::Oid *cl_oid = agr->getClass()->getOid().getOid();
06370       const eyedbsm::Oid *agr_oid = objoid.getOid();
06371       Size idx_size;
06372       Data idx_data = idx_ctx.code(idx_size);
06373 
06374       rpc_status = VDdataDelete(db->getDbHandle(),
06375                                     actual_cl_oid.getOid(), cl_oid, num,
06376                                     agr_oid, oid.getOid(),
06377                                     idx_data, idx_size);
06378       if (!rpc_status)
06379         agr->setDirty(True);
06380 
06381       return StatusMake(rpc_status);
06382     }
06383 
06384   return Success;
06385 }
06386 
06387 Status AttrVarDim::update(Database *db,
06388                                 const Oid& cloid,
06389                                 const Oid& objoid,
06390                                 Object *agr,
06391                                 AttrIdxContext &idx_ctx) const
06392 {
06393   if (!getIsLoaded(agr))
06394     return Success;
06395 
06396   Size wpsize, wvsize, size;
06397   Data pdata, vdata;
06398   Oid oid;
06399 
06400   getInfo(agr, pdata, vdata, wpsize, wvsize, oid);
06401   getSize(agr, size);
06402 
06403   if (is_basic_enum)
06404     wpsize += iniSize(size);
06405 
06406   Status s = update_realize(db, agr, cloid, objoid, size, wpsize, pdata, oid,
06407                                idx_ctx);
06408   getInfo(agr, pdata, vdata, wpsize, wvsize, oid);
06409   return s;
06410 }
06411 
06412 Status AttrVarDim::realize(Database *db, Object *agr,
06413                                  const Oid& cloid,
06414                                  const Oid& objoid,
06415                                  AttrIdxContext &idx_ctx,
06416                                  const RecMode *rcm) const
06417 {
06418   if (!getIsLoaded(agr))
06419     return Success;
06420 
06421   idx_ctx.push(db, cloid, this);
06422 
06423   Status status;
06424   //printf("realize(%s)\n", name);
06425   if (is_basic_enum) {
06426     status = update(db, cloid, objoid, agr, idx_ctx);
06427     idx_ctx.pop();
06428     return status;
06429   }
06430 
06431   Size size;
06432   Data pdata, vdata;
06433   int dd;
06434 
06435   getSize(agr, size);
06436   getData(agr, pdata, vdata);
06437   Oid vd_oid;
06438   getVarDimOid(agr, &vd_oid);
06439 
06440   dd = typmod.pdims * size;
06441 
06442   //#define TRACE_OFF
06443 
06444 #ifdef TRACE_OFF
06445   Offset OFFSET;
06446   eyedbsm::Oid xoid, hoid;
06447 #endif
06448 
06449   for (int j = 0; j < dd; j++) {
06450     Object *o;
06451 
06452     mcp(&o, vdata + (j * SIZEOFOBJECT),  sizeof(Object *));
06453 
06454     if (o) {
06455       status = o->setDatabase(db);
06456       if (status != Success)
06457         return status;
06458 
06459       //idx_ctx.pushOff(idr_poff +  (j * idr_item_psize), vd_oid);
06460 #ifdef TRACE_OFF
06461       getVarDimOid(agr, &vd_oid);
06462       printf("#1 %s vd_oid %s\n", name, vd_oid.toString());
06463 #endif
06464 
06465       idx_ctx.pushOff(j * idr_item_psize, vd_oid);
06466 
06467 #ifdef TRACE_OFF
06468       memcpy(&xoid, pdata +  + (j * idr_item_psize), sizeof(xoid));
06469       eyedbsm::x2h_oid(&hoid, &xoid);
06470       printf("#1 %s pdata %s at %d\n", name, Oid(hoid).toString(),  + (j * idr_item_psize));
06471 #endif
06472 
06473       /*
06474       printf("%s: vd_oid: %s %s %d\n", name, vd_oid.toString(),
06475              o->getClass()->getName(), IDB_OBJ_HEAD_SIZE);
06476       */
06477       status = o->realizePerform(cloid, objoid, idx_ctx, rcm);
06478           
06479       if (status)
06480         return status;
06481 
06482 #ifdef TRACE_OFF
06483       getVarDimOid(agr, &vd_oid);
06484       printf("#2 %s vd_oid %s\n", name, vd_oid.toString());
06485 
06486       memcpy(&xoid, pdata +  + (j * idr_item_psize), sizeof(xoid));
06487       eyedbsm::x2h_oid(&hoid, &xoid);
06488       printf("#2 %s pdata %s at %d\n", name, Oid(hoid).toString(),  + (j * idr_item_psize));
06489 #endif
06490 
06491       // needs XDR ? no
06492 #ifdef E_XDR_TRACE
06493       printf("%s: AttrVarDim::realize\n", name);
06494 #endif
06495       if (memcmp(pdata +  (j * idr_item_psize),
06496                  o->getIDR() + IDB_OBJ_HEAD_SIZE, idr_item_psize)) {
06497         memcpy(pdata +  (j * idr_item_psize),
06498                o->getIDR() + IDB_OBJ_HEAD_SIZE, idr_item_psize);
06499         
06500         // added 27/05/06
06501         agr->touch();
06502 
06503         Bool mustTouch;
06504         status = o->postRealizePerform(cloid, objoid,
06505                                        idx_ctx, mustTouch, rcm);
06506         if (status)
06507           return status;
06508         
06509         if (mustTouch)
06510           agr->touch();
06511       }
06512       
06513 #ifdef TRACE_OFF
06514       OFFSET = idx_ctx.getOff();
06515 #endif
06516 
06517       idx_ctx.popOff();
06518     }
06519   }
06520 
06521   status = update(db, cloid, objoid, agr, idx_ctx);
06522 
06523 #ifdef TRACE_OFF
06524   getVarDimOid(agr, &vd_oid);
06525   printf("#3 %s vd_oid %s\n", name, vd_oid.toString());
06526   if (pdata) {
06527     memcpy(&xoid, pdata, sizeof(xoid));
06528     eyedbsm::x2h_oid(&hoid, &xoid);
06529     printf("#3 %s pdata %s at %d\n", name, Oid(hoid).toString(), 0);
06530   }
06531   dataRead(db->getDbHandle(), OFFSET,
06532            sizeof(eyedbsm::Oid),
06533            (Data)&xoid, 0,
06534            vd_oid.getOid());
06535   eyedbsm::x2h_oid(&hoid, &xoid);
06536   printf("#3 %s DB pdata %s\n", name, Oid(hoid).toString());
06537   printf("\n");
06538 #endif
06539 
06540   idx_ctx.pop();
06541   return status;
06542 }
06543 
06544 Status AttrVarDim::remove(Database *db, Object *agr,
06545                                 const Oid& cloid,
06546                                 const Oid& objoid,
06547                                 AttrIdxContext &idx_ctx,
06548                                 const RecMode *rcm) const
06549 {
06550   Status status;
06551 
06552   idx_ctx.push(db, cloid, this);
06553 
06554   if (is_basic_enum)
06555     {
06556       status = remove_realize(db, cloid, objoid, agr, idx_ctx);
06557       idx_ctx.pop();
06558       return status;
06559     }
06560 
06561   AUTOLOAD(db, agr);
06562 
06563   Size size;
06564   Data pdata, vdata;
06565   int dd;
06566 
06567   getSize(agr, size);
06568   getData(agr, pdata, vdata);
06569 
06570   dd = typmod.pdims * size;
06571 
06572   for (int j = 0; j < dd; j++)
06573     {
06574       Object *o;
06575 
06576       // no XDR
06577       memcpy(&o, vdata + (j * SIZEOFOBJECT),  sizeof(Object *));
06578 
06579       if (o)
06580         {
06581           status = o->setDatabase(db);
06582           if (status != Success)
06583             return status;
06584 
06585           status = o->removePerform(cloid, objoid, idx_ctx, rcm);
06586 
06587           if (status != Success)
06588             return status;
06589 
06590           // needs XDR ?
06591           memcpy(pdata +  (j * idr_item_psize),
06592                  o->getIDR() + IDB_OBJ_HEAD_SIZE, idr_item_psize);
06593         }
06594     }
06595 
06596   status = remove_realize(db, cloid, objoid, agr, idx_ctx);
06597   idx_ctx.pop();
06598   return status;
06599 }
06600 
06601 Status
06602 AttrVarDim::load(Database *db,
06603                     Object *agr,
06604                     const Oid &cloid,
06605                     LockMode lockmode,
06606                     AttrIdxContext &idx_ctx,
06607                     const RecMode *rcm, Bool force) const
06608 {
06609   /*
06610   Size size;
06611   getSize(agr, size);
06612   */
06613 
06614   //printf("AttrVarDim::load(%s)\n", name);
06615   if (!force)
06616     {
06617       setIsLoaded(agr, False); // MIND: added on the 15/09/98
06618       // ref ##1: je pense que les 2 ligne suivantes ne sont pas
06619       // necessaire, dans la mesure ou on a fait un 
06620       // setSize_realize dans newObjRealize.
06621       // Attention cependant, ce setSize_realize n'a ete fait
06622       // que pour les is_basic_enum, je crois!
06623 
06624       /* disconnected the 16/5/00 */
06625       /*
06626       setSize_realize(agr, agr->getIDR(), size, False);
06627       setSizeChanged(agr, False);
06628       */
06629       // added the 3/2/00
06630       if (rcm->getType() == RecMode_NoRecurs)
06631         return Success;
06632     }
06633 
06634   Size size;
06635   getSize(agr, size);
06636 
06637   setIsLoaded(agr, True);
06638 
06639   Size wpsize, wvsize;
06640   Data pdata, vdata;
06641   Oid oid;
06642 
06643   getInfo(agr, pdata, vdata, wpsize, wvsize, oid);
06644 
06645   if (!oid.isValid())
06646     return Success;
06647 
06648   if (is_basic_enum)
06649     wpsize += iniSize(size);
06650 
06651   if (wpsize)
06652     {
06653       // added the 24/05/00
06654       if (!pdata)
06655         {
06656           setSize_realize(agr, agr->getIDR(), size, False);
06657           setSizeChanged(agr, False);
06658           getData(db, agr->getIDR(), pdata, vdata);
06659         }
06660 
06661       RPCStatus rpc_status;
06662 
06663       rpc_status = dataRead(db->getDbHandle(), 0, wpsize, pdata,
06664                                 0, oid.getOid());
06665 
06666       if (rpc_status != RPCSuccess)
06667         return StatusMake(rpc_status);
06668     }
06669 
06670   if (is_basic_enum)
06671     return Success;
06672 
06673   int dd;
06674 
06675   dd = typmod.pdims * size;
06676 
06677   idx_ctx.push(db, cloid, this);
06678 #ifdef E_XDR_TRACE
06679   printf("%s: AttrVarDim::load -> needs XDR ? no\n", name);
06680 #endif
06681   for (int j = 0; j < dd; j++)
06682     {
06683       Status status;
06684       Object *o;
06685 
06686       // no XDR
06687       memcpy(&o, vdata + (j * SIZEOFOBJECT), sizeof(Object *));
06688 
06689       // needs XDR ? no
06690       memcpy(o->getIDR() + IDB_OBJ_HEAD_SIZE,
06691              pdata +  (j * idr_item_psize), idr_item_psize);
06692 
06693       status = o->setDatabase(db);
06694 
06695       if (status != Success)
06696         return status;
06697 
06698       status = o->loadPerform(cloid, lockmode, idx_ctx, rcm);
06699 
06700       if (status != Success)
06701         return status;
06702 
06703       memcpy(pdata +  (j * idr_item_psize),
06704              o->getIDR() + IDB_OBJ_HEAD_SIZE, idr_item_psize);
06705     }
06706 
06707   idx_ctx.pop();
06708   return Success;
06709 }
06710 
06711 Status
06712 AttrVarDim::convert(Database *db, ClassConversion *conv,
06713                        Data in_idr, Size in_size) const
06714 {
06715   if (conv->getUpdtype() == ADD_ATTR)
06716     return add(db, conv, in_idr, in_size);
06717 
06718   return Exception::make(IDB_ERROR, "attribute %s::%s conversion error",
06719                             class_owner->getName(), name);
06720 }
06721 
06722 Status AttrVarDim::trace(const Object *agr, FILE *fd, int *indent, unsigned int flags, const RecMode *rcm) const
06723 {
06724   IDB_CHECK_INTR();
06725 
06726   char *indent_str = make_indent(*indent);
06727   TypeModifier tmod = typmod;
06728   Size size;
06729   Data pdata, vdata;
06730   char prefix[64];
06731   Status status = Success;
06732 
06733   AUTOLOAD((Database *)agr->getDatabase(), (Object *)agr);
06734 
06735   get_prefix(agr, class_owner, prefix, sizeof(prefix));
06736 
06737   getSize(agr, size);
06738   getData(agr, pdata, vdata);
06739 #ifdef TRACK_BUG1
06740   printf("%s::trace(): %s pdata = %p size = %d\n", name,
06741          agr->getOid().toString(), pdata, size);
06742 #endif
06743 
06744   tmod.pdims *= size;
06745 
06746   if (is_basic_enum)
06747     {
06748       Data inidata = pdata;
06749       pdata += iniSize(size);
06750       fprintf(fd, "%s%s%s = ", indent_str, prefix, name);
06751 
06752       //int len = strlen(indent_str) + strlen(prefix) + strlen(name) + 3;
06753       int len = *indent + INDENT_INC;
06754       if (cls->asBasicClass())
06755         {
06756           if (isNull(inidata, &tmod))
06757             PRINT_NULL(fd);
06758           else
06759             status = ((BasicClass *)cls)->traceData(fd, len, inidata, pdata, &tmod);
06760         }
06761       else
06762         {
06763           if (isNull(inidata, &tmod))
06764             PRINT_NULL(fd);
06765           else
06766             status = ((EnumClass *)cls)->traceData(fd, len, inidata, pdata, &tmod);
06767         }
06768       fprintf(fd, ";\n");
06769     }
06770   else
06771     for (int j = 0; j < tmod.pdims; j++)
06772       {
06773         Object *o;
06774 
06775 #ifdef TRACK_BUG1
06776         printf("%s::trace() -> #%d\n", name, j);
06777 #endif
06778         // no XDR
06779         memcpy(&o, vdata + (j * SIZEOFOBJECT), sizeof(Object *));
06780 
06781         if (!tmod.ndims)
06782           fprintf(fd, "%s%s%s %s = ", indent_str, prefix, name,
06783                   cls->getName());
06784         else
06785           fprintf(fd, "%s%s%s[%d] %s = ", indent_str, prefix, name, j,
06786                   cls->getName());
06787         status = ObjectPeer::trace_realize(o, fd, *indent + INDENT_INC, flags, rcm);
06788         if (status) break;
06789       }
06790 
06791   delete_indent(indent_str);
06792   return status;
06793 }
06794 
06795 //
06796 // AttrIndirectVarDim methods
06797 //
06798 
06799 AttrIndirectVarDim::AttrIndirectVarDim(const Attribute *agreg,
06800                                              const Class *_cls,
06801                                              const Class *_class_owner,
06802                                              const Class *_dyn_class_owner,
06803                                              int n) :
06804   AttrVD(agreg, _cls, _class_owner, _dyn_class_owner, n)
06805 {
06806   code = AttrIndirectVarDim_Code;
06807   idr_inisize = 0;
06808 }
06809 
06810 AttrIndirectVarDim::AttrIndirectVarDim(Database *db,
06811                                              Data data, Offset *offset,
06812                                              const Class *_dyn_class_owner,
06813                                              int n) :
06814   AttrVD(db, data, offset, _dyn_class_owner, n)
06815 {
06816   code = AttrIndirectVarDim_Code;
06817   idr_inisize = 0;
06818 }
06819 
06820 Status AttrIndirectVarDim::check() const
06821 {
06822   Status s = Attribute::check();
06823   if (s) return s;
06824   const TypeModifier *tmod = &typmod;
06825 
06826   for (int i = 0; i < tmod->ndims; i++)
06827     if (tmod->dims[i] < 0 && i != 0)
06828       return Exception::make(IDB_ATTRIBUTE_ERROR, "only left dimension is allowed to be variable in attribute '%s' in agregat class '%s'",
06829                                 name, class_owner->getName());
06830 
06831   return Success;
06832 }
06833 
06834 Status AttrIndirectVarDim::setSize(Object *agr, Size nsize) const
06835 {
06836   Size osize;
06837 
06838 #ifdef E_XDR_TRACE
06839   printf("%s: AttrIndirectVarDim::setSize #1 -> XDR\n", name);
06840 #endif
06841 
06842 #ifdef E_XDR
06843   x2h_32_cpy(&osize, agr->getIDR() + idr_poff);
06844 #else
06845   mcp(&osize, agr->getIDR() + idr_poff, sizeof(Size));
06846 #endif
06847   osize = CLEAN_SIZE(osize);
06848 
06849   if (osize == nsize)
06850     return Success;
06851 
06852   Size rsize = ((osize < nsize) ? osize : nsize);
06853 
06854 #ifdef E_XDR_TRACE
06855   printf("%s: AttrIndirectVarDim::setSize #2 -> XDR\n", name);
06856 #endif
06857 
06858 #ifdef E_XDR
06859   h2x_32_cpy(agr->getIDR() + idr_poff, &nsize);
06860 #else
06861   mcp(agr->getIDR() + idr_poff, &nsize, sizeof(Size));
06862 #endif
06863 
06864   Data odata, ndata, dummy;
06865   Size wrsize;
06866 
06867   getData(agr, odata, dummy);
06868 #ifdef E_XDR_TRACE
06869   printf("%s: AttrIndirectVarDim::setSize()\n", name);
06870 #endif
06871   if (nsize == 0)
06872     ndata = 0;
06873   else {
06874     Size wsize = idr_item_vsize * nsize * typmod.pdims;
06875     ndata = (unsigned char *)malloc(wsize);
06876     wrsize = idr_item_vsize * rsize * typmod.pdims;
06877 
06878     // needs XDR ? no
06879     memcpy(ndata, odata, wrsize);
06880     memset(ndata + wrsize, 0, wsize - wrsize);
06881   }
06882 
06883   setData(agr, ndata);
06884   free(odata);
06885 
06886   getDataOids(agr, odata);
06887 
06888   if (nsize == 0)
06889     ndata = 0;
06890   else {
06891     Size wsize = sizeof(Oid) * nsize * typmod.pdims;
06892     ndata = (unsigned char *)malloc(wsize);
06893     wrsize = sizeof(Oid) * rsize * typmod.pdims;
06894     
06895     // needs XDR ? no
06896     memcpy(ndata, odata, wrsize);
06897     memset(ndata + wrsize, 0, wsize - wrsize);
06898   }
06899 
06900   free(odata);
06901   setDataOids(agr, ndata);
06902 
06903   setSizeChanged(agr, True);
06904   agr->touch();
06905   return Success;
06906 }
06907 
06908 void AttrIndirectVarDim::setSizeChanged(Object *agr, Bool changed) const
06909 {
06910   Size size;
06911 #ifdef E_XDR_TRACE
06912   printf("%s: AttrIndirectVarDim::setSizeChanged -> XDR\n", name);
06913 #endif
06914 #ifdef E_XDR
06915   x2h_32_cpy(&size, agr->getIDR() + idr_poff);
06916   size = SET_SIZE_CHANGED(size, changed);
06917   h2x_32_cpy(agr->getIDR() + idr_poff, &size);
06918 #else
06919   mcp(&size, agr->getIDR() + idr_poff, sizeof(Size));
06920   size = SET_SIZE_CHANGED(size, changed);
06921   mcp(agr->getIDR() + idr_poff, &size, sizeof(Size));
06922 #endif
06923 }
06924 
06925 Bool AttrIndirectVarDim::isSizeChanged(const Object *agr) const
06926 {
06927   Size size;
06928 #ifdef E_XDR_TRACE
06929   printf("%s: AttrIndirectVarDim::isSizeChanged -> XDR\n", name);
06930 #endif
06931 #ifdef E_XDR
06932   x2h_32_cpy(&size, agr->getIDR() + idr_poff);
06933 #else
06934   mcp(&size, agr->getIDR() + idr_poff, sizeof(Size));
06935 #endif
06936   return IS_SIZE_CHANGED(size);
06937 }
06938 
06939 void AttrIndirectVarDim::getData(const Database *, Data _idr, Data& data, Data& dummy) const
06940 {
06941   // needs XDR ? guess no
06942 #ifdef E_XDR_TRACE
06943   printf("%s: AttrIndirectVarDim::getData -> needs XDR ? no\n", name);
06944 #endif
06945   mcp(&data, _idr + idr_voff, sizeof(Data));
06946 }
06947 
06948 void AttrIndirectVarDim::getData(const Object *agr, Data& data, Data& dummy) const
06949 {
06950   // needs XDR ? guess no
06951 #ifdef E_XDR_TRACE
06952   printf("%s: AttrIndirectVarDim::getData -> needs XDR ? no\n", name);
06953 #endif
06954   mcp(&data, agr->getIDR() + idr_voff, sizeof(Data));
06955 }
06956 
06957 void AttrIndirectVarDim::setData(const Object *agr, Data data) const
06958 {
06959   // needs XDR ? guess no
06960 #ifdef E_XDR_TRACE
06961   printf("%s: AttrIndirectVarDim::setData -> needs XDR ? no\n", name);
06962 #endif
06963   mcp(agr->getIDR() + idr_voff, &data, sizeof(Data));
06964 }
06965 
06966 void AttrIndirectVarDim::setData(const Database *, Data _idr, Data data) const
06967 {
06968   // needs XDR ? guess no
06969 #ifdef E_XDR_TRACE
06970   printf("%s: AttrIndirectVarDim::setData -> needs XDR ? no\n", name);
06971 #endif
06972   mcp(_idr + idr_voff, &data, sizeof(Data));
06973 }
06974 
06975 void AttrIndirectVarDim::getDataOids(Data _idr, Data& data) const
06976 {
06977   mcp(&data, _idr + idr_voff + SIZEOFDATA, sizeof(Data));
06978 }
06979 
06980 void AttrIndirectVarDim::getDataOids(const Object *agr, Data& data) const
06981 {
06982   mcp(&data, agr->getIDR() + idr_voff + SIZEOFDATA, sizeof(Data));
06983 }
06984 
06985 void AttrIndirectVarDim::setDataOids(Data _idr, Data data) const
06986 {
06987   mcp(_idr + idr_voff + SIZEOFDATA, &data, sizeof(Data));
06988 }
06989 
06990 void AttrIndirectVarDim::setDataOids(Object *agr, Data data) const
06991 {
06992   mcp(agr->getIDR() + idr_voff + SIZEOFDATA, &data, sizeof(Data));
06993 }
06994 
06995 void AttrIndirectVarDim::getInfo(const Object *agr, Size &wsize, Data &data, Oid &oid) const
06996 {
06997   Size size;
06998 
06999   getSize(agr, size);
07000   getVarDimOid(agr, &oid);
07001   Data dummy;
07002   getData(agr, data, dummy);
07003 
07004   wsize = size * idr_item_vsize * typmod.pdims;
07005 }
07006 
07007 void AttrIndirectVarDim::getInfoOids(const Object *agr, Size &wsize, Data &data, Oid &oid) const
07008 {
07009   Size size;
07010 
07011   getSize(agr, size);
07012   getVarDimOid(agr, &oid);
07013   getDataOids(agr, data);
07014 
07015   wsize = size * sizeof(Oid) * typmod.pdims;
07016 }
07017 
07018 Status AttrIndirectVarDim::compile_perst(const AgregatClass *ma, int *offset, int *size, int *inisize)
07019 {
07020   Status status;
07021   const TypeModifier *tmod = &typmod;
07022 
07023   if (status = check())
07024     return status;
07025 
07026   idr_poff = *offset;
07027   idr_inisize = 0;
07028 
07029   idr_item_psize = sizeof(Oid);
07030   idr_psize = sizeof(Size) + sizeof(Oid);
07031   *inisize = idr_inisize;
07032   
07033   compile_update(ma, idr_psize, offset, size);
07034 
07035   return Success;
07036 }
07037 
07038 Status AttrIndirectVarDim::compile_volat(const AgregatClass *ma, int *offset, int *size)
07039 {
07040   Status status;
07041   const TypeModifier *tmod = &typmod;
07042 
07043   idr_voff = *offset;
07044 
07045   idr_item_vsize = SIZEOFOBJECT;
07046   idr_vsize = SIZEOFDATA + SIZEOFDATA;
07047 
07048   compile_update(ma, idr_vsize, offset, size);
07049 
07050   return Success;
07051 }
07052 
07053 void AttrIndirectVarDim::setVarDimOid(Object *agr, const Oid *oid) const
07054 {
07055 #ifdef E_XDR_TRACE
07056   printf("%s: AttrIndirectVarDim::setVarDimOid -> XDR\n", name);
07057 #endif
07058 #ifdef E_XDR
07059   if (eyedbsm::cmp_oid(agr->getIDR() + idr_poff + sizeof(Size), oid->getOid())) {
07060     eyedbsm::h2x_oid(agr->getIDR() + idr_poff + sizeof(Size), oid->getOid());
07061     agr->touch();
07062   }
07063 #else
07064   if (memcmp(agr->getIDR() + idr_poff + sizeof(Size), oid,
07065              sizeof(Oid))) {
07066     mcp(agr->getIDR() + idr_poff + sizeof(Size), oid, sizeof(Oid));
07067     agr->touch();
07068   }
07069 #endif
07070   // 17/09/04: seems to be a tests => disconnected 
07071 #if 0
07072   else {
07073     Oid tmp;
07074     dataRead(agr->getDatabase()->getDbHandle(),
07075                  idr_poff + sizeof(Size), sizeof(Oid),
07076                  (const Data)&tmp,
07077                  0, agr->getOid().getOid());
07078     if (tmp != *oid)
07079       printf("HORROR differences %s vs. %s\n",
07080              tmp.getString(), oid->getString());
07081   }
07082 #endif
07083 }
07084 
07085 void AttrIndirectVarDim::getVarDimOid(Data _idr, Oid *oid) const
07086 {
07087 #ifdef E_XDR_TRACE
07088   printf("%s: AttrIndirectVarDim::getVarDimOid -> XDR\n", name);
07089 #endif
07090 #ifdef E_XDR
07091   eyedbsm::x2h_oid(oid->getOid(), _idr + idr_poff + sizeof(Size));
07092 #else
07093   mcp(oid, _idr + idr_poff + sizeof(Size), sizeof(Oid));
07094 #endif
07095 }
07096 
07097 void AttrIndirectVarDim::getVarDimOid(const Object *agr, Oid *oid) const
07098 {
07099   getVarDimOid(agr->getIDR(), oid);
07100 }
07101 
07102 Status AttrIndirectVarDim::setOid(Object *agr, const Oid *oid, int nb, int from, Bool check_class) const
07103 {
07104   CHECK_OBJ(agr);
07105   check_var_range(agr, from, nb, 0);
07106 
07107   if (oid->isValid() && check_class) {
07108     Class *o_class;
07109     Status status;
07110     Bool is;
07111 
07112     status = cls->isObjectOfClass(oid, &is, True, &o_class);
07113       
07114     if (status)
07115       return status;
07116 
07117     if (!is)
07118       return Exception::make(IDB_ATTRIBUTE_ERROR,
07119                                 "waiting for object of class '%s', got object of class '%s'",
07120                                 cls->getName(), o_class->getName());
07121   }
07122 
07123     
07124   Data data;
07125   getDataOids(agr, data);
07126 
07127 #ifdef E_XDR_TRACE
07128   printf("%s: AttrIndirectVarDim::setOid -> XDR\n", name);
07129 #endif
07130   // changed 17/09/04
07131   set_oid_realize(data, oid, nb, from);
07132   /*
07133   if (memcmp(data + (from * sizeof(Oid)), oid, nb * sizeof(Oid)))
07134     {
07135       mcp(data + (from * sizeof(Oid)), oid, nb * sizeof(Oid)); 
07136       agr->touch();
07137     }
07138   */
07139 
07140   return Success;
07141 }
07142 
07143 Status AttrIndirectVarDim::getOid(const Object *agr, Oid *oid, int nb, int from) const
07144 {
07145   CHECK_OBJ(agr);
07146   check_var_range(agr, from, nb, 0);
07147 
07148   Data data;
07149   getDataOids(agr, data);
07150 
07151 #ifdef E_XDR_TRACE
07152   printf("%s: AttrIndirectVarDim::getOid -> XDR\n", name);
07153 #endif
07154 
07155 #ifdef E_XDR_1
07156   for (int n = 0; n < nb; n++)
07157     eyedbsm::x2h_oid(oid[n].getOid(), data + (from + n) * sizeof(Oid)); 
07158 #else
07159   mcp(oid, data + (from * sizeof(Oid)), nb * sizeof(Oid)); 
07160 #endif
07161   return Success;
07162 }
07163 
07164 Status AttrIndirectVarDim::setValue(Object *agr, Data data,
07165                                            int nb, int from,
07166                                            Bool check_class) const
07167 {
07168   CHECK_OBJ(agr);
07169   CHECK_RTTYPE(agr);
07170   check_var_range(agr, from, nb, 0);
07171 
07172   Data vdata, dummy;
07173   getData(agr, vdata, dummy);
07174 
07175   return Attribute::setValue(agr, vdata, data, SIZEOFOBJECT,
07176                                 sizeof(Object *), nb, from, 0, True, 0,
07177                                 check_class);
07178 }
07179 
07180 Status AttrIndirectVarDim::getValue(const Object *agr, Data *data, int nb, int from, Bool *isnull) const
07181 {
07182   CHECK_OBJ(agr);
07183   CHECK_RTTYPE(agr);
07184 
07185   check_var_range(agr, from, nb, 0);
07186 
07187   Data vdata, dummy;
07188   getData(agr, vdata, dummy);
07189 
07190   mcp(data, vdata + from * SIZEOFOBJECT, nb * sizeof(Object *));
07191   return Success;
07192 }
07193 
07194 Status
07195 AttrIndirectVarDim::getTValue(Database *db, const Oid &objoid,
07196                                  Data *data, int nb, int from,
07197                                  Bool *isnull, Size *rnb, Offset poffset) const
07198 {
07199   Status status = tvalue_prologue(db, objoid);
07200   if (status) return status;
07201 
07202   unsigned char infodata[sizeof(Size)+sizeof(Oid)];
07203   if (status = StatusMake
07204       (dataRead(db->getDbHandle(),
07205                     poffset + idr_poff,
07206                     sizeof(Size)+sizeof(Oid), infodata,
07207                     0, objoid.getOid())))
07208     {
07209       CHECK_OID(objoid);
07210       return status;
07211     }
07212 
07213   Size size;
07214 #ifdef E_XDR_TRACE
07215   printf("%s: AttrIndirectVarDim::getTValue -> XDR", name);
07216 #endif
07217 #ifdef E_XDR
07218   x2h_32_cpy(&size, infodata);
07219 #else
07220   mcp(&size, infodata, sizeof(Size));
07221 #endif
07222   size = CLEAN_SIZE(size);
07223 
07224   if (status = checkVarRange(from, nb, size))
07225     return status;
07226 
07227   if (rnb)
07228     *rnb = size;
07229 
07230   Oid data_oid;
07231 #ifdef E_XDR
07232   eyedbsm::x2h_oid(data_oid.getOid(), infodata+sizeof(Size));
07233 #else
07234   mcp(&data_oid, infodata+sizeof(Size), sizeof(Oid));
07235 #endif
07236 
07237   if (!data_oid.isValid()) {
07238     if (isnull)
07239       *isnull = True;
07240     return Success;
07241   }
07242 
07243   Bool toAlloc;
07244   Data pdata;
07245 
07246   if (nb == wholeData) {
07247     pdata = 0;
07248     toAlloc = True;
07249     nb = size;
07250   }
07251   else
07252     {
07253       pdata = (Data)data;
07254       toAlloc = False;
07255     }
07256 
07257   if (toAlloc)
07258     *data = pdata = (unsigned char *)malloc(nb * idr_item_psize);
07259 
07260   if (status = StatusMake
07261       (dataRead(db->getDbHandle(),
07262                     from * idr_item_psize,
07263                     nb * idr_item_psize, pdata, 0, data_oid.getOid())))
07264     {
07265       if (toAlloc)
07266         free(*data);
07267       CHECK_OID(objoid);
07268       return status;
07269     }
07270   
07271 #ifdef E_XDR_1
07272   printf("IVD::getTValue() ??\n");
07273   for (int i = 0; i < nb; i++) {
07274     Oid tmp_oid;
07275     eyedbsm::x2h_oid(tmp_oid.getOid(), pdata+i*sizeof(Oid));
07276     memcpy(pdata+i*sizeof(Oid), tmp_oid.getOid(), sizeof(Oid));
07277   }
07278 #endif
07279 
07280   if (!isnull)
07281     return Success;
07282 
07283   *isnull = True;
07284   for (int i = 0; i < nb; i++) {
07285     Oid tmp_oid;
07286     mcp(&tmp_oid, pdata+i*sizeof(Oid), sizeof(Oid));
07287     if (tmp_oid.isValid()) {
07288       *isnull = False;
07289       break;
07290     }
07291   }
07292 
07293   return Success;
07294 }
07295 
07296 Status AttrIndirectVarDim::copy(Object *agr, Bool share) const
07297 {
07298   Data _idr = agr->getIDR();
07299   Size size;
07300   getSize(_idr, size);
07301 
07302 #ifdef E_XDR_TRACE
07303   printf("%s: AttrIndirectVarDim\n", name);
07304 #endif
07305   if (size)
07306     {
07307       Data pdata, vdata, dummy;
07308       getData(getDB(agr), _idr, vdata, dummy);
07309 
07310       if (!share)
07311         {
07312           getDataOids(_idr, pdata);
07313           
07314           int wpsize = size * idr_item_psize * typmod.pdims;
07315           Data npdata = (unsigned char *)malloc(wpsize);
07316           // needs XDR ? no
07317           memcpy(npdata, pdata, wpsize);
07318 
07319           int wvsize = size * idr_item_vsize * typmod.pdims;
07320           Data nvdata = (unsigned char *)malloc(wvsize);
07321           // needs XDR ? no
07322           memcpy(nvdata, vdata, wvsize);
07323           
07324           Status s = Attribute::incrRefCount(agr, nvdata, size);
07325           if (s)
07326             return s;
07327           
07328           setData(agr->getDatabase(), _idr, nvdata);
07329           setDataOids(_idr, npdata);
07330         }
07331       else if (vdata) {
07332         Status s = Attribute::incrRefCount(agr, vdata, size);
07333           if (s)
07334             return s;
07335       }
07336     }
07337 
07338   return Success;
07339 }
07340 
07341 #ifdef GBX_NEW_CYCLE
07342 void AttrIndirectVarDim::decrRefCountPropag(Object *agr, int) const
07343 {
07344   Data vdata, dummy;
07345   getData(agr, vdata, dummy);
07346 
07347   if (vdata) {
07348     Size size;
07349     getSize(agr, size);
07350     Attribute::decrRefCountPropag(vdata, typmod.pdims * size);
07351   }
07352 }
07353 #endif
07354 
07355 void AttrIndirectVarDim::garbage(Object *agr, int refcnt) const
07356 {
07357   Data vdata, dummy;
07358   getData(agr, vdata, dummy);
07359 
07360   if (vdata)
07361     {
07362       Size size;
07363       getSize(agr, size);
07364       Attribute::garbage(vdata, typmod.pdims * size);
07365       if (refcnt <= 1) // was refcnt == 1 12/10/00
07366         setSize(agr, 0);
07367     }
07368 }
07369 
07370 void AttrIndirectVarDim::manageCycle(Database *db, Object *o, gbxCycleContext &r) const
07371 {
07372   Data vdata, dummy;
07373   getData(o, vdata, dummy);
07374   if (vdata)
07375     {
07376       Size size;
07377       getSize(o, size);
07378       Attribute::manageCycle(o, vdata, typmod.pdims * size, r);
07379     }
07380 }
07381 
07382 Status AttrIndirectVarDim::trace(const Object *agr, FILE *fd, int *indent, unsigned int flags, const RecMode *rcm) const
07383 {
07384   IDB_CHECK_INTR();
07385 
07386   char *indent_str = make_indent(*indent);
07387   TypeModifier tmod = typmod;
07388   Size size;
07389   Data vdata;
07390   char prefix[64];
07391   Status status = Success;
07392 
07393   get_prefix(agr, class_owner, prefix, sizeof(prefix));
07394 
07395   getSize(agr, size);
07396   Data dummy;
07397   getData(agr, vdata, dummy);
07398 
07399   tmod.pdims *= size;
07400 
07401   for (int j = 0; j < tmod.pdims; j++)
07402     {
07403       Object *o;
07404       Oid oid;
07405 
07406       mcp(&o, vdata + (j * idr_item_vsize), sizeof(Object *));
07407       getOid(agr, &oid, 1, j);
07408 
07409       if (o) {
07410         fprintf(fd, "%s%s%s[%d] %s {%s} = ", indent_str, prefix, name, j,
07411                 o->getClass()->getName(), oid.getString());
07412         status = ObjectPeer::trace_realize(o, fd, *indent + INDENT_INC, flags, rcm);
07413         if (status) break;
07414       }
07415       else
07416         fprintf(fd, "%s%s%s[%d] = {%s};\n", indent_str, prefix, name, j,
07417                 oid.getString());
07418     }
07419 
07420   delete_indent(indent_str);
07421   return status;
07422 }
07423 
07424 Status
07425 AttrIndirectVarDim::realize(Database *db, Object *_o,
07426                                const Oid& cloid,
07427                                const Oid& objoid,
07428                                AttrIdxContext &idx_ctx,
07429                                const RecMode *rcm) const
07430 {
07431   Size size;
07432   int dd;
07433   Agregat *agr = (Agregat *)_o;
07434 
07435   getSize(agr, size);
07436   Data vdata, dummy;
07437   getData(agr, vdata, dummy);
07438 
07439   dd = typmod.pdims * size;
07440 
07441   for (int j = 0; j < dd; j++)
07442     {
07443       Status status;
07444       Object *o;
07445 
07446       mcp(&o, vdata + (j * idr_item_vsize), sizeof(Object *));
07447 
07448       if (o && rcm->isAgregRecurs(this, j, o))
07449         {
07450           status = o->setDatabase(db);
07451           if (status != Success)
07452             return status;
07453 
07454           if (o->asCollection())
07455             attrCollManage(this, o->asCollection(), _o);
07456 
07457           status = o->realize(rcm);
07458 
07459           if (status == Success)
07460             status = agr->setItemOid(this, &o->getOid(), 1, j);
07461 
07462           if (status)
07463             return status;
07464         }
07465       else if (!o)
07466         {
07467           if (card)
07468             {
07469               status = cardManage(db, agr, j);
07470               if (status)
07471                 return status;
07472             }
07473 
07474           if (inv_spec.oid_cl.isValid())
07475             {
07476               status = inverseManage(db, agr, j);
07477               if (status)
07478                 return status;
07479             }
07480         }
07481     }
07482 
07483   return update(db, cloid, objoid, agr, idx_ctx);
07484 }
07485 
07486 Status
07487 AttrIndirectVarDim::remove(Database *db, Object *_o,
07488                               const Oid& cloid,
07489                               const Oid& objoid,
07490                               AttrIdxContext &idx_ctx,
07491                               const RecMode *rcm) const
07492 {
07493   Size size;
07494   Data vdata;
07495   int dd;
07496   Agregat *agr = (Agregat *)_o;
07497 
07498   getSize(agr, size);
07499   Data dummy;
07500   getData(agr, vdata, dummy);
07501 
07502   dd = typmod.pdims * size;
07503 
07504   for (int j = 0; j < dd; j++)
07505     {
07506       Status status;
07507       Object *o;
07508 
07509       mcp(&o, vdata + (j * idr_item_vsize), sizeof(Object *));
07510 
07511       if (o && rcm->isAgregRecurs(this, j, o))
07512         {
07513           status = o->setDatabase(db);
07514           if (status != Success)
07515             return status;
07516           status = o->remove(rcm);
07517 
07518           if (status == Success ||
07519               status->getStatus() == IDB_OBJECT_NOT_CREATED)
07520             status = agr->setItemOid(this, &Oid::nullOid, 1, j);
07521 
07522           if (status)
07523             return status;
07524         }
07525     }
07526 
07527   return remove_realize(db, cloid, objoid, agr, idx_ctx);
07528 }
07529 
07530 Status AttrIndirectVarDim::update(Database *db,
07531                                         const Oid& cloid,
07532                                         const Oid& objoid,
07533                                         Object *agr,
07534                                         AttrIdxContext &idx_ctx) const
07535 {
07536   Size wsize, size;
07537   Data data;
07538   Oid oid;
07539 
07540   getInfoOids(agr, wsize, data, oid);
07541   getSize(agr, size);
07542 
07543   return update_realize(db, agr, cloid, objoid, size, wsize, data, oid, idx_ctx);
07544 }
07545 
07546 Status
07547 AttrIndirectVarDim::convert(Database *db, ClassConversion *conv,
07548                                Data in_idr, Size in_size) const
07549 {
07550   return Exception::make(IDB_ERROR, "attribute %s::%s conversion error",
07551                             class_owner->getName(), name);
07552 }
07553 
07554 Status
07555 AttrIndirectVarDim::load(Database *db,
07556                             Object *agr,
07557                             const Oid &cloid,
07558                             LockMode lockmode, 
07559                             AttrIdxContext &idx_ctx,
07560                             const RecMode *rcm, Bool force) const
07561 {
07562   Size wsize;
07563   Data data;
07564   Oid oid;
07565 
07566   getInfoOids(agr, wsize, data, oid);
07567 
07568   if (wsize)
07569     {
07570       RPCStatus rpc_status;
07571 
07572       free(data);
07573       data = (unsigned char *)malloc(wsize);
07574 
07575       if ((rpc_status = dataRead(db->getDbHandle(), 0, wsize, data, 0, oid.getOid()))
07576           == RPCSuccess)
07577         {
07578           setDataOids(agr, data);
07579           getInfo(agr, wsize, data, oid);
07580           data = (unsigned char *)malloc(wsize);
07581           memset(data, 0, wsize);
07582           setData(agr, data);
07583         }
07584       else
07585         free(data);
07586 
07587       if (rpc_status != RPCSuccess)
07588         return StatusMake(rpc_status);
07589     }
07590 
07591   Size size;
07592   getSize(agr, size);
07593 
07594   setSizeChanged(agr, False);
07595 
07596   int dd = size * typmod.pdims;
07597 
07598   for (int j = 0; j < dd; j++)
07599     if (rcm->isAgregRecurs(this, j))
07600       {
07601         Oid oid;
07602         
07603         getOid(agr, &oid, 1, j);
07604         
07605         if (oid.isValid())
07606           {
07607             Status status;
07608             Object *o;
07609 
07610             status = db->loadObject_realize(&oid, &o, lockmode, rcm);
07611         
07612             if (status != Success)
07613               return status;
07614 
07615             o->setMustRelease(false); // SMART_PTR
07616 
07617             status = setValue(agr, (Data)&o, 1, j, False);
07618 
07619             if (status != Success)
07620               return status;
07621           }
07622       }
07623 
07624   return Success;
07625 }
07626 
07627 void Attribute::pre_release()
07628 {
07629   if (attr_comp_set)
07630     attr_comp_set->release();
07631 
07632   attr_comp_set = 0;
07633 }
07634 
07635 Attribute::~Attribute()
07636 {
07637   free((void *)name);
07638 }
07639 
07640 //  s = std::string((TYP)i);
07641 
07642 #define MAKE_STR(TYP) \
07643 do { \
07644   TYP i; \
07645   mcp(&i, data, sizeof(i)); \
07646   s = str_convert((TYP)i); \
07647   return s.c_str(); \
07648 } while(0)
07649 
07650 const char *
07651 Attribute::dumpData(Data data)
07652 {
07653   static std::string s;
07654 
07655   if (isIndirect()) {
07656     Oid oid;
07657     mcp(&oid, data, sizeof(Oid));
07658     s = oid.toString();
07659     return s.c_str();
07660   }
07661   
07662   if (cls->asInt32Class())
07663     MAKE_STR(eyedblib::int32);
07664 
07665   if (cls->asInt64Class())
07666     MAKE_STR(eyedblib::int64);
07667 
07668   if (cls->asInt16Class())
07669     MAKE_STR(eyedblib::int16);
07670 
07671   if (cls->asFloatClass())
07672     MAKE_STR(double);
07673 
07674   if (cls->asCharClass())
07675     MAKE_STR(char);
07676 
07677   if (cls->asOidClass()) {
07678     //MAKE_STR(Oid);
07679     Oid x;
07680     mcp(&x, data, sizeof(x));
07681     s = x.toString();
07682     return s.c_str();
07683   }
07684 
07685   s = "";
07686   for (int i = 0; i < idr_item_psize; i++)
07687     {
07688       char tok[16];
07689       sprintf(tok, "%02x", data[i]);
07690       s += tok;
07691     }
07692   return s.c_str();
07693 }
07694 
07695 Status
07696 Attribute::getDefaultDataspace(const Dataspace *&) const
07697 {
07698   return Exception::make(IDB_ERROR,
07699                             "attribute %s: can get or set default dataspace"
07700                             " only on variable dimension attributes", name);
07701 }
07702 
07703 Status
07704 Attribute::setDefaultDataspace(const Dataspace *)
07705 {
07706   return Exception::make(IDB_ERROR,
07707                             "attribute %s: can get or set default dataspace"
07708                             " only on variable dimension attributes",
07709                             name);
07710 }
07711 
07712 void *Attribute::setUserData(void *nuser_data)
07713 {
07714   void *x = user_data;
07715   user_data = nuser_data;
07716   return x;
07717 }
07718 
07719 //
07720 // AttrIdxContext methods
07721 //
07722 
07723 AttrIdxContext::AttrIdxContext(const Data data, Size size)
07724 {
07725   init();
07726 
07727   if (!size)
07728     return;
07729 
07730   attrpath_computed = False;
07731   Offset offset = 0;
07732   char *s;
07733   string_decode(data, &offset, &s);
07734   class_owner = *s ? strdup(s) : 0;
07735   int dummy;
07736   int32_decode(data, &offset, &dummy);
07737   int16_decode(data, &offset, &attr_cnt);
07738   toFree = True;
07739   for (int i = 0; i < attr_cnt; i++) {
07740     string_decode(data, &offset, (char **)&s);
07741     attrs[i] = s;
07742   }
07743 }
07744 
07745 AttrIdxContext::AttrIdxContext(AttrIdxContext *idx_ctx)
07746 {
07747   idx_ctx_root = idx_ctx;
07748   attr_cnt = idx_ctx->attr_cnt;
07749   attr_off_cnt = idx_ctx->attr_off_cnt;
07750   class_owner = idx_ctx->class_owner;
07751   toFree = False;
07752 
07753   for (int n = 0; n < attr_cnt; n++)
07754     attrs[n] = idx_ctx->attrs[n];
07755 
07756   for (int n = 0; n < attr_off_cnt; n++)
07757     attr_off[n] = idx_ctx->attr_off[n];
07758 
07759   attrpath_computed = False;
07760 
07761   idx_ops_alloc = idx_ops_cnt = 0;
07762   idx_ops = 0;
07763 }
07764 
07765 std::string
07766 AttrIdxContext::getString() const
07767 {
07768   return getAttrName();
07769 }
07770 
07771 std::string
07772 AttrIdxContext::getAttrName(Bool ignore_class_owner) const
07773 {
07774   if (attrpath_computed && attrpath_ignore_class_owner == ignore_class_owner)
07775     return attrpath;
07776 
07777   attrpath_computed = True;
07778   attrpath_ignore_class_owner = ignore_class_owner;
07779 
07780   if (!ignore_class_owner) {
07781     if (!class_owner) {
07782       *attrpath = 0;
07783       return attrpath;
07784     }
07785 
07786     strcpy(attrpath, class_owner);
07787 
07788     for (int i = 0; i < attr_cnt; i++) {
07789       strcat(attrpath, ".");
07790       strcat(attrpath, attrs[i].c_str());
07791     }
07792 
07793     return attrpath;
07794   }
07795 
07796   *attrpath = 0;
07797   for (int i = 0; i < attr_cnt; i++) {
07798     if (i) strcat(attrpath, ".");
07799     strcat(attrpath, attrs[i].c_str());
07800   }
07801 
07802   return attrpath;
07803 }
07804 
07805 Data
07806 AttrIdxContext::code(Size &size) const
07807 {
07808   Data data = 0;
07809   Offset offset = 0;
07810   Size alloc_size = 0;
07811   string_code(&data, &offset, &alloc_size,
07812                   (class_owner ? class_owner : ""));
07813   int dummy = 0;
07814   int32_code(&data, &offset, &alloc_size, &dummy);
07815   int16_code(&data, &offset, &alloc_size, &attr_cnt);
07816 
07817   for (int i = 0; i < attr_cnt; i++)
07818     string_code(&data, &offset, &alloc_size, attrs[i].c_str());
07819 
07820   size = offset;
07821   return data;
07822 }
07823 
07824 int
07825 AttrIdxContext::operator==(const AttrIdxContext &idx_ctx) const
07826 {
07827   if (strcmp(class_owner, idx_ctx.class_owner))
07828     return 0;
07829 
07830   if (attr_cnt != idx_ctx.attr_cnt)
07831     return 0;
07832 
07833   for (int i = 0; i < attr_cnt; i++)
07834     if (strcmp(attrs[i].c_str(), idx_ctx.attrs[i].c_str()))
07835       return 0;
07836 
07837   return 1;
07838 }
07839 
07840 Attribute *
07841 AttrIdxContext::getAttribute(const Class *cls) const
07842 {
07843   const Attribute *attr = 0;
07844   for (int i = 0; i < attr_cnt; i++) {
07845     attr = cls->getAttribute(attrs[i].c_str());
07846     assert(attr);
07847     cls = attr->getClass();
07848     assert(cls);
07849   }
07850 
07851   return const_cast<Attribute *>(attr);
07852 }
07853 
07854 void AttrIdxContext::addIdxOP(const Attribute *attr, IdxOP op,
07855                                  Index *idx_t, eyedbsm::Idx *idx,
07856                                  unsigned char *data,
07857                                  unsigned int sz, Oid data_oid[2])
07858 {
07859   if (idx_ctx_root) {
07860     idx_ctx_root->addIdxOP(attr, op, idx_t, idx, data, sz, data_oid);
07861     return;
07862   }
07863 
07864   eyedblib::MutexLocker mtl(mut);
07865   if (idx_ops_cnt >= idx_ops_alloc) {
07866     idx_ops_alloc += 8;
07867     idx_ops = (IdxOperation *)realloc(idx_ops, sizeof(IdxOperation)*
07868                                       idx_ops_alloc);
07869   }
07870 
07871   IdxOperation *xop = &idx_ops[idx_ops_cnt++];
07872   xop->attr = attr;
07873   xop->op = op;
07874   xop->idx_t = idx_t;
07875   xop->idx = idx;
07876   xop->data = (unsigned char *)malloc(sz+1);
07877   memcpy(xop->data, data, sz);
07878   xop->data[sz] = 0;
07879 
07880   xop->data_oid[0] = data_oid[0];
07881   xop->data_oid[1] = data_oid[1];
07882 
07883 #ifdef NEW_NOTNULL_TRACE
07884   printf("add_%s_op : %s::%s, sz=%d, oid=%s",
07885          (op == IdxInsert ? "insert" : "remove"),
07886          attr->getClassOwner() ? attr->getClassOwner()->getName() : "<NULL>",
07887          attr->getName(),
07888          sz,
07889          data_oid[0].toString());
07890   
07891   if (attr->isString())
07892     printf(", data='%s'", data);
07893   else {
07894     printf("data {\n");
07895     for (int i = 0; i < sz; i++)
07896       printf("%s%d", (i > 0 ? ", " : ""), data[i]);
07897     printf("}\n");
07898   }
07899 
07900   printf("\n");
07901 #endif
07902 }
07903 
07904 Status
07905 AttrIdxContext::realizeIdxOP(Bool ok)
07906 {
07907   static const char fmt_error[] = "storage manager error '%s' reported when updating index entry in attribute '%s' in agregat class '%s'";
07908 
07909   assert(!idx_ctx_root);
07910   int ops_cnt = idx_ops_cnt;
07911   idx_ops_cnt = 0;
07912   for (int i = 0; i < ops_cnt; i++) {
07913     IdxOperation *xop = &idx_ops[i];
07914     if (ok) {
07915       eyedbsm::Status s;
07916 #ifdef TRACE_IDX
07917       printf("xop->op %s %s::%s\n", xop->op == IdxInsert ? "insert" : "remove", 
07918              xop->attr->getClassOwner() ? xop->attr->getClassOwner()->getName() : "<NULL>",
07919              xop->idx_t->getAttrpath().c_str());
07920 #endif
07921       if (xop->op == IdxInsert) {
07922         s = xop->idx->insert(xop->data, xop->data_oid);
07923         if (eyedbsm::hidx_gccnt > 20) {
07924           fprintf(stdout, "index %s getcell -> %d\n", xop->idx_t->getAttrpath().c_str(), eyedbsm::hidx_gccnt);
07925           fflush(stdout);
07926         }
07927         eyedbsm::hidx_gccnt = 0;
07928       }
07929       else {
07930         eyedbsm::Boolean found;
07931         s = xop->idx->remove(xop->data, xop->data_oid, &found);
07932         if (!s && !found)
07933           return Exception::make(IDB_INDEX_ERROR, fmt_error,
07934                                     "index entry not found",
07935                                     xop->idx_t->getAttrpath().c_str(),
07936                                     xop->attr->getClassOwner()->getName());
07937       }
07938 
07939       if (s)
07940         return Exception::make(IDB_INDEX_ERROR, fmt_error,
07941                                   eyedbsm::statusGet(s),
07942                                   //xop->attr->getName(),
07943                                   xop->idx_t->getAttrpath().c_str(),
07944                                   xop->attr->getClassOwner()->getName());
07945     }
07946 
07947     free(xop->data);
07948     xop->data = 0;
07949   }
07950 
07951   return Success;
07952 }
07953 
07954 void
07955 AttrIdxContext::pushOff(int off)
07956 {
07957   pushOff(off, Oid::nullOid);
07958 }
07959 
07960 void
07961 AttrIdxContext::pushOff(int off, const Oid &data_oid)
07962 {
07963   // 27/05/06: no more useful
07964 #ifdef TRACE_OFF
07965   printf("pushing [%d] %d %s\n", attr_off_cnt, off, data_oid.toString());
07966 #endif
07967   attr_off[attr_off_cnt].off = off;  
07968   attr_off[attr_off_cnt].data_oid = data_oid;
07969   attr_off_cnt++;
07970 }
07971 
07972 #undef TRACE_OFF
07973 
07974 void
07975 AttrIdxContext::popOff()
07976 {
07977   attr_off_cnt--;
07978 #ifdef TRACE_OFF
07979   printf("popOff [%d]\n", attr_off_cnt);
07980 #endif
07981 }
07982 
07983 int
07984 AttrIdxContext::getOff()
07985 {
07986   int off = 0;
07987 
07988 #ifdef TRACE_OFF
07989   printf("getOff(%d)\n", attr_off_cnt);
07990 #endif
07991   for (int n = attr_off_cnt-1; n >= 0; n--) {
07992     off += attr_off[n].off;
07993     if (attr_off[n].data_oid.isValid()) {
07994       break;
07995     }
07996   }
07997 
07998   off -= (attr_off_cnt - 1) * IDB_OBJ_HEAD_SIZE;
07999   //printf("getOff n=%d off=%d\n", attr_off_cnt, off);
08000   return off;
08001 }
08002 
08003 Oid
08004 AttrIdxContext::getDataOid()
08005 {
08006   for (int n = attr_off_cnt-1; n >= 0; n--) {
08007     if (attr_off[n].data_oid.isValid())
08008       return attr_off[n].data_oid;
08009   }
08010 
08011   return Oid::nullOid;
08012 }
08013 
08014 void
08015 AttrIdxContext::push(const Attribute *attr)
08016 {
08017   attrs[attr_cnt++] = attr->getName();
08018   attrpath_computed = False;
08019 }
08020 
08021 void
08022 AttrIdxContext::push(const char *attrname)
08023 {
08024   attrs[attr_cnt++] = attrname;
08025   attrpath_computed = False;
08026 }
08027 
08028 void
08029 AttrIdxContext::pop()
08030 {
08031   --attr_cnt;
08032   /*
08033   if (!attr_cnt)
08034     class_owner = 0;
08035   */
08036   attrpath_computed = False;
08037 }
08038 
08039 void
08040 AttrIdxContext::set(const Class *_class_owner)
08041 {
08042   class_owner = (char *)_class_owner->getName();
08043   attrpath_computed = False;
08044 }
08045 
08046 void
08047 AttrIdxContext::garbage(Bool all)
08048 {
08049   if (all) {
08050     assert(!idx_ops_cnt);
08051     free(idx_ops);
08052   }
08053 
08054   if (toFree) {
08055     free(class_owner);
08056   }
08057 }
08058 
08059 //
08060 // AttributeComponentSet related method
08061 //
08062 
08063 Status
08064 Attribute::createComponentSet(Database *db)
08065 {
08066   /*
08067   printf("creating component set %p %s::%s\n", this,
08068          (class_owner ? class_owner->getName() : "<unknown>"), name);
08069   */
08070   
08071   if (class_owner &&
08072       !strcmp(class_owner->getName(), "attribute_component_set"))
08073     return Success;
08074 
08075   if (attr_comp_set_oid.isValid())
08076     return Success;
08077 
08078   Status s;
08079   assert(dyn_class_owner);
08080   assert(class_owner);
08081 
08082   if (!dyn_class_owner->compare(class_owner)) {
08083     Attribute *attr = (Attribute *)class_owner->getAttribute(name);
08084     assert(attr != this);
08085     if (!attr->attr_comp_set_oid.isValid()) {
08086       s = attr->createComponentSet(db);
08087       if (s) return s;
08088     }
08089 
08090     attr_comp_set_oid = attr->attr_comp_set_oid;
08091     assert(attr_comp_set_oid.isValid());
08092     s = loadComponentSet(db, False);
08093     if (s) return s;
08094     assert(attr_comp_set);
08095     Class *xclass_owner = const_cast<Class *>(dyn_class_owner);
08096     /*
08097     printf("create #1 %s cls=%p\n", attr_comp_set_oid.toString(), xclass_owner);
08098     */
08099     assert(db->getSchema()->checkClass(xclass_owner));
08100     xclass_owner->touch();
08101     return xclass_owner->store();
08102   }
08103 
08104   attr_comp_set = new AttributeComponentSet(db);
08105   attr_comp_set->keep();
08106 
08107   Class *xclass_owner = const_cast<Class *>(class_owner);
08108   attr_comp_set->setAttrname((std::string(xclass_owner->getName()) + "." + name).c_str());
08109   attr_comp_set->setClassOwner(xclass_owner);
08110   
08111   s = attr_comp_set->store();
08112   if (s) return s;
08113   attr_comp_set_oid = attr_comp_set->getOid();
08114   //printf("create #2 %s cls=%p\n", attr_comp_set_oid.toString(), xclass_owner);
08115   assert(db->getSchema()->checkClass(xclass_owner));
08116   
08117   xclass_owner->touch();
08118   return xclass_owner->store();
08119 }
08120 
08121 Status
08122 Attribute::hasIndex(Database *db, bool &has_index, std::string &idx_str) const
08123 {
08124   Status s = loadComponentSet(db, False);
08125   if (s)
08126     return s;
08127 
08128   if (attr_comp_set)
08129     return attr_comp_set->hasIndex(has_index, idx_str);
08130 
08131   has_index = false;
08132   return Success;
08133 }
08134 
08135 Status
08136 Attribute::loadComponentSet(Database *db, Bool create) const
08137 {
08138   /*
08139   printf("loadComponentSet: %p %s %p %s\n", this, name, attr_comp_set,
08140          attr_comp_set_oid.getString());
08141   */
08142   if (attr_comp_set) {
08143     if (attr_comp_set->isRemoved()) {
08144       printf("REMOVED loadComponentSet: %p %s %p %s\n", this, name, attr_comp_set,
08145              attr_comp_set_oid.getString());
08146     }
08147     return Success;
08148   }
08149 
08150 #ifdef ATTRNAT_TRACE
08151   if (isNative()) {
08152     printf("native loading component set %p %s::%s -> %s\n", this,
08153            (dyn_class_owner ? dyn_class_owner->getName() : "<unknown>"), name,
08154            attr_comp_set_oid.getString());
08155   }
08156   else
08157     printf("loading component set %p %s::%s -> %s\n", this,
08158            (class_owner ? class_owner->getName() : "<unknown>"), name,
08159            attr_comp_set_oid.getString());
08160 #endif
08161 
08162   if (attr_comp_set_oid.isValid()) {
08163     /*
08164     printf("loading component set %p %s::%s -> %s\n", this,
08165            (class_owner ? class_owner->getName() : "<unknown>"), name,
08166            attr_comp_set_oid.getString());
08167     */
08168     Status s = db->loadObject(attr_comp_set_oid,
08169                               (Object *&)attr_comp_set);
08170     if (s) return s;
08171     attr_comp_set->keep();
08172     if (attr_comp_set->isRemoved()) {
08173       printf("REMOVED2 loadComponentSet: %p %s %p %s\n", this, name, attr_comp_set,
08174              attr_comp_set_oid.getString());
08175     }
08176     return Success;
08177   }
08178 
08179   if (create)
08180     return const_cast<Attribute *>(this)->createComponentSet(db);
08181 
08182   return Success;
08183 }
08184 
08185 Status
08186 Attribute::addComponent(Database *db, AttributeComponent *comp) const
08187 {
08188   Status s;
08189   if (!attr_comp_set) {
08190     s = loadComponentSet(db, True);
08191     if (s) return s;
08192   }
08193 
08194   /*printf("%s::%s: adding component %s %s\n", dyn_class_owner->getName(),
08195          name, comp->getName(), comp->getOid().toString());
08196   */
08197   s = attr_comp_set->addToCompsColl(comp);
08198   if (s) return s;
08199   attr_comp_set->invalidateCache();
08200   Class *clsown = attr_comp_set->getClassOwner();
08201   if (clsown) clsown->unmakeAttrCompList();
08202   return attr_comp_set->store();
08203 }
08204 
08205 Status
08206 Attribute::rmvComponent(Database *db, AttributeComponent *comp) const
08207 {
08208   Status s;
08209   if (!attr_comp_set) {
08210     s = loadComponentSet(db, False);
08211     if (s) return s;
08212   }
08213 
08214   /*
08215   printf("%s::%s: removing component %s %s\n", dyn_class_owner->getName(),
08216          name, comp->getName(), comp->getOid().toString());
08217   */
08218 
08219   if (!attr_comp_set)
08220     return Exception::make(IDB_INTERNAL_ERROR,
08221                               "no attribute component set tied to attribute "
08222                               "%s::%s", getClassOwner()->getName(), name);
08223   s = attr_comp_set->rmvFromCompsColl(comp);
08224   if (s) return s;
08225   attr_comp_set->invalidateCache();
08226   /*
08227   Class *clsown = attr_comp_set->getClassOwner();
08228 
08229   printf("rmvComponent: comp=%s clsown=%s class_owner=%s "
08230          "dyn_class_owner=%s\n",
08231          comp->getOid().toString(),
08232          (clsown ? clsown->getName() : "nil"),
08233          class_owner->getName(),
08234          dyn_class_owner->getName());
08235   */
08236 
08237   //if (clsown) clsown->unmakeAttrCompList();
08238   const_cast<Class *>(dyn_class_owner)->unmakeAttrCompList();
08239 
08240   return attr_comp_set->store();
08241 }
08242 
08243 //
08244 // AttributeComponentSet methods
08245 //
08246 
08247 void
08248 AttributeComponentSet::userInitialize()
08249 {
08250   index_cache = 0;
08251   unique_cache = 0;
08252   notnull_cache = 0;
08253   card_cache = 0;
08254   collimpl_cache = 0;
08255 }
08256 
08257 void
08258 AttributeComponentSet::userCopy(const Object &)
08259 {
08260   index_cache = 0;
08261   unique_cache = 0;
08262   notnull_cache = 0;
08263   card_cache = 0;
08264   collimpl_cache = 0;
08265 }
08266 
08267 void
08268 AttributeComponentSet::userGarbage()
08269 {
08270   delete index_cache;
08271   delete unique_cache;
08272   delete notnull_cache;
08273   delete card_cache;
08274   delete collimpl_cache;
08275 }
08276 
08277 AttributeComponentSet::Cache::Cache()
08278 {
08279   comp_count = 0;
08280   comp_alloc = 0;
08281   comps = 0;
08282 }
08283 
08284 AttributeComponentSet::Cache::Comp::Comp()
08285 {
08286 }
08287 
08288 AttributeComponentSet::Cache::Comp::~Comp()
08289 {
08290   abort();
08291   if (comp)
08292     comp->release();
08293   free(attrpath);
08294 }
08295 
08296 void
08297 AttributeComponentSet::Cache::add(AttributeComponent *comp)
08298 {
08299   if (comp_count >= comp_alloc) {
08300     comp_alloc += 4;
08301     comps = (Comp *)realloc(comps, comp_alloc * sizeof(Comp));
08302   }
08303 
08304   comps[comp_count].attrpath = strdup(comp->getAttrpath().c_str());
08305   comps[comp_count].comp = comp;
08306   comp_count++;
08307 }
08308 
08309 AttributeComponentSet::Cache::~Cache()
08310 {
08311   for (int n = 0; n < comp_count; n++) {
08312     free(comps[n].attrpath);
08313     if (comps[n].comp)
08314       comps[n].comp->release();
08315   }
08316 
08317   free(comps);
08318 }
08319 
08320 void
08321 AttributeComponentSet::Cache::getComponents(const char *prefix,
08322                                                int len, LinkedList &list)
08323 {
08324   for (int i = 0; i < comp_count; i++) {
08325     if (!strncmp(comps[i].comp->getAttrpath().c_str(), prefix, len)) {
08326       if (list.getPos(comps[i].comp) < 0)
08327         list.insertObject(comps[i].comp);
08328     }
08329   }
08330 }
08331 
08332 AttributeComponent *
08333 AttributeComponentSet::Cache::find(const char *attrpath)
08334 {
08335   for (int i = 0; i < comp_count; i++)
08336     if (!strcmp(attrpath, comps[i].attrpath))
08337       return comps[i].comp;
08338 
08339   return 0;
08340 }
08341 
08342 void
08343 AttributeComponentSet::invalidateCache()
08344 {
08345   delete index_cache;
08346   delete unique_cache;
08347   delete notnull_cache;
08348   delete collimpl_cache;
08349   delete card_cache;
08350 
08351   index_cache = 0;
08352   unique_cache = 0;
08353   notnull_cache = 0;
08354   collimpl_cache = 0;
08355   card_cache = 0;
08356 }
08357 
08358 Status
08359 AttributeComponentSet::makeCache()
08360 {
08361   invalidateCache();
08362 
08363   index_cache = new Cache();
08364   unique_cache = new Cache();
08365   notnull_cache = new Cache();
08366   collimpl_cache = new Cache();
08367   card_cache = new Cache();
08368 
08369   Status rs = 0;
08370   Collection *comps = getCompsColl(0, &rs);
08371   if (rs)
08372     return rs;
08373   Iterator iter(comps);
08374   ObjectArray obj_arr;
08375   Status s = iter.scan(obj_arr);
08376   if (s) return s;
08377   int cnt = obj_arr.getCount();
08378 
08379   for (int n = 0; n < cnt; n++) {
08380     AttributeComponent *comp = (AttributeComponent *)obj_arr[n];
08381     comp->keep();
08382     const char *clsname = comp->getClass()->getName();
08383 
08384     if (!strcmp(clsname, "notnull_constraint"))
08385       notnull_cache->add(comp);
08386     else if (!strcmp(clsname, "unique_constraint"))
08387       unique_cache->add(comp);
08388     else if (!strcmp(clsname, "cardinality_constraint_test"))
08389       card_cache->add(comp);
08390     else if (!strcmp(clsname, "collection_attribute_implementation"))
08391       collimpl_cache->add(comp);
08392     else if (!strcmp(clsname, "hashindex") || !strcmp(clsname, "btreeindex"))
08393       index_cache->add(comp);
08394     else
08395       assert(0);
08396   }
08397 
08398   return Success;
08399 }
08400 
08401 Status
08402 AttributeComponentSet::getAttrComponents(const Class *xcls,
08403                                             LinkedList &list)
08404 {
08405   /*
08406   static const char skipReentrant[] = "eyedb:get_attr_comp_set";
08407 
08408   if (xcls->getUserData(skipReentrant)) return Success;
08409   const_cast<Class *>(xcls)->setUserData(skipReentrant, AnyUserData);
08410   */
08411 
08412   if (!index_cache) {
08413     Status s = makeCache();
08414     if (s) {
08415       //const_cast<Class *>(xcls)->setUserData(skipReentrant, 0);
08416       return s;
08417     }
08418   }
08419 
08420   std::string prefix = std::string(xcls->getName()) + ".";
08421   int len = strlen(prefix.c_str());
08422   index_cache->getComponents(prefix.c_str(), len, list);
08423   unique_cache->getComponents(prefix.c_str(), len, list);
08424   notnull_cache->getComponents(prefix.c_str(), len, list);
08425   card_cache->getComponents(prefix.c_str(), len, list);
08426   collimpl_cache->getComponents(prefix.c_str(), len, list);
08427 
08428   //const_cast<Class *>(xcls)->setUserData(skipReentrant, 0);
08429   return Success;
08430 }
08431 
08432 Status
08433 AttributeComponentSet::find(const char *attrpath, Index *&index_comp)
08434 {
08435   Status s;
08436   if (!index_cache) {
08437     s = makeCache();
08438     if (s) return s;
08439   }
08440 
08441   index_comp = (Index *)index_cache->find(attrpath);
08442   return Success;
08443 }
08444 
08445 Status
08446 AttributeComponentSet::hasIndex(bool &has_index, std::string &idx_str)
08447 {
08448   Status s;
08449   if (!index_cache) {
08450     s = makeCache();
08451     if (s)
08452       return s;
08453   }
08454 
08455   if (index_cache) {
08456     has_index = index_cache->comp_count > 0;
08457     for (int n = 0; n < index_cache->comp_count; n++) {
08458       if (n > 0)
08459         idx_str += ", ";
08460       idx_str += index_cache->comps[n].attrpath;
08461     }
08462   }
08463   else
08464     has_index = false;
08465   return Success;
08466 }
08467 
08468 
08469 Status
08470 AttributeComponentSet::find(const char *attrpath, NotNullConstraint *&notnull_comp)
08471 {
08472   Status s;
08473   if (!notnull_cache) {
08474     s = makeCache();
08475     if (s) return s;
08476   }
08477 
08478   notnull_comp = (NotNullConstraint *)notnull_cache->find(attrpath);
08479   return Success;
08480 }
08481 
08482 Status
08483 AttributeComponentSet::find(const char *attrpath, UniqueConstraint *&unique_comp)
08484 {
08485   Status s;
08486   if (!unique_cache) {
08487     s = makeCache();
08488     if (s) return s;
08489   }
08490 
08491   unique_comp = (UniqueConstraint *)unique_cache->find(attrpath);
08492   return Success;
08493 }
08494 
08495 Status
08496 AttributeComponentSet::find(const char *attrpath, CardinalityConstraint_Test *&card_comp)
08497 {
08498   Status s;
08499   if (!card_cache) {
08500     s = makeCache();
08501     if (s) return s;
08502   }
08503 
08504   card_comp = (CardinalityConstraint_Test *)card_cache->find(attrpath);
08505   return Success;
08506 }
08507 
08508 Status
08509 AttributeComponentSet::find(const char *attrpath,
08510                                CollAttrImpl *&collimpl_comp)
08511 {
08512   Status s;
08513   if (!collimpl_cache) {
08514     s = makeCache();
08515     if (s) return s;
08516   }
08517 
08518   collimpl_comp = (CollAttrImpl *)collimpl_cache->find(attrpath);
08519   return Success;
08520 }
08521 
08522 Status
08523 Attribute::destroyIndex(Database *db, Index *idx) const
08524 {
08525   IDB_LOG(IDB_LOG_IDX_REMOVE,
08526           ("Remove Index (%s::%s, "
08527            "index=%s)\n",
08528            (class_owner ? class_owner->getName() : "<unknown>"),
08529            name, idx->getAttrpath().c_str()));
08530           
08531   /*
08532   printf("destroying index idx=%p %s\n", idx->idx,
08533          idx->getIdxOid().toString());
08534   */
08535 
08536   if (!idx->idx && idx->getIdxOid().isValid()) {
08537     Status s = openMultiIndexRealize(db, idx);
08538     if (s) return s;
08539   }
08540 
08541   assert(idx->idx || !idx->getIdxOid().isValid());
08542 
08543   if (!idx->idx)
08544     return Success;
08545 
08546   //printf("destroying index oid=%s\n", Oid(idx->idx->oid()).toString());
08547   eyedbsm::Status s = idx->idx->destroy();
08548   if (s)
08549     return Exception::make(IDB_INDEX_ERROR, eyedbsm::statusGet(s));
08550 
08551   return Success;
08552 }
08553 
08554 Status
08555 Attribute::getAttrComp(Database *db, const char *clsname,
08556                           const char *attrpath, Object *&o)
08557 {
08558   OQL q(db, "select %s.attrpath = \"%s\"", clsname, attrpath);
08559   ObjectArray obj_arr;
08560   Status s = q.execute(obj_arr);
08561   if (s) return s;
08562   if (!obj_arr.getCount()) {
08563     o = 0;
08564     return Success;
08565   }
08566 
08567   if (obj_arr.getCount() > 1)
08568     return Exception::make(IDB_ATTRIBUTE_ERROR, "multiple index with attrpath '%s'", attrpath);
08569 
08570   o = const_cast<Object *>(obj_arr[0]);
08571   return Success;
08572 }
08573 
08574 Status
08575 Attribute::getIndex(Database *db, const char *attrpath,
08576                         Index *&idx)
08577 {
08578   return getAttrComp(db, "index", attrpath, (Object *&)idx);
08579 }
08580   
08581 Status
08582 Attribute::getUniqueConstraint(Database *db, const char *attrpath,
08583                                   UniqueConstraint *&unique)
08584 {
08585   return getAttrComp(db, "unique_constraint", attrpath, (Object *&)unique);
08586 }
08587   
08588 Status
08589 Attribute::getNotNullConstraint(Database *db, const char *attrpath,
08590                                    NotNullConstraint *&notnull)
08591 {
08592   return getAttrComp(db, "notnull_constraint", attrpath, (Object *&)notnull);
08593 }
08594   
08595 Status
08596 Attribute::getCollAttrImpl(Database *db, const char *attrpath,
08597                               CollAttrImpl *&collimpl)
08598 {
08599   return getAttrComp(db, "collection_attribute_implementation", attrpath, (Object *&)collimpl);
08600 }
08601 
08602 }

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