odl.cc

00001 /* 
00002    EyeDB Object Database Management System
00003    Copyright (C) 1994-2008 SYSRA
00004    
00005    EyeDB is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Lesser General Public
00007    License as published by the Free Software Foundation; either
00008    version 2.1 of the License, or (at your option) any later version.
00009    
00010    EyeDB is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Lesser General Public License for more details.
00014    
00015    You should have received a copy of the GNU Lesser General Public
00016    License along with this library; if not, write to the Free Software
00017    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA 
00018 */
00019 
00020 /*
00021    Author: Eric Viara <viara@sysra.com>
00022 */
00023 
00024 
00025 #include "odl.h"
00026 #include "misc.h"
00027 #include "eyedb/internals/ClassPeer.h"
00028 #include "eyedb/internals/ObjectPeer.h"
00029 #include "oql_p.h"
00030 #include "CollectionBE.h"
00031 #include <sstream>
00032 #include <pthread.h>
00033 #include "eyedblib/butils.h"
00034 #include "oqlctb.h"
00035 
00036 using std::ostringstream;
00037 
00038 #define NO_DIRECT_SET
00039 
00040 #define NEW_REORDER
00041 #define NEW_DIFF_RELSHIP
00042 
00043 namespace eyedb {
00044 
00045   LinkedList *odl_decl_list;
00046   ProgLang odl_lang = (ProgLang)0;
00047   int odl_error;
00048   int odl_diff;
00049   const char *odl_rootclass;
00050   LinkedList qseq_list;
00051   odlAgregatClass *odlAgregatClass::superclass;
00052   unsigned int odlAgregatClass::class_count;
00053   static const char *odl_prefix;
00054   static std::string odl_db_prefix;
00055   static Bool odl_gencode = False;
00056   Bool odl_system_class = False;
00057   Bool odl_rmv_undef_attrcomp = False;
00058   Bool odl_update_index = False;
00059   Bool odl_dynamic_attr = False;
00060   Bool odl_class_enums = False;
00061   Bool odl_sch_rm = False;
00062   Bool odl_smartptr = False;
00063 
00064   LinkedList odl_cls_rm;
00065   static Bool odl_not_check_missing = IDBBOOL(getenv("EYEDBNOCHECKMISSING"));
00066   FILE *odl_fd = stdout;
00067   static FILE *odl_fdnull = fopen("/dev/null", "rw");
00068   LinkedList odlAgregatClass::declared_list;
00069 
00070   static const char odlUPDLIST[] = "eyedb:odl:update:list";
00071   static const char odlSELF[] = "eyedb:odl:self";
00072   char odlMTHLIST[] = "eyedb:odl:method";
00073   char odlGENCOMP[] = "eyedb:odl:gencomp";
00074   char odlGENCODE[] = "eyedb:odl:gencode";
00075 
00076 #define odlUPDLIST(M) ((LinkedList *)(M)->getUserData(odlUPDLIST))
00077 #define odlMTHLIST(C) ((LinkedList *)(C)->getUserData(odlMTHLIST))
00078 
00079   FILE *
00080   run_cpp(FILE *fd, const char *cpp_cmd, const char *cpp_flags,
00081           const char *file);
00082 
00083   static
00084   Database *odl_get_dummy_db(Schema *m)
00085   {
00086     static Database *dumdb;
00087     if (!dumdb) {
00088       dumdb = new Database("dummy");
00089       dumdb->setSchema(m);
00090     }
00091 
00092     return dumdb;
00093   }
00094 
00095   static int
00096   magorder_error(const Class *cls, const char *attrname, const char *type)
00097   {
00098     if (attrname)
00099       odl_add_error
00100         (std::string("attribute: ") + cls->getName() + "::" +
00101          attrname + " cannot have several " + type + " specifications\n");
00102     else
00103       odl_add_error
00104         (std::string("class: ") + cls->getName() +
00105          " cannot have several " + type + " specifications\n");
00106 
00107     return 0;
00108   }
00109 
00110   static std::string odl_str_error;
00111 
00112   void
00113   odl_add_error(Status s)
00114   {
00115     ostringstream ostr;
00116     ostr << s;
00117     odl_str_error += ostr.str();
00118     if (odl_str_error[odl_str_error.size()-1] != '\n')
00119       odl_str_error += "\n";
00120     odl_error++;
00121   }
00122 
00123   void
00124   odl_add_error(const char *fmt, ...)
00125   {
00126     va_list ap, aq;
00127     va_start(ap, fmt);
00128     va_copy(aq, ap);
00129 
00130     char *s = eyedblib::getFBuffer(fmt, ap);
00131     vsprintf(s, fmt, aq);
00132     va_end(ap);
00133     odl_str_error += s;
00134     odl_error++;
00135   }
00136 
00137   void
00138   odl_add_error(const std::string &s)
00139   {
00140     odl_str_error += s;
00141     odl_error++;
00142   }
00143 
00144   static Status
00145   odl_status_error(int r = 0)
00146   {
00147     if (odl_error)
00148       return Exception::make(IDB_ERROR, odl_str_error.c_str());
00149 
00150     if (odl_str_error != std::string(""))
00151       fprintf(stderr, "%s\n", odl_str_error.c_str());
00152     else if (r)
00153       return Exception::make(IDB_ERROR, "");
00154 
00155     return Success;
00156   }
00157 
00158   static Class *
00159   getClass(Schema *m, const char *name, const char *prefix)
00160   {
00161     Class *cls;
00162 
00163     cls = m->getClass(name);
00164 
00165     if (cls) return cls;
00166 
00167     return m->getClass(makeName(name, prefix));
00168   }
00169 
00170   static void
00171   odl_copy_attr_comp_sets(Class *ocls, Class *cls)
00172   {
00173     unsigned int attr_cnt;
00174     Attribute **attrs = (Attribute **)cls->getAttributes(attr_cnt);
00175 
00176     for (int i = 0; i < attr_cnt; i++)
00177       {
00178         const Attribute *oattr = ocls->getAttribute(attrs[i]->getName());
00179         if (oattr) {
00180           /*
00181           printf("%s::%s attr_comp_set_oid %s -> %s\n",
00182                  oattr->getAttrCompSetOid().toString(),
00183                  attrs[i]->getAttrCompSetOid().toString(),
00184                  attrs[i]->getDynClassOwner()->getName(),
00185                  attrs[i]->getName());
00186           */
00187           attrs[i]->setAttrCompSetOid(oattr->getAttrCompSetOid());
00188         }
00189       }
00190   }
00191 
00192   static bool is_in(const std::vector<Class *> &rm_v, Class *cls) {
00193     std::vector<Class *>::const_iterator begin = rm_v.begin();
00194     std::vector<Class *>::const_iterator end = rm_v.end();
00195     while (begin != end) {
00196       if (cls == *begin)
00197         return true;
00198       ++begin;
00199     }
00200     return false;
00201   }
00202 
00203   static void
00204   odl_check_removed(Schema *m, LinkedList *&list)
00205   {
00206     if (odl_sch_rm) {
00207       if (!list)
00208         list = new LinkedList();
00209       const LinkedList *cls_list = m->getClassList();
00210       odlUpdateHint *rmHints = new odlUpdateHint(odlUpdateHint::Remove);
00211       Class *cls;
00212       // bug corrected 21/01/06
00213 #if 1
00214       std::vector<Class *> rm_v;
00215 
00216       unsigned int cnt = 0;
00217 
00218       do {
00219         LinkedListCursor c(cls_list);
00220         cnt = 0;
00221         while (c.getNext((void *&)cls)) {
00222           if (cls->isSystem() || is_in(rm_v, cls))
00223             continue;
00224 
00225           Class **subclasses;
00226           unsigned int subclass_cnt;
00227           cls->getSubClasses(subclasses, subclass_cnt);
00228           bool subclass_notin = false;
00229           for (int n = 0; n < subclass_cnt; n++) {
00230             if (subclasses[n] != cls && !is_in(rm_v, subclasses[n])) {
00231               subclass_notin = true;
00232               break;
00233             }
00234           }
00235 
00236           if (!subclass_notin) {
00237             rm_v.push_back(cls);
00238             cnt++;
00239           }
00240         }
00241 
00242       } while(cnt);
00243 
00244       std::vector<Class *>::iterator begin = rm_v.begin();
00245       std::vector<Class *>::iterator end = rm_v.end();
00246       while (begin != end) {
00247         cls = *begin;
00248         odlClassSpec *clsspec = new odlClassSpec(cls->getName(), 0,
00249                                                  cls->getName(), 0);
00250         new odlAgregatClass(rmHints, odl_Struct,  clsspec,
00251                             new odlDeclRootList());
00252         ++begin;
00253       }
00254 #else
00255       LinkedListCursor c(cls_list);
00256       while (c.getNext((void *&)cls)) {
00257         if (cls->isSystem())
00258           continue;
00259         odlClassSpec *clsspec = new odlClassSpec(cls->getName(), 0,
00260                                                  cls->getName(), 0);
00261         new odlAgregatClass(rmHints, odl_Struct,  clsspec,
00262                             new odlDeclRootList());
00263       }
00264 #endif
00265 
00266       return;
00267     }
00268     
00269     if (odl_cls_rm.getCount() == 0)
00270       return;
00271 
00272     if (!list)
00273       list = new LinkedList();
00274 
00275     char *name;
00276     LinkedListCursor c(odl_cls_rm);
00277     odlUpdateHint *rmHints = new odlUpdateHint(odlUpdateHint::Remove);
00278     while (c.getNext((void * &)name)) {
00279       //printf("adding declaration %s for removal\n", name);
00280       odlClassSpec *clsspec = new odlClassSpec(name, 0, name, 0);
00281       new odlAgregatClass(rmHints, odl_Struct,
00282                           clsspec,
00283                           new odlDeclRootList());
00284     }
00285   }
00286 
00287   static Bool
00288   odl_check_renamed_from(Schema *m, LinkedList *list, Class *cls)
00289   {
00290     LinkedListCursor clx(list);
00291     odlDeclaration *decl;
00292 
00293     while (clx.getNext((void *&)decl))
00294       if (decl->asAgregatClass()) {
00295         odlUpdateHint *upd_hints = decl->asAgregatClass()->upd_hints;
00296         if (upd_hints && upd_hints->type == odlUpdateHint::RenameFrom &&
00297             !strcmp(upd_hints->detail, cls->getName()))
00298           return True;
00299       }
00300 
00301     return False;
00302   }
00303 
00304   static void
00305   odl_check_missing(Schema *m, LinkedList *list)
00306   {
00307     LinkedListCursor cm(m->getClassList());
00308     Class *cls;
00309 
00310     while (cm.getNext((void *&)cls))
00311       {
00312         if (cls->isPartiallyLoaded())
00313           {
00314             Status s = m->manageClassDeferred(cls);
00315             if (s)
00316               {
00317                 odl_add_error(s);
00318                 break;
00319               }
00320           }
00321 
00322         if (cls->isSystem() || cls->asCollectionClass())
00323           continue;
00324 
00325         LinkedListCursor cl(list);
00326         odlDeclaration *decl;
00327         Bool found = False;
00328         while (cl.getNext((void *&)decl))
00329           if (!strcmp(decl->getName(), cls->getName()) ||
00330               (decl->getAliasName() &&
00331                !strcmp(decl->getAliasName(), cls->getName())))
00332             {
00333               found = True;
00334               break;
00335             }
00336 
00337         if (!found)
00338           {
00339 #define MANAGE_MISSING_CLASSES
00340             // disconnected the 21/05/2001
00341             // because this put the bordel in the components of missing
00342             // classes (index, methods, constraints)!
00343 #ifdef MANAGE_MISSING_CLASSES
00344 
00345             if (!odl_gencode) { // add not declared class on the fly
00346               if (!odl_check_renamed_from(m, list, cls)) {
00347 #if 0
00348                 list->insertObject
00349                   (new odlAgregatClass(0, odl_Declare,
00350                                        new odlClassSpec(cls->getName(), 0, 0, 0),
00351                                        new odlDeclRootList()));
00352 #else
00353                 new odlAgregatClass(0, odl_Declare,
00354                                     new odlClassSpec(cls->getName(), 0, 0, 0),
00355                                     new odlDeclRootList());
00356 #endif
00357                 //printf("declaring %p %s\n", cls, cls->getName());
00358               }
00359             }
00360             else if (!odl_not_check_missing)
00361 #endif
00362               odl_add_error("class %s is missing in ODL\n", cls->getName());
00363           }
00364       }
00365   }
00366 
00367   static Bool
00368   odl_has_attribute(const Class *origcls, const Class *cls,
00369                     const char *attrname)
00370   {
00371 #if 1
00372     return True;
00373 #endif
00374     if (!cls)
00375       return False;
00376 
00377     if (cls->getAttribute(attrname))
00378       {
00379         odl_add_error("attribute '%s' exists both in class '%s' and its "
00380                       "superclass '%s'\n",
00381                       attrname,  origcls->getName(), cls->getName());
00382         return True;
00383       }
00384 
00385     return odl_has_attribute(origcls, cls->getParent(), attrname);
00386   }
00387 
00388 
00389   static void
00390   odl_check_attributes(const Class *cls)
00391   {
00392     unsigned int attr_cnt;
00393     Attribute **attrs = (Attribute **)cls->getAttributes(attr_cnt);
00394   
00395     for (int i = 0; i < attr_cnt; i++)
00396       {
00397         const Attribute *attr = attrs[i];
00398         if (!attr->isNative() && attr->getClassOwner()->compare(cls))
00399           odl_has_attribute(cls, cls->getParent(), attr->getName());
00400       }
00401   }
00402 
00403   int
00404   odl_realize(Database *db, Schema *m, LinkedList *list,
00405               const char *prefix, const char *db_prefix,
00406               const char *package, Bool diff)
00407   {
00408     if (!prefix)    prefix = "";
00409     if (!db_prefix) db_prefix = "";
00410     if (!package)   package = "";
00411 
00412     odl_prefix = prefix;
00413     odl_db_prefix = db_prefix;
00414 
00415     odl_check_removed(m, list);
00416 
00417     if (list && list->getCount()) {
00418       odlDeclaration *decl;
00419       
00420       m->setUserData(odlUPDLIST, new LinkedList());
00421       
00422       odl_check_missing(m, list);
00423       if (odl_error)
00424         return 1;
00425 
00426       LinkedListCursor curs(list);
00427 
00428       while (curs.getNext((void* &)decl))
00429         decl->record(db, m, prefix, db_prefix);
00430 
00431       if (odl_error)
00432         return 1;
00433 
00434       curs.restart();
00435       while (curs.getNext((void* &)decl))
00436         decl->realize(db, m, prefix, package, diff);
00437 
00438       if (odl_error)
00439         return 1;
00440 
00441 #ifdef NEW_REORDER
00442       curs.restart();
00443       while (curs.getNext((void* &)decl))
00444         if (decl->asAgregatClass())
00445           decl->asAgregatClass()->preManage(m);
00446 #endif
00447 
00448       if (odl_error)
00449         return 1;
00450 
00451       curs.restart();
00452       while (curs.getNext((void* &)decl))
00453         if (decl->asAgregatClass())
00454           decl->asAgregatClass()->postRealize(db, m, prefix);
00455 
00456       if (odl_error)
00457         return 1;
00458 
00459       curs.restart();
00460       while (curs.getNext((void* &)decl))
00461         if (decl->asAgregatClass())
00462           decl->asAgregatClass()->manageDifferences(db, m, diff);
00463     }
00464 
00465     const LinkedList *_class = m->getClassList();
00466     LinkedListCursor curs(_class);
00467 
00468     Class *cl;
00469 
00470     if (!odl_error && !odl_diff)
00471       while (curs.getNext((void *&)cl)) {
00472         Status status = cl->checkInverse(m);
00473         if (status)
00474           odl_add_error(status);
00475       
00476         odl_check_attributes(cl);
00477       
00478         if (cl->getUserData())
00479           odl_copy_attr_comp_sets((Class *)cl->getUserData(), cl);
00480       }
00481 
00482     if (odl_error) {
00483       odl_add_error("%d error%s found, compilation aborted\n",
00484                     odl_error, (odl_error > 1 ? "s" : ""));
00485       return 1;
00486     }
00487 
00488     return 0;
00489   }
00490 
00491   static char *
00492   get_superclass_name(const char *prefix = "")
00493   {
00494     static char *spname;
00495 
00496     if (!odlAgregatClass::superclass || spname)
00497       return spname;
00498 
00499     const char *name = odlAgregatClass::superclass->getName();
00500     if (prefix && *prefix)
00501       {
00502         spname = (char *)malloc(strlen(prefix)+strlen(name)+1);
00503         strcpy(spname, prefix);
00504         strcat(spname, name);
00505       }
00506     else
00507       spname = strdup(name);
00508 
00509     return spname;
00510   }
00511 
00512   int
00513   odl_generate_code(Database *db, Schema *m, ProgLang lang,
00514                     LinkedList *list,
00515                     const char *package, const char *schname,
00516                     const char *c_namespace,
00517                     const char *prefix, const char *db_prefix, Bool _export,
00518                     const GenCodeHints &gc_hints)
00519   {
00520     odl_gencode = True;
00521     odl_class_enums = gc_hints.class_enums;
00522 
00523     if (odl_realize(db, m, list, prefix, db_prefix, package))
00524       return 1;
00525 
00526     Class *superclass = NULL;
00527     if (odlAgregatClass::superclass) {
00528       superclass = m->getClass(get_superclass_name(odl_prefix));
00529       if (odlAgregatClass::superclass->getAgregSpec() == odl_RootClass)
00530         superclass->setIsRootClass();
00531     }
00532 
00533     Status status = m->generateCode
00534       (lang, package, schname,
00535        c_namespace, prefix, db_prefix, gc_hints,
00536        _export,
00537        superclass,
00538        &qseq_list);
00539 
00540     if (status) {
00541       odl_add_error(status);
00542       return 1;
00543     }
00544 
00545     return 0;
00546   }
00547 
00548 #define SWAP_CLSNAMES
00549 
00550   odlClassSpec::odlClassSpec(const char *_aliasname, const char *_parentname,
00551                              const char *_classname, odlIndexSpec *_index_spec)
00552   {
00553     if (getenv("SYSTEM_UPDATE"))
00554       {
00555         classname = (_aliasname ? strdup(_aliasname) : strdup(_classname));
00556         aliasname = 0;
00557       }
00558     else
00559       {
00560 #ifdef SWAP_CLSNAMES
00561         classname = (_classname ? strdup(_classname) : strdup(_aliasname));
00562         aliasname = strdup(_aliasname);
00563 #else
00564         classname = strdup(_classname);
00565         aliasname = (_aliasname ? strdup(_aliasname) : 0);
00566 #endif
00567       }
00568 
00569     parentname = (_parentname ? strdup(_parentname) : 0);
00570     index_spec = _index_spec;
00571   }
00572 
00573   static void
00574   rename_classes(Schema *m)
00575   {
00576     Class *cl;
00577     LinkedListCursor c(m->getClassList());
00578 
00579     while (c.getNext((void *&)cl))
00580       if (cl->asAgregatClass())
00581         cl->asAgregatClass()->completeInverse(m);
00582 
00583     LinkedListCursor cx(m->getClassList());
00584 
00585     while (cx.getNext((void *&)cl)) {
00586       if (strcmp(cl->getAliasName(), cl->getName()))
00587         cl->setName(cl->getAliasName());
00588     }
00589   }
00590 
00591   void
00592   odl_skip_volatiles(Database *db, Schema *m)
00593   {
00594     if (!odlAgregatClass::superclass ||
00595         odlAgregatClass::superclass->getAgregSpec() != odl_RootClass)
00596       return;
00597 
00598     db->transactionBegin();
00599     LinkedListCursor c(m->getClassList());
00600     Class *cl, *toSuppress = 0;
00601 
00602     char name[64];
00603     sprintf(name, "%s%s", odl_prefix, get_superclass_name());
00604     while (c.getNext((void *&)cl))
00605       {
00606         if (!strcmp(cl->getName(), name))
00607           toSuppress = cl;
00608         else if (cl->getParent() && !strcmp(cl->getParent()->getName(), name))
00609           ClassPeer::setParent(cl, cl->getParent()->getParent());
00610       }
00611 
00612     if (toSuppress)
00613       m->suppressClass(toSuppress);
00614 
00615     rename_classes(m);
00616 
00617     //  db->transactionAbort();
00618     db->transactionCommit();
00619   }
00620 
00621   int odlDeclaration::check(Schema *m, const char *prefix)
00622   {
00623     /*
00624       Class *cl;
00625       if (cl = getClass(m, name, prefix))
00626       {
00627       if (!cls->compare(cl))
00628       odl_add_error("class '%s' already exists in schema and differs from input class\n", name);
00629       return 1;
00630       }
00631     */
00632 
00633     return 0;
00634   }
00635 
00636   static void
00637   odl_rename_class(Schema *m, const Class *cls, const char *name)
00638   {
00639     odlUPDLIST(m)->insertObjectLast(new odlRenameClass(cls, name));
00640   }
00641 
00642   static void
00643   odl_migrate_attributes(Schema *m, const Class *cls);
00644 
00645   static void
00646   odl_remove_class(Database *db, Schema *m, const Class *cls);
00647 
00648   int
00649   odlAgregatClass::record(Database *db, Schema *m,
00650                           const char *prefix, const char *db_prefix)
00651   {
00652     if (parentname) {
00653       parent = eyedb::getClass(m, parentname, prefix);
00654       if (!parent)
00655         odl_add_error("cannot find parent '%s' for agregat_class '%s'\n",
00656                       parentname, name);
00657     }
00658     else
00659       parent = 0;
00660 
00661     if (agrspec == odl_Struct || agrspec == odl_SuperClass ||
00662         agrspec == odl_RootClass) {
00663       cls = new StructClass(makeName(name, prefix), parent);
00664       cls->setUserData(odlGENCODE, AnyUserData);
00665     }
00666     else if (agrspec == odl_Declare) {
00667       cls = m->getClass(name);
00668       if (!cls)
00669         odl_add_error("cannot find declared class '%s'\n", name);
00670       
00671       if (!odl_error)
00672         cls = new Class(cls->getName(), cls->getParent());
00673     }
00674     else if (agrspec == odl_NativeClass) {
00675         cls = m->getClass(name);
00676         if (!cls)
00677           odl_add_error("cannot find native class '%s'\n", name);
00678         else if (!cls->isSystem())
00679           odl_add_error("class '%s' is not native\n",
00680                         name);
00681         else if (aliasname && strcmp(aliasname, name))
00682           odl_add_error("cannot set an alias name on the native"
00683                         " class '%s'\n", name);
00684         else {
00685           /*
00686             odlDeclRootLink *l = decl_list->first;
00687             while (l) {
00688             if (!l->x->asExecSpec()) {
00689             odl_add_error("native class '%s' can include "
00690             " only methods or triggers.\n", name);
00691             break;
00692             }
00693             l = l->next;
00694             }
00695           */
00696         }
00697 
00698 #if 0
00699         if (!odl_error) {
00700           printf("NATIVE CLASS %s %s -> %p [system=%d] ", cls->getName(),
00701                  cls->isSystem() ? "system" : "user", cls, system);
00702         }
00703 #endif
00704         if (!odl_error) {
00705           cls = new Class(cls->getName(), cls->getParent());
00706           cls->setUserData(odlGENCOMP, AnyUserData);
00707           ClassPeer::setMType(cls, Class::System);
00708           if (db)
00709             cls->setDatabase(db);
00710         }
00711       }
00712     else {
00713       cls = new UnionClass(makeName(name, prefix), parent);
00714       cls->setUserData(odlGENCODE, AnyUserData);
00715     }
00716 
00717     if (!odl_lang && upd_hints && upd_hints->type == odlUpdateHint::RenameFrom)
00718       {
00719         const char *xname = upd_hints->detail;
00720         ocls = eyedb::getClass(m, xname, prefix);
00721         if (!ocls)
00722           odl_add_error("class %s: does not exist in database\n", xname);
00723         else
00724           {
00725             odl_rename_class(m, cls, xname);
00726             ocls->setName(name);
00727           }
00728       }
00729     else
00730       ocls = eyedb::getClass(m, (aliasname ? aliasname : name), prefix);
00731 
00732     if (!odl_lang && upd_hints && upd_hints->type == odlUpdateHint::Remove &&
00733         !ocls)
00734       odl_add_error("cannot remove class '%s'\n", name);
00735     else if (agrspec != odl_NativeClass && agrspec != odl_Declare)
00736       {
00737         if (aliasname)
00738           cls->setAliasName(aliasname);
00739         else if (db_prefix)
00740           cls->setAliasName(makeName(name, db_prefix));
00741 
00742         assert(ocls != cls);
00743         if (ocls && ocls != cls)
00744           {
00745             m->suppressClass(ocls);
00746             cls->setUserData(ocls);
00747             cls->setExtentImplementation(ocls->getExtentImplementation(),
00748                                          True);
00749             ObjectPeer::setOid(cls, ocls->getOid());
00750           }
00751       
00752         if (upd_hints && upd_hints->type == odlUpdateHint::Remove)
00753           {
00754             if (ocls->isSystem()) {
00755               odl_add_error("cannot remove the system class '%s'\n",
00756                             ocls->getName());
00757               return 1;
00758             } else {
00759               odl_remove_class(db, m, cls);
00760               cls = 0;
00761             }
00762           }
00763         else
00764           m->addClass(cls);
00765       }
00766     else if (odl_gencode && ocls)
00767       {
00768         m->suppressClass(ocls);
00769         if (upd_hints && upd_hints->type == odlUpdateHint::Remove)
00770           {
00771             if (ocls->isSystem()) {
00772               odl_add_error("cannot remove the system class '%s'\n",
00773                             ocls->getName());
00774               return 1;
00775             } else {
00776               odl_remove_class(db, m, cls);
00777               cls = 0;
00778             }
00779           }
00780         else
00781           m->addClass(cls);
00782 
00783         if (!odl_error && agrspec == odl_NativeClass) {
00784           /*
00785             printf("should report attributes from ocls %d to cls %d\n",
00786             ocls->getAttributesCount(), cls->getAttributesCount());
00787           */
00788           unsigned int attr_cnt;
00789           const Attribute **attrs = ocls->getAttributes(attr_cnt);
00790           Status status = cls->setAttributes((Attribute **)attrs, attr_cnt);
00791           if (status)
00792             odl_add_error(status);
00793         }
00794       }
00795   
00796     if (odl_system_class && !odl_error)
00797       ClassPeer::setMType(cls, Class::System);
00798 
00799     if (cls)
00800       cls->setUserData(odlSELF, this);
00801 
00802     if (cls && index_spec) {
00803       //printf("class %s has an implementation\n", cls->getName());
00804       odlIndexSpecItem::Type type;
00805       char *hints;
00806       if (!index_spec->make_class_prologue(cls->getName(), type, hints))
00807         return 1;
00808       IndexImpl *idximpl;
00809       Status s = IndexImpl::make
00810         ((db ? db : odl_get_dummy_db(m)),
00811          (type == odlIndexSpecItem::Hash ? IndexImpl::Hash :
00812           IndexImpl::BTree), hints, idximpl);
00813       if (!s) {
00814         if (cls->getOid().isValid()) {
00815           IndexImpl *oidximpl = cls->getExtentImplementation();
00816           if (!oidximpl->compare(idximpl)) {
00817             odl_add_error("class %s: extent implementation '%s' cannot be "
00818                           "dynamically changed to '%s' using eyedbodl\n",
00819                           cls->getName(),
00820                           oidximpl->getHintsString().c_str(),
00821                           idximpl->getHintsString().c_str());
00822             return 1;
00823           }
00824         }
00825         else
00826           s = cls->setExtentImplementation(idximpl);
00827       }
00828 
00829       if (s) {
00830         odl_add_error(s);
00831         return 1;
00832       }
00833     }
00834 
00835     return 0;
00836   }
00837       
00838   static void
00839   array_make(odlDeclItem *item, int* &dims, int &ndims)
00840   {
00841     if (item->array_list)
00842       {
00843         int count = item->array_list->count;
00844         odlArrayItemLink *l = item->array_list->first;
00845         dims = new int[count];
00846 
00847         for (ndims = 0; ndims < count; ndims++, l = l->next)
00848           {
00849             int v = l->x;
00850             if (v>0)
00851               dims[ndims] = v;
00852             else
00853               dims[ndims] = idbVarDim(-v);
00854           }
00855       }
00856     else
00857       {
00858         dims = 0;
00859         ndims = 0;
00860       }
00861   }
00862 
00863   static void
00864   sign_error(const char *method_name, const Class *cls)
00865   {
00866     odl_add_error("invalid hash method signature '%s' in "
00867                   "class '%s' in index declaration: must be "
00868                   "`classmethod int %s(in rawdata, in int)'.\n",
00869                   method_name, cls->getName(), method_name);
00870   }
00871 
00872 #define FIND_IDX_OPTIM
00873 
00874   Status
00875   odlIndex::findIndex(Schema *m, Index *&idx_obj)
00876   {
00877     if (!m->getDatabase())
00878       return Success;
00879 
00880 #ifdef FIND_IDX_OPTIM
00881     Status s;
00882     static ObjectArray *index_arr;
00883     static int index_arr_cnt;
00884     if (!index_arr)
00885       {
00886         index_arr = new ObjectArray();
00887         OQL q(m->getDatabase(), "select index");
00888         s = q.execute(*index_arr);
00889         if (s) return s;
00890         index_arr_cnt = index_arr->getCount();
00891       }
00892 
00893     // a hash table should be better!!
00894     const char *idxname = idx_obj->getName().c_str();
00895     for (int i = 0; i < index_arr_cnt; i++)
00896       if (!strcmp(idxname, ((Index *)(*index_arr)[i])->getName().c_str()))
00897         {
00898           idx_obj->release();
00899           idx_obj = (Index *)(*index_arr)[i];
00900           return Success;
00901         }
00902 
00903     return Success;
00904 #else      
00905     OQL q(m->getDatabase(), "select index.name = \"%s\"", idx_obj->getName());
00906 
00907     Object *o;
00908     Bool found;
00909     Status s;
00910 
00911     ObjectArray obj_arr;
00912     s = q.execute(obj_arr);
00913     if (s) return s;
00914 
00915     if (obj_arr.getCount())
00916       {
00917         idx_obj->release();
00918         idx_obj = (Index *)obj_arr[0];
00919       }
00920 
00921     return Success;
00922 #endif
00923   }
00924 
00925   static Bool
00926   odlIsType(odlDeclItem *item, const char *type)
00927   {
00928     if (strcmp(item->typname, type) || item->isref ||
00929         !item->array_list || item->array_list->count != 1)
00930       return False;
00931 
00932     return True;
00933   }
00934 
00935   static Bool
00936   odlIsString(odlDeclItem *item)
00937   {
00938     return odlIsType(item, char_class_name);
00939   }
00940 
00941   static Bool
00942   odlIsRawData(odlDeclItem *item)
00943   {
00944     return odlIsType(item, "byte");
00945   }
00946 
00947   static Signature *
00948   makeSign(Schema *m)
00949   {
00950     Signature *sign = new Signature();
00951     ArgType *type;
00952 
00953 #ifdef NO_DIRECT_SET
00954     type = sign->getRettype();
00955     *type = *ArgType::make(m, int32_class_name);
00956 #else
00957     type = ArgType::make(m, int32_class_name);
00958 #endif
00959 
00960     type->setType((ArgType_Type)(type->getType() | OUT_ARG_TYPE), False);
00961 
00962 #ifndef NO_DIRECT_SET
00963     sign->setRettype(type);
00964 #endif
00965     sign->setNargs(2);
00966 
00967 #ifdef NO_DIRECT_SET
00968     sign->setTypesCount(2);
00969     type = sign->getTypes(0);
00970     *type = *ArgType::make(m, "rawdata");
00971 #else
00972     type = ArgType::make(m, "rawdata");
00973 #endif
00974 
00975     type->setType((ArgType_Type)(type->getType() | IN_ARG_TYPE), False);
00976 
00977 #ifndef NO_DIRECT_SET
00978     sign->setTypes(0, type);
00979 #endif
00980 
00981 #ifdef NO_DIRECT_SET
00982     sign->setTypesCount(2);
00983     type = sign->getTypes(1);
00984     *type = *ArgType::make(m, int32_class_name);
00985 #else
00986     type = ArgType::make(m, int32_class_name);
00987 #endif
00988     type->setType((ArgType_Type)(type->getType() | IN_ARG_TYPE), False);
00989 
00990 #ifndef NO_DIRECT_SET
00991     sign->setTypes(1, type);
00992 #endif
00993 
00994     return sign;
00995   }
00996 
00997   static Signature *
00998   getHashSignature(Schema *m)
00999   {
01000     static Signature *sign;
01001 
01002     if (!sign)
01003       sign = makeSign(m);
01004  
01005     return sign;
01006   }
01007 
01008   odlBool
01009   odlDeclItem::hasInverseAttr() const
01010   {
01011     return inverse ? odlTrue : odlFalse;
01012 #if 0
01013     if (!attr_list)
01014       return odlFalse;
01015 
01016     odlAttrItemLink *l = attr_list->first;
01017 
01018     while (l)
01019       {
01020         odlAttrItem *attr = l->x;
01021         if (attr->asInverse())
01022           return odlTrue;
01023         l = l ->next;
01024       }
01025 
01026     return odlFalse;
01027 #endif
01028   }
01029 
01030 #if 0
01031   void
01032   odlDeclItem::attr_list_make(Schema *m, Class *cls,
01033                               int& index_mode, Index *&idx_item,
01034                               Index *&idx_comp,
01035                               char **invcname, char **invfname,
01036                               ClassComponent *comp[], int &comp_cnt)
01037   {
01038     index_mode = 0;
01039     idx_item = idx_comp = 0;
01040     *invcname = *invfname = 0;
01041   
01042     int ocomp_cnt = comp_cnt;
01043 
01044     if (attr_list)
01045       {
01046         odlAttrItemLink *l = attr_list->first;
01047 
01048         while (l)
01049           {
01050             odlAttrItem *attr = l->x;
01051             if (attr->asInverse())
01052               {
01053                 odlInverse *inv = attr->asInverse();
01054                 *invcname = inv->classname;
01055                 *invfname = inv->attrname;
01056               }
01057             if (attr->asCardinality())
01058               {
01059                 if (!coll_spec)
01060                   {
01061                     odl_add_error("cannot set cardinality_constraint on a not collection item '%s'\n", attrname);
01062                   }
01063                 else
01064                   {
01065                     odlCardinality *card = attr->asCardinality();
01066                     comp[comp_cnt++] =
01067                       new CardinalityConstraint(0, cls, attrname,
01068                                                 card->bottom, (int)card->bottom_excl,
01069                                                 card->top, (int)card->top_excl);
01070                   }
01071               }
01072             /*
01073               else
01074               abort();
01075             */
01076 
01077             l = l->next;
01078           }
01079       }
01080   }
01081 #endif
01082 
01083   static int key_w(const char *s, const char *key)
01084   {
01085     if (!s)
01086       return 0;
01087 
01088     if (!strcmp(s, key))
01089       {
01090         odl_add_error("use of invalid C++ keyword '%s' for attribute name or type name\n", s);
01091         return 1;
01092       }
01093     return 0;
01094   }
01095 
01096 #define KEY_W(K) if (key_w(typname, K) || key_w(attrname, K)) return 1
01097 
01098   static int
01099   check_name(Schema *m, const char *classname,
01100              const char *typname, const char *attrname,
01101              const char *prefix)
01102   {
01103     KEY_W("delete");
01104     KEY_W("operator");
01105 
01106     if (getClass(m, attrname, prefix))
01107       {
01108         // why??
01109         // because may be ambiguous in uses such as OQL, C++ or Java
01110         odl_add_error("cannot use a type name for an attribute name: '%s %s' in class '%s'\n", (typname ? typname : "identifier"), attrname, classname);
01111         return 1;
01112       }
01113 
01114     const LinkedList *_class = m->getClassList();
01115     LinkedListCursor *c = _class->startScan();
01116 
01117     Class *cl;
01118 
01119     char tmp[128];
01120     sprintf(tmp, "%s%s", prefix, classname);
01121     while (_class->getNextObject(c, (void *&)cl))
01122       if (cl->asEnumClass())
01123         {
01124           if (!strcmp(cl->getName(), tmp))
01125             continue;
01126 
01127           int count;
01128           const EnumItem **items = cl->asEnumClass()->getEnumItems(count);
01129           for (int i = 0; i < count; i++)
01130             if (!strcmp(attrname, items[i]->getName()))
01131               {
01132                 if (!typname)
01133                   odl_add_error("enum item name '%s' found in '%s' and '%s'\n",
01134                                 attrname, cl->getName(), tmp);
01135                 else
01136                   odl_add_error("cannot use a enum item name for "
01137                                 "an attribute name: '%s'\n", attrname);
01138                 _class->endScan(c);
01139                 return 1;
01140               }
01141         }
01142 
01143     _class->endScan(c);
01144   
01145     return 0;
01146   }
01147 
01148   static void
01149   add_quoted_seq(Class *cls, const char *quoted_seq)
01150   {
01151     char *tied_code = cls->getTiedCode();
01152     int len = strlen(quoted_seq)+1;
01153 
01154     if (!tied_code)
01155       tied_code = (char *)calloc(len, sizeof(char));
01156     else
01157       tied_code = (char *)realloc(tied_code, len+strlen(tied_code));
01158 
01159     strcat(tied_code, quoted_seq);
01160 
01161     cls->setTiedCode(tied_code);
01162   }
01163 
01164 
01165   struct ClassNotFound {
01166 
01167     static LinkedList list;
01168 
01169     static Bool get(const char *name) {
01170       LinkedListCursor c(list);
01171       char *s;
01172 
01173       while (c.getNext((void *&)s))
01174         if (!strcmp(s, name))
01175           return True;
01176 
01177       return False;
01178     }
01179 
01180     static void error(const char *name, const char *prefix = 0) {
01181       char *x = strdup(name);
01182       if (x[strlen(x)-1] == '*')
01183         x[strlen(x)-1] = 0;
01184 
01185       if (get(x))
01186         {
01187           free(x);
01188           return;
01189         }
01190 
01191       if (prefix) {
01192         std::string str = std::string(prefix) + " : cannot find class '%s'\n";
01193         odl_add_error(str.c_str(), x);
01194       }
01195       else
01196         odl_add_error("cannot find class '%s'\n", x);
01197       put(x);
01198     }
01199 
01200     static void put(const char *name) {
01201       list.insertObjectLast((void *)name);
01202     }
01203 
01204   };
01205 
01206   LinkedList ClassNotFound::list;
01207 
01208   // debug function
01209   std::string
01210   odlCollSpecToString(odlCollSpec *coll_spec)
01211   {
01212 #define STR(X) ((X) ? (X) : "<null>")
01213     std::string s = "collname=";
01214     s += STR(coll_spec->collname);
01215     s += " typename=";
01216 
01217     if (coll_spec->typname)
01218       s += coll_spec->typname;
01219     else if (coll_spec->coll_spec)
01220       s += std::string("{") + odlCollSpecToString(coll_spec->coll_spec) + "}";
01221     else
01222       s += "<null>";
01223 
01224     s += " isref=";
01225     s += str_convert((long)coll_spec->isref);
01226     s += " dim=";
01227     s += str_convert((long)coll_spec->dim);
01228     return s;
01229   }
01230 
01231   AttributeComponent *
01232   odlAttrComponent::make(Database *db, Schema *m, Class *cls,
01233                          const Attribute *&attr)
01234   {
01235     if (isCloned) {
01236       //printf("component %p is cloned\n", this);
01237       return 0;
01238     }
01239 
01240     std::string sattrpath;
01241     const char *clsname = cls->getAliasName();
01242     int len = strlen(clsname);
01243     std::string s = std::string(clsname) + ".";
01244     const char *p = strchr(attrpath, ':');
01245     if (p) {
01246       if (strncmp(attrpath, clsname, p - attrpath)) {
01247         odl_add_error("invalid syntax '%s' for attribute path: class name "
01248                       "expected before scope operator\n",
01249                       attrpath);
01250         return 0;
01251       }
01252       sattrpath = s + std::string(p + 2);
01253     }
01254     else if (!strncmp(attrpath, s.c_str(), len + 1))
01255       sattrpath = attrpath;
01256     else
01257       sattrpath = s + attrpath;
01258 
01259     const Class *xcls;
01260     Status st = Attribute::checkAttrPath(m, xcls, attr, sattrpath.c_str());
01261     if (st) {
01262       odl_add_error(st);
01263       return 0;
01264     }
01265 
01266     free(attrpath);
01267     attrpath = strdup(sattrpath.c_str());
01268     return make_realize(db, m, const_cast<Class *>(cls), attr);
01269   }
01270 
01271   static odlBool
01272   is_update_attribute(odlUpdateItem *ci, const Attribute *attr)
01273   {
01274     if (!ci->asUpdateAttribute())
01275       return odlFalse;
01276 
01277     const Attribute *cattr = ci->asUpdateAttribute()->item;
01278     if (cattr->getClassOwner() == attr->getClassOwner()) { // reconnected the 27/05/02
01279       return odlTrue;
01280     }
01281 
01282     /*
01283       if (cattr == attr)
01284       return odlTrue;
01285     */
01286 
01287 
01288     /*
01289       if (attr->getClassOwner() == cattr->getClassOwner()) {
01290       printf("update attribute %s returns TRUE becaus of %s\n", attr->getName(),
01291       attr->getClassOwner()->getName());
01292       return odlTrue;
01293       }
01294     */
01295 
01296     return odlFalse;
01297   }
01298 
01299   static odlBool
01300   is_remove_attribute(odlUpdateItem *ci, const Attribute *attr)
01301   {
01302     return ci->asRemoveAttribute() &&
01303       ci->asRemoveAttribute()->item == attr ? odlTrue : odlFalse;
01304   }
01305 
01306   //static Bool is_pred_bypass = IDBBOOL(getenv("IS_PRED_BYPASS"));
01307 
01308   static const Attribute *
01309   odl_is_pred_attribute(Schema *m, const Attribute *attr,
01310                         odlBool (*pred)(odlUpdateItem *,
01311                                         const Attribute *),
01312                         const char *predname)
01313   {
01314     LinkedListCursor c(odlUPDLIST(m));
01315     odlUpdateItem *ci;
01316 
01317     //printf("XCOMP: is_%s_attribute -> %s\n", predname, attr->getName());
01318     while (c.getNext((void *&)ci)) {
01319       if (pred(ci, attr))
01320         return attr;
01321 
01322       //if (is_pred_bypass) return 0;
01323 
01324       if (!attr->isIndirect() && attr->getClass()->asAgregatClass()) {
01325         unsigned int attr_cnt;
01326         const Attribute **attrs = attr->getClass()->getAttributes(attr_cnt);
01327         /*
01328           printf("XCOMP: is_%s_attribute recursion in %s\n", predname,
01329           attr->getClass()->getName());
01330         */
01331         for (int i = 0; i < attr_cnt; i++) {
01332           if (!attrs[i]->isNative() &&
01333               odl_is_pred_attribute(m, attrs[i], pred, predname))
01334             return attrs[i];
01335         }
01336       }
01337     }
01338   
01339     return 0;
01340   }
01341 
01342   static const Attribute *
01343   odl_is_update_attribute(Schema *m, const Attribute *attr)
01344   {
01345     return odl_is_pred_attribute(m, attr, is_update_attribute, "update");
01346   }
01347 
01348   static const Attribute *
01349   odl_is_remove_attribute(Schema *m, const Attribute *attr)
01350   {
01351     return odl_is_pred_attribute(m, attr, is_remove_attribute, "remove");
01352   }
01353 
01354   void odlAgregatClass::realize(Database *db, odlAttrComponent *odl_comp,
01355                                 Schema *m, const char *prefix)
01356   {
01357     if (!cls) {
01358       odl_add_error(std::string("class ") + ocls->getName() + " is removed : "
01359                     "cannot add components");
01360       return ;
01361     }
01362 
01363     const Attribute *attr;
01364     AttributeComponent *attr_comp = odl_comp->make
01365       (db, m, const_cast<Class *>(cls), attr);
01366     /*
01367       printf("realize::AttrComponent %p '%s' %s attr_comp=%p\n",
01368       odl_comp, odl_comp->attrpath, cls->getName(), attr_comp);
01369     */
01370 
01371     if (attr_comp) {
01372       if (db && db->isOpened() && ocls) {
01373         const LinkedList *dlist;
01374         // to force attrcomplist loading
01375         Status s = const_cast<Class *>(ocls)->getAttrCompList(dlist);
01376 
01377         if (s) {
01378           odl_add_error(s);
01379           return;
01380         }
01381 
01382         AttributeComponent *oattr_comp = 0;
01383         s = ocls->getAttrComp(attr_comp->getName().c_str(), oattr_comp);
01384 
01385         if (s) {
01386           odl_add_error(s);
01387           return;
01388         }
01389 
01390         if (oattr_comp) {
01391           if (!attr_comp->getClass()->compare(oattr_comp->getClass())) {
01392             if (attr_comp->asIndex()) {
01393               if (odl_update_index)
01394                 odl_add_error("index on %s has not the same implementation type "
01395                               "in database : use idxupdate to change manually "
01396                               "its implementation type\n",
01397                               attr_comp->getAttrpath().c_str());
01398             }
01399             else
01400               odl_add_error("internal error in "
01401                             "attribute component management\n");
01402             return;
01403           }
01404 
01405           ObjectPeer::setOid(attr_comp, oattr_comp->getOid());
01406         }
01407       }
01408 
01409       cls->add(attr_comp->getInd(), attr_comp);
01410     }
01411   }
01412 
01413   int
01414   odlIndexSpec::make_class_prologue(const char *clsname,
01415                                     odlIndexSpecItem::Type &type,
01416                                     char *&hints) const
01417   {
01418     return make_prologue(True, clsname, type, hints, 0);
01419   }
01420 
01421   int
01422   odlIndexSpec::make_attr_prologue(const char *attrpath,
01423                                    odlIndexSpecItem::Type &type,
01424                                    char *&hints, const Attribute *attr) const
01425   {
01426     return make_prologue(False, attrpath, type, hints, attr);
01427   }
01428 
01429   int
01430   odlIndexSpec::make_prologue(Bool isclass, const char *name,
01431                               odlIndexSpecItem::Type &type,
01432                               char *&hints, 
01433                               const Attribute *attr) const
01434   {
01435     odlIndexSpecItem::Type undefType = odlIndexSpecItem::UndefType;
01436 
01437     type = undefType;
01438     hints = 0;
01439 
01440     for (int i = 0; i < item_cnt; i++) {
01441       odlIndexSpecItem *item = &items[i];
01442       if (item->type != undefType) {
01443         if (type != undefType) {
01444           if (isclass)
01445             odl_add_error("class implementation'%s': index type is "
01446                           "defined twice", name);
01447           else
01448             odl_add_error("attribute '%s': index type is defined twice",
01449                           name);
01450           return 0;
01451         }
01452         type = item->type;
01453       }
01454       else if (item->hints) {
01455         if (hints) {
01456           if (isclass)
01457             odl_add_error("class implementation '%s': index hints are "
01458                           "defined twice", name);
01459           else
01460             odl_add_error("attribute '%s': index hints are defined twice",
01461                           name);
01462           return 0;
01463         }
01464         hints = item->hints;
01465       }
01466     }
01467 
01468     if (type == undefType) {
01469       if (isclass)
01470         type = odlIndexSpecItem::Hash;
01471       else if (attr &&
01472                (attr->isString() || attr->isIndirect() ||
01473                 attr->getClass()->asCollectionClass())) // what about enums
01474         type = odlIndexSpecItem::Hash;
01475       else
01476         type = odlIndexSpecItem::BTree;
01477     }
01478 
01479     return 1;
01480   }
01481 
01482   odlBool
01483   odlAttrComponent::similar(odlAttrComponent *comp,
01484                             const Class *cls1, const Class *cls2)
01485   {
01486     /*
01487       printf("MUST CHECK BETTER %s %s/%s %s\n",
01488       cls1->getName(), attrpath, cls2->getName(), comp->attrpath);
01489     */
01490 
01491     if (!strcmp(comp->attrpath, attrpath))
01492       return odlTrue;
01493 
01494     std::string s1 = std::string(cls1->getName()) + ".";
01495     std::string s2 = std::string(cls2->getName()) + ".";
01496     int len1 = strlen(s1.c_str());
01497     int len2 = strlen(s2.c_str());
01498     if (!strncmp(attrpath, s1.c_str(), len1)) {
01499       if (!strncmp(comp->attrpath, s2.c_str(), len2)) {
01500         return !strcmp(&attrpath[len1], &comp->attrpath[len2]) ?
01501           odlTrue : odlFalse;
01502       }
01503       else
01504         return !strcmp(&attrpath[len1], comp->attrpath) ?
01505           odlTrue : odlFalse;
01506     }
01507     else {
01508       if (!strncmp(comp->attrpath, s2.c_str(), len2)) {
01509         return !strcmp(attrpath, &comp->attrpath[len2]) ?
01510           odlTrue : odlFalse;
01511       }
01512     }
01513 
01514     return odlFalse;
01515   }
01516 
01517   odlBool
01518   odlIndex::similar(odlAttrComponent *comp,
01519                     const Class *cls1, const Class *cls2)
01520   {
01521     if (!comp->asIndex())
01522       return odlFalse;
01523     return odlAttrComponent::similar(comp, cls1, cls2);
01524   }
01525 
01526   odlBool
01527   odlCardinality::similar(odlAttrComponent *comp,
01528                           const Class *cls1, const Class *cls2)
01529   {
01530     if (!comp->asCardinality())
01531       return odlFalse;
01532     return odlAttrComponent::similar(comp, cls1, cls2);
01533   }
01534 
01535   odlBool
01536   odlImplementation::similar(odlAttrComponent *comp,
01537                              const Class *cls1, const Class *cls2)
01538   {
01539     if (!comp->asImplementation())
01540       return odlFalse;
01541     return odlAttrComponent::similar(comp, cls1, cls2);
01542   }
01543 
01544   odlBool
01545   odlNotnull::similar(odlAttrComponent *comp,
01546                       const Class *cls1, const Class *cls2)
01547   {
01548     if (!comp->asNotnull())
01549       return odlFalse;
01550     return odlAttrComponent::similar(comp, cls1, cls2);
01551   }
01552 
01553   odlBool
01554   odlUnique::similar(odlAttrComponent *comp,
01555                      const Class *cls1, const Class *cls2)
01556   {
01557     if (!comp->asUnique())
01558       return odlFalse;
01559     return odlAttrComponent::similar(comp, cls1, cls2);
01560   }
01561 
01562   AttributeComponent *
01563   odlIndex::make_realize(Database *db, Schema *m, Class *cls,
01564                          const Attribute *attr)
01565   {
01566     odlIndexSpecItem::Type type;
01567     char *hints;
01568 
01569     if (index_spec) {
01570       if (!index_spec->make_attr_prologue(attrpath, type, hints, attr))
01571         return 0;
01572     }
01573     else {
01574       hints = 0;
01575       if (attr &&
01576           (attr->isString() || attr->isIndirect() ||
01577            attr->getClass()->asCollectionClass())) // what about enums
01578         type = odlIndexSpecItem::Hash;
01579       else
01580         type = odlIndexSpecItem::BTree;
01581     }
01582 
01583     Bool hasDB = IDBBOOL(db);
01584 
01585     if (!db)
01586       db = odl_get_dummy_db(m);
01587 
01588     Index *idx;
01589     Status s;
01590     if (type == odlIndexSpecItem::Hash)
01591       s = HashIndex::make(db,
01592                           const_cast<Class *>(cls), attrpath,
01593                           IDBBOOL(propagate), attr->isString(), hints,
01594                           (HashIndex *&)idx);
01595     else
01596       s = BTreeIndex::make(db,
01597                            const_cast<Class *>(cls), attrpath,
01598                            IDBBOOL(propagate), attr->isString(), hints,
01599                            (BTreeIndex *&)idx);
01600   
01601     if (s) { 
01602       odl_add_error(s);
01603       return 0;
01604     }
01605 
01606     return idx;
01607   }
01608 
01609   AttributeComponent *
01610   odlImplementation::make_realize(Database *db, Schema *m, Class *cls,
01611                                   const Attribute *attr)
01612   {
01613     //printf("odlImplementation::make_realize(%s)\n", attrpath);
01614     odlIndexSpecItem::Type type;
01615     char *hints;
01616 
01617     if (index_spec) {
01618       if (!index_spec->make_attr_prologue(attrpath, type, hints, attr))
01619         return 0;
01620     }
01621     else {
01622       hints = 0;
01623       type = odlIndexSpecItem::Hash;
01624     }
01625 
01626     Bool hasDB = IDBBOOL(db);
01627     if (!db)
01628       db = odl_get_dummy_db(m);
01629 
01630     CollAttrImpl *impl;
01631     Status s = CollAttrImpl::make
01632       (db, const_cast<Class *>(cls), attrpath, IDBBOOL(propagate),
01633        (type == odlIndexSpecItem::Hash ? IndexImpl::Hash :
01634         IndexImpl::BTree),
01635        hints, (CollAttrImpl *&)impl);
01636   
01637     if (s) { 
01638       odl_add_error(s);
01639       return 0;
01640     }
01641 
01642     return impl;
01643   }
01644 
01645   AttributeComponent *
01646   odlNotnull::make_realize(Database *db, Schema *m, Class *cls,
01647                            const Attribute *)
01648   {
01649     return new NotNullConstraint(db, cls, attrpath, IDBBOOL(propagate));
01650   }
01651 
01652   AttributeComponent *
01653   odlUnique::make_realize(Database *db, Schema *m, Class *cls,
01654                           const Attribute *)
01655   {
01656     return new UniqueConstraint(db, cls, attrpath, IDBBOOL(propagate));
01657   }
01658 
01659   AttributeComponent *
01660   odlCardinality::make_realize(Database *db, Schema *m, Class *cls,
01661                                const Attribute *)
01662   {
01663     return 0;
01664   }
01665 
01666   void odlAgregatClass::realize(odlDeclItem *item,
01667                                 Schema *m, const char *prefix,
01668                                 int n, ClassComponent **comp,
01669                                 int &comp_cnt, Attribute **agr)
01670   {
01671     Class *cl = NULL;
01672     int *dims, ndims, index_mode;
01673     Status status;
01674 
01675     if (item->typname)
01676       {
01677         /*
01678           if (!strcmp(item->typname, "int"))
01679           cl = m->Int32_Class;
01680           else */
01681         cl = eyedb::getClass(m, item->typname, prefix);
01682       }
01683 
01684     if (item->typname && !cl)
01685       {
01686         ClassNotFound::error(item->typname, 
01687                              (std::string("class ") + name +
01688                               ", attribute #" + str_convert((long)n+1)).c_str());
01689         return;
01690       }
01691 
01692     if (check_name(m, name, item->typname, item->attrname, prefix))
01693       {
01694         odl_error++;
01695         return;
01696       }
01697 
01698     array_make(item, dims, ndims);
01699 
01700     char *invcname, *invfname;
01701     if (item->inverse) {
01702       invcname = item->inverse->classname;
01703       invfname = item->inverse->attrname;
01704     }
01705     else {
01706       invcname = invfname = 0;
01707     }
01708     
01709 #if 0
01710     Index *idx_item, *idx_comp;
01711     item->attr_list_make(m, cls, index_mode, idx_item, idx_comp,
01712                          &invcname, &invfname, comp, comp_cnt);
01713 #endif
01714 
01715     if (invcname)
01716       invcname = strdup(makeName(invcname, prefix));
01717 
01718     if (item->coll_spec)
01719       {
01720         odlCollSpec *coll_spec = item->coll_spec;
01721         odlCollSpec *coll_spec_arr[64];
01722         int coll_spec_cnt = 0;
01723 
01724         while (coll_spec)
01725           {
01726             //printf("coll_spec #%d: %s\n", coll_spec_cnt, collSpecToString(coll_spec));
01727             coll_spec_arr[coll_spec_cnt++] = coll_spec;
01728             coll_spec = coll_spec->coll_spec;
01729           }
01730 
01731         const char *coll_typname = coll_spec_arr[coll_spec_cnt-1]->typname;
01732         Class *mcoll = NULL;
01733 
01734         for (int i = coll_spec_cnt-1; i >= 0; i--)
01735           {
01736             coll_spec = coll_spec_arr[i];
01737             cl = eyedb::getClass(m, coll_typname, prefix);
01738 
01739             if (!cl) {
01740               ClassNotFound::error(coll_typname,
01741                                    (std::string("class ") + name).c_str());
01742               return;
01743             }
01744 
01745             Exception::Mode mode = Exception::setMode(Exception::StatusMode);
01746             if (!strcmp(coll_spec->collname, "set")) {
01747               if (coll_spec->dim)
01748                 mcoll = new CollSetClass(cl, coll_spec->dim);
01749               else
01750                 mcoll = new CollSetClass(cl, (Bool)coll_spec->isref);
01751             }
01752             else if (!strcmp(coll_spec->collname, "bag")) {
01753               if (coll_spec->dim)
01754                 mcoll = new CollBagClass(cl, coll_spec->dim);
01755               else
01756                 mcoll = new CollBagClass(cl, (Bool)coll_spec->isref);
01757             }
01758             else if (!strcmp(coll_spec->collname, "array")) {
01759               if (coll_spec->dim)
01760                 mcoll = new CollArrayClass(cl, coll_spec->dim);
01761               else
01762                 mcoll = new CollArrayClass(cl, (Bool)coll_spec->isref);
01763             }
01764             else if (!strcmp(coll_spec->collname, "list")) {
01765               if (coll_spec->dim)
01766                 mcoll = new CollListClass(cl, coll_spec->dim);
01767               else
01768                 mcoll = new CollListClass(cl, (Bool)coll_spec->isref);
01769             }
01770             else {
01771               odl_add_error("invalid collection type '%s'\n",
01772                             coll_spec->collname);
01773               return;
01774             }
01775 
01776             mcoll->setUserData(odlGENCODE, AnyUserData);
01777             Exception::setMode(mode);
01778           
01779             /*
01780             if (!coll_spec->isref) {
01781               odl_add_error("'%s<%s> %s%s': only collection of objects are "
01782                             "supported\n",
01783                             coll_spec->collname, cl->getName(),
01784                             (item->isref ? "*" : ""), item->attrname);
01785               return;
01786             }
01787             */
01788 
01789             status = mcoll->asCollectionClass()->getStatus();
01790             if (status) {
01791               odl_add_error("attribute error '%s::%s': ", name, item->attrname);
01792               odl_add_error(status);
01793               odl_error--;
01794               return;
01795             }
01796 
01797             Class *mcoll_old = m->getClass(mcoll->getName());
01798 
01799             if (mcoll_old) {
01800               mcoll->release();
01801               mcoll = mcoll_old;
01802             }
01803             else
01804               m->addClass(mcoll);
01805 
01806             coll_typname = mcoll->getName();
01807           }
01808 
01809         if (invfname)
01810           {
01811             if (invcname)
01812               {
01813                 if (strcmp(invcname, cl->getName()) &&
01814                     strcmp(invcname, cl->getAliasName()))
01815                   {
01816                     odl_add_error("inverse class incoherency: got '%s', expected '%s'\n", invcname, mcoll->getName());
01817                     return;
01818                   }
01819               }
01820             else
01821               invcname = strdup(cl->getAliasName());
01822           }
01823 
01824         agr[n] =
01825           new Attribute(mcoll, item->attrname, (Bool)item->isref, ndims, dims);
01826 
01827         //agr[n]->setMagOrder(getMagOrder(cls, item->attr_list, agr[n]->getName()));
01828         agr[n]->setUserData(item->upd_hints);
01829 
01830         status = agr[n]->check();
01831         if (status)
01832           odl_add_error(status);
01833       }
01834     else
01835       {
01836         if (invfname)
01837           {
01838             if (invcname)
01839               {
01840                 if (strcmp(invcname, cl->getName()) &&
01841                     strcmp(invcname, cl->getAliasName()))
01842                   {
01843                     odl_add_error("inverse class incoherency: got '%s', expected '%s'\n", invcname, cl->getName());
01844                     return;
01845                   }
01846               }
01847             else
01848               invcname = strdup(cl->getAliasName());
01849           }
01850 
01851         agr[n] = new Attribute(cl, item->attrname, (Bool)item->isref,
01852                                ndims, dims);
01853         //agr[n]->setMagOrder(getMagOrder(cls, item->attr_list, agr[n]->getName()));
01854         agr[n]->setUserData(item->upd_hints);
01855         status = agr[n]->check();
01856         if (status)
01857           odl_add_error(status);
01858       }
01859 
01860     if (invcname)
01861       {
01862         status = agr[n]->setInverse(invcname, invfname);
01863       
01864         if (status)
01865           odl_add_error(status);
01866       }
01867   }
01868 
01869   static TriggerType
01870   makeTrigType(const char *loc)
01871   {
01872     if (!strcmp(loc, "create_before"))
01873       return TriggerCREATE_BEFORE;
01874     if (!strcmp(loc, "create_after"))
01875       return TriggerCREATE_AFTER;
01876     if (!strcmp(loc, "update_before"))
01877       return TriggerUPDATE_BEFORE;
01878     if (!strcmp(loc, "update_after"))
01879       return TriggerUPDATE_AFTER;
01880     if (!strcmp(loc, "load_before"))
01881       return TriggerLOAD_BEFORE;
01882     if (!strcmp(loc, "load_after"))
01883       return TriggerLOAD_AFTER;
01884     if (!strcmp(loc, "remove_before"))
01885       return TriggerREMOVE_BEFORE;
01886     if (!strcmp(loc, "remove_after"))
01887       return TriggerREMOVE_AFTER;
01888 
01889     odl_add_error("invalid trigger localisation '%s'\n", loc);
01890     return (TriggerType)0;
01891   }
01892 
01893   static Signature *
01894   makeSignature(Schema *m, const char *clsname, const char *mthname,
01895                 const char *rettype, odlArgSpecList *arglist,
01896                 int &missNames)
01897   {
01898     ArgType *type = ArgType::make(m, rettype);
01899 
01900     if (!type)
01901       {
01902         type = ArgType::make(m, (odl_db_prefix + rettype).c_str());
01903         if (!type) {
01904           ClassNotFound::error(rettype,
01905                                (std::string("method ") + clsname + "::" +
01906                                 mthname).c_str());
01907           return 0;
01908         }
01909       }
01910 
01911     missNames = 0;
01912     type->setType((ArgType_Type)(type->getType() | OUT_ARG_TYPE), False);
01913 
01914     Signature *sign = new Signature();
01915 #ifdef NO_DIRECT_SET
01916     *sign->getRettype() = *type;
01917 #endif
01918 
01919 #ifndef NO_DIRECT_SET
01920     sign->setRettype(type);
01921 #endif
01922     sign->setNargs(arglist->count);
01923     odlArgSpecLink *l = arglist->first;
01924 
01925 #ifdef NO_DIRECT_SET
01926     sign->setTypesCount(arglist->count);
01927 #endif
01928     char **names = new char *[arglist->count];
01929 
01930     int n = 0;
01931     while (l)
01932       {
01933         type = ArgType::make(m, l->x->typname);
01934         if (!type)
01935           {
01936             type = ArgType::make(m, (odl_db_prefix + l->x->typname).c_str());
01937             if (!type) {
01938               ClassNotFound::error(l->x->typname,
01939                                    (std::string("method ") + clsname + "::" +
01940                                     mthname + ", argument #" +
01941                                     str_convert((long)n+1)).c_str());
01942               if (sign)
01943                 sign->release();
01944               sign = 0;
01945               //return 0;
01946             }
01947           }
01948 
01949         if (sign) {
01950           type->setType((ArgType_Type)(type->getType() | l->x->inout), False);
01951 #ifdef NO_DIRECT_SET
01952           *sign->getTypes(n) = *type;
01953 #else
01954           sign->setTypes(n, type);
01955 #endif
01956           names[n] = (l->x->varname ? strdup(l->x->varname) : 0);
01957           if (!names[n])
01958             missNames++;
01959         }
01960 
01961         l = l->next;
01962         n++;
01963       }
01964 
01965     if (!sign) return 0;
01966     odlSignUserData *sud = new odlSignUserData(names);
01967     sign->setUserData(sud);
01968     return sign;
01969   }
01970 
01971   int
01972   odlMethodSpec::getParamNames(char **&typnames, char **&varnames)
01973   {
01974     int param_cnt = arglist->count;
01975     typnames = new char*[param_cnt];
01976     varnames = new char*[param_cnt];
01977 
01978     odlArgSpecLink *l = arglist->first;
01979 
01980     for (int n = 0; l; n++)
01981       {
01982         const char *s;
01983         if (l->x->inout == INOUT_ARG_TYPE)
01984           s = "inout";
01985         else if (l->x->inout == IN_ARG_TYPE)
01986           s = "in";
01987         else
01988           s = "out";
01989         typnames[n] = strdup((std::string(s) + "$" + l->x->typname).c_str());
01990         varnames[n] = l->x->varname;
01991         l = l->next;
01992       }
01993 
01994     return param_cnt;
01995   }
01996 
01997   std::string
01998   odlTriggerSpec::makeOQLBody(const Class *cls) const
01999   {
02000     return std::string("oql$") + cls->getAliasName() + "$" + name + "(this) ";
02001   }
02002 
02003   static void
02004   compileMethod(Schema *m, const Class *cls, odlMethodSpec *mth)
02005   {
02006     if (!m->getDatabase() || !m->getDatabase()->isOpened())
02007       return;
02008 
02009     char **typnames;
02010     char **varnames;
02011     int param_cnt = mth->getParamNames(typnames, varnames);
02012     std::string oqlConstruct;
02013 
02014     std::string body = BEMethod_OQL::makeExtrefBody(cls, mth->oqlSpec,
02015                                                     mth->fname,
02016                                                     typnames, varnames,
02017                                                     param_cnt,
02018                                                     oqlConstruct);
02019 
02020     oqmlStatus *s = oqml_realize(m->getDatabase(),
02021                                  (char *)oqlConstruct.c_str(), 0,
02022                                  oqml_True);
02023     if (s)
02024       odl_add_error("compiling '%s::%s': %s\n",
02025                     cls->getAliasName(), mth->fname, s->msg);
02026 
02027     free(mth->oqlSpec);
02028     mth->oqlSpec = strdup(body.c_str());
02029   }
02030 
02031   static void
02032   compileTrigger(Schema *m, const Class *cls, odlTriggerSpec *trig)
02033   {
02034     std::string oqlConstruct;
02035 
02036     std::string body = Trigger::makeExtrefBody(cls, trig->oqlSpec,
02037                                                trig->name,
02038                                                oqlConstruct);
02039 
02040     oqmlStatus *s = oqml_realize(m->getDatabase(),
02041                                  (char *)oqlConstruct.c_str(), 0,
02042                                  oqml_True);
02043     if (s)
02044       odl_add_error("compiling trigger '%s::%s': %s\n",
02045                     cls->getAliasName(), trig->name, s->msg);
02046 
02047     /*
02048       char *str = strdup(std::string("function ") + trig->makeOQLBody(cls) +
02049       trig->oqlSpec);
02050 
02051       oqmlStatus *s = oqml_realize(m->getDatabase(), (char *)str, 0, oqml_True);
02052       if (s)
02053       odl_add_error("compiling trigger '%s::%s': %s\n",
02054       cls->getAliasName(), trig->name, s->msg);
02055     */
02056 
02057     free(trig->oqlSpec);
02058     trig->oqlSpec = strdup(body.c_str());
02059   }
02060 
02061   void odlAgregatClass::realize(Database *db, Schema *m,
02062                                 odlExecSpec *ex, const char *def_extref)
02063   {
02064     ClassComponent *comp = 0;
02065     odlMethodSpec *mth;
02066     odlTriggerSpec *trig;
02067 
02068     if (mth = ex->asMethodSpec()) {
02069       int missNames;
02070       Signature *sign = makeSignature(m, name, mth->fname,
02071                                       mth->rettype, mth->arglist,
02072                                       missNames);
02073 
02074       if (!sign)
02075         return;
02076 
02077       if (mth->oqlSpec) {
02078         if (missNames) {
02079           odl_add_error("method '%s::%s' : signatures for OQL"
02080                         " methods must contains parameter names\n",
02081                         cls->getName(), mth->fname);
02082           return;
02083         }
02084 
02085         compileMethod(m, cls, mth);
02086 
02087         comp = new BEMethod_OQL(0, cls, mth->fname, sign,
02088                                 (Bool)mth->isClassMethod,
02089                                 odl_system_class,
02090                                 mth->oqlSpec);
02091       }
02092       else if (mth->mth_hints.isClient)
02093         comp = new FEMethod_C(0, cls, mth->fname, sign,
02094                               (Bool)mth->isClassMethod,
02095                               odl_system_class,
02096                               mth->extref ? mth->extref : def_extref);
02097       else
02098         comp = new BEMethod_C(0, cls, mth->fname, sign,
02099                               (Bool)mth->isClassMethod,
02100                               odl_system_class,
02101                               mth->extref ? mth->extref : def_extref);
02102       ((odlSignUserData *)sign->getUserData())->mth_hints = &mth->mth_hints;
02103       ((odlSignUserData *)sign->getUserData())->upd_hints = mth->upd_hints;
02104       comp->setUserData(sign->getUserData());
02105       comp->asMethod()->getEx()->getSign()->setUserData(sign->getUserData());
02106     }
02107     else if (trig = ex->asTriggerSpec()) {
02108       TriggerType ttype = makeTrigType(trig->localisation);
02109       if (ttype) {
02110         if (trig->oqlSpec)
02111           compileTrigger(m, cls, trig);
02112         const char *extref;
02113         if (trig->oqlSpec)
02114           extref = trig->oqlSpec;
02115         else if (trig->extref)
02116           extref = trig->extref;
02117         else
02118           extref = def_extref;
02119 
02120         comp = new Trigger(0, cls, ttype,
02121                            (trig->oqlSpec ? OQL_LANG : C_LANG),
02122                            odl_system_class,
02123                            trig->name, trig->light ? True : False,
02124                            extref);
02125 
02126         odlSignUserData *sud = new odlSignUserData(0);
02127         sud->upd_hints = trig->upd_hints;
02128         comp->setUserData(sud);
02129       }
02130     }
02131     else
02132       abort();
02133 
02134     if (!odl_error){
02135       if (ex->asMethodSpec()) {
02136         if (!cls->getUserData(odlMTHLIST))
02137           cls->setUserData(odlMTHLIST, new LinkedList());
02138         odlMTHLIST(cls)->insertObject(comp);
02139       }
02140       cls->add(comp->getInd(), comp);
02141     }
02142   }
02143 
02144   void
02145   odl_add_component(Schema *m, ClassComponent *comp)
02146   {
02147     if (odl_error)
02148       return;
02149 
02150     //printf("odlAddComponent('%s')\n", comp->getName());
02151     odlUPDLIST(m)->insertObjectLast(new odlAddComponent(comp));
02152     comp->getClassOwner()->touch();
02153   }
02154 
02155   void
02156   odl_add_component(Schema *m, AttributeComponent *comp)
02157   {
02158     if (odl_error)
02159       return;
02160 
02161     //printf("odlAddComponent('%s') -> %p\n", comp->getName(), comp);
02162     odlUPDLIST(m)->insertObjectLast(new odlAddComponent(comp));
02163     //odlUPDLIST(m)->insertObjectFirst(new odlAddComponent(comp));
02164   }
02165 
02166   void
02167   odl_remove_component(Schema *m, ClassComponent *comp)
02168   {
02169     if (odl_error)
02170       return;
02171 
02172     //printf("odlRemoveComponent('%s')\n", comp->getName());
02173     odlUPDLIST(m)->insertObjectLast(new odlRemoveComponent(comp));
02174     comp->getClassOwner()->touch();
02175   }
02176 
02177   void
02178   odl_remove_component(Schema *m, AttributeComponent *comp)
02179   {
02180     if (odl_error)
02181       return;
02182 
02183     //printf("odlRemoveComponent('%s') -> %p\n", comp->getName(), comp);
02184     odlUPDLIST(m)->insertObjectLast(new odlRemoveComponent(comp));
02185   }
02186 
02187   static void
02188   odl_add_relationship(Schema *m, Class *cls, const char *name,
02189                        const Attribute *item,
02190                        const Attribute *invitem)
02191   {
02192     cls->touch();
02193     odlUPDLIST(m)->insertObjectLast(new odlAddRelationship(item, invitem));
02194   }
02195 
02196   static void
02197   odl_remove_relationship(Schema *m, Class *cls, const char *name,
02198                           const Attribute *item,
02199                           const Attribute *invitem)
02200   {
02201     cls->touch();
02202     odlUPDLIST(m)->insertObjectLast(new odlRemoveRelationship(item, invitem));
02203   }
02204 
02205   static void
02206   odl_add_class(Schema *m, const Class *cls)
02207   {
02208     if (odl_error)
02209       return;
02210 
02211     if (!odl_rootclass || strcmp(cls->getName(), odl_rootclass))
02212       odlUPDLIST(m)->insertObjectLast(new odlAddClass(cls));
02213   }
02214 
02215   static void
02216   odl_remove_class(Database *db, Schema *m, const Class *cls)
02217   {
02218     if (odl_error)
02219       return;
02220 
02221     odlUPDLIST(m)->insertObjectLast(new odlRemoveClass(db, cls,
02222                                                        odlUPDLIST(m)));
02223   }
02224 
02225   static void
02226   odl_migrate_attributes(Schema *m, const Class *cls)
02227   {
02228     unsigned int attr_cnt;
02229     const Attribute **attrs  = cls->getAttributes(attr_cnt);
02230 
02231     for (int i = 0; i < attr_cnt; i++)
02232       {
02233         const Attribute *attr = attrs[i];
02234         odlUpdateHint *upd_hints = (odlUpdateHint *)attr->getUserData();
02235         if (upd_hints && upd_hints->type == odlUpdateHint::MigrateFrom)
02236           {
02237             const Class *ocls = eyedb::getClass(m, upd_hints->detail, odl_db_prefix.c_str());
02238             if (!ocls)
02239               {
02240                 ClassNotFound::error(upd_hints->detail);
02241                 continue;
02242               }
02243 
02244             ocls = (const Class *)ocls->getUserData();
02245             assert(ocls);
02246 
02247             const Attribute *oattr = ocls->getAttribute(upd_hints->detail2);
02248             if (!oattr)
02249               {
02250                 odl_add_error("attribute %s not found in class %s\n",
02251                               upd_hints->detail2, upd_hints->detail);
02252                 continue;
02253               }
02254 
02255             const_cast<Attribute *>(oattr)->setUserData
02256               (new odlUpdateHint
02257                (odlUpdateHint::MigrateTo,
02258                 cls->getName(), attr->getName(), upd_hints->detail3));
02259           }
02260       }
02261   }
02262 
02263   static void
02264   odl_reparent_class(Schema *m, const Class *cls)
02265   {
02266     odlUPDLIST(m)->insertObjectLast(new odlReparentClass(cls));
02267   }
02268 
02269   static void
02270   odl_add_attribute(Schema *m, const Class *cls,
02271                     const Attribute *attr)
02272   {
02273     //printf("XCOMP: add_attribute(%s, %p)\n", attr->getName(), cls);
02274     odlUPDLIST(m)->insertObjectLast(new odlAddAttribute(cls, attr));
02275   }
02276 
02277   static void
02278   odl_remove_attribute(Schema *m, const Class *cls,
02279                        const Attribute *attr)
02280   {
02281     //printf("XCOMP: remove_attribute(%s)\n", attr->getName());
02282     odlUPDLIST(m)->insertObjectLast(new odlRemoveAttribute(cls, attr));
02283   }
02284 
02285   static void
02286   odl_rename_attribute(Schema *m, const Class *cls,
02287                        const Attribute *attr,
02288                        odlUpdateHint *upd_hints)
02289   {
02290     odlUPDLIST(m)->insertObjectLast(new odlRenameAttribute(cls, attr, upd_hints));
02291   }
02292 
02293   static void
02294   odl_migrate_attribute(Schema *m, const Class *cls,
02295                         const Attribute *attr, odlUpdateHint *upd_hints)
02296   {
02297     odlUPDLIST(m)->insertObjectLast(new odlMigrateAttribute(cls, attr, upd_hints));
02298   }
02299   static void
02300   odl_convert_attribute(Schema *m, const Class *cls,
02301                         const Attribute *oattr, const Attribute *attr,
02302                         odlUpdateHint *upd_hints = 0)
02303   {
02304     odlUPDLIST(m)->insertObjectLast(new odlConvertAttribute(cls, oattr, attr, upd_hints));
02305   }
02306 
02307   static Bool
02308   odl_reorder_attr(Schema *m, const Class *cls,
02309                    const Attribute *attr, int newnum)
02310   {
02311     if (attr->getNum() != newnum)
02312       {
02313         odlUPDLIST(m)->insertObjectLast
02314           (new odlReorderAttribute(cls, attr, newnum, attr->getNum()));
02315         const_cast<Attribute *>(attr)->setNum(newnum);
02316         return True;
02317       }
02318 
02319     return False;
02320   }
02321 
02322   static int
02323   cmp_attr(const void *x1, const void *x2)
02324   {
02325     return (*(Attribute **)x1)->getNum() - (*(Attribute **)x2)->getNum();
02326   }
02327 
02328   static Attribute *
02329   odl_get_renamed_attr(Attribute *attrs[], int attr_cnt,
02330                        const Attribute *oattr)
02331   {
02332     // check if not renamed!
02333     for (int j = 0; j < attr_cnt; j++)
02334       {
02335         const Attribute *attr = attrs[j];
02336         odlUpdateHint *upd_hints = (odlUpdateHint *)attr->getUserData();
02337         if (upd_hints && upd_hints->type == odlUpdateHint::RenameFrom &&
02338             !strcmp(upd_hints->detail, oattr->getName()))
02339           return const_cast<Attribute *>(attr);
02340       }
02341 
02342     return 0;
02343   }
02344 
02345 #define COMPLETE(CLS) \
02346   if ((CLS)->isPartiallyLoaded()) \
02347     { \
02348       Status s = m->manageClassDeferred((Class *)CLS); \
02349       if (s) \
02350         { \
02351           odl_add_error(s); \
02352           return; \
02353         } \
02354     }
02355 
02356 #ifdef NEW_REORDER
02357   static Bool
02358   odl_class_need_reorder(const Class *ocls,
02359                          Attribute **attrs, int attr_cnt)
02360   {
02361     int onum = 0;
02362     for (int i = 0; i < attr_cnt; i++)
02363       {
02364         const Attribute *attr = attrs[i];
02365         const Attribute *oattr;
02366 
02367         if (oattr = ocls->getAttribute(attr->getName())) {
02368           if (oattr->getNum() < onum) {
02369             //printf("%s NEEDING REORDER!\n", ocls->getName());
02370             return True;
02371           }
02372           onum = oattr->getNum();
02373         }
02374       }
02375 
02376     //printf("%s DOES NOT NEED REORDER!\n", ocls->getName());
02377     return False;
02378   }
02379 
02380   static void
02381   odl_class_premanage(Schema *m, const Class *ocls, const Class *cls)
02382   {
02383     static const int invalid_num = -1;
02384     unsigned int attr_cnt;
02385     Attribute **attrs = (Attribute **)cls->getAttributes(attr_cnt);
02386     int i;
02387 
02388     COMPLETE(cls);
02389     COMPLETE(ocls);
02390 
02391     if (!odl_class_need_reorder(ocls, attrs, attr_cnt))
02392       return;
02393 
02394     //
02395     // ignore attribute reordering
02396     //
02397 
02398     Bool is_renum = False;
02399     int attr_num = 0;
02400     for (i = 0; i < attr_cnt; i++)
02401       {
02402         const Attribute *attr = attrs[i];
02403         const Attribute *oattr;
02404 
02405         if (oattr = ocls->getAttribute(attr->getName())) {
02406           if (odl_reorder_attr(m, cls, attr, oattr->getNum()))
02407             is_renum = True;
02408           attr_num++;
02409         }
02410         else
02411           {
02412             odlUpdateHint *upd_hints = (odlUpdateHint *)attr->getUserData();
02413             if (upd_hints && upd_hints->type == odlUpdateHint::RenameFrom)
02414               {
02415                 oattr = ocls->getAttribute(upd_hints->detail);
02416                 if (oattr) {
02417                   if (odl_reorder_attr(m, cls, attr, oattr->getNum()))
02418                     is_renum = True;
02419                   attr_num++;
02420                 }
02421                 else
02422                   const_cast<Attribute *>(attr)->setNum(invalid_num);
02423               }
02424             else
02425               const_cast<Attribute *>(attr)->setNum(invalid_num);
02426           }
02427       }
02428 
02429     for (i = 0; i < attr_cnt; i++) {
02430       const Attribute *attr = attrs[i];
02431       if (attr->getNum() == invalid_num) {
02432         const_cast<Attribute *>(attr)->setNum(attr_num++);
02433         is_renum = True;
02434       }
02435     }
02436 
02437     qsort(attrs, attr_cnt, sizeof(Attribute *), cmp_attr);
02438     if (is_renum) const_cast<Class *>(cls)->compile();
02439   }
02440 #endif
02441 
02442   static void
02443   odl_class_compare(Schema *m, const Class *ocls, const Class *cls,
02444                     odlUpdateHint *cls_hints)
02445   {
02446     unsigned int oattr_cnt, attr_cnt;
02447     Attribute **oattrs = (Attribute **)ocls->getAttributes(oattr_cnt);
02448     Attribute **attrs = (Attribute **)cls->getAttributes(attr_cnt);
02449     int i;
02450 
02451     COMPLETE(cls);
02452     COMPLETE(ocls);
02453 
02454     // check removed and converted attributes
02455     for (i = 0; i < oattr_cnt; i++) {
02456       const Attribute *oattr = oattrs[i];
02457       const Attribute *attr;
02458       Bool migrate = False;
02459 
02460       odlUpdateHint *upd_hints = (odlUpdateHint *)oattr->getUserData();
02461       if (upd_hints && upd_hints->type == odlUpdateHint::MigrateTo) {
02462         migrate = True;
02463         odl_migrate_attribute(m, cls, oattr, upd_hints);
02464       }
02465 
02466       if (!(attr = cls->getAttribute(oattr->getName()))) {
02467         attr = odl_get_renamed_attr(attrs, attr_cnt, oattr);
02468         if (!attr) {
02469           if (!migrate) {
02470             if (cls_hints && cls_hints->type == odlUpdateHint::Extend) {
02471               if (upd_hints && upd_hints->type == odlUpdateHint::Remove)
02472                 odl_remove_attribute(m, cls, oattr);
02473             }
02474             else
02475               odl_remove_attribute(m, cls, oattr);
02476           }
02477         }
02478         else if (upd_hints && upd_hints->type == odlUpdateHint::Convert)
02479           odl_convert_attribute(m, cls, oattr, attr, upd_hints);
02480         else if (!oattr->compare(m->getDatabase(), attr,
02481                                  False,  // compClassOwner
02482                                  False,  // compNum
02483                                  False,  // compName
02484                                  True))  // inDepth
02485           odl_convert_attribute(m, cls, oattr, attr);
02486       }
02487       else if (upd_hints && upd_hints->type == odlUpdateHint::Convert)
02488         odl_convert_attribute(m, cls, oattr, attr, upd_hints);
02489       else if (!oattr->compare(m->getDatabase(), attr,
02490                                False,  // compClassOwner
02491                                False,  // compNum
02492                                False,  // compName
02493                                True))  // inDepth
02494         odl_convert_attribute(m, cls, oattr, attr);
02495     }
02496 
02497     // check added attributes
02498     for (i = 0; i < attr_cnt; i++) {
02499       const Attribute *attr = attrs[i];
02500       const Attribute *oattr;
02501       
02502       const char *name = attr->getName();
02503       odlUpdateHint *upd_hints = (odlUpdateHint *)attr->getUserData();
02504       if (upd_hints && upd_hints->type == odlUpdateHint::RenameFrom) {
02505         name = upd_hints->detail;
02506         if (oattr = ocls->getAttribute(name))
02507           odl_rename_attribute(m, cls, attr, upd_hints);
02508         else
02509           odl_add_error("class %s: no attribute named %s\n",
02510                         cls->getName(), name);
02511       }
02512 
02513       if (!(oattr = ocls->getAttribute(name))) {
02514         if (!upd_hints || upd_hints->type != odlUpdateHint::MigrateFrom)
02515           odl_add_attribute(m, cls, attr);
02516       }
02517     }
02518 
02519     if (odl_error) return;
02520 
02521 #ifndef NEW_REORDER
02522     // check attribute order
02523     int cnt = 0;
02524     for (i = 0; i < attr_cnt; i++) {
02525       const Attribute *attr = attrs[i];
02526       const Attribute *oattr;
02527 
02528       if (oattr = ocls->getAttribute(attr->getName()))
02529         odl_reorder_attr(m, cls, attr, oattr->getNum() + cnt);
02530       else {
02531         odlUpdateHint *upd_hints = (odlUpdateHint *)attr->getUserData();
02532         if (upd_hints && upd_hints->type == odlUpdateHint::RenameFrom) {
02533           oattr = ocls->getAttribute(upd_hints->detail);
02534           if (oattr)
02535             odl_reorder_attr(m, cls, attr, oattr->getNum() + cnt);
02536           else
02537             cnt++;
02538         }
02539         else
02540           cnt++;
02541       }
02542     }
02543 
02544     // ignore attribute reordering!
02545     qsort(attrs, attr_cnt, sizeof(Attribute *), cmp_attr);
02546 #endif
02547   }
02548 
02549   static void
02550   odl_class_parent_compare(Schema *m, const Class *ocls, const Class *cls)
02551   {
02552     const Class *parent = cls->getParent();
02553     if (odl_rootclass && !strcmp(parent->getName(), odl_rootclass))
02554       parent = parent->getParent();
02555     const Class *oparent = ocls->getParent();
02556     if (odl_rootclass && !strcmp(oparent->getName(), odl_rootclass))
02557       oparent = oparent->getParent();
02558 
02559     /*
02560       if (!parent->compare(oparent))
02561       odl_reparent_class(m, cls);
02562     */
02563 
02564     if (strcmp(parent->getName(), oparent->getName()))
02565       odl_reparent_class(m, cls);
02566   }
02567 
02568   Bool
02569   odl_find_component(ClassComponent *&comp, const LinkedList *complist,
02570                      Bool strictCheck, ClassComponent *&fclcomp)
02571   {
02572     //printf("LOOKING for component '%s'\n", comp->getName());
02573     if (strchr(comp->getName().c_str(), '.')) {
02574       fclcomp = comp;
02575       return True;
02576     }
02577 
02578     fclcomp = 0;
02579     LinkedListCursor c(complist);
02580     ClassComponent *tmpcomp;
02581     while (c.getNext((void *&)tmpcomp))
02582       {
02583         if (!strcmp(comp->getName().c_str(), tmpcomp->getName().c_str()))
02584           {
02585             if (!comp->asAgregatClassExecutable()) {
02586               fclcomp = tmpcomp;
02587               return True;
02588             }
02589 
02590             Executable *ex = comp->asAgregatClassExecutable()->getEx();
02591             Executable *tmpex = tmpcomp->asAgregatClassExecutable()->getEx();
02592 
02593             if (strictCheck &&
02594                 strcmp(ex->getExtrefBody().c_str(), tmpex->getExtrefBody().c_str()))
02595               {
02596                 tmpex->setExtrefBody(ex->getExtrefBody());
02597                 if ((ex->getLang() & SYSTEM_EXEC) && !odl_system_class)
02598                   {
02599                     odl_add_error("cannot modify system method "
02600                                   "'%s'\n", comp->getName().c_str());
02601                     fclcomp = tmpcomp;
02602                     return True;
02603                   }
02604             
02605                 if (ex->getLoc() != tmpex->getLoc()) {
02606                   return False;
02607                 }
02608                   
02609                 comp = tmpcomp;
02610                 return False;
02611               }
02612             else if (ex->getLoc() != tmpex->getLoc()) {
02613               return False;
02614             }
02615 
02616             fclcomp = tmpcomp;
02617             return True;
02618           }
02619       }
02620 
02621     if (comp->asAgregatClassExecutable() &&
02622         ((comp->asAgregatClassExecutable()->getEx()->getLang() &
02623           SYSTEM_EXEC) && !odl_system_class)) {
02624       fclcomp = comp;
02625       return True;
02626     }
02627 
02628     return False;
02629   }
02630 
02631   Bool
02632   odl_compare_index_hints(const Index *idx1, const Index *idx2)
02633   {
02634     if (idx1->getImplHintsCount() != idx2->getImplHintsCount())
02635       return False;
02636 
02637     int cnt = idx1->getImplHintsCount();
02638     for (int i = 0; i < cnt; i++) {
02639       if (idx1->getImplHints(i) && idx2->getImplHints(i) &&
02640           idx1->getImplHints(i) != idx2->getImplHints(i))
02641         return False;
02642     }
02643 
02644     return True;
02645   }
02646 
02647   Bool
02648   odl_compare_index(const HashIndex *idx1, const HashIndex *idx2)
02649   {
02650     if (idx1->getKeyCount() && idx2->getKeyCount() &&
02651         idx1->getKeyCount() != idx2->getKeyCount())
02652       return False;
02653 
02654     if (!const_cast<HashIndex *>(idx1)->compareHashMethod(const_cast<HashIndex *>(idx2)))
02655       return False;
02656 
02657     return odl_compare_index_hints(idx1, idx2);
02658   }
02659 
02660   Bool
02661   odl_compare_index(const BTreeIndex *idx1, const BTreeIndex *idx2)
02662   {
02663     if (idx1->getDegree() && idx2->getDegree() &&
02664         idx1->getDegree() != idx2->getDegree())
02665       return False;
02666 
02667     return odl_compare_index_hints(idx1, idx2);
02668   }
02669 
02670   AttributeComponent *
02671   odl_report_index_hints(const Index *idx1, Index *idx2)
02672   {
02673     int cnt1 = idx1->getImplHintsCount();
02674     int cnt2 = idx2->getImplHintsCount();
02675     for (int i = 0; i < cnt1; i++)
02676       idx2->setImplHints(i, idx1->getImplHints(i));
02677 
02678     for (int i = cnt1; i < cnt2; i++)
02679       idx2->setImplHints(i, 0);
02680 
02681     return idx2;
02682   }
02683 
02684   AttributeComponent *
02685   odl_report_index(Index *idx1, Index *idx2)
02686   {
02687     ObjectPeer::setOid(idx1, idx2->getOid());
02688     idx1->setIdxOid(idx2->getIdxOid());
02689     return idx1;
02690   }
02691 
02692   Bool
02693   odl_find_component(AttributeComponent *&comp, const LinkedList *complist,
02694                      Bool strictCheck, AttributeComponent *&fattr_comp)
02695   {
02696     fattr_comp = 0;
02697     LinkedListCursor c(complist);
02698     AttributeComponent *tmpcomp;
02699     while (c.getNext((void *&)tmpcomp)) {
02700       if (!strcmp(comp->getName().c_str(), tmpcomp->getName().c_str())) {
02701         fattr_comp = tmpcomp;
02702         if (strictCheck) {
02703           if (comp->asIndex()) {
02704             BTreeIndex *bidx = comp->asBTreeIndex();
02705             BTreeIndex *tmpbidx = tmpcomp->asBTreeIndex();
02706             HashIndex *hidx = comp->asHashIndex();
02707             HashIndex *tmphidx = tmpcomp->asHashIndex();
02708 
02709             if (hidx && tmphidx) {
02710               if (odl_update_index && !odl_compare_index(hidx, tmphidx)) {
02711                 comp = odl_report_index(hidx, tmphidx);
02712                 return False;
02713               }
02714             }
02715             else if (bidx && tmpbidx) {
02716               if (odl_update_index && !odl_compare_index(bidx, tmpbidx)) {
02717                 comp = odl_report_index(bidx, tmpbidx);
02718                 return False;
02719               }
02720             }
02721             else
02722               return False;
02723           }
02724 
02725           if (odl_update_index && comp->getPropagate() != tmpcomp->getPropagate()) {
02726             tmpcomp->setPropagate(comp->getPropagate());
02727             comp = tmpcomp;
02728             return False;
02729           }
02730         }
02731 
02732         return True;
02733       }
02734     }
02735 
02736     return False;
02737   }
02738 
02739   static int
02740   completeInverse(Schema *m, const char *cname,
02741                   const char *fname, const Attribute *&invitem)
02742   {
02743     if (invitem)
02744       return 0;
02745 
02746     if (cname && fname)
02747       {
02748         const Class *cls = m->getClass(cname);
02749         if (!cls)
02750           {
02751             odl_error++;
02752             return 1;
02753           }
02754 
02755         invitem = cls->getAttribute(fname);
02756       }
02757 
02758     return 0;
02759   }
02760 
02761   //
02762   // 17/09/01:
02763   // THIS FUNCTION IS WRONG IF THE SCHEMA HAS EVOLVED (MORE OR LESS ATTRIBUTES
02764   // OR RENAMED ATTRIBUTES)!!
02765   // 
02766 
02767 #ifdef NEW_DIFF_RELSHIP
02768   int
02769   odl_remove_relationships(Database *, Schema *m, Class *ocls)
02770   {
02771     // function not really pertinent
02772     if (true)
02773       return 0;
02774 
02775     if (!ocls)
02776       return 0;
02777 
02778     unsigned int oattr_cnt;
02779     const Attribute **oattrs  = ocls->getAttributes(oattr_cnt);
02780 
02781     for (int i = 0; i < oattr_cnt; i++) {
02782       const Attribute *oattr = oattrs[i];
02783 
02784       const char *ocname, *ofname;
02785       const Attribute *oinvitem;
02786 
02787       oattr->getInverse(&ocname, &ofname, &oinvitem);
02788       completeInverse(m, ocname, ofname, oinvitem);
02789       
02790       if (oinvitem)
02791         odl_remove_relationship(m, ocls, ocls->getName(), oattr, oinvitem);
02792     }
02793 
02794     return 0;
02795   }
02796 
02797 
02798   int
02799   odlAgregatClass::manageDiffRelationShips(Database *, Schema *m, Bool diff)
02800   {
02801     if (!ocls)
02802       return 0;
02803 
02804     unsigned int oattr_cnt, attr_cnt;
02805     const Attribute **attrs  = cls->getAttributes(attr_cnt);
02806     const Attribute **oattrs  = ocls->getAttributes(oattr_cnt);
02807 
02808     for (int i = 0; i < oattr_cnt; i++)
02809       {
02810         const Attribute *oattr = oattrs[i];
02811         const Attribute *attr;
02812 
02813         if (!(attr = cls->getAttribute(oattr->getName()))) {
02814           const char *ocname, *ofname;
02815           const Attribute *oinvitem;
02816 
02817           oattr->getInverse(&ocname, &ofname, &oinvitem);
02818           completeInverse(m, ocname, ofname, oinvitem);
02819 
02820           if (oinvitem)
02821             odl_remove_relationship(m, cls, name, oattr, oinvitem);
02822         }
02823       }
02824 
02825     for (int i = 0; i < attr_cnt; i++)
02826       {
02827         const Attribute *attr = attrs[i];
02828         const Attribute *oattr;
02829         const Attribute *invitem;
02830         const char *cname, *fname;
02831 
02832         attr->getInverse(&cname, &fname, &invitem);
02833         completeInverse(m, cname, fname, invitem);
02834 
02835         if (oattr = ocls->getAttribute(attr->getName())) {
02836           const char *ocname, *ofname;
02837           const Attribute *oinvitem;
02838 
02839           oattr->getInverse(&ocname, &ofname, &oinvitem);
02840           completeInverse(m, ocname, ofname, oinvitem);
02841 
02842           if (oinvitem && !invitem)
02843             odl_remove_relationship(m, cls, name, attr, oinvitem);
02844           else if (invitem && !oinvitem)
02845             odl_add_relationship(m, cls, name, attr, invitem);
02846           else if (invitem && oinvitem &&
02847                    strcmp(invitem->getName(), oinvitem->getName())) {
02848             odl_remove_relationship(m, cls, name, attr, oinvitem);
02849             odl_add_relationship(m, cls, name, attr, invitem);
02850           }
02851         }
02852         else if (invitem)
02853           odl_add_relationship(m, cls, name, attr, invitem);
02854       }
02855 
02856     return 0;
02857   }
02858 #else
02859   int
02860   odlAgregatClass::manageDiffRelationShips(Schema *m, Bool diff)
02861   {
02862     int attr_cnt, oattr_cnt;
02863     const Attribute **attrs  = cls->getAttributes(attr_cnt);
02864     const Attribute **oattrs = ocls->getAttributes(oattr_cnt);
02865 
02866     //assert(attr_cnt == oattr_cnt);
02867     int cnt = (attr_cnt < oattr_cnt ? attr_cnt : oattr_cnt);
02868 
02869     for (int i = 0; i < cnt; i++)
02870       {
02871         const char *cname, *fname, *ocname, *ofname;
02872         const Attribute *invitem, *oinvitem;
02873 
02874         attrs[i]->getInverse(&cname, &fname, &invitem);
02875         oattrs[i]->getInverse(&ocname, &ofname, &oinvitem);
02876 
02877         completeInverse(m, ocname, ofname, oinvitem);
02878         completeInverse(m, cname, fname, invitem);
02879 
02880         if (oinvitem && !invitem)
02881           {
02882             cls->touch();
02883             odl_remove_relationship(m, name, attrs[i], oinvitem);
02884           }
02885         else if (invitem && !oinvitem)
02886           {
02887             cls->touch();
02888             odl_add_relationship(m, name, oattrs[i], invitem);
02889           }
02890       }
02891 
02892     return 0;
02893   }
02894 #endif
02895 
02896   Bool
02897   odl_exec_removed(ClassComponent *comp)
02898   {
02899     if (!comp)
02900       return False;
02901   
02902     if (!comp->asTrigger() && !comp->asMethod())
02903       return False;
02904 
02905     odlSignUserData *sud = (odlSignUserData *)comp->getUserData();
02906     return (sud && sud->upd_hints &&
02907             sud->upd_hints->type == odlUpdateHint::Remove ?
02908             True : False);
02909   }
02910 
02911 #ifdef NEW_REORDER
02912   int
02913   odlAgregatClass::preManage(Schema *m)
02914   {
02915     if (odl_gencode || !m->getDatabase() || !cls)
02916       return 0;
02917 
02918     if (!ocls)
02919       {
02920         odl_add_class(m, cls);
02921         return 0;
02922       }
02923 
02924     // added 31/05/01
02925     if (agrspec == odl_Declare)
02926       return 0;
02927 
02928     if (agrspec != odl_NativeClass) {
02929       odl_class_premanage(m, ocls, cls);
02930       if (odl_error)
02931         return 0;
02932     }
02933 
02934     return 0;
02935   }
02936 #endif
02937 
02938   const Attribute *
02939   odl_getattr(const Class *cls, const AttributeComponent *attr_comp)
02940   {
02941     char *s = strdup(attr_comp->getAttrpath().c_str());
02942     char *q = strchr(s, '.');
02943 
02944     if (!q) {
02945       odl_add_error("unexpected attrpath '%s'\n", s);
02946       free(s);
02947       return 0;
02948     }
02949 
02950     *q = 0;
02951     char *p = strchr(q+1, '.');
02952     if (p) *p = 0;
02953     const Attribute *attr = cls->getAttribute(q+1);
02954 
02955     if (!attr) {
02956       odl_add_error("attribute %s not found in class %s\n", q+1, cls->getName());
02957       free(s);
02958       return 0;
02959     }
02960 
02961     free(s);
02962     return attr;
02963   }
02964 
02965   static int
02966   odl_remove_components(Schema *m, Class *ocls, Class *cls)
02967   {
02968     m->getDatabase()->transactionBegin();
02969 
02970     const char *name = ocls->getName();
02971     const LinkedList *ocomplist = ocls->getCompList();
02972     LinkedListCursor oc(ocomplist);
02973     ClassComponent *clcomp;
02974     while (oc.getNext((void *&)clcomp)) {
02975       if (!strcmp(clcomp->getClassOwner()->getName(), name))
02976         odl_remove_component(m, clcomp);
02977     }
02978 
02979     const LinkedList *attr_ocomplist;
02980     Status s = ocls->getAttrCompList(attr_ocomplist);
02981     if (s) {odl_add_error(s); return 1;}
02982 
02983     AttributeComponent *attr_comp;
02984     LinkedListCursor attr_oc(attr_ocomplist);
02985 
02986     while (attr_oc.getNext((void *&)attr_comp)) {
02987       //if (!strcmp(attrcomp->getClassOwner()->getName(), name))
02988       AttributeComponent *cattr_comp = 0;
02989       if (ocls && ocls->getDatabase() &&
02990           attr_comp->find(ocls->getDatabase(), ocls->getParent(),
02991                           cattr_comp) == Success) {
02992         if (!cattr_comp || !cattr_comp->getPropagate())
02993           odl_remove_component(m, attr_comp);
02994       }
02995       else
02996         odl_remove_component(m, attr_comp);
02997     }
02998 
02999     m->getDatabase()->transactionAbort();
03000     return 0;
03001   }
03002 
03003   int
03004   odlAgregatClass::manageDifferences(Database *db, Schema *m, Bool diff)
03005   {
03006     if (upd_hints && upd_hints->type == odlUpdateHint::Remove &&
03007         !odl_gencode && m->getDatabase()) {
03008       int r = odl_remove_components(m, ocls, cls);
03009       if (r)
03010         return r;
03011       return odl_remove_relationships(db, m, ocls);
03012     }
03013 
03014     if (odl_gencode || !m->getDatabase() || !cls)
03015       return 0;
03016 
03017     odl_migrate_attributes(m, cls);
03018     if (!ocls) {
03019 #ifndef NEW_REORDER
03020       odl_add_class(m, cls);
03021 #endif
03022       return 0;
03023     }
03024     
03025     // added 31/05/01
03026     if (agrspec == odl_Declare)
03027       return 0;
03028 
03029     if (agrspec != odl_NativeClass) {
03030       odl_class_compare(m, ocls, cls, upd_hints);
03031       if (odl_error)
03032         return 0;
03033       odl_class_parent_compare(m, ocls, cls);
03034     }
03035 
03036     const LinkedList *complist = cls->getCompList();
03037     const LinkedList *ocomplist = ocls->getCompList();
03038 
03039     LinkedListCursor oc(ocomplist);
03040     LinkedListCursor c(complist);
03041 
03042     //printf("NEW COMLIST = %d %s\n", complist->getCount(), cls->getName());
03043     ClassComponent *clcomp = 0, *fclcomp;
03044 
03045     m->getDatabase()->transactionBegin();
03046 
03047     while (oc.getNext((void *&)clcomp)) {
03048       if (clcomp->getClassOwner()->compare(ocls)) {
03049         if (!odl_find_component(clcomp, complist, False, fclcomp)) {
03050           if ((!upd_hints || upd_hints->type != odlUpdateHint::Extend) &&
03051               agrspec != odl_NativeClass)
03052             odl_remove_component(m, clcomp);
03053         }
03054         else if (odl_exec_removed(fclcomp))
03055           odl_remove_component(m, clcomp);
03056       }
03057     }
03058   
03059     while (c.getNext((void *&)clcomp)) {
03060       ClassComponent *oclcomp = clcomp;
03061       if (clcomp->getClassOwner()->compare(cls)) {
03062         if (!odl_find_component(clcomp, ocomplist, True, fclcomp)) {
03063           if (!odl_exec_removed(oclcomp))
03064             odl_add_component(m, clcomp);
03065           else {
03066             fprintf(stderr, "warning: cannot remove non existing '");
03067             clcomp->m_trace(stderr, 0, 0, NoRecurs);
03068             fprintf(stderr, "'\n");
03069           }
03070         }
03071       }
03072     }
03073 
03074     const LinkedList *attr_ocomplist, *attr_complist;
03075     Status s = cls->getAttrCompList(attr_complist);
03076     if (s) {odl_add_error(s); return 1;}
03077     s = ocls->getAttrCompList(attr_ocomplist);
03078     if (s) {odl_add_error(s); return 1;}
03079 
03080     /*
03081       printf("\nClass %s Attribute Component List Count=%d, Old Count=%d\n",
03082       cls->getName(),
03083       (attr_complist ? attr_complist->getCount() : -1),
03084       (attr_ocomplist ? attr_ocomplist->getCount() : -1));
03085     */
03086 
03087     LinkedListCursor attr_oc(attr_ocomplist);
03088     LinkedListCursor attr_c(attr_complist);
03089 
03090     AttributeComponent *attr_comp, *fattr_comp;
03091     int err = 0;
03092     while (attr_oc.getNext((void *&)attr_comp)) {
03093       if (!odl_find_component(attr_comp, attr_complist, False,
03094                               fattr_comp)) {
03095         const Attribute *attr = odl_getattr(ocls, attr_comp);
03096         if (!attr) return 1;
03097         if (attr = odl_is_remove_attribute(m, attr)) {
03098           std::string s = std::string("removed attribute '") +
03099             attr->getClassOwner()->getName () + "::" + attr->getName() +
03100             "' : must remove " +
03101             (attr_comp->asIndex() ? "index" : "constraint") +
03102             " '" +  attr_comp->getAttrpath() + "' manually using '" +
03103             (attr_comp->asIndex() ? "idxdelete" : "consdelete") +
03104             "' before updating the schema\n";
03105           odl_add_error(s);
03106           err++;
03107         }
03108         // warning: odl_rmv_undef_attrcomp is not well implemented !
03109         if (odl_rmv_undef_attrcomp &&
03110             (!upd_hints || upd_hints->type != odlUpdateHint::Extend))
03111           odl_remove_component(m, attr_comp);
03112       }
03113     }
03114     if (err) return 1;
03115 
03116     LinkedList torm_list;
03117 
03118     while (attr_c.getNext((void *&)attr_comp)) {
03119       AttributeComponent *oattr_comp = attr_comp;
03120       if (!odl_find_component(attr_comp, attr_ocomplist, True, fattr_comp)) {
03121         //printf("component %s not found\n", attr_comp->getName());
03122         odl_add_component(m, attr_comp);
03123         const Attribute *attr = odl_getattr(cls, attr_comp);
03124         if (!attr) return 1;
03125         if (odl_is_update_attribute(m, attr))
03126           torm_list.insertObject(attr_comp);
03127       }
03128     }
03129 
03130     LinkedListCursor ctorm(torm_list);
03131     while (ctorm.getNext((void *&)attr_comp)) {
03132       //printf("XCOMP: SUPPRESSING %s\n", attr_comp->getName());
03133       cls->suppress(attr_comp->getInd(), attr_comp);
03134     }
03135 
03136     if (agrspec != odl_NativeClass && !odl_error)
03137       manageDiffRelationShips(db, m, diff);
03138 
03139     m->getDatabase()->transactionAbort();
03140     return 0;
03141   }
03142 
03143   // WARNING: this should centralized in a .h
03144 #define HASH_COEF 64
03145 #define DEFAULT_MAG_ORDER 60000
03146   // .....
03147 
03148 #if 0
03149   unsigned int
03150   odlImplementation::getMagOrder() const
03151   {
03152     unsigned magorder;
03153     if (!strcasecmp(ident, "btree"))
03154       return IDB_COLL_BIDX_MASK;
03155 
03156     if (!strcasecmp(ident, "hash"))
03157       return (nentries ? nentries * HASH_COEF : DEFAULT_MAG_ORDER);
03158 
03159     odl_add_error("expected keyword 'btree' or 'hash', got '%s'", ident);
03160     return 0;
03161   }
03162 #endif
03163 
03164   odlBool
03165   odlAgregatClass::hasSimilarComp(odlAttrComponent *comp,
03166                                   const Class *cls2)
03167   {
03168     //printf("ODL AGREGAT CLASS %s %s\n", cls->getName(), cls2->getName());
03169     odlDeclRootLink *l = decl_list->first;
03170     while(l) {
03171       odlAttrComponent *xcomp = l->x->asAttrComponent();
03172       if (xcomp && xcomp->similar(comp, cls, cls2))
03173         return odlTrue;
03174       l = l->next;
03175     }
03176 
03177     return odlFalse;
03178   }
03179 
03180   void
03181   odlAgregatClass::addComp(odlAttrComponent *comp)
03182   {
03183     decl_list->add(comp->clone());
03184   }
03185 
03186   int
03187   odlAgregatClass::propagateComponents(Database *db, Schema *m)
03188   {
03189     odlDeclRootLink *l = decl_list->first;
03190     if (!l)
03191       return 0;
03192 
03193     //printf("\npropagate components %s\n", cls->getAliasName());
03194     Class **subclasses;
03195     unsigned int subclass_cnt;
03196     Status s = cls->getSubClasses(subclasses, subclass_cnt);
03197     if (s) {
03198       odl_add_error(s);
03199       return 1;
03200     }
03201 
03202     while(l) {
03203       odlAttrComponent *comp = l->x->asAttrComponent();
03204       if (comp && comp->propagate) {
03205         //printf("checking comp %s\n", comp->attrpath);
03206         for (int i = 0; i < subclass_cnt; i++) {
03207           Class *clsx = subclasses[i];
03208           if (clsx == cls) continue;
03209           odlAgregatClass *x = (odlAgregatClass *)clsx->getUserData(odlSELF);
03210           if (x && !x->hasSimilarComp(comp, cls)) {
03211             // warning: odl_rmv_undef_attrcomp is not well implemented !
03212             if (odl_rmv_undef_attrcomp) {
03213               //printf("%s -> %s %s\n", cls->getName(), clsx->getName(), comp->attrpath);
03214               odl_add_error("attribute component %s: "
03215                             "when using the -rmv-undef-attrcomp option, all the "
03216                             "attribute components must be defined in the ODL",
03217                             comp->attrpath);
03218               return 1;
03219             }
03220             //printf("adding component %s to %s\n", comp->attrpath, clsx->getAliasName());
03221             x->addComp(comp);
03222           }
03223           /*
03224             else
03225             printf("%s has a similar component %s\n", clsx->getAliasName(),
03226             comp->attrpath);
03227           */
03228         }
03229       }
03230       l = l->next;
03231     }
03232 
03233     return 0;
03234   }
03235 
03236   int odlAgregatClass::postRealize(Database *db, Schema *m,
03237                                    const char *prefix)
03238   {
03239     odlDeclRootLink *l = decl_list->first;
03240 
03241     while(l) {
03242       if (l->x->asAttrComponent())
03243         realize(db, l->x->asAttrComponent(), m, prefix);
03244       l = l->next;
03245     }
03246 
03247     return 0;
03248   }
03249 
03250   int odlAgregatClass::realize(Database *db, Schema *m, const char *prefix,
03251                                const char *package, Bool diff)
03252   {
03253     if (!cls)
03254       return 0;
03255 
03256 #if 0
03257     unsigned int magorder = getMagOrder(cls, attr_list);
03258 
03259     if (magorder)
03260       cls->setMagOrder(magorder);
03261 #endif
03262 
03263     Attribute **agr;
03264 
03265     agr = new Attribute*[decl_list->count];
03266     memset(agr, 0, sizeof(Attribute *) * decl_list->count);
03267 
03268     ClassComponent **comp = new ClassComponent*[decl_list->count*8];
03269 
03270     int comp_cnt = 0, agr_cnt = 0;
03271 
03272     char *def_extref_fe = new char[strlen(package)+strlen("mthfe")+1];
03273     sprintf(def_extref_fe, "%smthfe", package);
03274 
03275     char *def_extref_be = new char[strlen(package)+strlen("mthbe")+1];
03276     sprintf(def_extref_be, "%smthbe", package);
03277 
03278     odlDeclRootLink *l = decl_list->first;
03279 
03280     while(l) {
03281       if (l->x->asExecSpec()) {
03282         odlBool isClient =
03283           (l->x->asExecSpec()->asMethodSpec() ?
03284            l->x->asExecSpec()->asMethodSpec()->mth_hints.isClient : odlFalse);
03285         realize(db, m, l->x->asExecSpec(),
03286                 (isClient ? def_extref_fe : def_extref_be));
03287       }
03288     
03289       l = l->next;
03290     }
03291 
03292     l = decl_list->first;
03293 
03294     while(l) {
03295       if (l->x->asDeclItem()) {
03296         realize(l->x->asDeclItem(), m, prefix, agr_cnt, comp, comp_cnt, agr);
03297         agr_cnt++;
03298       }
03299       else if (l->x->asQuotedSeq())
03300         add_quoted_seq(cls, l->x->asQuotedSeq()->quoted_seq);
03301 
03302       l = l->next;
03303     }
03304 
03305     if (odl_error) {
03306       if (agrspec != odl_NativeClass && agrspec != odl_Declare)
03307         m->suppressClass(cls);
03308       return odl_error;
03309     }
03310 
03311     if (agrspec != odl_NativeClass && agrspec != odl_Declare) {
03312       Status status;
03313       status = cls->setAttributes(agr, agr_cnt);
03314 
03315       if (status) {
03316         odl_add_error(status);
03317         return 0;
03318       }
03319     }
03320   
03321     for (int i = 0; i < comp_cnt; i++)
03322       cls->add(comp[i]->getInd(), comp[i]);
03323 
03324     return propagateComponents(db, m);
03325   }
03326 
03327   int
03328   odlEnumClass::record(Database *, Schema *m,
03329                        const char *prefix, const char *db_prefix)
03330   {
03331     if (check(m, prefix))
03332       odl_error++;
03333 
03334     cls = new EnumClass(makeName(name, prefix));
03335     cls->setUserData(odlGENCODE, AnyUserData);
03336 
03337     if (aliasname)
03338       cls->setAliasName(aliasname);
03339     else if (db_prefix)
03340       cls->setAliasName(makeName(name, db_prefix));
03341 
03342     // added the 17/01/01
03343     ocls = eyedb::getClass(m, (aliasname ? aliasname : name), prefix);
03344     if (ocls && ocls != cls)
03345       {
03346         m->suppressClass(ocls);
03347         cls->setUserData(ocls);
03348         ObjectPeer::setOid(cls, ocls->getOid());
03349       }
03350     // ...
03351 
03352     m->addClass(cls);
03353     if (odl_system_class)
03354       ClassPeer::setMType(cls, Class::System);
03355     return 0;
03356   }
03357 
03358   int odlEnumClass::realize(Database *db, Schema *m, const char *prefix,
03359                             const char *, Bool)
03360   {
03361     EnumItem **en = new EnumItem*[enum_list->count];
03362 
03363     memset(en, 0, sizeof(EnumItem *) * enum_list->count);
03364 
03365     odlEnumItemLink *l = enum_list->first;
03366   
03367     int n = 0;
03368     int lastvalue, value;
03369     lastvalue = 0;
03370 
03371     while(l)
03372       {
03373         odlEnumItem *item = l->x;
03374 
03375         if (item->novalue)
03376           value = lastvalue;
03377         else
03378           value = item->value;
03379 
03380         //      if (check_name(m, name, 0, item->name, prefix))
03381         if (check_name(m, (aliasname ? aliasname : name), 0, item->name, prefix))
03382           odl_error++;
03383 
03384         en[n++] = new EnumItem(item->name, item->aliasname, value);
03385 
03386         lastvalue = value + 1;
03387         l = l->next;
03388       }
03389 
03390     Status status;
03391     status = ((EnumClass *)cls)->setEnumItems(en, n);
03392 
03393     if (status)
03394       odl_add_error(status);
03395 
03396     return 0;
03397   }
03398 
03399   const char *odl_get_typname(const char *typname)
03400   {
03401     if (!strcmp(typname, "int"))
03402       return int32_class_name;
03403 
03404     if (!strcmp(typname, "short"))
03405       return int16_class_name;
03406 
03407     if (!strcmp(typname, "long"))
03408       return int64_class_name;
03409 
03410     if (!strcmp(typname, "octet"))
03411       return "byte";
03412 
03413     if (!strcmp(typname, "boolean"))
03414       return int32_class_name;
03415 
03416     if (!strcmp(typname, "double"))
03417       return "float";
03418 
03419     if (!strcmp(typname, "sequence"))
03420       return "array";
03421 
03422     return typname;
03423   }
03424 
03425   int
03426   odl_generate(Schema *m, const char *ofile)
03427   {
03428     FILE *fd;
03429 
03430     Class *superclass = NULL;
03431     if (odlAgregatClass::superclass)
03432       {
03433         superclass = m->getClass(get_superclass_name());
03434         if (odlAgregatClass::superclass->getAgregSpec() == odl_RootClass)
03435           superclass->setIsRootClass();
03436       }
03437 
03438     if (!ofile)
03439       fd = odl_fd;
03440     else
03441       {
03442         fd = fopen(ofile, "w");
03443         if (!fd)
03444           {
03445             odl_add_error("cannot open file '%s' for reading.\n",
03446                           ofile);
03447             return 1;
03448           }
03449       }
03450 
03451     m->genODL(fd);
03452 
03453     return 0;
03454   }
03455 
03456   static int odl_echo;
03457 
03458   void
03459   odl_prompt_init(FILE *fd)
03460   {
03461     odl_echo = isatty(fileno(fd));
03462   }
03463 
03464   void
03465   odl_prompt(const char *prompt)
03466   {
03467     if (odl_echo)
03468       {
03469         fprintf(odl_fd, prompt);
03470         fflush(odl_fd);
03471       }
03472   }
03473 
03474   // ----------------------------------------------------------------------------
03475   //
03476   // Database API
03477   //
03478   // ----------------------------------------------------------------------------
03479 
03480   static Status
03481   odl_post_update_non_components(Database *db, Schema *m)
03482   {
03483     LinkedList *list = odlUPDLIST(m);
03484     LinkedListCursor c(list);
03485     Status s;
03486     odlUpdateItem *ci;
03487     while (c.getNext((void *&)ci)) {
03488       if (ci->asUpdateComponent() ||
03489           ci->asUpdateRelationship() ||
03490           ci->asRemoveClass())
03491         continue;
03492 
03493       s = ci->postPerform(db, m);
03494       if (s) return s;
03495     }
03496 
03497     return Success;
03498   }
03499 
03500   static Status
03501   odl_post_update_components_1(Database *db, Schema *m)
03502   {
03503     LinkedList *list = odlUPDLIST(m);
03504     LinkedListCursor c(list);
03505     Status s;
03506     odlUpdateItem *ci;
03507     while (c.getNext((void *&)ci)) {
03508       if (!ci->asUpdateComponent())
03509         continue;
03510 
03511       ClassComponent *comp = ci->asUpdateComponent()->cls_comp;
03512 
03513       if (comp && comp->asMethod()) {
03514         s = ci->postPerform(db, m);
03515         if (s) return s;
03516       }
03517     }
03518 
03519     return Success;
03520   }
03521 
03522   static Status
03523   odl_post_update_components_2(Database *db, Schema *m)
03524   {
03525     LinkedList *list = odlUPDLIST(m);
03526     LinkedListCursor c(list);
03527     Status s;
03528     odlUpdateItem *ci;
03529     while (c.getNext((void *&)ci)) {
03530       if (!ci->asUpdateComponent())
03531         continue;
03532 
03533       ClassComponent *cls_comp = ci->asUpdateComponent()->cls_comp;
03534       AttributeComponent *attr_comp = ci->asUpdateComponent()->attr_comp;
03535     
03536       if ((cls_comp && cls_comp->asMethod()) ||
03537           (attr_comp && attr_comp->asIndex()))
03538         continue;
03539     
03540       s = ci->postPerform(db, m);
03541       if (s) return s;
03542     }
03543 
03544     return Success;
03545   }
03546 
03547   static Status
03548   odl_post_update_indexes(Database *db, Schema *m)
03549   {
03550     LinkedList *list = odlUPDLIST(m);
03551     LinkedListCursor c(list);
03552     odlUpdateItem *ci;
03553     Status s;
03554 
03555     while (c.getNext((void *&)ci)) {
03556       if (!ci->asUpdateComponent())
03557         continue;
03558 
03559       AttributeComponent *comp = ci->asUpdateComponent()->attr_comp;
03560     
03561       if (comp && comp->asIndex()) {
03562         s = ci->postPerform(db, m);
03563         if (s) return s;
03564       }
03565     }
03566 
03567     return Success;
03568   }
03569 
03570   static Status
03571   odl_post_update_relships(Database *db, Schema *m)
03572   {
03573     LinkedList *list = odlUPDLIST(m);
03574     LinkedListCursor c(list);
03575     Status s;
03576     odlUpdateItem *ci;
03577     while (c.getNext((void *&)ci)) {
03578       if (!ci->asUpdateRelationship())
03579         continue;
03580 
03581       const Attribute *invitem = ci->asUpdateRelationship()->invitem;
03582 
03583       if (!invitem)
03584         continue;
03585     
03586       s = ci->postPerform(db, m);
03587       if (s) return s;
03588     }
03589 
03590     return Success;
03591   }
03592 
03593   static Status
03594   odl_post_update_remove_classes(Database *db, Schema *m)
03595   {
03596     LinkedList *list = odlUPDLIST(m);
03597     LinkedListCursor c(list);
03598     Status s;
03599     odlUpdateItem *ci;
03600     while (c.getNext((void *&)ci)) {
03601       if (!ci->asRemoveClass())
03602         continue;
03603 
03604       s = ci->postPerform(db, m);
03605       if (s) return s;
03606     }
03607 
03608     return Success;
03609   }
03610 
03611   static Status
03612   odl_post_update_components(Database *db, Schema *m)
03613   {
03614     Status s;
03615     s = odl_post_update_components_1(db, m);
03616     if (s) return s;
03617 
03618     s = odl_post_update_indexes(db, m);
03619     if (s) return s;
03620 
03621     s = odl_post_update_components_2(db, m);
03622     if (s) return s;
03623 
03624     return odl_post_update_relships(db, m);
03625   }
03626 
03627   static Status
03628   odl_post_update_items(Database *db, Schema *m)
03629   {
03630     if (odlUPDLIST(m)) {
03631       Status s;
03632       s = odl_post_update_non_components(db, m);
03633       if (s) return s;
03634 
03635       s = odl_post_update_components(db, m);
03636       if (s) return s;
03637 
03638       s = odl_post_update_remove_classes(db, m);
03639       if (s) return s;
03640     }
03641 
03642     return odl_post_update(db);
03643   }
03644 
03645   static Status
03646   odl_pre_update_items(Database *db, Schema *m)
03647   {
03648     if (!odlUPDLIST(m))
03649       return Success;
03650 
03651     LinkedList *list = odlUPDLIST(m);
03652     LinkedListCursor c(list);
03653     Status s;
03654     odlUpdateItem *ci;
03655     while (c.getNext((void *&)ci))
03656       {
03657         s = ci->prePerform(db, m);
03658         if (s) return s;
03659       }
03660 
03661     return Success;
03662   }
03663 
03664   static void
03665   odl_diff_realize(Database *db, Schema *m, const char *odlfile)
03666   {
03667     LinkedList *list = odlUPDLIST(m);
03668 
03669     if (!list)
03670       return;
03671 
03672     //m->trace();
03673 
03674     LinkedListCursor c(list);
03675     odlUpdateItem *ci;
03676     while (c.getNext((void *&)ci))
03677       {
03678         odl_diff++;
03679         ci->displayDiff(db, odlfile);
03680       }
03681 
03682     db->transactionAbort();
03683   }
03684 
03685 
03686   static int odl_finished;
03687 
03688   static void  *
03689   patient_thr(void *arg)
03690   {
03691     if (getenv("EYEDBNOPATIENT")) // for debugging only
03692       return 0;
03693 
03694     sleep(4);
03695     while (!odl_finished)
03696       {
03697         fprintf(odl_fd, ".");
03698         fflush(odl_fd);
03699         sleep(1);
03700       }
03701 
03702     return (void *)0;
03703   }
03704 
03705   static void
03706   run_patient()
03707   {
03708     pthread_t tid;
03709     pthread_create(&tid, NULL, patient_thr, NULL);
03710   }
03711 
03712   static int
03713   odl_update_realize(Database *db, Schema *m, const char *dbname,
03714                      const char *schname)
03715   {
03716     odl_skip_volatiles(db, m);
03717 
03718     fprintf(odl_fd, "Updating '%s' schema in database %s...",  schname, dbname);
03719     fflush(odl_fd);
03720 
03721     Status s;
03722 
03723     if (db->getUserData() && (s = m->storeName()))
03724       {
03725         odl_add_error(s);
03726         return 1;
03727       }
03728 
03729     s = odl_pre_update_items(db, m);
03730 
03731     if (s)
03732       {
03733         odl_add_error(s);
03734         return 1;
03735       }
03736 
03737     run_patient();
03738     s = m->realize();
03739 
03740     if (s)
03741       {
03742         odl_add_error(s);
03743         return 1;
03744       }
03745 
03746     s = odl_post_update_items(db, m);
03747 
03748     if (s)
03749       {
03750         odl_add_error(s);
03751         return 1;
03752       }
03753 
03754     if (!getenv("EYEDBABORT"))
03755       s = db->transactionCommit();
03756     odl_finished = 1;
03757 
03758     if (s)
03759       {
03760         odl_add_error(s);
03761         return 1;
03762       }
03763 
03764     fprintf(odl_fd, "\nDone\n");
03765 
03766     return 0;
03767   }
03768 
03769   static int
03770   check_odlfile(const char *file, const char *cpp_cmd, const char *cpp_flags)
03771   {
03772     odl_decl_list = new LinkedList();
03773 
03774     if (file) {
03775       FILE *fd;
03776       
03777       if (!strcmp(file, "-"))
03778         odlin = stdin;
03779       else {
03780         fd = fopen(file, "r");
03781         if (!fd) {
03782           odl_add_error("cannot open file '%s' for reading\n",
03783                         file);
03784           return 1;
03785         }
03786 
03787         if (odlin && odlin != stdin)
03788           fclose(odlin);
03789         
03790         odlin = run_cpp(fd, cpp_cmd, cpp_flags, file);
03791         if (!odlin)
03792           return 1;
03793       }
03794     }
03795 
03796     if (file) {
03797       odl_prompt_init(odlin);
03798       odl_prompt("ODL construct expected on standard input (end input by a ^D) :\n");
03799       odl_prompt();
03800     }
03801   
03802     return 0;
03803   }
03804 
03805   /*
03806     static Status
03807     x_transaction_begin(Database *db)
03808     {
03809     TransactionParams params = Database::getGlobalDefaultTransactionParams();
03810     params.lockmode = DatabaseX;
03811     params.wait_timeout = 1;
03812 
03813     Status s = db->transactionBegin(params);
03814     if (s) {
03815     if (s->getStatus() == SE_LOCK_TIMEOUT) {
03816     fprintf(stderr,
03817     "cannot acquire exclusive lock on database %s\n",
03818     db->getName());
03819     exit(1);
03820     }
03821     }
03822 
03823     return s;
03824     }
03825   */
03826 
03827   static int
03828   odl_check_db(Database *db, const char *&schname, const char *package,
03829                Schema *&m, Bool update = False)
03830   {
03831     if (!schname)
03832       schname = package;
03833 
03834     if (db) {
03835       Status s;
03836       Exception::Mode mode =
03837         Exception::setMode(Exception::StatusMode);
03838 
03839       if (update)
03840         s = db->transactionBeginExclusive();
03841       else
03842         s = db->transactionBegin();
03843 
03844       if (s) {
03845         odl_add_error(s);
03846         return 1;
03847       }
03848 
03849       Exception::setMode(mode);
03850       m = db->getSchema();
03851       if (strcmp(m->getName(), schname))
03852         db->setUserData(AnyUserData);
03853 
03854       LinkedListCursor c(m->getClassList());
03855       Class *cls;
03856       while (c.getNext((void *&)cls))
03857         if (!cls->isSystem())
03858           cls->setUserData(odlGENCODE, AnyUserData);
03859     }
03860     else {
03861       m = new Schema();
03862       m->init();
03863       syscls::updateSchema(m);
03864       oqlctb::updateSchema(m);
03865       utils::updateSchema(m);
03866     }
03867     
03868     m->setName(schname);
03869     return 0;
03870   }
03871 
03872   Status
03873   odl_prelim(Database *db, const char *odlfile, const char *package,
03874              const char *&schname, const char *prefix, const char *db_prefix,
03875              Bool diff, const char *cpp_cmd,  const char *cpp_flags,
03876              Schema *&m, Bool update = False)
03877   {
03878     odl_error = 0;
03879     odl_str_error = "";
03880 
03881     int r;
03882     r = odl_check_db(db, schname, package, m, update);
03883     if (r || odl_error) return odl_status_error(r);
03884 
03885     r = check_odlfile(odlfile, cpp_cmd, cpp_flags);
03886 
03887     if (r || odl_error) return odl_status_error(r);
03888 
03889     if (odlfile) {
03890       r = odlparse();
03891       if (r || odl_error) return odl_status_error(r);
03892     }
03893 
03894     odl_realize(db, m, odl_decl_list, prefix, db_prefix, package, diff);
03895 
03896     return odl_status_error();
03897   }
03898 
03899   Status
03900   Database::updateSchema(const char *odlfile, const char *package,
03901                          const char *schname, const char *db_prefix,
03902                          FILE *fd, const char *cpp_cmd,
03903                          const char *cpp_flags)
03904   {
03905     odl_fd = (fd ? fd : odl_fdnull);
03906     Schema *m;
03907     Status s;
03908     s = odl_prelim(this, odlfile, package, schname, db_prefix, db_prefix,
03909                    False, cpp_cmd, cpp_flags, m, True);
03910     if (s) return s;
03911 
03912     odl_update_realize(this, sch, name, schname);
03913     return odl_status_error();
03914   }
03915 
03916   Status
03917   Schema::displaySchemaDiff(Database *db, const char *odlfile,
03918                             const char *package,
03919                             const char *db_prefix,
03920                             FILE *fd, const char *cpp_cmd,
03921                             const char *cpp_flags)
03922   {
03923     odl_fd = (fd ? fd : odl_fdnull);
03924     Schema *m;
03925     const char *schname = "";
03926     Status s;
03927     s =  odl_prelim(db, odlfile, package, schname, db_prefix, db_prefix,
03928                     True, cpp_cmd, cpp_flags, m);
03929     if (s) return s;
03930     if (odl_error) return odl_status_error();
03931     odl_diff_realize(db, m, odlfile);
03932     return odl_status_error();
03933   }
03934 
03935 #ifdef SUPPORT_CORBA
03936   Status
03937   Schema::genIDL(Database *db, const char *odlfile,
03938                  const char *package,
03939                  const char *module,
03940                  const char *schname,
03941                  const char *prefix,
03942                  const char *db_prefix,
03943                  const char *idltarget,
03944                  const char *imdlfile,
03945                  Bool no_generic_idl,
03946                  const char *generic_idl,
03947                  Bool no_factory,
03948                  Bool imdl_synchro,
03949                  GenCodeHints *gc_hints,
03950                  Bool comments,
03951                  const char *cpp_cmd, const char *cpp_flags,
03952                  const char *ofile)
03953   {
03954     if (!gc_hints) gc_hints = new GenCodeHints();
03955     Schema *m;
03956     Status s;
03957     s = odl_prelim(db, odlfile, package, schname, prefix, db_prefix,
03958                    False, cpp_cmd, cpp_flags, m);
03959     if (s) return s;
03960 
03961     imdl_realize(db, m, package, module, False, False,
03962                  schname, prefix,
03963                  db_prefix, cpp_cmd, cpp_flags,
03964                  idltarget, imdlfile,
03965                  no_generic_idl, generic_idl,
03966                  no_factory, imdl_synchro, gc_hints, comments,
03967                  ofile);
03968 
03969     return odl_status_error();
03970   }
03971 
03972   Status
03973   Schema::genORB(const char *orb,
03974                  Database *db, const char *odlfile,
03975                  const char *package,
03976                  const char *module,
03977                  const char *schname,
03978                  const char *prefix,
03979                  const char *db_prefix,
03980                  const char *idltarget,
03981                  const char *imdlfile,
03982                  Bool no_generic_idl,
03983                  const char *generic_idl,
03984                  Bool no_factory,
03985                  Bool imdl_synchro,
03986                  GenCodeHints *gc_hints,
03987                  Bool comments,
03988                  const char *cpp_cmd, const char *cpp_flags)
03989   {
03990     if (!gc_hints) gc_hints = new GenCodeHints();
03991     Schema *m;
03992     Status s;
03993     s = odl_prelim(db, odlfile, package, schname, prefix, db_prefix,
03994                    False, cpp_cmd, cpp_flags, m);
03995     if (s) return s;
03996 
03997     Bool orbix_gen, orbacus_gen;
03998     if (!strcasecmp(orb, "orbix"))
03999       {
04000         orbix_gen = True;
04001         orbacus_gen = False;
04002       }
04003     else
04004       {
04005         orbix_gen = False;
04006         orbacus_gen = True;
04007       }
04008 
04009     imdl_realize(db, m, package, module, orbix_gen, orbacus_gen,
04010                  schname, prefix,
04011                  db_prefix, cpp_cmd, cpp_flags,
04012                  idltarget, imdlfile,
04013                  no_generic_idl, generic_idl,
04014                  no_factory, imdl_synchro, gc_hints, comments, 0);
04015 
04016     return odl_status_error();
04017   }
04018 #endif
04019 
04020   Status
04021   Schema::genC_API(Database *db, const char *odlfile,
04022                    const char *package,
04023                    const char *schname,
04024                    const char *c_namespace,
04025                    const char *prefix,
04026                    const char *db_prefix,
04027                    Bool _export,
04028                    GenCodeHints *gc_hints,
04029                    const char *cpp_cmd, const char *cpp_flags)
04030   {
04031     odl_error = 0;
04032     odl_str_error = "";
04033 
04034     if (!gc_hints) gc_hints = new GenCodeHints();
04035     Schema *m;
04036     odl_check_db(db, schname, package, m);
04037 
04038     int r = check_odlfile(odlfile, cpp_cmd, cpp_flags);
04039 
04040     if (r || odl_error) return odl_status_error(r);
04041 
04042     if (odlfile)
04043       {
04044         r = odlparse();
04045         if (r || odl_error) return odl_status_error(r);
04046       }
04047 
04048     odl_generate_code(db, m, ProgLang_C,
04049                       odl_decl_list,
04050                       package,
04051                       schname,
04052                       c_namespace,
04053                       prefix,
04054                       db_prefix,
04055                       _export,
04056                       *gc_hints);
04057 
04058     return odl_status_error();
04059   }
04060 
04061   Status
04062   Schema::genJava_API(Database *db, const char *odlfile,
04063                       const char *package,
04064                       const char *schname,
04065                       const char *prefix,
04066                       const char *db_prefix,
04067                       Bool _export,
04068                       GenCodeHints *gc_hints,
04069                       const char *cpp_cmd, const char *cpp_flags)
04070   {
04071     if (!gc_hints) gc_hints = new GenCodeHints();
04072     Schema *m;
04073     Status s;
04074 
04075     odl_check_db(db, schname, package, m);
04076 
04077     int r = check_odlfile(odlfile, cpp_cmd, cpp_flags);
04078 
04079     if (r || odl_error) return odl_status_error(r);
04080 
04081     if (odlfile)
04082       {
04083         r = odlparse();
04084         if (r || odl_error) return odl_status_error(r);
04085       }
04086 
04087     odl_generate_code(db, m, ProgLang_Java,
04088                       odl_decl_list,
04089                       package,
04090                       schname,
04091                       NULL,
04092                       prefix,
04093                       db_prefix,
04094                       _export,
04095                       *gc_hints);
04096 
04097     return odl_status_error();
04098   }
04099 
04100   Status
04101   Schema::checkODL(const char *odlfile, const char *package,
04102                    const char *cpp_cmd, const char *cpp_flags)
04103   {
04104     odl_error = 0;
04105     odl_str_error = "";
04106 
04107     Schema *m;
04108     const char *schname = "";
04109     return odl_prelim(0, odlfile, package, schname, "", "",
04110                       False, cpp_cmd, cpp_flags, m);
04111   }
04112 
04113   Status
04114   Schema::genODL(Database *db,
04115                  const char *odlfile,
04116                  const char *package,
04117                  const char *schname,
04118                  const char *prefix,
04119                  const char *db_prefix,
04120                  const char *ofile,
04121                  const char *cpp_cmd, const char *cpp_flags)
04122   {
04123     odl_error = 0;
04124     odl_str_error = "";
04125 
04126     Schema *m;
04127 
04128     if (odlfile)
04129       {
04130         Status s;
04131         s = odl_prelim(db, odlfile, package, schname, prefix, db_prefix,
04132                        False, cpp_cmd, cpp_flags, m);
04133         if (s) return s;
04134       }
04135     else
04136       {
04137         int r = odl_check_db(db, schname, package, m);
04138         if (r || odl_error) return odl_status_error(r);
04139       }
04140 
04141     odl_generate(m, ofile);
04142 
04143     return odl_status_error();
04144   }
04145 }

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