Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

cProtoBase.cpp

Go to the documentation of this file.
00001 /******************************************************************************/
00002 /*                                                                            */
00003 /* POLiTe - Persistent Object Library Test                                    */
00004 /*                                        Ph.D. Thesis by Mgr. Michal Kopecky */
00005 /*                                                                            */
00006 /* Charles University Prague                                                  */
00007 /*                                                                            */
00008 /******************************************************************************/
00009 /*                                                                            */
00010 /* File name: ...                                                             */
00011 /* Module: ......                                                             */
00012 /*                                                                            */
00013 /******************************************************************************/
00014 
00015 // Standard Header(s)
00016 #include <stdio.h>
00017 #include <malloc.h>
00018 
00019 // Common POLiTe Header(s)
00020 #include <lStr.h>
00021 #include <lExceptions.h>
00022 
00023 // Own Header
00024 #include <cProtoBase.h>
00025 
00026 // Other POLiTe Header(s)
00027 #include <cObject.h>
00028 #include <cPersistentObject.h>
00029 #include <cRefBase.h>
00030 #include <cResultBase.h>
00031 #include <cCursor.h>
00032 #include <cClassRegister.h>
00033 #include <cComplexQuery.h>
00034 
00035 ProtoBase *ProtoBase::_root = NULL;
00036 ProtoBase *ProtoBase::_first = NULL;
00037 
00038 typedef unsigned char Object::*MemberPtr;
00039 
00040 typedef struct {
00041         bool key;                       // member belongs to primary key
00042         bool rw;                        // member can be propagated back to database
00043         MemberPtr member;       // address of member inside the instance
00044         char *atrname;          // name of member attribute
00045         char *colname;          // SQL expr. for selecting its value
00046         char *varname;          // name of SQL placeholder
00047         void* bufaddr;          // address of internal buffer for SQL communication
00048         char  buftype;          // buffer type
00049         int   buflen;           // length of buffer in bytes
00050         short indic;            // indicator for SQL comunication (NULL values)
00051 } sqlVar;
00052 
00053 void ProtoBase::Register(ProtoBase *_p, const char *_n)
00054 {
00055         // Insert the prototype into the tree of prototypes
00056         // according to name _n
00057         ProtoBase **t = &_root;
00058         int c;
00059         while (*t) {
00060                 c = StrCmp((*t)->ClassName(),_n);
00061                 if (c > 0)
00062                         t = &((*t)->_left);
00063                 else if (c < 0)
00064                         t = &((*t)->_right);
00065                 else
00066                         break;
00067         };
00068         if (!(*t))
00069                 *t = _p;
00070         // Insert the prototype at the beginning of the list
00071         _p->_next = _first;
00072         _first = _p;
00073 };
00074 
00075 bool ProtoBase::_ExportAttributes(const class Object &o)
00076 {
00077         _Initialise();
00078         void *source;
00079         char **addrptr;
00080         for(int i=0;i<_fullParentPrototypeCount;i++)
00081         {
00082                 int j=0;
00083                 if (i>0)
00084                         j=_fullParentPrototype[i]->_sqlVars.KeyCount;
00085                 for( ; j<_fullParentPrototype[i]->_sqlVars.Count; j++)
00086                 {
00087                         sqlVar &var = ((sqlVar*)(_fullParentPrototype[i]->_sqlVars.Arr))[j];
00088                         source = (void *)&(o.*var.member);
00089                         //_fullParentPrototype[i]->Bind(o,var.atrname,source);
00090                         var.indic=0;
00091                         switch (var.buftype)
00092                         {
00093                                 case TYPE_PTR:
00094                                         *(long int *)(var.bufaddr)=*(long int *)source;
00095                                         if ((*(long int *)(var.bufaddr))>0)
00096                                                 var.indic=0;
00097                                         else
00098                                                 var.indic=-1;
00099                                         break;
00100                                 case TYPE_INT:
00101                                         if (var.buflen == sizeof(long int))
00102                                                 *(long int *)(var.bufaddr)=*(long int *)source;
00103                                         else if (var.buflen == sizeof(int))
00104                                                 *(int *)(var.bufaddr)=*(int *)source;
00105                                         else if (var.buflen == sizeof(short int))
00106                                                 *(short int *)(var.bufaddr)=*(short int *)source;
00107                                         else if (var.buflen == sizeof(signed char))
00108                                                 *(signed char *)(var.bufaddr)=*(signed char *)source;
00109                                         break;
00110                                 case TYPE_UNSIGNED:
00111                                         if (var.buflen == sizeof(unsigned long int))
00112                                                 *(unsigned long int *)(var.bufaddr)=*(unsigned long int *)source;
00113                                         else if (var.buflen == sizeof(unsigned int))
00114                                                 *(unsigned int *)(var.bufaddr)=*(unsigned int *)source;
00115                                         else if (var.buflen == sizeof(unsigned short int))
00116                                                 *(unsigned short int *)(var.bufaddr)=*(unsigned short int *)source;
00117                                         else if (var.buflen == sizeof(unsigned char))
00118                                                 *(unsigned char *)(var.bufaddr)=*(unsigned char *)source;
00119                                         break;
00120                                 case TYPE_FLOAT:
00121                                         if (var.buflen == sizeof(double))
00122                                                 *(double *)(var.bufaddr)=*(double *)source;
00123                                         else if (var.buflen == sizeof(float))
00124                                                 *(double *)(var.bufaddr)=*(double *)source;
00125                                         break;
00126                                 case TYPE_CHAR:
00127                                         *(char *)(var.bufaddr)=*(char *)source;
00128                                         break;
00129                                 case TYPE_STRING:
00130                                         addrptr = (char **)&(var.bufaddr);
00131                                         //direct cast (char *)(var.addr) uses temporary variable
00132                                         //buffer is pre-allocated and shouldn't be changed
00133                                         if (*(const char **)source)
00134                                                 // copy at most bufflen characters from source and terminate it with '\0'
00135                                                 StrExp(*addrptr,*(const char **)source,var.buflen);
00136                                         else // no value in string
00137                                                 *addrptr[0] = '\0';
00138                                         break;
00139                         };
00140                 };
00141                 for(j=_fullParentPrototype[i]->_sqlVars.Count ; j<_fullParentPrototype[i]->_sqlVars.SpecCount; j++)
00142                 {
00143                         // The only spec column is the class name of PersistentObject descendants
00144                         // thus this body executer at most once
00145                         // corresponding buffer is of type string
00146                         sqlVar &var = ((sqlVar*)(_fullParentPrototype[i]->_sqlVars.Arr))[j];
00147                         addrptr = (char **)&(var.bufaddr);
00148                         //direct cast (char *)(var.addr) uses temporary variable
00149                         //buffer is pre-allocated and shouldn't be changed
00150                         StrExp(*addrptr,_fullParentPrototype[_fullParentPrototypeCount-1]->ClassName(),var.buflen);
00151                         var.indic=0;
00152                 };
00153         };
00154         return true;
00155 };
00156 
00157 bool ProtoBase::_ExportKeyAttributes(const class Object &o)
00158 {
00159         _Initialise();
00160         void *source;
00161         char **addrptr;
00162         for(int j=0 ; j<_rootPrototype->_sqlVars.KeyCount; j++)
00163         {
00164                 sqlVar &var = ((sqlVar*)(_rootPrototype->_sqlVars.Arr))[j];
00165                 source = (void *)&(o.*var.member);
00166                 //_rootPrototype->Bind(o,var.atrname,source);
00167                 var.indic=0;
00168                 switch (var.buftype)
00169                 {
00170                         case TYPE_INT:
00171                                 if (var.buflen == sizeof(long int))
00172                                         *(long int *)(var.bufaddr)=*(long int *)source;
00173                                 else if (var.buflen == sizeof(int))
00174                                         *(int *)(var.bufaddr)=*(int *)source;
00175                                 else if (var.buflen == sizeof(short int))
00176                                         *(short int *)(var.bufaddr)=*(short int *)source;
00177                                 else if (var.buflen == sizeof(signed char))
00178                                         *(signed char *)(var.bufaddr)=*(signed char *)source;
00179                                 break;
00180                         case TYPE_UNSIGNED:
00181                                 if (var.buflen == sizeof(unsigned long int))
00182                                         *(unsigned long int *)(var.bufaddr)=*(unsigned long int *)source;
00183                                 else if (var.buflen == sizeof(unsigned int))
00184                                         *(unsigned int *)(var.bufaddr)=*(unsigned int *)source;
00185                                 else if (var.buflen == sizeof(unsigned short int))
00186                                         *(unsigned short int *)(var.bufaddr)=*(unsigned short int *)source;
00187                                 else if (var.buflen == sizeof(unsigned char))
00188                                         *(unsigned char *)(var.bufaddr)=*(unsigned char *)source;
00189                                 break;
00190                         case TYPE_FLOAT:
00191                                 if (var.buflen == sizeof(double))
00192                                         *(double *)(var.bufaddr)=*(double *)source;
00193                                 else if (var.buflen == sizeof(float))
00194                                         *(double *)(var.bufaddr)=*(double *)source;
00195                                 break;
00196                         case TYPE_CHAR:
00197                                 *(char *)(var.bufaddr)=*(char *)source;
00198                                 break;
00199                         case TYPE_STRING:
00200                                 addrptr = (char **)&(var.bufaddr);
00201                                 //direct cast (char *)(var.addr) uses temporary variable
00202                                 //buffer is pre-allocated and shouldn't be changed
00203                                 if (*(const char **)source)
00204                                         // copy at most bufflen characters from source and terminate it with '\0'
00205                                         StrExp(*addrptr,*(const char **)source,var.buflen);
00206                                 else // no value in string
00207                                         *addrptr[0] = '\0';
00208                                 break;
00209                 };
00210         };
00211         return true;
00212 };
00213 
00214 bool ProtoBase::_ExportKeyAttributes(const class RefBase &x)
00215 {
00216         _Initialise();
00217         // values are stored in comma separated list,
00218         // each encoded by StrEncode
00219         char * keyvals = StrCpy(x._ObjectIdentification._SelectKeyValues);
00220         char * keyval1 = NULL;
00221         char * decoded = NULL;
00222         int v = 0;
00223         while(StrSplit(keyvals,',',keyval1))
00224         {
00225                 // one encoded value retrieved from list
00226         StrDecode(decoded,keyval1);
00227                 sqlVar &var = ((sqlVar*)(_rootPrototype->_sqlVars.Arr))[v];
00228                 var.indic=0;
00229                 switch (var.buftype)
00230                 {
00231                 case TYPE_STRING:
00232                         StrExp((char *)var.bufaddr,decoded,var.buflen);
00233                         break;
00234                 case TYPE_CHAR:
00235                         if (decoded)
00236                                 ((char *)var.bufaddr)[1] = *decoded;
00237                         break;
00238                 case TYPE_FLOAT:
00239                         if (var.buflen == sizeof(double))
00240                                 sscanf(decoded,"%lf",(double *)var.bufaddr);
00241                         else if (var.buflen == sizeof(float))
00242                                 sscanf(decoded,"%f",(float *)var.bufaddr);
00243                         break;
00244                 case TYPE_INT:
00245                         if (var.buflen == sizeof(long))
00246                                 sscanf(decoded,"%ld",(long *)var.bufaddr);
00247                         else if (var.buflen == sizeof(int))
00248                                 sscanf(decoded,"%d",(int *)var.bufaddr);
00249                         else if (var.buflen == sizeof(short))
00250                                 sscanf(decoded,"%hd",(short *)var.bufaddr);
00251                         break;
00252                 case TYPE_UNSIGNED:
00253                         if (var.buflen == sizeof(unsigned long))
00254                                 sscanf(decoded,"%lu",(unsigned long *)var.bufaddr);
00255                         else if (var.buflen == sizeof(unsigned int))
00256                                 sscanf(decoded,"%u",(unsigned int *)var.bufaddr);
00257                         else if (var.buflen == sizeof(unsigned short))
00258                                 sscanf(decoded,"%hu",(unsigned short *)var.bufaddr);
00259                         break;
00260                 };
00261                 v++;
00262         };
00263         StrFree(keyvals);
00264         StrFree(keyval1);
00265         StrFree(decoded);
00266         return true;
00267 };
00268 
00269 bool ProtoBase::_ImportAttributes(class Object &o)
00270 {
00271         _Initialise();
00272         void *source;
00273         for(int i=0;i<_fullParentPrototypeCount;i++)
00274         {
00275                 int j=0;
00276                 if (i>0)
00277                         j=_fullParentPrototype[i]->_sqlVars.KeyCount;
00278                 for( ; j<_fullParentPrototype[i]->_sqlVars.Count; j++)
00279                 {
00280                         sqlVar &var = ((sqlVar*)(_fullParentPrototype[i]->_sqlVars.Arr))[j];
00281                         source = &(o.*var.member);
00282                         switch (var.buftype)
00283                         {
00284                                 case TYPE_PTR:
00285                                         if (var.indic<0)
00286                                                 *(long int *)source=0; //DBNULL
00287                                         else
00288                                                 *(long int *)source=*(long int *)(var.bufaddr);
00289                                         break;
00290                                 case TYPE_INT:
00291                                         if (var.buflen == sizeof(long int))
00292                                                 *(long int *)source=*(long int *)(var.bufaddr);
00293                                         else if (var.buflen == sizeof(int))
00294                                                 *(int *)source=*(int *)(var.bufaddr);
00295                                         else if (var.buflen == sizeof(short int))
00296                                                 *(short int *)source=*(short int *)(var.bufaddr);
00297                                         else if (var.buflen == sizeof(signed char))
00298                                                 *(signed char *)source=*(signed char *)(var.bufaddr);
00299                                         break;
00300                                 case TYPE_UNSIGNED:
00301                                         if (var.buflen == sizeof(unsigned long int))
00302                                                 *(unsigned long int *)source=*(unsigned long int *)(var.bufaddr);
00303                                         else if (var.buflen == sizeof(unsigned int))
00304                                                 *(unsigned int *)source=*(unsigned int *)(var.bufaddr);
00305                                         else if (var.buflen == sizeof(unsigned short int))
00306                                                 *(unsigned short int *)source=*(unsigned short int *)(var.bufaddr);
00307                                         else if (var.buflen == sizeof(unsigned char))
00308                                                 *(unsigned char *)source=*(unsigned char *)(var.bufaddr);
00309                                         break;
00310                                 case TYPE_FLOAT:
00311                                         if (var.buflen == sizeof(double))
00312                                                 *(double *)source=*(double *)(var.bufaddr);
00313                                         else if (var.buflen == sizeof(float))
00314                                                 *(float *)source=*(float *)(var.bufaddr);
00315                                         break;
00316                                 case TYPE_CHAR:
00317                                         *(char *)source=*(char *)(var.bufaddr);
00318                                         break;
00319                                 case TYPE_STRING:
00320                                         StrCpy(*(char **)source,(char *)(var.bufaddr));
00321                                         break;
00322                         };
00323                 };
00324         };
00325         return true;
00326 };
00327 
00328 bool ProtoBase::_KeyValues(char *&s)
00329 // stores comma-separated list of key values into s
00330 {
00331         _Initialise();
00332         char * decoded = NULL;
00333         char * encoded = NULL;
00334         const char * delim = NULL;
00335         StrFree(s);
00336         for(int j=0 ; j<_rootPrototype->_sqlVars.KeyCount; j++)
00337         {
00338                 StrFree(decoded);
00339                 sqlVar &var = ((sqlVar*)(_rootPrototype->_sqlVars.Arr))[j];
00340                 switch (var.buftype)
00341                 {
00342                         case TYPE_INT:
00343                                 if (var.buflen == sizeof(long int))
00344                                         decoded = LongToStr(*(long int *)(var.bufaddr));
00345                                 else if (var.buflen == sizeof(int))
00346                                         decoded = LongToStr(*(int *)(var.bufaddr));
00347                                 else if (var.buflen == sizeof(short int))
00348                                         decoded = LongToStr(*(short int *)(var.bufaddr));
00349                                 break;
00350                         case TYPE_UNSIGNED:
00351                                 if (var.buflen == sizeof(long int))
00352                                         decoded = ULongToStr(*(unsigned long int *)(var.bufaddr));
00353                                 else if (var.buflen == sizeof(int))
00354                                         decoded = ULongToStr(*(unsigned int *)(var.bufaddr));
00355                                 else if (var.buflen == sizeof(short int))
00356                                         decoded = ULongToStr(*(unsigned short int *)(var.bufaddr));
00357                                 break;
00358                         case TYPE_FLOAT:
00359                                 if (var.buflen == sizeof(double))
00360                                         decoded = FloatToStr(*(float *)(var.bufaddr));
00361                                 else if (var.buflen == sizeof(float))
00362                                         decoded = FloatToStr(*(double *)(var.bufaddr));
00363                                 break;
00364                         case TYPE_CHAR:
00365                                 decoded=(char *)malloc(2);
00366                                 *decoded=*(char *)(var.bufaddr);
00367                                 *(decoded+1)='\'';
00368                                 break;
00369                         case TYPE_STRING:
00370                                 decoded = StrCpy((char *)var.bufaddr);
00371                                 break;
00372                 };
00373         StrEncode(encoded,decoded);
00374         StrCat(s,2,
00375                 delim,
00376                 encoded
00377                 );
00378         delim=",";
00379         };
00380         StrFree(encoded);
00381         StrFree(decoded);
00382         return true;
00383 };
00384 
00385 char * ProtoBase::_KeyValues(const class Object &o)
00386 {
00387         _ExportKeyAttributes(o);
00388         char *keyvals = NULL;
00389         _KeyValues(keyvals);
00390         return keyvals;
00391 };
00392 
00393 bool ProtoBase::_ImportKeyAttributes(class RefBase &x)
00394 {
00395         _Initialise();
00396         return _KeyValues(x._ObjectIdentification._SelectKeyValues);
00397 };
00398 
00399 void ProtoBase::_ResetProcessed(ProtoBase * const _p)
00400 {
00401         if (_p)
00402         {
00403                 _p->_processed=false;
00404                 _ResetProcessed(_p->_left);
00405                 _ResetProcessed(_p->_right);
00406         };
00407 };
00408 
00410 //Executes a given Query and returns pointer to a ResultBase object.
00411 
00412 class ResultBase *ProtoBase::ExecuteQuery(
00413         const QueRefProto &Q,
00414         class Connection *DbCon,
00415         const int i,
00416         class ResultBase * QR
00417         )
00418 {
00419         #ifdef C_OBJECT_TRACE
00420                 logmsg("ResultBase *ProtoBase::ExecuteQuery(...) invoked");
00421         #endif
00422 
00423         QR->_Strategies = DbCon->_Strategies;
00424         QR->_query = new ComplexQuery(Q);
00425         // Translate C++ notation to pure SQL
00426         QR->_queryPrototype = this;
00427         _TranslateToSql(*(QR->_query));
00428 
00429         QR->_sql_select = _StmtSelectPtr(*(QR->_query),i);
00430         QR->_queryConnection = DbCon;
00431         QR->_cursor = DbCon->_GetNewCursor();
00432 
00433         QR->_SetSqlCommand(NULL);
00434         // for parameter NULL the sql statement is taken from
00435         // the prototype according the query Q
00436         QR->Open();
00437 
00438         #ifdef C_OBJECT_TRACE
00439                 logmsg("ResultBase *Object::ExecuteQuery(QueRefProto *Q, Connection *DbCon, const int i, const int j)finished");
00440         #endif
00441 
00442         return(QR);
00443 };
00444 
00445 void ProtoBase::_Initialise()
00446 {
00447         // Avoid multiple reinicialisation
00448         if (_initialised)
00449                 return;
00450         _initialised=true;
00451         if (!StrCmp(BaseClassName(),"Object"))
00452                 _isObject=true;
00453         else if (!StrCmp(BaseClassName(),"ImmutableObject"))
00454                 _isImmutableObject=true;
00455         else if (!StrCmp(BaseClassName(),"DatabaseObject"))
00456                 _isDatabaseObject=true;
00457         else if (!StrCmp(BaseClassName(),"PersistentObject"))
00458                 _isPersistentObject=true;
00459         if (!StrCmp(ClassName(),"Object"))
00460                 _isRootClass=true;
00461         else if (!StrCmp(ClassName(),"ImmutableObject"))
00462                 _isRootClass=true;
00463         else if (!StrCmp(ClassName(),"DatabaseObject"))
00464                 _isRootClass=true;
00465         else if (!StrCmp(ClassName(),"PersistentObject"))
00466                 _isRootClass=true;
00467         //First all class prototypes
00468         //must known all its direct predecessors
00469         _InitialiseParentPrototype();
00470         //All predecessors are set as not visited
00471         _ResetProcessed(_root);
00472         //Then all predecessors are recursively detected
00473         _InitialiseFullParentPrototype(this);
00474         //We know all predecessors. That eliminates recurses in the future
00475         for (int i=0; i<_parentPrototypeCount; i++)
00476                 _parentPrototype[i]->_Initialise();
00477         //Now we initiate internal database SqlVar about all members
00478         _InitialiseSqlVar();
00479         //Based on the knowledge of all predecessors
00480         //and info about its members we can precompute
00481         //needed string fragments for SQL
00482         _InitialiseSelect();
00483         _InitialiseFullSelect();
00484         _InitialiseKeySelect();
00485         _InitialiseInto();
00486         //_InitialiseFullInto();
00487         //_InitialiseKeyInto();
00488         _InitialiseFullFrom();
00489         _InitialiseWhere();
00490         _InitialiseFullWhere();
00491         _InitialiseKeyWhere();
00492         _InitialiseGroupBy();
00493         _InitialiseHaving();
00494         _InitialiseStmtSelect();
00495         _InitialiseStmtInsert();
00496         _InitialiseStmtDelete();
00497         _InitialiseStmtUpdate();
00498 };
00499 
00500 void ProtoBase::_InitialiseParentPrototype()
00501 {
00502         char *_parents = NULL;
00503         char *_1parent = NULL;
00504         StrCpy(_parents,ParentClassNames());
00505         while(StrSplit(_parents,',',_1parent))
00506         {
00507                 _parentPrototypeCount++;
00508                 _parentPrototype=(class ProtoBase **)realloc(
00509                         _parentPrototype,_parentPrototypeCount*sizeof(class ProtoBase *)
00510                         );
00511                 if (_parentPrototype)
00512                         _parentPrototype[_parentPrototypeCount-1]=Find(_1parent);
00513         };
00514         StrFree(_parents);
00515         StrFree(_1parent);
00516 };
00517 
00518 void ProtoBase::_InitialiseFullParentPrototype(class ProtoBase *_p)
00519 {
00520         if (_processed)
00521                 return;
00522         char *_parents = NULL;
00523         char *_1parent = NULL;
00524         class ProtoBase *_x;
00525         StrCpy(_parents,ParentClassNames());
00526         while(StrSplit(_parents,',',_1parent))
00527         {
00528                 _x = Find(_1parent);
00529                 if (_x)
00530                         _x->_InitialiseFullParentPrototype(_p);
00531         };
00532         StrFree(_parents);
00533         StrFree(_1parent);
00534         _p->_fullParentPrototypeCount++;
00535         _p->_fullParentPrototype=(class ProtoBase **)realloc(
00536                 _p->_fullParentPrototype,_p->_fullParentPrototypeCount*sizeof(class ProtoBase *)
00537                 );
00538         if (_p->_fullParentPrototype)
00539                 _p->_fullParentPrototype[_p->_fullParentPrototypeCount-1]=this;
00540         _processed=true;
00541 };
00542 
00543 void ProtoBase::_InitialiseSqlVar()
00544 {
00545         _sqlVars.KeyCount = 0;
00546         _sqlVars.Count = 0;
00547         _sqlVars.SpecCount = 0;
00548         int i = 0;
00549         int v = 0;
00550         int b;
00551         const char *atr;
00552         MemberPtr mem;
00553         const char *col;
00554         char *trimcol = NULL;
00555         char ctype;
00556         unsigned int clen;
00557         bool crw;
00558         char *thistable = NULL;
00559         StrCat(thistable,2,From(),".");
00560         _MapKey(i,atr,mem,col,ctype,clen,crw);
00561         while (ctype!=TYPE_UNKNOWN)
00562         {
00563                 _sqlVars.KeyCount++;
00564                 _sqlVars.Count++;
00565                 _sqlVars.SpecCount++;
00566                 _sqlVars.Arr=realloc(_sqlVars.Arr,_sqlVars.Count*sizeof(sqlVar));
00567                 sqlVar &var=((sqlVar *)_sqlVars.Arr)[v];
00568                 // remove preffix (table name) from primary key column
00569                 // table name will be used instead
00570                 StrCpy(trimcol,col);
00571                 StrPrefixCut(trimcol,'.');
00572                 var.key = true;
00573                 var.rw = crw;
00574                 var.member = mem;
00575                 var.indic = 0;
00576                 StrCpy(var.atrname = NULL, atr);
00577                 // first store table name, and add "." plus column name without prefix
00578                 StrCpy(var.colname = NULL, From());
00579                 StrCat(var.colname,2,".",trimcol);
00580                 StrFree(trimcol);
00581                 var.varname = NULL;
00582                 StrCat(
00583                         var.varname,4,
00584                         ":",
00585                         From(),
00586                         "_",
00587                         atr
00588                         );
00589                 var.buftype = ctype;
00590                 var.buflen=clen;
00591                 switch (ctype)
00592                 {
00593                         case TYPE_INT:
00594                         case TYPE_UNSIGNED:
00595                         case TYPE_FLOAT:
00596                         case TYPE_CHAR:
00597                         case TYPE_PTR:
00598                                 var.bufaddr=malloc(var.buflen);
00599                                 for(b=0; (var.bufaddr && (b<var.buflen)); *(((unsigned char *)var.bufaddr)+b)='\0', b++);
00600                                 break;
00601                         case TYPE_STRING:
00602                                 var.bufaddr=new char[var.buflen+1];
00603                                 *((unsigned char *)var.bufaddr)='\0';
00604                                 break;
00605                 };
00606                 v++;
00607                 i++;
00608                 _MapKey(i,atr,mem,col,ctype,clen,crw);
00609         };
00610         i = 0;
00611         _Map(i,atr,mem,col,ctype,clen,crw);
00612         while (ctype!=TYPE_UNKNOWN)
00613         {
00614                 _sqlVars.Count++;
00615                 _sqlVars.SpecCount++;
00616                 _sqlVars.Arr = realloc(_sqlVars.Arr,_sqlVars.Count*sizeof(sqlVar));
00617                 sqlVar &var=((sqlVar *)_sqlVars.Arr)[v];
00618                 var.key = false;
00619                 var.rw = crw;
00620                 var.member = mem;
00621                 var.indic = 0;
00622                 StrCpy(var.atrname = NULL, atr);
00623                 StrCpy(var.colname = NULL, col);
00624                 // non primary key columns can be expressions
00625                 // all occurences of #T should be replaced by table name
00626                 StrReplaceAll(var.colname,THIS_TABLE ".",thistable);
00627                 var.varname = NULL;
00628                 StrCat(
00629                         var.varname,4,
00630                         ":",
00631                         From(),
00632                         "_",
00633                         atr
00634                         );
00635                 var.buftype = ctype;
00636                 var.buflen=clen;
00637                 switch (ctype)
00638                 {
00639                         case TYPE_INT:
00640                         case TYPE_UNSIGNED:
00641                         case TYPE_FLOAT:
00642                         case TYPE_CHAR:
00643                         case TYPE_PTR:
00644                                 var.bufaddr=malloc(var.buflen);
00645                                 for(b=0; (var.bufaddr && (b<var.buflen)); *(((unsigned char *)var.bufaddr)+b)='\0', b++);
00646                                 break;
00647                         case TYPE_STRING:
00648                                 var.bufaddr=new char[var.buflen+1];
00649                                 *((unsigned char *)var.bufaddr)='\0';
00650                                 break;
00651                 };
00652                 v++;
00653                 i++;
00654                 _Map(i,atr,mem,col,ctype,clen,crw);
00655         };
00656         // Key fields are processed
00657         // Class Persistent Object use special field for class name
00658         if (_isPersistentObject && _isRootClass)
00659         {
00660                 _sqlVars.SpecCount++;
00661                 _sqlVars.Arr=realloc(_sqlVars.Arr,_sqlVars.SpecCount*sizeof(sqlVar));
00662                 sqlVar &var=((sqlVar *)_sqlVars.Arr)[v];
00663                 var.key = false;
00664                 var.rw = true;
00665                 var.member = NULL;
00666                 StrCpy(var.atrname = NULL, "ClassName");
00667                 StrCpy(var.colname = NULL, From());
00668                 StrCat(var.colname,".CLASS_NAME");
00669                 StrFree(trimcol);
00670                 var.varname = NULL;
00671                 StrCat(
00672                         var.varname,3,
00673                         ":",
00674                         From(),
00675                         "_ClassName"
00676                         );
00677                 var.buftype = TYPE_STRING;
00678                 var.buflen=MAX_CLASS_NAME_LEN;
00679                 var.bufaddr=malloc(MAX_CLASS_NAME_LEN+1);
00680         };
00681         // Special fields processed
00682         StrFree(thistable);
00683 };
00684 
00685 void ProtoBase::_InitialiseSelect()
00686 {
00687         const char *_delim = NULL;
00688         int v;
00689         for (v=0; v < _sqlVars.Count; v++)
00690         {
00691                 (void)StrCat(_select,2,_delim,((sqlVar*)_sqlVars.Arr)[v].colname);
00692                 _delim=", ";
00693         };
00694 };
00695 
00696 void ProtoBase::_InitialiseFullSelect()
00697 {
00698         const char *_delim = NULL;
00699         class ProtoBase **_p = _fullParentPrototype;
00700         for(int i=0; i<_fullParentPrototypeCount; i++, _p++)
00701                 // only non-key columns are selected
00702                 for(int v=(*_p)->_sqlVars.KeyCount; v<(*_p)->_sqlVars.Count; v++)
00703                 {
00704                         (void)StrCat(_fullSelect,2,_delim,((sqlVar*)((*_p)->_sqlVars.Arr))[v].colname);
00705                         _delim=", ";
00706                 };
00707 };
00708 
00709 void ProtoBase::_InitialiseKeySelect()
00710 {
00711         const char *_delim = NULL;
00712         for (int v=0; v < _rootPrototype->_sqlVars.KeyCount; v++)
00713         {
00714                 (void)StrCat(_keySelect,2,_delim,((sqlVar*)_rootPrototype->_sqlVars.Arr)[v].colname);
00715                 _delim=", ";
00716         };
00717 };
00718 
00719 void ProtoBase::_InitialisePtrSelect()
00720 {
00721         const char *_delim = NULL;
00722         int v;
00723         for (v=0; v < _rootPrototype->_sqlVars.KeyCount; v++)
00724         {
00725                 (void)StrCat(_keySelect,2,_delim,((sqlVar*)_rootPrototype->_sqlVars.Arr)[v].colname);
00726                 _delim=", ";
00727         };
00728         for (v=_rootPrototype->_sqlVars.Count; v < _rootPrototype->_sqlVars.SpecCount; v++)
00729         {
00730                 (void)StrCat(_keySelect,2,_delim,((sqlVar*)_rootPrototype->_sqlVars.Arr)[v].colname);
00731                 _delim=", ";
00732         };
00733 };
00734 
00735 void ProtoBase::_InitialiseInto()
00736 {
00737         const char *_delim = NULL;
00738         int v;
00739         for (v=0; v < _sqlVars.Count; v++)
00740         {
00741                 (void)StrCat(_into,2,_delim,((sqlVar*)_sqlVars.Arr)[v].varname);
00742                 _delim=", ";
00743         };
00744 };
00745 
00746 /*
00747 void ProtoBase::_InitialiseFullInto()
00748 {
00749         const char *_delim = NULL;
00750         class ProtoBase **_p = _fullParentPrototype;
00751         for(int i=0; i<_fullParentPrototypeCount; i++, _p++)
00752                 // only non-key columns are selected
00753                 for(int v=(*_p)->_sqlVars.KeyCount; v<(*_p)->_sqlVars.Count; v++)
00754                 {
00755                         (void)StrCat(_fullInto,2,_delim,((sqlVar*)((*_p)->_sqlVars.Arr))[v].varname);
00756                         _delim=", ";
00757                 };
00758 };
00759 */
00760 
00761 /*
00762 void ProtoBase::_InitialiseKeyInto()
00763 {
00764         const char *_delim = NULL;
00765         for (int v=0; v < _rootPrototype->_sqlVars.KeyCount; v++)
00766         {
00767                 (void)StrCat(_keyInto,2,_delim,((sqlVar*)_rootPrototype->_sqlVars.Arr)[v].varname);
00768                 _delim=", ";
00769         };
00770 };
00771 */
00772 
00773 void ProtoBase::_InitialiseFullFrom()
00774 {
00775         char *_delim = NULL;
00776         for(int i=0;i<_fullParentPrototypeCount;i++)
00777         {
00778                 (void)StrCat(_fullFrom,2,_delim,_fullParentPrototype[i]->From());
00779                 (void)StrCpy(_delim,", ");
00780         };
00781         StrFree(_delim);
00782 };
00783 
00784 void ProtoBase::_InitialiseWhere()
00785 {
00786         if (_isPersistentObject)
00787                 // Persistent object don't use Where clause
00788                 return;
00789         char *thistable = NULL;
00790         StrCat(thistable,2,From(),".");
00791         // obtain where clause defined in the class T
00792         // from Proto<T> using virtual function _ProtoTWhere()
00793         StrCpy(_where,_ProtoTWhere());
00794         StrReplaceAll(_where,THIS_TABLE ".", thistable);
00795         StrFree(thistable);
00796 };
00797 
00798 void ProtoBase::_InitialiseFullWhere()
00799 {
00800         const char *_delim = NULL;
00801         class ProtoBase **_x = _fullParentPrototype;
00802         class ProtoBase **_p = _fullParentPrototype;
00803         for(int i=0; i<_fullParentPrototypeCount; i++, _p++)
00804         {
00805                 for(int v=0; (i>0) && (v<_sqlVars.KeyCount) && (v<(*_p)->_sqlVars.KeyCount); v++)
00806                 {
00807                         (void)StrCat(_fullWhere,6,
00808                                 _delim,
00809                                 "(",
00810                                 ((sqlVar*)((*_x)->_sqlVars.Arr))[v].colname,
00811                                 "=",
00812                                 ((sqlVar*)((*_p)->_sqlVars.Arr))[v].colname,
00813                                 ")"
00814                                 );
00815                         _delim = " AND ";
00816                 };
00817                 if ((*_p)->Where() && StrCmp((*_p)->Where(),""))
00818                 {
00819                         (void)StrCat(_fullWhere,4,_delim,"(",(*_p)->Where(),")");
00820                         _delim = " AND ";
00821                 };
00822         };
00823 };
00824 
00825 void ProtoBase::_InitialiseKeyWhere()
00826 {
00827         const char *_delim = NULL;
00828         for (int v=0; v < _sqlVars.KeyCount; v++)
00829         {
00830                 (void)StrCat(_keyWhere,4,
00831                         _delim,
00832                         ((sqlVar*)_sqlVars.Arr)[v].colname,
00833                         " = ",
00834                         ((sqlVar*)_sqlVars.Arr)[v].varname
00835                         );
00836                 _delim=" AND ";
00837         };
00838 };
00839 
00840 void ProtoBase::_InitialiseGroupBy()
00841 {
00842         if (_isDatabaseObject || _isPersistentObject)
00843                 // DatabaseObject descendants ignore GROUP BY
00844                 return;
00845         char *thistable = NULL;
00846         StrCat(thistable,2,From(),".");
00847         // obtain group by clause defined in the class T
00848         // from Proto<T> using virtual function _ProtoTWhere()
00849         StrCpy(_groupBy,_ProtoTGroupBy());
00850         StrReplaceAll(_groupBy,THIS_TABLE ".", thistable);
00851         StrFree(thistable);
00852 };
00853 
00854 void ProtoBase::_InitialiseHaving()
00855 {
00856         if (_isDatabaseObject || _isPersistentObject)
00857                 // DatabaseObject descendants ignore HAVING
00858                 return;
00859         char *thistable = NULL;
00860         StrCat(thistable,2,From(),".");
00861         // obtain having clause defined in the class T
00862         // from Proto<T> using virtual function _ProtoTWhere()
00863         StrCpy(_having,_ProtoTHaving());
00864         StrReplaceAll(_having,THIS_TABLE ".", thistable);
00865         StrFree(thistable);
00866 };
00867 
00868 void ProtoBase::_InitialiseStmtSelect()
00869 {
00870         if (_isObject)
00871                 // Object descendants need not to be selected individually
00872                 return;
00873         char * where = NULL;
00874         StrCpy(where,_rootPrototype->_keyWhere);
00875         StrAnd(where,_fullWhere);
00876         StrClause(where,"WHERE");
00877         char * groupBy = NULL;
00878         StrCpy(groupBy,_groupBy);
00879         StrClause(groupBy,"GROUP BY");
00880         char * having = NULL;
00881         StrCpy(having,_having);
00882         StrClause(having,"HAVING");
00883         StrCat(_stmtSelect,9,
00884                 "SELECT ",      _fullSelect,
00885                 //" INTO ",     _fullInto,
00886                 " FROM ",       _fullFrom,
00887         /*      " WHERE ",*/    " ", where,
00888         /*      " GROUP BY ",*/ " ", groupBy,
00889         /*      " HAVING ",*/   " ", having
00890                 );
00891         StrFree(where);
00892         StrFree(groupBy);
00893         StrFree(having);
00894 };
00895 
00896 void ProtoBase::_InitialiseStmtInsert()
00897 {
00898         if (_isObject || _isImmutableObject)
00899                 // Object and ImmutableObject descendants need not to be inserted
00900                 return;
00901         char * inscols = NULL;
00902         char * insvars = NULL;
00903         const char * delim = NULL;
00904         for (int v=0; v < _sqlVars.SpecCount; v++)
00905         {
00906                 sqlVar &var = ((sqlVar *)_sqlVars.Arr)[v];
00907                 if (var.rw)
00908                 {
00909                         char * colwithoutprefix = StrCpy(var.colname);
00910                         StrPrefixCut(colwithoutprefix,'.');
00911                         StrCat(inscols,2,
00912                                 delim, colwithoutprefix
00913                                 );
00914                         StrCat(insvars,2,
00915                                 delim, var.varname
00916                                 );
00917                         delim=", ";
00918                         StrFree(colwithoutprefix);
00919                 };
00920         };
00921         StrCat(_stmtInsert,7,
00922                 "INSERT INTO ", From(), " (", inscols,
00923                 ") VALUES (", insvars, ")"
00924                 );
00925         StrFree(inscols);
00926         StrFree(insvars);
00927 };
00928 
00929 void ProtoBase::_InitialiseStmtUpdate()
00930 {
00931         if (_isObject || _isImmutableObject)
00932                 // Object and ImmutableObject descendants need not to be updated
00933                 return;
00934         StrCat(_stmtUpdate,3,
00935                 "UPDATE ", From(), " SET "
00936                 );
00937         const char *delim = NULL;
00938         for (int v=_sqlVars.KeyCount; v < _sqlVars.Count; v++)
00939         {
00940                 sqlVar &var = ((sqlVar *)_sqlVars.Arr)[v];
00941                 if (var.rw)
00942                 {
00943                         StrCat(_stmtUpdate,4,
00944                                 delim, var.colname, " = ", var.varname
00945                                 );
00946                         delim=", ";
00947                 };
00948         };
00949         char * where = NULL;
00950         StrCpy(where,_keyWhere);
00951         StrAnd(where,_where);
00952         StrClause(where," WHERE");
00953         StrCat(_stmtUpdate,where);
00954         StrFree(where);
00955 };
00956 
00957 void ProtoBase::_InitialiseStmtDelete()
00958 {
00959         StrCat(_stmtDelete,4,
00960                 "DELETE FROM ", From(),
00961                 " WHERE ", _keyWhere
00962                 );
00963 };
00964 
00965 char *ProtoBase::_StmtSelectPtr(
00966 // Method creates a SQL SELECT command
00967 // that selects only primary key
00968 // plus special columns like ClassName
00969 // and adds additional condition.
00970 // In case of Object descendants, all columns are selected,
00971 // Because such objects need not have suitable primary key
00972 // Wanted result :
00973 // SELECT [DISTINCT] - FROM - WHERE - GROUP BY - HAVING - ORDER BY
00974         const QueRefProto &Q,
00975         const int i
00976         )
00977 {
00978         _Initialise();
00979         // new instances of strings forming SELECT statement
00980         char * NWhere = Q._Where();
00981         char * NOrderBy = Q._OrderBy();
00982         char * NSelect = Q._Select();
00983         char * NFrom = Q._From();
00984         //Realiasing Query
00985         _RealiasT(NWhere,i);
00986         _RealiasT(NOrderBy,i);
00987         //_RealiasT(NSelect,1,1);
00988         //_RealiasT(NFrom,1,1);
00989         char *res = _StmtSelectPtr(
00990                 NWhere,
00991                 NOrderBy,
00992                 NSelect,
00993                 NFrom,
00994                 i
00995                 );
00996         StrFree(NWhere);
00997         StrFree(NOrderBy);
00998         StrFree(NSelect);
00999         StrFree(NFrom);
01000         return res;
01001 };
01002 
01003 char *ProtoBase::_StmtSelectPtr(
01004 // Method creates a SQL SELECT command
01005 // that selects only primary key
01006 // plus special columns like ClassName
01007 // and adds additional condition.
01008 // In case of Object descendants, all columns are selected,
01009 // Because such objects need not have suitable primary key
01010 // Wanted result :
01011 // SELECT [DISTINCT] - FROM - WHERE - GROUP BY - HAVING - ORDER BY
01012         const char *const _where_clause,
01013         const char *const _order_by_clause,
01014         const char *const _select_clause,
01015         const char *const _from_clause,
01016         const int i
01017         )
01018 {
01019         _Initialise();
01020         char * qselect = NULL;
01021         char * qfrom = NULL;
01022         char * qwhere = NULL;
01023         const char * qsdelim = "";
01024         const char * qfdelim = "";
01025         const char * qwdelim = "";
01026         char * rootalias = AliasT(i,0);
01027         char * alias = NULL;
01028         for (int p=0; p<_fullParentPrototypeCount; p++)
01029         {
01030                 // go through all classes and build:
01031                 // SELECT keys + special columm(s) a ClassName
01032                 // FROM all tables
01033                 // WHERE join of them by primery keys
01034                 // use aliases for tables
01035                 alias = AliasT(i,p);
01036                 if (p==0) // root table, build select part
01037                 {
01038                         char * trimcol = NULL;
01039                         int v;
01040                         if (_isObject)
01041                         {
01042                                 for (v=0; v<_fullParentPrototype[p]->_sqlVars.Count; v++)
01043                                 {
01044                                         sqlVar &var = ((sqlVar*)(_fullParentPrototype[p]->_sqlVars.Arr))[v];
01045                                         StrCat(qselect,2,qsdelim,var.colname);
01046                                         qsdelim=", ";
01047                                 };
01048                         }
01049                         else
01050                         {
01051                                 for (v=0; v<_fullParentPrototype[p]->_sqlVars.KeyCount; v++)
01052                                 {
01053                                         sqlVar &var = ((sqlVar*)(_fullParentPrototype[p]->_sqlVars.Arr))[v];
01054                                         StrCpy(trimcol,var.colname);
01055                                         StrPrefixCut(trimcol,'.');
01056                                         StrCat(qselect,4,qsdelim,alias,".",trimcol);
01057                                         qsdelim=", ";
01058                                         StrFree(trimcol);
01059                                 };
01060                                 for (v=_fullParentPrototype[p]->_sqlVars.Count; v<_fullParentPrototype[p]->_sqlVars.SpecCount; v++)
01061                                 {
01062                                         sqlVar &var = ((sqlVar*)(_fullParentPrototype[p]->_sqlVars.Arr))[v];
01063                                         StrCpy(trimcol,var.colname);
01064                                         StrPrefixCut(trimcol,'.');
01065                                         StrCat(qselect,4,qsdelim,alias,".",trimcol);
01066                                         qsdelim=", ";
01067                                         StrFree(trimcol);
01068                                 };
01069                         };
01070                 };
01071                 // add table to from clause
01072                 if (_isObject)
01073                         StrCat(qfrom,2,qfdelim,_fullParentPrototype[p]->From());
01074                 else
01075                         StrCat(qfrom,4,qfdelim,_fullParentPrototype[p]->From()," ",alias);
01076                 qfdelim=", ";
01077                 // add condition of the class if necessary
01078                 if (_where && *_where)
01079                 {
01080                         char * cwhere = NULL;
01081                         StrCpy(cwhere,_where);
01082                         _RealiasT(cwhere,i);
01083                         StrCat(qwhere,4,qwdelim,"(",cwhere,")");
01084                         qwdelim=" AND ";
01085                         StrFree(cwhere);
01086                 };
01087                 // add condition that joins table with root table if necessary
01088                 if (p>0)
01089                 {
01090                         //Join the table with root table;
01091                         char * trimcol = NULL;
01092                         int v;
01093                         for (v=0; v<_fullParentPrototype[p]->_sqlVars.KeyCount; v++)
01094                         {
01095                                 sqlVar &rootvar = ((sqlVar*)(_rootPrototype->_sqlVars.Arr))[v];
01096                                 sqlVar &thisvar = ((sqlVar*)(_fullParentPrototype[p]->_sqlVars.Arr))[v];
01097                                 StrCpy(trimcol,thisvar.colname);
01098                                 StrPrefixCut(trimcol,'.');
01099                                 StrCat(qwhere,5,qwdelim,"(",alias,".",trimcol);
01100                                 StrFree(trimcol);
01101                                 StrCpy(trimcol,rootvar.colname);
01102                                 StrPrefixCut(trimcol,'.');
01103                                 StrCat(qwhere,5,"=",rootalias,".",trimcol,")");
01104                                 StrFree(trimcol);
01105                                 qwdelim=" AND ";
01106                         };
01107                 };
01108                 StrFree(alias);
01109         };
01110         StrFree(rootalias);
01111         // all three parts are built, now process other details
01112         if (_from_clause && *_from_clause)
01113         {
01114                 //there is an additinal fragment of where clause in the query
01115                 //add it to the query
01116                 StrCat(qfrom,2,qfdelim,_from_clause);
01117                 //qwdelim=" AND ";
01118         };
01119         if (_where_clause && *_where_clause)
01120         {
01121                 //there is an additinal fragment of where clause in the query
01122                 //add it to the query
01123                 StrCat(qwhere,4,qwdelim,"(",_where_clause,")");
01124                 //qwdelim=" AND ";
01125         };
01126         if (_select_clause && *_select_clause)
01127         {
01128                 // there are selected other columns than key columns of the class
01129                 // join those columns together with primary keys
01130                 //
01131                 // BUT this branch is not currently used
01132         };
01133         // Let's connect all fragments together!
01134         char * statement = NULL;
01135         char * qgroupBy = NULL;
01136         char * qhaving = NULL;
01137         char * qorderby = NULL;
01138         StrCpy(qgroupBy,_groupBy);
01139         _RealiasT(qgroupBy,i);
01140         StrCpy(qhaving,_having);
01141         _RealiasT(qhaving,i);
01142         StrCpy(qorderby,_order_by_clause);
01143         StrClause(qwhere,"WHERE");
01144         StrClause(qgroupBy,"GROUP BY");
01145         StrClause(qhaving,"HAVING");
01146         StrClause(qorderby,"ORDER BY");
01147         StrCat(statement,12,
01148                 "SELECT ",      qselect,
01149                 " FROM ",       qfrom,
01150         /*      " WHERE ",*/    " ", qwhere,
01151         /*      " GROUP BY ",*/ " ", qgroupBy,
01152         /*      " HAVING ",*/   " ", qhaving,
01153         /*      " ORDER BY ",*/ " ", qorderby
01154                 );
01155         StrFree(qselect);
01156         StrFree(qfrom);
01157         StrFree(qwhere);
01158         StrFree(qgroupBy);
01159         StrFree(qhaving);
01160         StrFree(qorderby);
01161         return statement;
01162 };
01163 
01164 bool ProtoBase::_BindPtr(
01165 // Method binds all columns of _StmtSelectPtr's statement
01166         class Cursor *C
01167         )
01168 {
01169         int v;
01170         int i=0;
01171         if (_isObject)
01172         {
01173                 // Object descendants select all columns
01174                 for (v=0; v<_rootPrototype->_sqlVars.Count; v++)
01175                 {
01176                         i++;
01177                         sqlVar &var=((sqlVar *)(_rootPrototype->_sqlVars.Arr))[v];
01178                         C->_PreFetchBind(i,var.bufaddr,var.buflen,var.buftype);
01179                 };
01180         }
01181         else
01182         {
01183                 // ImmutableObject, DatabaseObject and PersistentObject descendants
01184                 // select only key columns
01185                 for (v=0; v<_rootPrototype->_sqlVars.KeyCount; v++)
01186                 {
01187                         i++;
01188                         sqlVar &var=((sqlVar *)(_rootPrototype->_sqlVars.Arr))[v];
01189                         C->_PreFetchBind(i,var.bufaddr,var.buflen,var.buftype);
01190                 };
01191                 for (v=_rootPrototype->_sqlVars.Count; v<_rootPrototype->_sqlVars.SpecCount; v++)
01192                 {
01193                         i++;
01194                         sqlVar &var=((sqlVar *)(_rootPrototype->_sqlVars.Arr))[v];
01195                         C->_PreFetchBind(i,var.bufaddr,var.buflen,var.buftype);
01196                 };
01197         };
01198         return true;
01199 };
01200 
01201 ProtoBase *ProtoBase::_PtrPrototype()
01202 // Method returns prototype for last fetched class name
01203 {
01204         _Initialise();
01205 #ifndef NO_DATABASE_PRESENT
01206         if (_isPersistentObject)
01207                 return Class[(char *)(((sqlVar *)(_rootPrototype->_sqlVars.Arr))[_rootPrototype->_sqlVars.Count].bufaddr)];
01208         else
01209 #endif
01210                 return this;
01211 };
01212 
01213 ProtoBase * ProtoBase::Find(const char *_n)
01214 {
01215         ProtoBase *p = _root;
01216         int c;
01217         while (p) {
01218         c = StrCmp(p->ClassName(),_n);
01219         if (c > 0)
01220                 p = p->_left;
01221         else if (c < 0)
01222                 p = p->_right;
01223         else
01224                 break;
01225         };
01226         return p;
01227 };
01228 
01229 bool ProtoBase::operator<(class ProtoBase &_p)
01230 {
01231         _Initialise();
01232         int i = 0;
01233         while((i<_fullParentPrototypeCount-1) && (_fullParentPrototype[i]!=&_p))
01234         i++;
01235         return ((i<_fullParentPrototypeCount-1) && (_fullParentPrototype[i]==&_p));
01236 };
01237 
01238 ProtoBase::~ProtoBase()
01239 {
01240         StrFree(_condition);
01241         if (_sqlVars.Arr)
01242         {
01243                 for (int i=0; i<_sqlVars.Count; i++)
01244                 {
01245                         StrFree(((sqlVar*)_sqlVars.Arr)[i].atrname);
01246                         if (((sqlVar*)_sqlVars.Arr)[i].bufaddr) free(((sqlVar*)_sqlVars.Arr)[i].bufaddr);
01247                 };
01248                 free(_sqlVars.Arr);
01249    };
01250    free(_parentPrototype);
01251    free(_fullParentPrototype);
01252    StrFree(_select);
01253    StrFree(_fullSelect);
01254    StrFree(_keySelect);
01255    StrFree(_ptrSelect);
01256    StrFree(_into);
01257    //StrFree(_fullInto);
01258    //StrFree(_keyInto);
01259    StrFree(_fullFrom);
01260    StrFree(_where);
01261    StrFree(_fullWhere);
01262    StrFree(_keyWhere);
01263    StrFree(_stmtSelect);
01264    StrFree(_stmtInsert);
01265    StrFree(_stmtDelete);
01266    StrFree(_stmtUpdate);
01267 };
01268 
01269 class ProtoBase * ProtoBase::ParentPrototype(const int i)
01270 {
01271         _Initialise();
01272         if ((i<0)||(i>=_parentPrototypeCount))
01273                 return NULL;
01274         return _parentPrototype[i];
01275 };
01276 
01277 class ProtoBase * ProtoBase::FullParentPrototype(const int i)
01278 {
01279         _Initialise();
01280         if ((i<0)||(i>=_fullParentPrototypeCount))
01281                 return NULL;
01282         return _fullParentPrototype[i];
01283 };
01284 
01285 const char* ProtoBase::ColumnTable(const char* const col)
01286 // Returns a table name containing the given column
01287 {
01288         _Initialise();
01289         for(int i=0;i<_fullParentPrototypeCount;i++)
01290                 for(int j=1; j<=_fullParentPrototype[i]->_sqlVars.Count; j++)
01291                         if (!StrCmpUp(col,(((sqlVar*)(_fullParentPrototype[i]->_sqlVars.Arr))[j-1]).colname))
01292                                 return _fullParentPrototype[i]->From();
01293         return NULL;
01294 };
01295 
01296 bool ProtoBase::_InsertAll(class Object *target)
01297 //Inserts complete instance
01298 {
01299         _Initialise();
01300         bool retval;
01301 
01302         #ifdef C_PROTOBASE_TRACE
01303                 logmsg("bool ProtoBase::_InsertAll() invoked");
01304         #endif
01305 
01306         retval = _ExportAttributes(*target);
01307         for(int i=0; i<_fullParentPrototypeCount; i++)
01308                 retval = retval && _fullParentPrototype[i]->_Insert(target->_Connection);
01309 
01310         #ifdef C_PROTOBASE_TRACE
01311                 logmsg("bool ProtoBase::_InsertAll() finished");
01312         #endif
01313 
01314         return retval;
01315 };
01316 
01317 bool ProtoBase::_Insert(class Connection *aDbConn)
01318 //Inserts piece of an instance
01319 {
01320         bool retval = true;
01321 
01322         #ifdef C_PROTOBASE_TRACE
01323                 logmsg("bool ProtoBase::_Insert() invoked");
01324         #endif
01325 
01326         retval = retval && aDbConn->_Open();
01327         retval = retval && aDbConn->_Prepare(_stmtInsert);
01328         // Bind input variables now
01329         int v;
01330         for (v=0 ; v<_fullParentPrototype[0]->_sqlVars.KeyCount; v++)
01331         {
01332                 sqlVar &rootvar = ((sqlVar *)_fullParentPrototype[0]->_sqlVars.Arr)[v];
01333                 sqlVar &thisvar = ((sqlVar *)_sqlVars.Arr)[v];
01334                 retval = retval && aDbConn->_PreExecBind(
01335                         thisvar.varname,
01336                         rootvar.bufaddr,
01337                         rootvar.buflen,
01338                         rootvar.buftype,
01339                         &rootvar.indic
01340                         );
01341         };
01342         for (v=_sqlVars.KeyCount ; v<_sqlVars.SpecCount; v++)
01343         {
01344                 sqlVar &var = ((sqlVar *)_sqlVars.Arr)[v];
01345                 if (var.rw)
01346                 {
01347                         retval = retval && aDbConn->_PreExecBind(
01348                                 var.varname,
01349                                 var.bufaddr,
01350                                 var.buflen,
01351                                 var.buftype,
01352                                 &var.indic
01353                                 );
01354                 };
01355         };
01356         retval = retval && aDbConn->_Execute();
01357         retval = retval && aDbConn->_Close();
01358 
01359         #ifdef C_PROTOBASE_TRACE
01360                 logmsg("bool ProtoBase::_Insert() finished");
01361         #endif
01362 
01363         return retval;
01364 };
01365 
01367 
01368 bool ProtoBase::_UpdateAll(class Object *target)
01369 //Writes complete object from the memory to the disk.
01370 {
01371         _Initialise();
01372         bool retval;
01373 
01374         #ifdef C_PROTOBASE_TRACE
01375                 logmsg("bool ProtoBase::_UpdateAll() invoked");
01376         #endif
01377 
01378         retval = _ExportAttributes(*target);
01379         for(int i=0; i<_fullParentPrototypeCount; i++)
01380                 retval = retval && _fullParentPrototype[i]->_Update(target->_Connection);
01381         target->_MarkAsClean();
01382 
01383         #ifdef C_PROTOBASE_TRACE
01384                 logmsg("bool ProtoBase::_Insert() finished");
01385         #endif
01386 
01387         return retval;
01388 };
01389 
01390 bool ProtoBase::_Update(class Connection *aDbConn)
01391 //Writes piece of an object from the memory to the disk.
01392 {
01393         bool retval;
01394 
01395         #ifdef C_PROTOBASE_TRACE
01396                 logmsg("bool ProtoBase::_Update() invoked");
01397         #endif
01398 
01399         if (_sqlVars.Count == _sqlVars.KeyCount)
01400                 // there are no no-key attributes in this class => no update is necessary
01401                 return true;
01402 
01403         retval = aDbConn->_Open();
01404         retval = retval && aDbConn->_Prepare(_stmtUpdate);
01405         //Bind input variables
01406         int v;
01407         for (v=_sqlVars.KeyCount; v<_sqlVars.Count; v++)
01408         {
01409                 sqlVar &var = ((sqlVar *)_sqlVars.Arr)[v];
01410                 if (var.rw)
01411                 {
01412                         retval = retval && aDbConn->_PreExecBind(
01413                                 var.varname,
01414                                 var.bufaddr,
01415                                 var.buflen,
01416                                 var.buftype,
01417                                 &var.indic
01418                                 );
01419                 };
01420         };
01421         for (v=0; v<_fullParentPrototype[0]->_sqlVars.KeyCount; v++)
01422         {
01423                 sqlVar &rootvar = ((sqlVar *)_fullParentPrototype[0]->_sqlVars.Arr)[v];
01424                 sqlVar &thisvar = ((sqlVar *)_sqlVars.Arr)[v];
01425                 retval = retval && aDbConn->_PreExecBind(
01426                         thisvar.varname,
01427                         rootvar.bufaddr,
01428                         rootvar.buflen,
01429                         rootvar.buftype,
01430                         &rootvar.indic
01431                         );
01432         };
01433         retval = retval && aDbConn->_Execute();
01434         retval = retval && aDbConn->_Close();
01435 
01436         #ifdef C_PROTOBASE_TRACE
01437                 logmsg("bool ProtoBase::_Update() finished");
01438         #endif
01439         return retval;
01440 };
01441 
01442 bool ProtoBase::_DeleteAll(class RefBase *target)
01443 {
01444         _Initialise();
01445         bool retval;
01446 
01447         #ifdef C_PROTOBASE_TRACE
01448                 logmsg("bool ProtoBase::_DeleteAll(RefBase *) invoked");
01449         #endif
01450 
01451         #ifdef NO_DATABASE_CASCADE_DELETE
01452                 for(int i=_fullParentPrototypeCount-1; i>0; i--)
01453                         retval = retval && _fullParentPrototype[i]->_Delete(target->_Connection);
01454         #else
01455                 retval = _fullParentPrototype[0]->_Delete(target->_Connection);
01456         #endif
01457 
01458         #ifdef C_PROTOBASE_TRACE
01459                 logmsg("bool ProtoBase::_DeleteAll(RefBase *) finished");
01460         #endif
01461 
01462         return retval;
01463 };
01464 
01465 bool ProtoBase::_DeleteAll(class Object *target)
01466 {
01467         _Initialise();
01468         bool retval;
01469 
01470         #ifdef C_PROTOBASE_TRACE
01471                 logmsg("bool ProtoBase::_DeleteAll(Object *) invoked");
01472         #endif
01473 
01474         #ifdef NO_DATABASE_CASCADE_DELETE
01475                 for(int i=_fullParentPrototypeCount-1; i>0; i--)
01476                         retval = retval && _fullParentPrototype[i]->_Delete(target->_Connection);
01477         #else
01478                 retval = _fullParentPrototype[0]->_Delete(target->_Connection);
01479         #endif
01480 
01481         #ifdef C_PROTOBASE_TRACE
01482                 logmsg("bool ProtoBase::_DeleteAll(Object *) finished");
01483         #endif
01484 
01485         return retval;
01486 };
01487 
01488 bool ProtoBase::_Delete(class Connection * aDbConn)
01489 {
01490         bool retval;
01491 
01492         #ifdef C_PROTOBASE_TRACE
01493         logmsg("bool ProtoBase::_Delete() invoked");
01494         #endif
01495 
01496         retval = aDbConn->_Open();
01497         retval = retval && aDbConn->_Prepare(_stmtDelete);
01498         //Bind input variables
01499         for (int v=0; v < _rootPrototype->_sqlVars.KeyCount; v++)
01500         {
01501                 sqlVar &rootvar = ((sqlVar *)_rootPrototype->_sqlVars.Arr)[v];
01502                 sqlVar &thisvar = ((sqlVar *)_sqlVars.Arr)[v];
01503                 retval = retval && aDbConn->_PreExecBind(
01504                         thisvar.varname,
01505                         rootvar.bufaddr,
01506                         rootvar.buflen,
01507                         rootvar.buftype
01508                         );
01509         };
01510 
01511         retval = retval && aDbConn->_Execute();
01512         retval = retval && aDbConn->_Close();
01513 
01514         #ifdef C_PROTOBASE_TRACE
01515                 logmsg("bool ProtoBase::_Delete() finished");
01516         #endif
01517 
01518         return retval;
01519 };
01520 
01522 //Private method which loads data from the given connection
01523 //to the memory
01524 bool ProtoBase::_Load(
01525         class Object &o
01526         )
01527 {
01528         bool retval = true;
01529         #ifdef C_PROTOBASE_TRACE
01530                 logmsg("ProtoBase::_Load(Object) invoked");
01531         #endif
01532 
01533         if (o.IsPersistent())
01534         {
01535                 _Initialise();
01536                 char * statement = NULL;
01537                 StrCpy(statement,_stmtSelect);
01538                 if (o.CurrentLockingStrategy() == LS_Exclusive)
01539                 {
01540                         StrCat(statement," FOR UPDATE");
01541                         if (o.CurrentWaitingStrategy() == WS_Nowait)
01542                                 StrCat(statement," NOWAIT");
01543                         else
01544                                 /*StrCat(statement," WAIT")*/;
01545                 };
01546                 retval = retval && o._Connection->_Open();
01547                 retval = retval && o._Connection->_Prepare(statement);
01548                 // Bind input variables now
01549                 for (int v=0; v < _rootPrototype->_sqlVars.KeyCount; v++)
01550                 {
01551                         sqlVar &var = ((sqlVar *)_rootPrototype->_sqlVars.Arr)[v];
01552                         retval = retval && o._Connection->_PreExecBind(
01553                                 var.varname,
01554                                 var.bufaddr,
01555                                 var.buflen,
01556                                 var.buftype
01557                                 );
01558                 };
01559                 retval = retval && o._Connection->_Execute();
01560                 // Bind output variables now
01561                 int col = 0;
01562                 for (int i=0; i<_fullParentPrototypeCount; i++)
01563                         for (int v=_fullParentPrototype[i]->_sqlVars.KeyCount; v<_fullParentPrototype[i]->_sqlVars.Count; v++)
01564                         {
01565                                 sqlVar &var = ((sqlVar *)_fullParentPrototype[i]->_sqlVars.Arr)[v];
01566                                 retval = retval && o._Connection->_PreFetchBind(
01567                                         ++col,
01568                                         var.bufaddr,
01569                                         var.buflen,
01570                                         var.buftype,
01571                                         &var.indic
01572                                         );
01573                         };
01574                 retval = retval && o._Connection->_FetchNext();
01575                 retval = retval && o._Connection->_Close();
01576                 retval = retval && _ImportAttributes(o) && o.PostLoad();
01577                 if (o.CurrentLockingStrategy() == LS_Exclusive)
01578                 {
01579                         o._ForUpdate = true;
01580                 }
01581                 o._MarkAsClean();
01582         };
01583         #ifdef C_PROTOBASE_TRACE
01584                 logmsg("char * ProtoBase::_Load() finished");
01585         #endif
01586         return(retval);
01587 };
01588 
01590 // Method lock a table assigned to target class in desired mode
01591 // the method works for really persistent objects
01592 bool ProtoBase::LockTable(
01593         class Connection *aDbCon,
01594         enum LockingStrategy aLockingStrategy,
01595         enum WaitingStrategy aWaitingStrategy
01596         )
01597 {
01598         bool _retval;
01599         if (aDbCon && (aLockingStrategy != LS_None))
01600         {
01601                 if (aLockingStrategy == LS_Default)
01602                         aLockingStrategy = DEFAULT_LOCKING_STRATEGY;
01603                 if (aWaitingStrategy == WS_Default)
01604                         aWaitingStrategy = DEFAULT_WAITING_STRATEGY;
01605                 if (IsDatabaseObject() || IsPersistentObject())
01606                 {
01607                         char *lock = NULL;
01608                         StrCat(lock,3,"LOCK TABLE ",From()," IN");
01609                         switch (aLockingStrategy)
01610                         {
01611                                 case LS_Shared:
01612                                         StrCat(lock," SHARED MODE");
01613                                         break;
01614                                 case LS_Exclusive:
01615                                         StrCat(lock," EXCLUSIVE MODE");
01616                                         break;
01617                         };
01618                         switch (aWaitingStrategy)
01619                         {
01620                                 case WS_Wait:
01621                                         break;
01622                                 case WS_Nowait:
01623                                         StrCat(lock," NOWAIT");
01624                                         break;
01625                         };
01626                         _retval = aDbCon->Sql(lock);
01627                         StrFree(lock);
01628                 }
01629                 else
01630                         _retval = false;
01631         }
01632         else
01633                 _retval = false;
01634         return _retval;
01635 };
01636 
01637 
01638 char * ProtoBase::_RealiasT(
01639         char * &fragment,
01640         const char *table,
01641         const int i,
01642         const int j
01643         )
01644 {
01645         _Initialise();
01646         char *_Alias = StrCpy(_Alias=NULL ,AliasT(i,j));
01647         char *_TableName = StrCpy(_TableName=NULL,table);
01648         StrCat(_Alias,".");
01649         StrCat(_TableName,".");
01650         StrReplaceAll(fragment,_TableName,_Alias,true);
01651         StrFree(_Alias);
01652         StrFree(_TableName);
01653         return fragment;
01654 };
01655 
01656 char * ProtoBase::_RealiasT(
01657         char * &fragment,
01658         const int i
01659         )
01660 {
01661         _Initialise();
01662         for (int j=0; j < _fullParentPrototypeCount; j++)
01663                 _RealiasT(fragment,_fullParentPrototype[j]->From(),i,j);
01664         return fragment;
01665 };
01666 
01667 bool ProtoBase::WriteDDL(ofstream &S, class Database &Db)
01668 // generates DDL stements nedded for the library to run
01669 {
01670         if (!S.rdbuf()->is_open())
01671                 return false;
01672         _Initialise();
01673         if (!From() || !*From())
01674                 return true;
01675         if (!_isPersistentObject)
01676                 return true;
01677         S << "-- Table " << From() << " associated with class " << ClassName() << endl;
01678         // first line with CREATE TABLE
01679         S << "CREATE TABLE " << From() << "(";
01680         char *col = NULL;
01681         char *typ = NULL;
01682         const char *delimcols = "";
01683         const char *delimkeys = "";
01684         int i;
01685         // column definition
01686         for(i=0; i<_sqlVars.SpecCount; i++)
01687         {
01688                 sqlVar &var = ((sqlVar *)(_sqlVars.Arr))[i];
01689                 col = StrCpy(var.colname);
01690                 StrPrefixCut(col,'.');
01691                 typ = Db.ColumnTypeDDL(var.buftype,var.buflen);
01692                 S << delimcols << endl << col << " " << typ;
01693                 StrFree(col);
01694                 StrFree(typ);
01695                 delimcols = ",";
01696         };
01697         // primary key declaration
01698         S << delimcols << endl << "CONSTRAINT " << From() << "_PK PRIMARY KEY(";
01699         for(i=0; i<_sqlVars.KeyCount; i++)
01700         {
01701                 sqlVar &var = ((sqlVar *)(_sqlVars.Arr))[i];
01702                 col = StrCpy(var.colname);
01703                 StrPrefixCut(col,'.');
01704                 S << delimkeys << col;
01705                 StrFree(col);
01706                 delimkeys = ",";
01707         };
01708         S << ")";
01709         delimcols = ",";
01710         // foreign key declaration
01711         for(int p=0; p<_parentPrototypeCount; p++)
01712         {
01713                 S << delimcols << endl << "CONSTRAINT " << From() << "_FK_" << _parentPrototype[p]->From();
01714                 S << " FOREIGN KEY(";
01715                 delimkeys = "";
01716                 for(i=0; i<_sqlVars.KeyCount; i++)
01717                 {
01718                         sqlVar &var = ((sqlVar *)(_sqlVars.Arr))[i];
01719                         col = StrCpy(var.colname);
01720                         StrPrefixCut(col,'.');
01721                         S << delimkeys << col;
01722                         StrFree(col);
01723                         delimkeys = ",";
01724                 };
01725                 S << ") REFERENCES " << _parentPrototype[p]->From() << "(";
01726                 delimkeys = "";
01727                 for(i=0; i<_parentPrototype[p]->_sqlVars.KeyCount; i++)
01728                 {
01729                         sqlVar &var = ((sqlVar *)(_parentPrototype[p]->_sqlVars.Arr))[i];
01730                         col = StrCpy(var.colname);
01731                         StrPrefixCut(col,'.');
01732                         S << delimkeys << col;
01733                         StrFree(col);
01734                         delimkeys = ",";
01735                 };
01736                 S << ") ON DELETE CASCADE";
01737                 delimcols = ",";
01738         };
01739         // last line that closes the table definition
01740         S << endl << ");" << endl << endl;
01741         S.flush();
01742         return true;
01743 };
01744 
01745 char* ProtoBase::FullFrom(int k)
01746 {
01747         _Initialise();
01748         char *result = NULL;
01749         char *alias = NULL;
01750         const char *delim = "";
01751         for (int i=0; i<_fullParentPrototypeCount; i++)
01752         {
01753                 alias = AliasT(k,i);
01754                 StrCat(result,4,delim,_fullParentPrototype[i]->From()," ",alias);
01755                 delim = ",";
01756                 StrFree(alias);
01757         };
01758         return result;
01759 };
01760 
01761 char* ProtoBase::FullWhere(int k)
01762 {
01763         _Initialise();
01764         char *result = NULL;
01765         char *rootalias = AliasT(k,0);
01766         char *alias = NULL;
01767         const char *delim = "";
01768         for (int p=1; p<_fullParentPrototypeCount; p++)
01769         {
01770                 alias = AliasT(k,p);
01771                 char * trimcol = NULL;
01772                 int v;
01773                 for (v=0; v<_fullParentPrototype[p]->_sqlVars.KeyCount; v++)
01774                 {
01775                         sqlVar &rootvar = ((sqlVar*)(_rootPrototype->_sqlVars.Arr))[v];
01776                         sqlVar &thisvar = ((sqlVar*)(_fullParentPrototype[p]->_sqlVars.Arr))[v];
01777                         StrCpy(trimcol,thisvar.colname);
01778                         StrPrefixCut(trimcol,'.');
01779                         StrCat(result,5,delim,"(",alias,".",trimcol);
01780                         StrFree(trimcol);
01781                         StrCpy(trimcol,rootvar.colname);
01782                         StrPrefixCut(trimcol,'.');
01783                         StrCat(result,5,"=",rootalias,".",trimcol,")");
01784                         StrFree(trimcol);
01785                         delim=" AND ";
01786                 };
01787                 StrFree(alias);
01788         };
01789         StrFree(rootalias);
01790         return result;
01791 };
01792 
01793 char *ProtoBase::ColumnTypeDDL(int i, class Database &Db)
01794 // returns correct database column type for i-th attribute
01795 {
01796         _Initialise();
01797         if ((i<0) || (i>=_sqlVars.SpecCount))
01798                 return StrCpy("UNKNOWN");
01799         else
01800         {
01801                 sqlVar &var = ((sqlVar *)(_sqlVars.Arr))[i];
01802                 return Db.ColumnTypeDDL(var.buftype,var.buflen);
01803         };
01804 };
01805 
01806 char *ProtoBase::_TranslateToSql(char * (&dst), const char * const src)
01807 // replaces C++ operator and names by relational ones
01808 {
01809         _Initialise();
01810         StrCpy(dst,src);
01811         StrReplaceAll(dst,"==","=");
01812         StrReplaceAll(dst,"!=","<>");
01813         StrReplaceAll(dst,"&&"," AND ");
01814         StrReplaceAll(dst,"||"," OR ");
01815         StrReplaceAll(dst,"!"," NOT ");
01816         char *cpp = NULL;
01817         char *sql = NULL;
01818         //if (!_isObject)
01819         //{
01820         ProtoBase *ClassProto;
01821         ProtoBase *AttrProto;
01822         for(int c=0; c<_fullParentPrototypeCount; c++)
01823         {
01824                 ClassProto = _fullParentPrototype[c];
01825                 for (int a=(ClassProto->_fullParentPrototypeCount)-1; a>=0; a--)
01826                 {
01827                         AttrProto = ClassProto->_fullParentPrototype[a];
01828                         for(int v=0; v<AttrProto->_sqlVars.SpecCount; v++)
01829                         {
01830                                 sqlVar &var = ((sqlVar*)(AttrProto->_sqlVars.Arr))[v];
01831                                 StrCat(cpp,3,ClassProto->ClassName(),"::",var.atrname);
01832                                 StrCat(sql,3,"(",var.colname,")");
01833                                 StrReplaceAll(dst,cpp,sql,true,true);
01834                                 StrFree(cpp);
01835                                 StrFree(sql);
01836                         };
01837                 };
01838         };
01839         //};
01840         return dst;
01841 };
01842 
01843 char *ProtoBase::_TranslateToSql(char * (&src))
01844 // replaces C++ operator and names by relational ones
01845 {
01846         char *dst = NULL;
01847         _TranslateToSql(dst,src);
01848         StrFree(src);
01849         src=dst;
01850         return src;
01851 };
01852 
01853 class Query &ProtoBase::_TranslateToSql(class Query &Q)
01854 // replaces C++ operators in both where and oreder-by part
01855 {
01856         _TranslateToSql(Q._where);
01857         _TranslateToSql(Q._order_by);
01858         return Q;
01859 };

Generated on Sun Jul 14 20:51:15 2002 for POLiTe by doxygen1.2.16