00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #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
00034
00035 #define ATTR_COMP_SET_OID_OFFSET 40
00036 #define CODE_ENDOFF
00037
00038 #define NEW_RELEASE
00039
00040
00041
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
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
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
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
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
00158
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
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
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
00536 eyedblib::int16 k = (eyedblib::int16)mode;
00537 int16_code(data, offset, alloc_size, &k);
00538
00539 int32_code(data, offset, alloc_size, &pdims);
00540
00541 int32_code(data, offset, alloc_size, &maxdims);
00542
00543 int16_code(data, offset, alloc_size, &ndims);
00544
00545
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));
00555
00556
00557 eyedblib::int16 k;
00558
00559 int16_decode(data, offset, &k);
00560 mode = (enum _mode)k;
00561
00562 int32_decode(data, offset, &pdims);
00563
00564 int32_decode(data, offset, &maxdims);
00565
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
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
00637
00638
00639
00640
00641 oid = xcls->getOid();
00642
00643
00644
00645
00646
00647
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
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
00673
00674
00675
00676
00677
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
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
00692 oid_code(data, offset, alloc_size, inv_spec.oid_cl.getOid());
00693
00694 int16_code(data, offset, alloc_size, &inv_spec.num);
00695
00696 char_code(data, offset, alloc_size, &is_basic_enum);
00697
00698 char_code(data, offset, alloc_size, &is_string);
00699
00700 int16_code(data, offset, alloc_size, &dspid);
00701
00702
00703
00704
00705
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
00715 string_code(data, offset, alloc_size, name);
00716
00717
00718 int32_code(data, offset, alloc_size, (eyedblib::int32 *)&idr_inisize);
00719
00720 int32_code(data, offset, alloc_size, (eyedblib::int32 *)&idr_poff);
00721
00722 int32_code(data, offset, alloc_size, (eyedblib::int32 *)&idr_item_psize);
00723
00724 int32_code(data, offset, alloc_size, (eyedblib::int32 *)&idr_psize);
00725
00726 int32_code(data, offset, alloc_size, (eyedblib::int32 *)&idr_voff);
00727
00728 int32_code(data, offset, alloc_size, (eyedblib::int32 *)&idr_item_vsize);
00729
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;
00765 oid_code(&data, offset, &alloc_size, cls->getOid().getOid());
00766 oid_code(&data, offset, &alloc_size, class_owner->getOid().getOid());
00767
00768
00769
00770
00771
00772
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
00782
00783 #ifdef CODE_ENDOFF
00784 int32_decode(data, offset, (eyedblib::int32 *)&endoff);
00785 #endif
00786 int16_decode(data, offset, &code);
00787
00788
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
00801
00802 oid_decode(data, offset, &_oid);
00803 inv_spec.oid_cl.setOid(_oid);
00804
00805 int16_decode(data, offset, &inv_spec.num);
00806
00807 char_decode(data, offset, &is_basic_enum);
00808
00809 char_decode(data, offset, &is_string);
00810
00811 int16_decode(data, offset, &dspid);
00812
00813 oid_decode(data, offset, &_oid);
00814 attr_comp_set_oid.setOid(_oid);
00815
00816
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
00826
00827
00828
00829
00830
00831
00832
00833
00834
00835
00836 int32_decode(data, offset, (eyedblib::int32 *)&idr_inisize);
00837
00838 int32_decode(data, offset, (eyedblib::int32 *)&idr_poff);
00839
00840 int32_decode(data, offset, (eyedblib::int32 *)&idr_item_psize);
00841
00842 int32_decode(data, offset, (eyedblib::int32 *)&idr_psize);
00843
00844 int32_decode(data, offset, (eyedblib::int32 *)&idr_voff);
00845
00846 int32_decode(data, offset, (eyedblib::int32 *)&idr_item_vsize);
00847
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
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
00915
00916
00917
00918
00919
00920
00921
00922
00923
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;
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
01020
01021
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
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
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
01289 o->asCollection()->setCardinalityConstraint(card_to_set);
01290
01291 o->asCollection()->setInverse(oid, num);
01292
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
01305
01306
01307 return Success;
01308 }
01309
01310 CollAttrImpl *collimpl;
01311 Status s = collimplPrologue(db, idx_ctx, collimpl);
01312
01313
01314
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
01323
01324
01325 o->asCollection()->setImplementation(idximpl);
01326
01327
01328
01329
01330
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,
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
01388 assert(isIndirect() == is_indirect);
01389
01390 if (!is_indirect) {
01391
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
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
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
01503
01504 memcpy(&o, data, sizeof(Object *));
01505
01506 bool should_release_masterobj = false;
01507
01508 bool auto_affect = false;
01509
01510 if (vdata) {
01511
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
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
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
01565
01566
01567
01568
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 {
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
01596
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
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,
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
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
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
01672
01673 for (int n = 0; n < nb; n++, data += SIZEOFOBJECT)
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
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
01728 mset(_idr, 0, sizeof(Object *));
01729
01730
01731
01732
01733
01734
01735 #if 0
01736 if (!isIndirect())
01737 mo->setDamaged(this);
01738 #endif
01739 }
01740
01741 if (r.isCycle()) {
01742
01743
01744
01745 return;
01746 }
01747 }
01748 }
01749
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
01900
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
01911
01912
01913
01914
01915
01916 se_idx = (idx ? idx->idx : 0);
01917 return Success;
01918 }
01919
01920
01921 #define NEW_ARGARR
01922
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
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
02091
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;
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
02155
02156
02157
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
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
02285 static const char fmt_error[] = "storage manager error '%s' "
02286 "reported when opening index in attribute '%s' of class '%s'";
02287
02288 Oid idx_oid;
02289
02290 Status status;
02291
02292
02293
02294
02295
02296
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
02310
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
02336
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),
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
02388
02389
02390
02391
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
02417
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),
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
02454
02455
02456
02457
02458
02459
02460 se_idx = new eyedbsm::HIdx
02461 (get_eyedbsm_DbHandle((DbHandle *)db->getDbHandle()->u.dbh),
02462 ktypes,
02463 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
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
02545
02546 if (!count)
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
02592
02593
02594
02595
02596
02597
02598
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
02612
02613
02614 #ifdef NEW_NOTNULL
02615
02616
02617
02618
02619
02620
02621
02622
02623
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
02635
02636
02637
02638
02639
02640
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
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
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
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 ¬null_comp, Bool ¬null,
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
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;
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
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);
02986 if (indirect) {
02987 eyedbsm::Oid toid;
02988 eyedbsm::x2h_oid(&toid, data);
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
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)
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
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
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
03388
03389 if ( 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
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
03551 {
03552 if (cls && cls->asCollectionClass() && !isIndirect())
03553 return Success;
03554
03555
03556
03557
03558
03559
03560
03561
03562
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
03631 {
03632
03633
03634
03635
03636
03637
03638
03639
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) {
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
03742
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
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
03848
03849
03850
03851
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
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
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);
03996 memcpy(vdata + (j * idr_item_vsize), &oo, sizeof(Object *));
03997 }
03998
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
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
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
04066
04067
04068 idx_ctx.push(db, cloid, this);
04069
04070 for (int j = 0; j < typmod.pdims; j++) {
04071 Object *o;
04072
04073
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
04090
04091
04092
04093 status = o->realizePerform(cloid, objoid, idx_ctx, rcm);
04094
04095 if (status)
04096 return status;
04097
04098
04099 #ifdef E_XDR_TRACE
04100 printf("%s: AttrDirect::realize : cmp\n", name);
04101 #endif
04102
04103
04104
04105
04106
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
04117
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
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
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
04299
04300
04301
04302
04303
04304
04305
04306
04307
04308
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
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
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
04404
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())
04464 cls->asEnumClass()->getRawData((Data)data, inidata+idr_inisize, nb);
04465 #ifdef E_XDR
04466 else
04467
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
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
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
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);
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();
04820 status = o->setDatabase(db);
04821 if (status != Success)
04822 return status;
04823
04824
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
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
05024
05025
05026
05027
05028
05029
05030
05031
05032
05033
05034
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
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
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
05258
05259
05260
05261
05262
05263
05264
05265
05266
05267
05268
05269
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
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
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
05605
05606
05607
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
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)
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
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
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)
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
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++)
05778 {
05779 Object *oo;
05780
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);
05786
05787 memcpy(nvdata + (j * idr_item_vsize), &oo, sizeof(Object *));
05788 }
05789
05790
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
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
05856
05857
05858
05859
05860
05861
05862
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
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
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
06012
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)
06126 {
06127
06128 #if 1
06129
06130
06131 setSize_realize(agr, agr->getIDR(), 0, True, True);
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
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
06167
06168
06169
06170
06171
06172
06173
06174
06175
06176
06177
06178
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)
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
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
06214 #ifdef E_XDR_TRACE
06215 printf("%s: AttrVarDim::copy -> needs XDR ? no\n", name);
06216 #endif
06217
06218
06219 if (pdata == VARS_DATA(_idr))
06220 npdata = pdata;
06221 else
06222 {
06223 npdata = (unsigned char *)malloc(wpsize);
06224
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
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
06261
06262
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
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
06281
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
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
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
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
06475
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
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
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
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
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
06611
06612
06613
06614
06615 if (!force)
06616 {
06617 setIsLoaded(agr, False);
06618
06619
06620
06621
06622
06623
06624
06625
06626
06627
06628
06629
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
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
06687 memcpy(&o, vdata + (j * SIZEOFOBJECT), sizeof(Object *));
06688
06689
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
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
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
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
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
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
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
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
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
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
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
07131 set_oid_realize(data, oid, nb, from);
07132
07133
07134
07135
07136
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
07317 memcpy(npdata, pdata, wpsize);
07318
07319 int wvsize = size * idr_item_vsize * typmod.pdims;
07320 Data nvdata = (unsigned char *)malloc(wvsize);
07321
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)
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);
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
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
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
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
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
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
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
08034
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
08061
08062
08063 Status
08064 Attribute::createComponentSet(Database *db)
08065 {
08066
08067
08068
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
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
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
08140
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
08165
08166
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
08195
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
08216
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
08228
08229
08230
08231
08232
08233
08234
08235
08236
08237
08238 const_cast<Class *>(dyn_class_owner)->unmakeAttrCompList();
08239
08240 return attr_comp_set->store();
08241 }
08242
08243
08244
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
08407
08408
08409
08410
08411
08412 if (!index_cache) {
08413 Status s = makeCache();
08414 if (s) {
08415
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
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 *¬null_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
08533
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
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 *¬null)
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 }