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