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 #define protected public
00026 #include "odl.h"
00027 #include "misc.h"
00028 #include "eyedb/internals/ClassPeer.h"
00029 #include "eyedb/internals/ObjectPeer.h"
00030
00031 #include "oql_p.h"
00032 #include "CollectionBE.h"
00033 #include <sstream>
00034 using std::ostringstream;
00035
00036
00037
00038 using namespace std;
00039
00040 namespace eyedb {
00041
00042 extern FILE *odl_fd;
00043 #define SHBE " must "
00044
00045 class odlPostUpdate {
00046 static LinkedList list;
00047 Oid oclsoid;
00048 Class *cls;
00049
00050 odlPostUpdate(const Oid &_oclsoid, Class *_cls) {
00051 oclsoid = _oclsoid;
00052 cls = _cls;
00053 }
00054
00055 Status perform(Database *db);
00056
00057 public:
00058 static void add(const Oid &oclsoid, Class *cls);
00059 static Status realize(Database *db);
00060 };
00061
00062 LinkedList odlPostUpdate::list;
00063
00064
00065
00066
00067
00068 void
00069 odlUpdateItem::initDisplay()
00070 {
00071 static int init;
00072
00073 if (!init)
00074 {
00075 fprintf(odl_fd, "\n");
00076 init = 1;
00077 }
00078 }
00079
00080 void
00081 odlUpdateItem::initDisplayDiff(Database *_db, const char *_odlfile)
00082 {
00083 static Database *db;
00084 static const char *odlfile;
00085 static int init;
00086
00087 if (_db)
00088 {
00089 db = _db;
00090 odlfile = _odlfile;
00091 return;
00092 }
00093
00094 if (!init)
00095 {
00096 fprintf(odl_fd, "\nDifferences between database '%s' and '%s':\n\n",
00097 db->getName(), odlfile);
00098 init = 1;
00099 }
00100 }
00101
00102
00103
00104
00105
00106 void
00107 odlUpdateComponent::realize(Database *db, Schema *m)
00108 {
00109 if (cls_comp) {
00110 cls_comp->setDatabase(db);
00111 cls_comp->setClassOwner(m->getClass(cls_comp->getClassOwner()->getName()));
00112
00113 Class *clown = cls_comp->getClassOwner();
00114 if (!clown->getIDR() && clown->getUserData())
00115 ObjectPeer::setIDR(clown,
00116 ((Class *)clown->getUserData())->getIDR());
00117 cls_comp->setClassOwnerOid(cls_comp->getClassOwner()->getOid());
00118 }
00119 else {
00120 attr_comp->setDatabase(db);
00121 }
00122 }
00123
00124 Status
00125 odlRemoveComponent::prePerform(Database *db, Schema *m)
00126 {
00127 return Success;
00128 }
00129
00130 odlAddComponent::odlAddComponent(ClassComponent *_comp) :
00131 odlUpdateComponent(_comp)
00132 {
00133 #ifdef TRACE
00134 printf("AddComponent(%p)\n", this);
00135 printf("AddComponent(%p)\n", this);
00136 printf("%s '", cls_comp->getClass()->getCanonicalName());
00137 cls_comp->m_trace(stdout, 0, 0, NoRecurs);
00138 printf("\n");
00139 #endif
00140 }
00141
00142 odlAddComponent::odlAddComponent(AttributeComponent *_attr_comp) :
00143 odlUpdateComponent(_attr_comp)
00144 {
00145 #ifdef TRACE
00146 printf("AddComponent(%p)\n", this);
00147 printf("%s '", attr_comp->getClassOwner()->getCanonicalName());
00148 comp->m_trace(stdout, 0, AttrCompDetailTrace, NoRecurs);
00149 printf("\n");
00150 #endif
00151 }
00152
00153 Status
00154 odlAddComponent::postPerform(Database *db, Schema *m)
00155 {
00156 realize(db, m);
00157 display();
00158
00159 #ifdef TRACE
00160 printf("realizing component %p %s %s addcomponent::postPerform\n", comp,
00161 cls_comp->getName(), cls_comp->getOid().toString());
00162 #endif
00163 if (cls_comp)
00164 return cls_comp->realize_for_update();
00165 return attr_comp->realize();
00166 }
00167
00168 odlRemoveComponent::odlRemoveComponent(ClassComponent *_cls_comp) :
00169 odlUpdateComponent(_cls_comp)
00170 {
00171 #ifdef TRACE
00172 printf("RemoveComponent(%p)\n", this);
00173 printf("%s '", cls_comp->getClass()->getCanonicalName());
00174 comp->m_trace(stdout, 0, 0, NoRecurs);
00175 printf("\n");
00176 #endif
00177 }
00178
00179 odlRemoveComponent::odlRemoveComponent(AttributeComponent *_attr_comp) :
00180 odlUpdateComponent(_attr_comp)
00181 {
00182 #ifdef TRACE
00183 printf("RemoveComponent(%p)\n", this);
00184 printf("%s '", attr_comp->getClassOwner()->getCanonicalName());
00185 comp->m_trace(stdout, 0, AttrCompDetailTrace, NoRecurs);
00186 printf("\n");
00187 #endif
00188 }
00189
00190 Status
00191 odlRemoveComponent::postPerform(Database *db, Schema *m)
00192 {
00193 if (cls_comp && cls_comp->isRemoved())
00194 return Success;
00195
00196 if (attr_comp && attr_comp->isRemoved())
00197 return Success;
00198
00199 realize(db, m);
00200 display();
00201
00202 if (cls_comp)
00203 return cls_comp->remove_for_update();
00204
00205 return attr_comp->remove();
00206 }
00207
00208 void
00209 odlUpdateComponent::display()
00210 {
00211 odlUpdateItem::initDisplay();
00212
00213
00214
00215 if (asRemoveComponent())
00216 fprintf(odl_fd, "Removing ");
00217
00218
00219
00220
00221 else if (updating)
00222 fprintf(odl_fd, "Updating ");
00223 else
00224 fprintf(odl_fd, "Creating ");
00225
00226 if (cls_comp) {
00227
00228 fprintf(odl_fd, "%s '", cls_comp->getClass()->getCanonicalName());
00229 cls_comp->m_trace(odl_fd, 0, 0, NoRecurs);
00230 }
00231 else {
00232
00233 fprintf(odl_fd, "%s '", attr_comp->getClass()->getCanonicalName());
00234 attr_comp->m_trace(odl_fd, 0, AttrCompDetailTrace, NoRecurs);
00235 }
00236
00237 if (asRemoveComponent())
00238 fprintf(odl_fd, "' from ");
00239 else
00240 fprintf(odl_fd, "' on ");
00241
00242 fprintf(odl_fd, "class '%s'...\n", (cls_comp ? cls_comp->getClassOwner()->getName() : attr_comp->getClassOwner()->getName()));
00243 }
00244
00245 void
00246 odlUpdateComponent::displayDiff(Database *db, const char *odlfile)
00247 {
00248 odlUpdateItem::initDisplayDiff(db, odlfile);
00249
00250 if (cls_comp) {
00251 fprintf(odl_fd, " class %s: ", cls_comp->getClassOwner()->getName());
00252 cls_comp->m_trace(odl_fd, 0, 0, NoRecurs);
00253 } else {
00254 fprintf(odl_fd, " class %s: ", attr_comp->getClassOwner()->getName());
00255 attr_comp->m_trace(odl_fd, 0, AttrCompDetailTrace, NoRecurs);
00256 }
00257
00258 fprintf(odl_fd, SHBE);
00259 if (asAddComponent())
00260 fprintf(odl_fd, "be added to database");
00261 else
00262 fprintf(odl_fd, "be removed from database");
00263
00264 fprintf(odl_fd, "\n");
00265 }
00266
00267
00268
00269
00270
00271 Status
00272 odlAddClass::prePerform(Database *db, Schema *m)
00273 {
00274 display();
00275 return Success;
00276 }
00277
00278 bool must_remove(const Class *cls, const Oid &cls_oid, bool check_self)
00279 {
00280 if (check_self && cls->getOid() == cls_oid)
00281 return true;
00282
00283 if (cls->asCollectionClass()) {
00284 const Class *coll_class = cls->asCollectionClass()->getCollClass();
00285 if (coll_class->getOid() == cls_oid)
00286 return true;
00287
00288 return false;
00289 }
00290
00291 if (cls->getParent() && cls->getParent()->getOid() == cls_oid)
00292 return true;
00293
00294 return false;
00295 }
00296
00297 odlRemoveClass::odlRemoveClass(Database *db, const Class *_cls,
00298 LinkedList *list) :
00299 odlUpdateClass(_cls), list(list)
00300 {
00301 Oid cls_oid = cls->getOid();
00302 }
00303
00304 Status
00305 odlRemoveClass::prePerform(Database *db, Schema *_m)
00306 {
00307 Oid cls_oid = cls->getOid();
00308
00309 const Schema *m = db->getSchema();
00310 const LinkedList *cls_lst = m->getClassList();
00311 LinkedListCursor c(cls_lst);
00312 Class *xcls;
00313
00314 string err;
00315
00316 while (c.getNext((void *&)xcls)) {
00317 if (must_remove(xcls, cls_oid, false))
00318 err += string("\n must remove class ") + xcls->getName();
00319 else {
00320 unsigned int attr_cnt;
00321 const Attribute **attrs = xcls->getAttributes(attr_cnt);
00322 for (int n = 0; n < attr_cnt; n++) {
00323 if (must_remove(attrs[n]->getClass(), cls_oid, true))
00324 err += string("\n must remove class ") + xcls->getName() +
00325 " or remove attribute " + attrs[n]->getClassOwner()->getName() +
00326 "::" + attrs[n]->getName();
00327 }
00328 }
00329 }
00330
00331 if (err.size())
00332 return Exception::make((string("while removing class ") + cls->getName() + ": " +
00333 err).c_str());
00334
00335 return Success;
00336 }
00337
00338 Status
00339 odlRemoveClass::postPerform(Database *db, Schema *m)
00340 {
00341 display();
00342
00343 const Class *ocls = (const Class *)cls->getUserData();
00344
00345 if (!ocls->isRemoved() && ocls->getOid().isValid()) {
00346 Status s = const_cast<Class *>(ocls)->remove_r
00347 (RecMode::NoRecurs, Class::RemoveInstances);
00348 if (s) return s;
00349 }
00350
00351 return Success;
00352 }
00353
00354 Status
00355 odlRenameClass::prePerform(Database *db, Schema *m)
00356 {
00357 return Success;
00358 }
00359
00360 Status
00361 odlReparentClass::prePerform(Database *db, Schema *m)
00362 {
00363 return Success;
00364 }
00365
00366 Status
00367 odlConvertClass::prePerform(Database *db, Schema *m)
00368 {
00369 return Success;
00370 }
00371
00372 void
00373 odlUpdateClass::display()
00374 {
00375 odlUpdateItem::initDisplay();
00376
00377 if (asRemoveClass())
00378 fprintf(odl_fd, "Removing");
00379 else if (asAddClass())
00380 fprintf(odl_fd, "Adding");
00381 else if (asConvertClass())
00382 fprintf(odl_fd, "Converting");
00383 else if (asReparentClass())
00384 fprintf(odl_fd, "Reparenting");
00385 else if (asRenameClass())
00386 fprintf(odl_fd, "Renaming");
00387
00388 fprintf(odl_fd, " class %s", cls->getName());
00389 if (asRenameClass())
00390 fprintf(odl_fd, " from %s", asRenameClass()->name);
00391 fprintf(odl_fd, "\n");
00392 }
00393
00394 void
00395 odlUpdateClass::displayDiff(Database *db, const char *odlfile)
00396 {
00397 odlUpdateItem::initDisplayDiff(db, odlfile);
00398
00399 fprintf(odl_fd, " class %s:" SHBE, cls->getName());
00400
00401 if (asRemoveClass())
00402 fprintf(odl_fd, "be removed from database");
00403 else if (asAddClass())
00404 fprintf(odl_fd, "be added to database");
00405 else if (asConvertClass())
00406 fprintf(odl_fd, "be converted");
00407 else if (asReparentClass())
00408 fprintf(odl_fd, "be reparented to %s", cls->getParent()->getName());
00409 else if (asRenameClass())
00410 fprintf(odl_fd, "be renamed from %s", asRenameClass()->name);
00411
00412 fprintf(odl_fd, "\n");
00413 }
00414
00415 Status
00416 odlUpdateClass::postPerform(Database *db, Schema *m)
00417 {
00418 if (!clsconv)
00419 return Success;
00420
00421 clsconv->setOidN(cls->getOid());
00422 return clsconv->realize();
00423 }
00424
00425
00426
00427
00428
00429 Status
00430 odlAddRelationship::postPerform(Database *db, Schema *m)
00431 {
00432 display();
00433 return Success;
00434 }
00435
00436 Status
00437 odlRemoveRelationship::postPerform(Database *db, Schema *m)
00438 {
00439 display();
00440 return Success;
00441 }
00442
00443 static const char *
00444 get_relship_card(const Attribute *item, const Attribute *invitem)
00445 {
00446 if (item->getClass()->asCollectionClass())
00447 {
00448 if (invitem->getClass()->asCollectionClass())
00449 return "many-to-many";
00450 return "many-to-one";
00451 }
00452
00453 if (invitem->getClass()->asCollectionClass())
00454 return "one-to-many";
00455 return "one-to-one";
00456 }
00457
00458 void
00459 odlUpdateRelationship::display()
00460 {
00461 odlUpdateItem::initDisplay();
00462
00463
00464
00465 if (asRemoveRelationship())
00466 fprintf(odl_fd, "Removing ");
00467 else
00468 fprintf(odl_fd, "Creating ");
00469
00470 fprintf(odl_fd, "%s relationship %s::%s <-> %s::%s\n",
00471 get_relship_card(item, invitem),
00472 item->getClassOwner()->getName(), item->getName(),
00473 invitem->getClassOwner()->getName(),
00474 invitem->getName());
00475 }
00476
00477 void
00478 odlUpdateRelationship::displayDiff(Database *db, const char *odlfile)
00479 {
00480 odlUpdateItem::initDisplayDiff(db, odlfile);
00481
00482 fprintf(odl_fd, " class %s: ", item->getClassOwner()->getName());
00483 fprintf(odl_fd, "%s relationship %s::%s <-> %s::%s",
00484 get_relship_card(item, invitem),
00485 item->getClassOwner()->getName(), item->getName(),
00486 invitem->getClassOwner()->getName(),
00487 invitem->getName());
00488
00489 fprintf(odl_fd, SHBE);
00490 if (asAddRelationship())
00491 fprintf(odl_fd, "be added to database");
00492 else
00493 fprintf(odl_fd, "be removed from database");
00494
00495 fprintf(odl_fd, "\n");
00496 }
00497
00498
00499
00500
00501
00502 void
00503 odlUpdateAttribute::display()
00504 {
00505 odlUpdateItem::initDisplay();
00506
00507 if (asAddAttribute())
00508 fprintf(odl_fd, "Adding");
00509 else if (asRemoveAttribute())
00510 fprintf(odl_fd, "Removing");
00511
00512 fprintf(odl_fd, " attribute %s::%s", cls->getName(), item->getName());
00513
00514 fprintf(odl_fd, "\n");
00515 }
00516
00517 void
00518 odlUpdateAttribute::displayDiff(Database *db, const char *odlfile)
00519 {
00520 odlUpdateItem::initDisplayDiff(db, odlfile);
00521
00522 fprintf(odl_fd, " class %s: attribute %s", cls->getName(), item->getName());
00523
00524 fprintf(odl_fd, SHBE);
00525 if (asAddAttribute())
00526 fprintf(odl_fd, "be added to database");
00527 else if (asRemoveAttribute())
00528 fprintf(odl_fd, "be removed from database");
00529
00530 fprintf(odl_fd, "\n");
00531 }
00532
00533 Status
00534 odlUpdateAttribute::invalidateCollClassOid(Database *db,
00535 const Class *ocls)
00536 {
00537 const LinkedList *list = db->getSchema()->getClassList();
00538 LinkedListCursor c(list);
00539 Class *xcls;
00540 while (c.getNext((void *&)xcls))
00541 {
00542 CollectionClass *cls_c = xcls->asCollectionClass();
00543 if (!cls_c)
00544 continue;
00545 if (cls_c->getCollClass()->getOid() == ocls->getOid())
00546 cls_c->invalidateCollClassOid();
00547 }
00548
00549 return Success;
00550 }
00551
00552 Status
00553 odlUpdateAttribute::invalidateInverseOid(Database *db,
00554 const Class *ocls)
00555 {
00556 const LinkedList *list = db->getSchema()->getClassList();
00557 LinkedListCursor c(list);
00558 Class *xcls;
00559 while (c.getNext((void *&)xcls))
00560 {
00561 AgregatClass *cls_c = xcls->asAgregatClass();
00562 if (!cls_c || cls_c->isSystem())
00563 continue;
00564 unsigned int attr_cnt;
00565 const Attribute **attrs = cls_c->getAttributes(attr_cnt);
00566 for (int i = 0; i < attr_cnt; i++)
00567 {
00568 const char *clsname = 0;
00569 attrs[i]->getInverse(&clsname, 0, 0);
00570 if (clsname && !strcmp(clsname, ocls->getName()))
00571 {
00572 xcls->touch();
00573 break;
00574 }
00575 }
00576 }
00577
00578 return Success;
00579 }
00580
00581 Status
00582 odlUpdateAttribute::reportExtentOid(Database *db, const Class *ocls)
00583 {
00584 Collection *extent = 0, *cls_comp;
00585 Status s = ocls->getExtent(extent);
00586 if (s) return s;
00587 s = ocls->getComponents(cls_comp);
00588 if (s) return s;
00589 const_cast<Class *>(cls)->setExtentCompOid(extent->getOid(),
00590 cls_comp->getOid());
00591 return Success;
00592 }
00593
00594 static Bool
00595 odlIsInSchema(Database *db, const Class *scls)
00596 {
00597 Schema *m = db->getSchema();
00598 const LinkedList *list = m->getClassList();
00599 LinkedListCursor c(list);
00600
00601 Class *cls;
00602 while (c.getNext((void *&)cls))
00603 if (cls == scls)
00604 return True;
00605
00606 return False;
00607 }
00608
00609 Status
00610 odlUpdateAttribute::check()
00611 {
00612 if (!odlAgregatClass::getDeclaredCount())
00613 return Success;
00614
00615 std::string s = "when the schema is evolving all database user classes "
00616 "must be defined in the odl file:\nmissing ";
00617 LinkedList &list = odlAgregatClass::getDeclaredList();
00618 LinkedListCursor c(list);
00619 char *name;
00620 for (int i = 0; c.getNext((void *&)name); i++)
00621 s += std::string(i ? ", " : "") + name;
00622 s += std::string(" class definition") + (list.getCount() > 1 ? "s" : "");
00623 return Exception::make(IDB_ERROR, s);
00624 }
00625
00626 static Bool
00627 is_defined(const Class *cls)
00628 {
00629 LinkedList &list = odlAgregatClass::getDeclaredList();
00630 LinkedListCursor c(list);
00631 char *name;
00632
00633 while (c.getNext((void *&)name))
00634 if (!strcmp(name, cls->getName()))
00635 return False;
00636
00637 return True;
00638 }
00639
00640 static Bool
00641 refer_to(const Attribute *attr, const Class *cls);
00642
00643 static Bool
00644 refer_to(const Class *xcls, const Class *cls)
00645 {
00646 if (xcls->state)
00647 return False;
00648
00649 const_cast<Class *>(xcls)->state |= 1;
00650
00651 unsigned int attr_cnt;
00652 const Attribute **attrs = xcls->getAttributes(attr_cnt);
00653 for (int i = 0; i < attr_cnt; i++)
00654 if (refer_to(attrs[i], cls)) {
00655 const_cast<Class *>(xcls)->state &= ~1;
00656 return True;
00657 }
00658
00659 const_cast<Class *>(xcls)->state &= ~1;
00660 return False;
00661 }
00662
00663 static Bool
00664 refer_to(const Attribute *attr, const Class *cls)
00665 {
00666 const Class *attr_cls = attr->getClass();
00667 assert(attr_cls);
00668
00669 if (attr_cls->asBasicClass() ||
00670 attr_cls->asEnumClass() || attr_cls->asCollectionClass())
00671 return False;
00672
00673
00674 if (!strcmp(attr_cls->getName(), cls->getName()))
00675 return True;
00676
00677 return refer_to(attr_cls, cls);
00678 }
00679
00680 Status
00681 odlUpdateAttribute::check(Database *db, const Class *cls)
00682 {
00683 if (!odlAgregatClass::getDeclaredCount())
00684 return Success;
00685
00686 LinkedListCursor c(db->getSchema()->getClassList());
00687 Class *xcls;
00688 std::string s = "when the schema is evolving all database user classes "
00689 "referring to an evolving classes "
00690 "must be defined in the odl file:\n";
00691
00692 int n = 0;
00693 while (c.getNext((void *&)xcls))
00694 if (refer_to(xcls, cls) && !is_defined(xcls)) {
00695 s += std::string("class ") + xcls->getName() + " refers to class " +
00696 cls->getName() + " and definition is missing\n";
00697 n++;
00698 }
00699
00700 if (!n)
00701 return Success;
00702
00703 return Exception::make(IDB_ERROR, s);
00704 }
00705
00706
00707
00708
00709
00710
00711
00712 Status
00713 odlPostUpdate::perform(Database *db)
00714 {
00715 Collection *components;
00716 Status s = cls->getComponents(components, True);
00717 if (s) return s;
00718
00719 Iterator c(components);
00720
00721 #ifdef TRACE
00722 printf("REALIZING %s %s\n", cls->getName(), oclsoid.toString());
00723 #endif
00724 ClassComponent *cls_comp;
00725 for (;;) {
00726 Bool found;
00727 s = c.scanNext(found, (Object *&)cls_comp);
00728 if (s) return s;
00729 if (!found) break;
00730 if (cls_comp->getClassOwner()->getOid() == oclsoid) {
00731 #ifdef TRACE
00732 printf("changing class owner for %s\n", cls_comp->getName());
00733 #endif
00734 cls_comp->setClassOwner(cls);
00735 s = cls_comp->realize();
00736 if (s) return s;
00737 }
00738 }
00739
00740 unsigned int attr_cnt;
00741 Attribute **attrs = (Attribute **)cls->getAttributes(attr_cnt);
00742
00743 return Success;
00744 }
00745
00746 Status
00747 odlPostUpdate::realize(Database *db)
00748 {
00749 LinkedListCursor c(list);
00750 odlPostUpdate *p;
00751 while (c.getNext((void *&)p)) {
00752 Status s = p->perform(db);
00753 if (s) return s;
00754 }
00755 return Success;
00756 }
00757
00758 void
00759 odlPostUpdate::add(const Oid &oclsoid, Class *cls)
00760 {
00761 list.insertObjectLast(new odlPostUpdate(oclsoid, (Class *)cls));
00762 }
00763
00764 Status
00765 odl_post_update(Database *db)
00766 {
00767 return odlPostUpdate::realize(db);
00768 }
00769
00770 static void
00771 odl_components_manage(const Class *cls, const Class *ocls)
00772 {
00773 ClassComponent *cls_comp;
00774 LinkedListCursor c(cls->getCompList());
00775
00776 #ifdef TRACE
00777 printf("Components of new class %s %s\n", cls->getName(), cls->getOid().toString());
00778 #endif
00779 while (c.getNext((void *&)cls_comp)) {
00780 #ifdef TRACE
00781 printf("\t%s %s\n", cls_comp->getOid().toString(), cls_comp->getName());
00782 #endif
00783 if (!cls_comp->getOid().isValid()) {
00784
00785 LinkedListCursor oc(ocls->getCompList());
00786 ClassComponent *ocls_comp;
00787 const char *cname = cls_comp->getName().c_str();
00788 while (oc.getNext((void *&)ocls_comp)) {
00789 if (!strcmp(cname, ocls_comp->getName().c_str())) {
00790 ObjectPeer::setOid(cls_comp, ocls_comp->getOid());
00791 #ifdef TRACE
00792 printf("\tsetting %p %s to %s [%s vs. %s %p %p]\n", comp, ocls_comp->getOid().toString(), cls_comp->getName(), cls_comp->getClassOwner()->getOid().toString(),
00793 ocls_comp->getClassOwner()->getOid().toString(),
00794 cls_comp->getClassOwner(), ocls_comp->getClassOwner());
00795 #endif
00796 break;
00797 }
00798 }
00799 #ifdef TRACE
00800 if (!cls_comp->getOid().isValid()) {
00801 printf("WARNING %s has no oid\n", cls_comp->getName());
00802 }
00803 #endif
00804 }
00805
00806
00807
00808
00809
00810 }
00811
00812 const_cast<LinkedList *>(cls->getCompList())->empty();
00813 const_cast<Class *>(cls)->setUserData("eyedb:odl::update", AnyUserData);
00814
00815 #ifdef TRACE
00816 printf("Components of old class %s %s\n", ocls->getName(), ocls->getOid().toString());
00817
00818 LinkedListCursor oc(ocls->getCompList());
00819 while (oc.getNext((void *&)comp)) {
00820 printf("\t%s %s\n", cls_comp->getOid().toString(), cls_comp->getName());
00821 }
00822 #endif
00823 }
00824
00825 Status
00826 odlUpdateAttribute::initClassConv(Database *db)
00827 {
00828 Status s = check(db, cls);
00829 if (s) return s;
00830
00831 clsconv = new ClassConversion(db);
00832
00833 const Class *ocls = (const Class *)cls->getUserData();
00834 assert(ocls);
00835 odl_components_manage(cls, ocls);
00836
00837 #ifdef TRACE
00838 printf("ocls %s [%p] %s in_schema=%s is_removed=%s\n", ocls->getName(), ocls,
00839 ocls->getOid().toString(), odlIsInSchema(db, ocls) ? "yes" : "no",
00840 ocls->isRemoved() ? "yes" : "no");
00841 printf("cls %s [%p] %s in_schema=%s is_removed=%s\n\n", cls->getName(), cls,
00842 cls->getOid().toString(), odlIsInSchema(db, cls) ? "yes" : "no",
00843 cls->isRemoved() ? "yes" : "no");
00844 #endif
00845 clsconv->setOidO(ocls->getOid());
00846 if (!ocls->isRemoved() && ocls->getOid().isValid())
00847 {
00848 #ifdef TRACE
00849 printf("removing class %p %s %s keeping %p\n", ocls, ocls->getName(),
00850 ocls->getOid().toString(), cls);
00851 #endif
00852 odlPostUpdate::add(ocls->getOid(), (Class *)cls);
00853 Status s = const_cast<Class *>(ocls)->remove_r();
00854 if (s) return s;
00855
00856 s = invalidateCollClassOid(db, ocls);
00857 if (s) return s;
00858 s = invalidateInverseOid(db, ocls);
00859 if (s) return s;
00860 s = reportExtentOid(db, ocls);
00861 if (s) return s;
00862 ObjectPeer::setOid(const_cast<Class *>(cls), Oid::nullOid);
00863 const_cast<Class *>(cls)->setXInfo(IDB_XINFO_CLASS_UPDATE);
00864 }
00865
00866 #ifdef TRACE
00867 printf("[after] ocls %s [%p] %s in_schema=%s is_removed=%s\n", ocls->getName(), ocls,
00868 ocls->getOid().toString(), odlIsInSchema(db, ocls) ? "yes" : "no",
00869 ocls->isRemoved() ? "yes" : "no");
00870 printf("[after] cls %s [%p] %s in_schema=%s is_removed=%s\n\n", cls->getName(), cls,
00871 cls->getOid().toString(), odlIsInSchema(db, cls) ? "yes" : "no",
00872 cls->isRemoved() ? "yes" : "no");
00873 #endif
00874
00875 clsconv->setClsname(cls->getName());
00876 clsconv->setAttrname(item->getName());
00877 clsconv->setAttrnum(item->getNum());
00878 return Success;
00879 }
00880
00881 Status
00882 odlUpdateAttribute::postPerform(Database *db, Schema *m)
00883 {
00884 if (!clsconv)
00885 return Success;
00886
00887 clsconv->setOidN(cls->getOid());
00888 return clsconv->realize();
00889 }
00890
00891 Status
00892 odlAddAttribute::prePerform(Database *db, Schema *m)
00893 {
00894 display();
00895 Offset offset;
00896 Size item_psize, psize, item_inisize;
00897 item->getPersistentIDR(offset, item_psize, psize, item_inisize);
00898
00899 Status s = initClassConv(db);
00900 if (s) return s;
00901
00902 clsconv->setUpdtype(ADD_ATTR);
00903 clsconv->setOffsetO(0);
00904 clsconv->setOffsetN(offset);
00905 clsconv->setSizeO(0);
00906 clsconv->setSizeN(psize);
00907
00908 #ifdef TRACE
00909 printf("add attribute %s: %d %d %d %d\n", item->getName(), offset,
00910 item_psize, psize, item_inisize);
00911 #endif
00912 return Success;
00913 }
00914
00915 Status
00916 odlRemoveAttribute::prePerform(Database *db, Schema *m)
00917 {
00918 display();
00919
00920 Offset offset;
00921 Size item_psize, psize, item_inisize;
00922 item->getPersistentIDR(offset, item_psize, psize, item_inisize);
00923
00924 Status s = initClassConv(db);
00925 if (s) return s;
00926
00927 clsconv->setUpdtype(RMV_ATTR);
00928 clsconv->setOffsetO(0);
00929 clsconv->setOffsetN(offset);
00930 clsconv->setSizeO(0);
00931 clsconv->setSizeN(psize);
00932
00933 #ifdef TRACE
00934 printf("remove attribute %s: %d %d %d %d\n", item->getName(), offset,
00935 item_psize, psize, item_inisize);
00936 #endif
00937
00938 return Success;
00939 }
00940
00941 Status
00942 odlRenameAttribute::prePerform(Database *db, Schema *m)
00943 {
00944 display();
00945 const_cast<Class *>(cls)->touch();
00946 return Success;
00947 }
00948
00949 #define CNV(CLSTYP, CNVTYP) \
00950 if (ncls->as##CLSTYP##Class()) { \
00951 clsconv->setCnvtype(CNVTYP); \
00952 odlUpdateItem::initDisplay(); \
00953 fprintf(odl_fd, "Converting attribute %s::%s using " #CNVTYP " conversion method\n", cls->getName(), item->getName()); \
00954 return Success; \
00955 }
00956
00957 #define CNV_TO_CHAR(CNVTYP) \
00958 if (ncls->asCharClass()) { \
00959 odlUpdateItem::initDisplay(); \
00960 if (item->isVarDim()) { \
00961 clsconv->setCnvtype(CNVTYP##_TO_STRING); \
00962 fprintf(odl_fd, "Converting attribute %s::%s using " #CNVTYP "_TO_STRING conversion method\n", cls->getName(), item->getName()); \
00963 } \
00964 else { \
00965 clsconv->setCnvtype(CNVTYP##_TO_CHAR); \
00966 fprintf(odl_fd, "Converting attribute %s::%s using " #CNVTYP "_TO_CHAR conversion method\n", cls->getName(), item->getName()); \
00967 } \
00968 return Success; \
00969 }
00970
00971 #define CNV_FROM_CHAR(CLSTYP, CNVTYP) \
00972 if (ncls->as##CLSTYP##Class()) { \
00973 odlUpdateItem::initDisplay(); \
00974 if (oitem->isVarDim()) { \
00975 clsconv->setCnvtype(STRING_TO_##CNVTYP); \
00976 fprintf(odl_fd, "Converting attribute %s::%s using STRING_TO_" #CNVTYP " conversion method\n", cls->getName(), item->getName()); \
00977 } \
00978 else { \
00979 clsconv->setCnvtype(CHAR_TO_##CNVTYP); \
00980 fprintf(odl_fd, "Converting attribute %s::%s using CHAR_TO_" #CNVTYP " conversion method\n", cls->getName(), item->getName()); \
00981 } \
00982 return Success; \
00983 }
00984
00985 #define CNV_FROM_CHAR_TO_CHAR() \
00986 if (ncls->asCharClass()) { \
00987 odlUpdateItem::initDisplay(); \
00988 if (item->isVarDim()) { \
00989 if (oitem->isVarDim()) \
00990 return Exception::make(IDB_ERROR, "internal error: unexpected string to string conversion"); \
00991 clsconv->setCnvtype(CHAR_TO_STRING); \
00992 fprintf(odl_fd, "Converting attribute %s::%s using CHAR_TO_STRING conversion method\n", cls->getName(), item->getName()); \
00993 } \
00994 else { \
00995 if (oitem->isVarDim()) {\
00996 clsconv->setCnvtype(STRING_TO_CHAR); \
00997 fprintf(odl_fd, "Converting attribute %s::%s using STRING_TO_CHAR conversion method\n", cls->getName(), item->getName()); \
00998 } \
00999 else { \
01000 clsconv->setCnvtype(CHAR_TO_CHAR); \
01001 fprintf(odl_fd, "Converting attribute %s::%s using CHAR_TO_CHAR conversion method\n", cls->getName(), item->getName()); \
01002 } \
01003 } \
01004 return Success; \
01005 }
01006
01007 static Index *
01008 odl_fill_index(Index *ridx, Index *idx)
01009 {
01010 return 0;
01011 }
01012
01013 static Index *
01014 odl_clone_index(Index *idx)
01015 {
01016 return 0;
01017 }
01018
01019 Status
01020 odlConvertAttribute::prePerformBasic(Schema *m, const Class *ncls,
01021 const Class *ocls)
01022 {
01023 assert(0);
01024
01025 if (ocls->asInt16Class()) {
01026 CNV(Int16, INT16_TO_INT16);
01027 CNV(Int32, INT16_TO_INT32);
01028 CNV(Int64, INT16_TO_INT64);
01029 CNV(Float, INT16_TO_FLOAT);
01030 CNV(Byte, INT16_TO_BYTE);
01031 CNV_TO_CHAR(INT16);
01032 }
01033 else if (ocls->asInt32Class()) {
01034 CNV(Int32, INT32_TO_INT32);
01035 CNV(Int16, INT32_TO_INT16);
01036 CNV(Int64, INT32_TO_INT64);
01037 CNV(Float, INT32_TO_FLOAT);
01038 CNV(Byte, INT32_TO_BYTE);
01039 CNV_TO_CHAR(INT32);
01040 }
01041 else if (ocls->asInt64Class()) {
01042 CNV(Int64, INT64_TO_INT64);
01043 CNV(Int16, INT64_TO_INT16);
01044 CNV(Int32, INT64_TO_INT32);
01045 CNV(Float, INT64_TO_FLOAT);
01046 CNV(Byte, INT64_TO_BYTE);
01047 CNV_TO_CHAR(INT64);
01048 }
01049 else if (ocls->asFloatClass()) {
01050 CNV(Float, FLOAT_TO_FLOAT);
01051 CNV(Int16, FLOAT_TO_INT16);
01052 CNV(Int32, FLOAT_TO_INT32);
01053 CNV(Int64, FLOAT_TO_INT64);
01054 CNV(Byte, FLOAT_TO_BYTE);
01055 CNV_TO_CHAR(FLOAT);
01056 }
01057 else if (ocls->asCharClass()) {
01058 CNV_FROM_CHAR_TO_CHAR();
01059 CNV_FROM_CHAR(Int16, INT16);
01060 CNV_FROM_CHAR(Int32, INT32);
01061 CNV_FROM_CHAR(Int64, INT64);
01062 CNV_FROM_CHAR(Byte, BYTE);
01063 CNV_FROM_CHAR(Float, FLOAT);
01064 }
01065 else if (ocls->asByteClass()) {
01066 CNV(Byte, BYTE_TO_BYTE);
01067 CNV(Int16, BYTE_TO_INT16);
01068 CNV(Int32, BYTE_TO_INT32);
01069 CNV(Int64, BYTE_TO_INT64);
01070 CNV(Float, BYTE_TO_FLOAT);
01071 CNV_TO_CHAR(BYTE);
01072 }
01073 else if (ocls->asEnumClass()) {
01074 CNV(Enum, ENUM_TO_ENUM);
01075 CNV(Int16, ENUM_TO_INT16);
01076 CNV(Int32, ENUM_TO_INT32);
01077 CNV(Int64, ENUM_TO_INT64);
01078 CNV(Byte, ENUM_TO_BYTE);
01079 CNV(Char, ENUM_TO_CHAR);
01080 CNV(Float, ENUM_TO_FLOAT);
01081 }
01082 else
01083 return Exception::make(IDB_ERROR,
01084 "conversion from class %s to class %s "
01085 "is not supported",
01086 ocls->getName(), ncls->getName());
01087
01088 return Success;
01089 }
01090
01091 static inline int
01092 get_dim(const TypeModifier &tmod)
01093 {
01094 return (tmod.mode & TypeModifier::VarDim) ? (-tmod.pdims) : tmod.pdims;
01095 }
01096
01097 #define NOT_(X, Y) \
01098 if (clsconv->getCnvtype() == X) \
01099 return Exception::make(IDB_ERROR, "conversion " #X " is not " #Y)
01100
01101 #define NOT_IMPLEMENTED(X) \
01102 NOT_(X, "yet implemented")
01103
01104 #define NOT_SUPPORTED(X) \
01105 NOT_(X, "supported")
01106
01107 Status
01108 odlConvertAttribute::prePerform(Database *db, Schema *m)
01109 {
01110 odlUpdateItem::initDisplay();
01111
01112 const Class *ocls = oitem->getClass();
01113 const TypeModifier &otmod = oitem->getTypeModifier();
01114 const Class *ncls = item->getClass();
01115 const TypeModifier &tmod = item->getTypeModifier();
01116
01117 if (tmod.ndims > 1 || otmod.ndims > 1)
01118 return Exception::make(IDB_ERROR, "attribute %s::%s: "
01119 "no automatic conversion for multi-"
01120 "dimensional arrays",
01121 cls->getName(), item->getName());
01122
01123 Status s = initClassConv(db);
01124 if (s) return s;
01125 Offset offset_o, offset_n;
01126 Size dummy, psize_o, psize_n, item_psize_o, item_psize_n;
01127
01128 item->getPersistentIDR(offset_n, item_psize_n, psize_n, dummy);
01129 oitem->getPersistentIDR(offset_o, item_psize_o, psize_o, dummy);
01130
01131 clsconv->setOffsetO(offset_o);
01132 clsconv->setOffsetN(offset_n);
01133 clsconv->setUpdtype(CNV_ATTR);
01134
01135 clsconv->setSrcDim(get_dim(otmod));
01136 clsconv->setDestDim(get_dim(tmod));
01137
01138 #ifdef TRACE
01139 printf("odlConvertAttribute(%s::%s) dims = %d vs. %d\n",
01140 cls->getName(), item->getName(), clsconv->getSrcDim(),
01141 clsconv->getDestDim());
01142 #endif
01143
01144
01145 clsconv->setSizeO(psize_o);
01146 clsconv->setSizeN(psize_n);
01147
01148 if (ncls->asBasicClass() && (ocls->asBasicClass() || ocls->asEnumClass()))
01149 return prePerformBasic(m, ncls, ocls);
01150
01151
01152 if ( !strcmp(ncls->getName(), ocls->getName()))
01153 {
01154 if (!oitem->isIndirect() && !item->isIndirect() &&
01155 !ncls->asCollectionClass())
01156 {
01157 #ifdef TRACE
01158 printf("class %s: class modification propagation on attribute "
01159 "%s::%s\n",
01160 cls->getOid().toString(), cls->getName(), item->getName());
01161 printf("new class %s %s\n", ncls->getOid().toString(),
01162 ncls->getName());
01163 printf("old class %s %s\n", ocls->getOid().toString(),
01164 ocls->getName());
01165 printf("attribute old class oid %s\n",
01166 oitem->getClass()->getOid().toString());
01167 #endif
01168
01169 #ifdef VERBOSE_2
01170 odlUpdateItem::initDisplay();
01171 fprintf(odl_fd, "Converting attribute %s::%s", cls->getName(),
01172 item->getName());
01173 fprintf(odl_fd, " using CLASS_TO_CLASS conversion method\n");
01174 #endif
01175
01176
01177
01178 clsconv->setSizeO(item_psize_o);
01179 clsconv->setSizeN(item_psize_n);
01180 clsconv->setRoidO(ocls->getOid());
01181 clsconv->setCnvtype(CLASS_TO_CLASS);
01182
01183 return Success;
01184 }
01185
01186 if (!oitem->isIndirect() && item->isIndirect())
01187 return Exception::make(IDB_ERROR, "attribute %s::%s: "
01188 "conversion between a direct "
01189 "and an indirect attribute is not supported",
01190 cls->getName(), item->getName());
01191
01192 if (oitem->isIndirect() && !item->isIndirect())
01193 return Exception::make(IDB_ERROR, "attribute %s::%s: "
01194 "conversion between an indirect "
01195 "and a direct attribute is not supported",
01196 cls->getName(), item->getName());
01197
01198 clsconv->setCnvtype(NIL_CNV);
01199
01200
01201
01202
01203 #ifdef TRACE
01204 printf("nil conversion on %s::%s\n", cls->getName(), item->getName());
01205 #endif
01206 return Success;
01207 }
01208
01209
01210
01211
01212
01213
01214
01215
01216 NOT_SUPPORTED(STRING_TO_CHAR);
01217
01218 NOT_SUPPORTED(STRING_TO_INT16);
01219
01220 NOT_SUPPORTED(STRING_TO_INT32);
01221
01222 NOT_SUPPORTED(STRING_TO_INT64);
01223
01224 NOT_SUPPORTED(STRING_TO_FLOAT);
01225
01226 NOT_SUPPORTED(STRING_TO_BYTE);
01227
01228 return Exception::make(IDB_ERROR, "conversion from class %s to class %s "
01229 "is not supported",
01230 ocls->getName(), ncls->getName());
01231 }
01232
01233 Status
01234 odlReorderAttribute::prePerform(Database *db, Schema *m)
01235 {
01236 display();
01237 return Success;
01238 }
01239
01240 Status
01241 odlMigrateAttribute::prePerform(Database *db, Schema *m)
01242 {
01243 display();
01244 return Success;
01245 }
01246
01247 void
01248 odlReorderAttribute::display()
01249 {
01250 odlUpdateItem::initDisplay();
01251
01252 fprintf(odl_fd, "Ignoring %s::%s position in the ODL:",
01253 cls->getName(), item->getName());
01254
01255 fprintf(odl_fd, " has been reordered from #%d to #%d position\n",
01256 asReorderAttribute()->oldnum, asReorderAttribute()->newnum);
01257 }
01258
01259 void
01260 odlReorderAttribute::displayDiff(Database *db, const char *odlfile)
01261 {
01262 odlUpdateItem::initDisplayDiff(db, odlfile);
01263
01264 fprintf(odl_fd, " class %s: attribute %s", cls->getName(), item->getName());
01265
01266 fprintf(odl_fd, " automatically reordered from #%d to #%d in the ODL\n",
01267 oldnum, newnum);
01268 }
01269
01270 void
01271 odlConvertAttribute::display()
01272 {
01273 odlUpdateItem::initDisplay();
01274
01275 fprintf(odl_fd, "Converting attribute %s::%s", cls->getName(),
01276 item->getName());
01277
01278 if (upd_hints)
01279 fprintf(odl_fd, " using %s method", upd_hints->detail);
01280
01281 fprintf(odl_fd, "\n");
01282 }
01283
01284 void
01285 odlConvertAttribute::displayDiff(Database *db, const char *odlfile)
01286 {
01287 odlUpdateItem::initDisplayDiff(db, odlfile);
01288
01289 fprintf(odl_fd, " class %s: attribute %s", cls->getName(), item->getName());
01290
01291 fprintf(odl_fd, " must be converted");
01292 if (upd_hints)
01293 fprintf(odl_fd, " using %s method", upd_hints->detail);
01294
01295 fprintf(odl_fd, "\n");
01296 }
01297
01298 void
01299 odlRenameAttribute::display()
01300 {
01301 odlUpdateItem::initDisplay();
01302
01303 fprintf(odl_fd, "Renaming attribute %s::%s", cls->getName(),
01304 item->getName());
01305
01306 if (asRenameAttribute())
01307 fprintf(odl_fd, " from %s", upd_hints->detail);
01308
01309 if (upd_hints->detail2)
01310 fprintf(odl_fd, " using %s method", upd_hints->detail2);
01311
01312 fprintf(odl_fd, "\n");
01313 }
01314
01315 void
01316 odlRenameAttribute::displayDiff(Database *db, const char *odlfile)
01317 {
01318 odlUpdateItem::initDisplayDiff(db, odlfile);
01319
01320 fprintf(odl_fd, " class %s: attribute %s", cls->getName(), item->getName());
01321
01322 fprintf(odl_fd, " must be renamed from %s", upd_hints->detail);
01323
01324 if (upd_hints->detail2)
01325 fprintf(odl_fd, " using %s method", upd_hints->detail2);
01326
01327 fprintf(odl_fd, "\n");
01328 }
01329
01330 void
01331 odlMigrateAttribute::display()
01332 {
01333 odlUpdateItem::initDisplay();
01334
01335 fprintf(odl_fd, "Migrating attribute %s::%s", cls->getName(),
01336 item->getName());
01337
01338 fprintf(odl_fd, " to %s::%s", upd_hints->detail, upd_hints->detail2);
01339
01340 if (upd_hints->detail3)
01341 fprintf(odl_fd, " using %s method", upd_hints->detail3);
01342
01343 fprintf(odl_fd, "\n");
01344 }
01345
01346 void
01347 odlMigrateAttribute::displayDiff(Database *db, const char *odlfile)
01348 {
01349 odlUpdateItem::initDisplayDiff(db, odlfile);
01350
01351 fprintf(odl_fd, " class %s: attribute %s", cls->getName(), item->getName());
01352
01353 fprintf(odl_fd, " must migrate to %s::%s", upd_hints->detail, upd_hints->detail2);
01354
01355 if (upd_hints->detail3)
01356 fprintf(odl_fd, " using %s method", upd_hints->detail3);
01357
01358 fprintf(odl_fd, "\n");
01359 }
01360
01361 }