oqlnewdel.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 <stdlib.h>
00026 #include <stdio.h>
00027 #include <string.h>
00028 #include <assert.h>
00029 #include <eyedb/oqlctb.h>
00030 
00031 #include "oql_p.h"
00032 
00033 // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
00034 //
00035 // static utility functions
00036 //
00037 // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
00038 
00039 namespace eyedb {
00040 
00041 static oqmlStatus *
00042 oqmlGetValidAtomType(oqmlNode *node, const Attribute *attr,
00043                      int ndims, oqmlAtomType &at)
00044 {
00045   const Class *cls = attr->getClass();
00046   int attr_ndims = attr->getTypeModifier().ndims;
00047   const char *name = cls->getName();
00048 
00049   int mode = attr_ndims - ndims;
00050 
00051   if (mode < 0)
00052     return new oqmlStatus(node, "invalid assignation for attribute '%s': to many array specifiers", attr->getName());
00053 
00054   if (mode > 1)
00055     return new oqmlStatus(node, "invalid assignation for attribute '%s': not enough array specifiers", attr->getName());
00056 
00057   if (attr->isIndirect()) {
00058     at.type = oqmlATOM_OID;
00059     at.comp = oqml_False;
00060   }
00061   else if ((!strcmp(name, char_class_name) || !strcmp(name, "byte")) &&
00062            mode) {
00063     at.type = oqmlATOM_STRING;
00064     at.comp = oqml_True;
00065   }
00066   else {
00067     if (cls->asInt32Class() || cls->asInt16Class() || cls->asInt64Class())
00068       at.type = oqmlATOM_INT;
00069     else if (!strcmp(name, char_class_name) || !strcmp(name, "byte"))
00070       at.type = oqmlATOM_CHAR;
00071     else if (!strcmp(name, "float") || !strcmp(name, "double"))
00072       at.type = oqmlATOM_DOUBLE;
00073     else if (!strcmp(name, "oid"))
00074       at.type = oqmlATOM_OID;
00075     else if (cls->asEnumClass())
00076       at.type = oqmlATOM_INT;
00077     else
00078       at.type = oqmlATOM_OBJ; // changed from OID to OBJ the 28/12/00
00079     at.comp = oqml_False;
00080   }
00081   /*
00082     return new oqmlStatus(node, "invalid assignation for attribute '%s'",
00083                           attr->getName());
00084   */
00085 
00086   return oqmlSuccess;
00087 }
00088 
00089 static oqmlStatus *
00090 oqmlCheckType(oqmlNode *node, Database *db,
00091               const Attribute *attr,
00092               const oqmlAtomType *at, int ndims)
00093 {
00094   if (at->type == oqmlATOM_UNKNOWN_TYPE)
00095     return oqmlSuccess;
00096 
00097   oqmlAtomType vat;
00098   oqmlStatus *s;
00099   s = oqmlGetValidAtomType(node, attr, ndims, vat);
00100 
00101   if (s)
00102     return s;
00103 
00104   if (vat.type == at->type)
00105     return oqmlSuccess;
00106 
00107   /*
00108   // added the 19/06/01
00109   if ((vat.type == oqmlATOM_OID && at->type == oqmlATOM_OBJ) ||
00110       (vat.type == oqmlATOM_OBJ && at->type == oqmlATOM_OID))
00111     return oqmlSuccess;
00112   */
00113 
00114   return oqmlStatus::expected(node, &vat, (oqmlAtomType *)at);
00115 }
00116 
00117 // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
00118 //
00119 // oqmlNew methods
00120 //
00121 // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
00122 
00123 oqmlNew::oqmlNew(oqmlNode *_location, const char *_ident,
00124                  oqml_IdentList * _ident_list) : oqmlNode(oqmlNEW)
00125 {
00126   location = _location;
00127   ident = strdup(_ident);
00128   ident_list = _ident_list;
00129   ql = 0;
00130   comp = 0;
00131   if (!location)
00132     eval_type.type = oqmlATOM_OBJ;
00133   else
00134     eval_type.type = oqmlATOM_OID;
00135   quoted_odl = 0;
00136 }
00137 
00138 oqmlNew::oqmlNew(oqmlNode *_location, const char *_ident, oqmlNode *_ql) :
00139   oqmlNode(oqmlNEW)
00140 {
00141   location = _location;
00142   ident = strdup(_ident);
00143   ident_list = 0;
00144   ql = _ql;
00145   comp = 0;
00146   eval_type.type = oqmlATOM_OID;
00147   cst_atom = 0;
00148   quoted_odl = 0;
00149 }
00150 
00151 oqmlNew::oqmlNew(oqmlNode *_location, const char *_quoted_odl) :
00152   oqmlNode(oqmlNEW)
00153 {
00154   location = _location;
00155   ident = 0;
00156   ident_list = 0;
00157   ql = 0;
00158   comp = 0;
00159   eval_type.type = oqmlATOM_LIST;
00160   cst_atom = 0;
00161   quoted_odl = strdup(_quoted_odl);
00162 }
00163 
00164 void
00165 oqmlNew::lock()
00166 {
00167   oqmlNode::lock();
00168   if (location)
00169     location->lock();
00170   if (ident_list)
00171     ident_list->lock();
00172 }
00173 
00174 void
00175 oqmlNew::unlock()
00176 {
00177   oqmlNode::unlock();
00178   if (location)
00179     location->unlock();
00180   if (ident_list)
00181     ident_list->unlock();
00182 }
00183 
00184 oqmlNew::~oqmlNew()
00185 {
00186   free(ident);
00187   free(quoted_odl);
00188   delete ident_list;
00189   delete comp;
00190 }
00191 
00192 #define IS_NUM(AT) ((AT).type == oqmlATOM_DOUBLE || \
00193                     (AT).type == oqmlATOM_INT || \
00194                     (AT).type == oqmlATOM_CHAR)
00195 oqmlStatus *
00196 oqmlNew::compileNode(Database *db, oqmlContext *ctx, const Class *cls)
00197 {
00198   if (!cls->asBasicClass() && !cls->asEnumClass())
00199     return new oqmlStatus(this, "class '%s' is not a basic class", ident);
00200 
00201   _class = (Class *)cls;
00202   if (cls->asEnumClass())
00203     {
00204       if (ql->getType() == oqmlIDENT)
00205         {
00206           const char *name = ((oqmlIdent *)ql)->getName();
00207           const EnumItem *en = cls->asEnumClass()->
00208             getEnumItemFromName(name);
00209 
00210           if (!en)
00211             return new oqmlStatus(this,
00212                                   "unknown value '%s' for enum class '%s'",
00213                                   name, ident);
00214           cst_atom = new oqmlAtom_int(en->getValue());
00215         }
00216     }
00217       
00218   oqmlStatus *s = ql->compile(db, ctx);
00219   if (s) return s;
00220 
00221   oqmlAtomType at;
00222   ql->evalType(db, ctx, &at);
00223 
00224   if (at.type == oqmlATOM_UNKNOWN_TYPE)
00225     return oqmlSuccess;
00226 
00227 #if 0
00228   if (cls->asFloatClass())
00229     {
00230       if (!IS_NUM(at))
00231         return oqmlStatus::expected(this, "float", at.getString());
00232     }
00233   else if (cls->asByteClass() || cls->asCharClass())
00234     {
00235       if (!IS_NUM(at))
00236         return oqmlStatus::expected(this, "char", at.getString());
00237     }
00238   else if (cls->asInt32Class() || cls->asInt64Class() || cls->asInt16Class())
00239     {
00240       if (!IS_NUM(at))
00241         return oqmlStatus::expected(this, "integer", at.getString());
00242     }
00243   else if (cls->asOidClass())
00244     {
00245       if (at.type != oqmlATOM_OID)
00246         return oqmlStatus::expected(this, "oid", at.getString());
00247     }
00248   else
00249     return new oqmlStatus(this, "class '%s' not supported", cls->getName());
00250 #endif
00251   
00252   if (ql->isConstant())
00253     {
00254       oqmlAtomList *al;
00255       s = ql->eval(db, ctx, &al);
00256       if (s)
00257         return s;
00258       if (al->cnt != 1)
00259         return new oqmlStatus(this, "constant expected");
00260       cst_atom = al->first->copy();
00261     }
00262   
00263   return oqmlSuccess;
00264 }
00265 
00266 oqmlStatus *
00267 oqmlNew::compileIdent(Database *db, oqmlContext *ctx, const Class *cls,
00268                       oqmlNode *left, int n, int &ndims)
00269 {
00270   comp->attr[n] = (Attribute *)cls->getAttribute
00271     ( ((oqmlIdent *)left)->getName() );
00272   if (!comp->attr[n])
00273     return new oqmlStatus(this, "cannot find attribute '%s' in class '%s'",
00274                           ((oqmlIdent *)left)->getName(),
00275                           cls->getName());
00276   comp->attrname[n] = strdup(((oqmlIdent *)left)->getName());
00277   return oqmlSuccess;
00278 }
00279 
00280 oqmlStatus *
00281 oqmlNew::compileDot(Database *db, oqmlContext *ctx, const Class *cls,
00282                     oqmlNode *left, int n, int &ndims)
00283 {
00284   if (ctx->getDotContext())
00285     return new oqmlStatus(this, "internal error #110");
00286   
00287   comp->dot_ctx[n] = new oqmlDotContext(0, cls);
00288   oqmlDotContext *dot_ctx = comp->dot_ctx[n];
00289   
00290   ctx->setDotContext(dot_ctx);
00291           
00292   oqmlStatus *s = left->compile(db, ctx);
00293   if (s) return s;
00294 
00295   s = left->asDot()->check(db, dot_ctx);
00296   if (s) return s;
00297 
00298   ctx->setDotContext(0);
00299   oqmlDotDesc *d = &dot_ctx->desc[dot_ctx->count - 1];
00300   
00301   comp->attr[n] = (Attribute *)d->attr;
00302 
00303   if (!comp->attr[n])
00304     return new oqmlStatus(this, "internal error #111");
00305   
00306   comp->attrname[n] = strdup(d->attrname);
00307   ndims = (d->array ? d->array->count : 0);
00308   return oqmlSuccess;
00309 }
00310 
00311 oqmlStatus *
00312 oqmlNew::compileArray(Database *db, oqmlContext *ctx, 
00313                     const Class *cls, oqmlNode *left, int n, int &ndims)
00314 {
00315   comp->dot_ctx[n] = new oqmlDotContext(0, cls);
00316   
00317   oqmlArray *array = (oqmlArray *)left;
00318   oqmlNode *xident = array->getLeft();
00319   
00320   if (xident->getType() != oqmlIDENT)
00321     return new oqmlStatus(this, "left part of array is not an ident");
00322   
00323   comp->attr[n] = (Attribute *)
00324     cls->getAttribute
00325     (((oqmlIdent *)xident)->getName() );
00326 
00327   if (!comp->attr[n])
00328     return new oqmlStatus(this, "compilation array error in new operator");
00329   
00330   comp->attrname[n] = strdup(((oqmlIdent *)xident)->getName());
00331   comp->list[n] = array->getArrayList();
00332   ndims = comp->list[n]->count;
00333   return oqmlSuccess;
00334 }
00335 
00336 oqmlStatus *oqmlNew::compile(Database *db, oqmlContext *ctx)
00337 {
00338   oqmlStatus *s = oqml_get_location(db, ctx, location);
00339   if (s) return s;
00340   newdb = db;
00341 
00342   if (!db->isInTransaction())
00343     return new oqmlStatus(this, "must be done within the scope of "
00344                           "a transaction in database '%s'", db->getName());
00345 
00346   Class *cls;
00347 
00348   cls = db->getSchema()->getClass(ident);
00349 
00350   if (!cls)
00351     return new oqmlStatus(this, "invalid class '%s'", ident);
00352 
00353   if (ql)
00354     return compileNode(db, ctx, cls);
00355 
00356   comp = new newCompile(cls, (ident_list ? ident_list->cnt : 0));
00357 
00358   oqml_IdentLink *l = (ident_list ? ident_list->first : 0);
00359 
00360   if (!location)
00361     eval_type.type = oqmlATOM_OBJ;
00362   else
00363     eval_type.type = oqmlATOM_OID;
00364 
00365   eval_type.cls = cls;
00366 
00367   int n = 0;
00368 
00369   while (l)
00370     {
00371       oqmlNode *left = l->left;
00372       oqmlTYPE xtype = left->getType();
00373       int ndims = 0;
00374 
00375       if (xtype == oqmlIDENT)
00376         {
00377           s = compileIdent(db, ctx, cls, left, n, ndims);
00378           if (s) return s;
00379         }
00380       else if (xtype == oqmlDOT)
00381         {
00382           s = compileDot(db, ctx, cls, left, n, ndims);
00383           if (s) return s;
00384         }
00385       else if (xtype == oqmlARRAY)
00386         {
00387           s = compileArray(db, ctx, cls, left, n, ndims);
00388           if (s) return s;
00389         }
00390       else
00391         return new oqmlStatus(this, "left part is not a left value");
00392 
00393       s = l->ql->compile(db, ctx);
00394       if (s)
00395         return s;
00396 
00397       oqmlAtomType at;
00398       l->ql->evalType(db, ctx, &at);
00399 
00400       if (s = oqmlCheckType(this, db, comp->attr[n], &at, ndims))
00401         return s;
00402 
00403       l = l->next;
00404       n++;
00405     }
00406 
00407   return oqmlSuccess;
00408 }
00409 
00410 oqmlStatus *
00411 oqmlNew::makeAtom(Database *db, oqmlContext *ctx, Object *o,
00412                   oqmlAtom *&r)
00413 {
00414   if (!location)
00415     {
00416       r = oqmlObjectManager::registerObject(o);
00417       return oqmlSuccess;
00418     }
00419 
00420   o->setDatabase(db);
00421   Status is = o->realize();
00422   if (is)
00423     {
00424       o->release();
00425       return new oqmlStatus(this, is);
00426     }
00427 
00428   r = new oqmlAtom_oid(o->getOid());
00429   o->release();
00430   return oqmlSuccess;
00431 }
00432 
00433 #define oqmlDEF_GET_NUM(TYP1, TYP2) \
00434 oqmlStatus * \
00435 get##TYP1##Val(oqmlNode *node, oqmlAtom *x, unsigned char buff[]) \
00436 { \
00437   TYP2 i; \
00438   if (x->as_int()) \
00439     i = OQML_ATOM_INTVAL(x); \
00440   else if (x->as_double()) \
00441     i = OQML_ATOM_DBLVAL(x); \
00442   else if (x->as_char()) \
00443     i = OQML_ATOM_CHARVAL(x); \
00444   else \
00445     return new oqmlStatus(node, "unexpected '%s' atom type", \
00446                           x->type.getString()); \
00447   mcp(buff, &i, sizeof(i)); \
00448   return oqmlSuccess;\
00449 }
00450 
00451 #define oqmlGET_VAL(TYP) \
00452  (_class->as##TYP##Class()) \
00453   { \
00454     s = get##TYP##Val(this, atom, buff); \
00455     if (s) return s; \
00456   }
00457 
00458 oqmlDEF_GET_NUM(Int32, eyedblib::int32)
00459 oqmlDEF_GET_NUM(Int64, eyedblib::int64)
00460 oqmlDEF_GET_NUM(Int16, eyedblib::int16)
00461 oqmlDEF_GET_NUM(Char,  char)
00462 oqmlDEF_GET_NUM(Byte,  char)
00463 oqmlDEF_GET_NUM(Float, double)
00464 
00465 oqmlStatus *
00466 getOidVal(oqmlNode *node, oqmlAtom *x, unsigned char buff[])
00467 {
00468   if (!x->as_oid())
00469     return new oqmlStatus(node, "unexpected '%s' atom type",
00470                           x->type.getString());
00471 
00472   mcp(buff, &OQML_ATOM_OIDVAL(x), sizeof(Oid));
00473   return oqmlSuccess;
00474 }
00475 
00476 oqmlStatus *oqmlNew::evalNode(Database *db, oqmlContext *ctx,
00477                               oqmlAtomList **alist)
00478 {
00479   oqmlAtom *atom;
00480   oqmlStatus *s;
00481   oqmlAtom *r;
00482 
00483   if (cst_atom)
00484     atom = cst_atom;
00485   else
00486     {
00487       oqmlAtomList *al;
00488       s = ql->eval(db, ctx, &al);
00489       if (s)
00490         return s;
00491       if (al->cnt != 1)
00492         return new oqmlStatus(this, "constant expected");
00493       atom = al->first->copy();
00494     }
00495 
00496   Object *o = _class->newObj();
00497   
00498   unsigned char buff[32];
00499   
00500   if oqmlGET_VAL(Int32)
00501   else if oqmlGET_VAL(Int64)
00502   else if oqmlGET_VAL(Int16)
00503   else if oqmlGET_VAL(Float)
00504   else if oqmlGET_VAL(Char)
00505   else if oqmlGET_VAL(Byte)
00506   else if oqmlGET_VAL(Oid)
00507   else
00508     return new oqmlStatus(this, "class '%s' not supported", _class->getName());
00509 
00510   Status is = o->setValue(buff);
00511   if (is)
00512     {
00513       o->release();
00514       return new oqmlStatus(this, is);
00515     }
00516       
00517   s = makeAtom(db, ctx, o, r);
00518   if (s) return s;
00519   (*alist)->append(r);
00520 
00521   return oqmlSuccess;
00522 }
00523 
00524 oqmlStatus *
00525 oqmlNew::evalItem(Database *db, oqmlContext *ctx,
00526                   Agregat *o, oqml_IdentLink *l, int n,
00527                   oqmlBool &stop, oqmlAtomList **alist)
00528 {
00529   oqmlAtomList *at;
00530   oqmlStatus *s = l->ql->eval(db, ctx, &at);
00531   oqmlTYPE xtype = l->left->getType();
00532 
00533   if (s)
00534     {
00535       o->release();
00536       return s;
00537     }
00538   
00539   stop = oqml_False;
00540   oqmlAtom *value = at->first;
00541   
00542   if (xtype == oqmlDOT)
00543     {
00544       oqmlAtomList *dummy = new oqmlAtomList;
00545       s = comp->dot_ctx[n]->eval_perform(db, ctx, o, value, 1, &dummy);
00546       if (s)
00547         {
00548           o->release();
00549           return s;
00550         }
00551       return oqmlSuccess;
00552     }
00553 
00554   Data val;
00555   unsigned char data[16];
00556   Size size;
00557   int len;
00558   Bool isIndirect = (comp->attr[n]->isIndirect());
00559           
00560   size = sizeof(data);
00561   if (value && value->getData(data, &val, size, len,
00562                               comp->attr[n]->getClass()))
00563     {
00564       int nb, s_ind, e_ind;
00565               
00566       if (xtype == oqmlIDENT)
00567         {
00568           s_ind = e_ind = 0;
00569           nb = len;
00570         }
00571       else if (xtype == oqmlARRAY)
00572         {
00573           ctx->setDotContext(comp->dot_ctx[n]);
00574           oqml_ArrayList *list = ((oqmlArray *)l->left)->
00575             getArrayList();
00576           s = list->eval(this, db, ctx,
00577                          comp->attr[n]->getClassOwner()->getName(),
00578                          comp->attr[n]->getName(),
00579                          &comp->attr[n]->getTypeModifier(),
00580                          &s_ind, &e_ind, oqml_False);
00581           if (s)
00582             {
00583               o->release();
00584               return s;
00585             }
00586           nb = 1;
00587           ctx->setDotContext(0);
00588         }
00589       else
00590         assert(0);
00591               
00592       nb = len; // really??
00593 
00594       // added the 2/07/01 because CheckType has not been done during
00595       // compilation if atom was of unknown type!
00596       s = oqmlCheckType(this, db, comp->attr[n], &value->type, 0);
00597       if (s) return s;
00598 
00599       Status is;
00600 
00601       oqmlBool enough;
00602       if (isIndirect) {
00603         int tnb = e_ind - s_ind + 1;
00604         is = oqml_check_vardim(comp->attr[n], o, OQMLBOOL(value),
00605                                enough,
00606                                s_ind, tnb,
00607                                comp->attr[n]->getTypeModifier().pdims,
00608                                OQMLCOMPLETE(value));
00609       }
00610       else
00611         is = oqml_check_vardim(comp->attr[n], o, OQMLBOOL(value),
00612                                enough,
00613                                s_ind, nb,
00614                                comp->attr[n]->getTypeModifier().pdims,
00615                                OQMLCOMPLETE(value));
00616 
00617       if (is)
00618         {
00619           o->release();
00620           return new oqmlStatus(this, is);
00621         }
00622 
00623       if (!enough)
00624         {
00625           if (value)
00626             return oqmlSuccess;
00627           else
00628             {
00629               stop = oqml_True;
00630               return oqmlSuccess;
00631             }
00632         }
00633 
00634       for (int ind = s_ind; ind <= e_ind; ind++)
00635         {
00636           OQML_CHECK_INTR();
00637           Status status;
00638           if (isIndirect)
00639             status = o->setItemOid(comp->attr[n], (Oid *)data,
00640                                    1, ind);
00641           else
00642             status = o->setItemValue(comp->attr[n], (val ? val : data),
00643                                      nb, ind);
00644           if (status)
00645             {
00646               o->release();
00647               return new oqmlStatus(this, status);
00648             }
00649         }
00650       return oqmlSuccess;
00651     }
00652 
00653   o->release();
00654   return new oqmlStatus(this, "error null data");
00655 }
00656 
00657 static Agregat *
00658 make_new_obj(Database *db, Class *cls)
00659 {
00660   // 5/02/01: I think that as there is the consapp mechanism
00661   // the following code for connection and database classes are
00662   // not still necessary!
00663 
00664   const char *name = cls->getName();
00665   char c = name[0];
00666 
00667   if (c == 'c')
00668     {
00669       if (!strcmp(name, "connection"))
00670         return new OqlCtbConnection(db);
00671     }
00672   else if (c == 'd')
00673     {
00674       if (!strcmp(name, "database"))
00675         return new OqlCtbDatabase(db);
00676     }
00677 
00678   // added the 5/02/01
00679   Database::consapp_t consapp = db->getConsApp(cls);
00680   if (consapp)
00681     return (Agregat *)consapp(cls, 0);
00682 
00683   return (Agregat*)cls->newObj();
00684 }
00685 
00686 oqmlStatus *oqmlNew::eval(Database *db, oqmlContext *ctx,
00687                           oqmlAtomList **alist, oqmlComp *, oqmlAtom *)
00688 {
00689   oqmlStatus *s;
00690   db = newdb;
00691 
00692   *alist = new oqmlAtomList();
00693 
00694   // added the 3/05/01
00695   db = newdb;
00696 
00697   if (ql)
00698     return evalNode(db, ctx, alist);
00699 
00700   oqml_IdentLink *l = (ident_list ? ident_list->first : 0);
00701 
00702   Agregat *o = make_new_obj(db, comp->cls);
00703 
00704   if (!o)
00705     {
00706       (*alist)->append(new oqmlAtom_null());
00707       return oqmlSuccess;
00708     }
00709 
00710   Status status = o->setDatabase(db);
00711   if (status)
00712     {
00713       o->release();
00714       return new oqmlStatus(this, status);
00715     }
00716 
00717   int n = 0;
00718 
00719   while (l)
00720     {
00721       oqmlBool stop;
00722       s = evalItem(db, ctx, o, l, n, stop, alist);
00723       if (s) return s;
00724       if (stop) break;
00725 
00726       l = l->next;
00727       n++;
00728     }
00729 
00730   oqmlAtom *r;
00731   s = makeAtom(db, ctx, o, r);
00732   if (s) return s;
00733   (*alist)->append(r);
00734   return oqmlSuccess;
00735 }
00736 
00737 void oqmlNew::evalType(Database *db, oqmlContext *ctx, oqmlAtomType *at)
00738 {
00739   *at = eval_type;
00740 }
00741 
00742 oqmlBool oqmlNew::isConstant() const
00743 {
00744   return oqml_False;
00745 }
00746 
00747 std::string
00748 oqmlNew::toString(void) const
00749 {
00750   std::string s = std::string("new") +
00751     (location ? std::string("<") + location->toString() + "> " : std::string(" ")) +
00752     ident + "(";
00753   
00754   if (ident_list)
00755     {
00756       oqml_IdentLink *l = ident_list->first;
00757       for (int n = 0; l; n++)
00758         {
00759           if (n) s += ",";
00760           s += l->left->toString() + ":" + l->ql->toString();
00761           l = l->next;
00762         }
00763     }
00764 
00765   return s + ")" + oqml_isstat();
00766 }
00767 
00768 oqmlNew::newCompile::newCompile(Class *_class, int n)
00769 {
00770   cls = _class;
00771   cnt = n;
00772   attr  = idbNewVect(Attribute *, n);
00773   attrname = idbNewVect(char *, n);
00774   list = idbNewVect(oqml_ArrayList *, n);
00775   dot_ctx = idbNewVect(oqmlDotContext *, n);
00776 }
00777 
00778 oqmlNew::newCompile::~newCompile()
00779 {
00780   idbFreeIndVect(dot_ctx, cnt);
00781   for (int i = 0; i < cnt; i++)
00782     free(attrname[i]);
00783   free(attrname);
00784 
00785   free(attr);
00786   free(list);
00787 }
00788 
00789 // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
00790 //
00791 // oqmlDelete methods
00792 //
00793 // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
00794 
00795 oqmlDelete::oqmlDelete(oqmlNode * _ql) : oqmlNode(oqmlDELETE)
00796 {
00797   ql = _ql;
00798 }
00799 
00800 oqmlDelete::~oqmlDelete()
00801 {
00802 }
00803 
00804 oqmlStatus *oqmlDelete::compile(Database *db, oqmlContext *ctx)
00805 {
00806   oqmlStatus *s;
00807   s = ql->compile(db, ctx);
00808 
00809   if (s)
00810     return s;
00811 
00812   ql->evalType(db, ctx, &eval_type);
00813 
00814   if (eval_type.type != oqmlATOM_IDENT && eval_type.type != oqmlATOM_OID &&
00815       eval_type.type != oqmlATOM_UNKNOWN_TYPE)
00816     return oqmlStatus::expected(this, "oid", eval_type.getString());
00817 
00818   return oqmlSuccess;
00819 }
00820 
00821 oqmlStatus *oqmlDelete::eval(Database *db, oqmlContext *ctx, oqmlAtomList **alist, oqmlComp *, oqmlAtom *)
00822 {
00823   oqmlStatus *s;
00824   oqmlAtomList *al;
00825 
00826   s = ql->eval(db, ctx, &al);
00827 
00828   if (s) return s;
00829 
00830   if (al->cnt == 0)
00831     return oqmlStatus::expected(this, "oid", "nil");
00832 
00833   if (al->cnt > 1)
00834     return new oqmlStatus(this, "internal error #112");
00835 
00836   oqmlAtom *a = al->first;
00837   
00838   if (!OQML_IS_OID(a))
00839     return oqmlStatus::expected(this, "oid", a->type.getString());
00840 
00841   Status is = db->removeObject(&OQML_ATOM_OIDVAL(a));
00842 
00843   if (is)
00844     return new oqmlStatus(this, is);
00845 
00846   *alist = new oqmlAtomList(a);
00847 
00848   return oqmlSuccess;
00849 }
00850 
00851 void oqmlDelete::evalType(Database *db, oqmlContext *ctx, oqmlAtomType *at)
00852 {
00853   *at = eval_type;
00854 }
00855 
00856 oqmlBool oqmlDelete::isConstant() const
00857 {
00858   return oqml_False;
00859 }
00860 
00861 std::string
00862 oqmlDelete::toString(void) const
00863 {
00864   if (is_statement)
00865     return std::string("delete ") + ql->toString() + "; ";
00866   return std::string("(delete ") + ql->toString() + ")";
00867 }
00868 }

Generated on Mon Dec 22 18:16:06 2008 for eyedb by  doxygen 1.5.3