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

cOneToManyRelationBase.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 // Common POLiTe Header(s)
00016 #include <lTrace.h>
00017 #include <lDefs.h>
00018 
00019 
00020 // Own Header
00021 #include <cOneToManyRelationBase.h>
00022 
00023 // Other POLiTe Header(s)
00024 #include <cChainedRelationBase.h>
00025 #include <cClassRegister.h>
00026 #include <cRefBase.h>
00027 #include <cRefBase.h>
00028 #include <cConnection.h>
00029 #include <cComplexQuery.h>
00030 
00031 OneToManyRelationBase::OneToManyRelationBase(
00032         const char *a_left_class_name,
00033         const char *a_right_class_name,
00034         const char *a_table_name,
00035         class Connection *a_database_connection,
00036         const char *a_left_column_name,
00037         const char *a_right_column_name
00038         ) :
00039 Relation(
00040         a_left_class_name,
00041         a_right_class_name,
00042         a_table_name,
00043         a_database_connection
00044         )
00045 {
00046         ProtoBase *_left_prototype=Class[_leftClassName];
00047         ProtoBase *_right_prototype=Class[_rightClassName];
00048         char *_str = NULL;
00049         char *_separator = NULL;
00050         char *_column = NULL;
00051 
00052         if (!a_left_column_name || !*a_left_column_name)
00053         {
00054                 StrCpy(_str,_left_prototype->KeySelect());
00055                 while (StrSplit(_str,',',_column)) 
00056                 {
00057                         StrPrefixCut(_column,'.');
00058                         StrCat(_leftColumnName,4,_separator,_tableName,"_",_column);
00059                         _separator = ", ";
00060                 };
00061         }
00062         else
00063                 StrCpy(_leftColumnName=NULL,a_left_column_name);
00064 
00065         if (!a_right_column_name || !*a_right_column_name)
00066                 StrCpy(_rightColumnName, _right_prototype->KeySelect());
00067         else
00068                 StrCpy(_rightColumnName=NULL,a_right_column_name);
00069 
00070         StrFree(_str);
00071 };
00072 
00073 bool OneToManyRelationBase::InsertCouple(RefBase &left, RefBase &right)
00074         //Inserts a couple <L, R> to the OMT-relation.
00075 {
00076         if (left.IsTransient() || right.IsTransient())
00077                 return false;
00078         ProtoBase *_left_prototype=Class[_leftClassName];
00079         ProtoBase *_right_prototype=Class[_rightClassName];
00080 
00081         //UPDATE RTAB SET REL_KEY = LVAL WHERE KEY = RKEY
00082 
00083         bool _retval;
00084         char *_update = StrCpy(_update = NULL, _right_prototype->From());
00085         StrClause(_update,"UPDATE");
00086         char *_columns = StrCpy(_columns = NULL, _leftColumnName);
00087         char *_1column = NULL;
00088         char *_values = left._KeyValues();
00089         char *_1value = NULL;
00090         char *_set = NULL;
00091         char *_separator = NULL;
00092         while (StrSplit(_columns,',',_1column) && StrSplit(_values,',',_1value)) {
00093                 StrCat(_set,4,_separator,_1column," = ",_1value);
00094                 _separator = ", ";
00095                 };
00096         StrClause(_set,"SET");
00097         StrCpy(_columns,_right_prototype->KeySelect());
00098         StrFree(_1column);
00099         StrFree(_values);
00100         _values = right._KeyValues();
00101         StrFree(_1value);
00102         char *_where = NULL;
00103         _separator = "(";
00104         while (StrSplit(_columns,',',_1column) && StrSplit(_values,',',_1value)) {
00105                 StrPrefixCut(_1column,'.');
00106                 StrCat(_where,4,_separator,_1column," = ",_1value);
00107                 _separator = ") AND (";
00108                 };
00109         StrCat(_where,")");
00110         StrClause(_where,"WHERE");
00111         StrFree(_columns);
00112         StrFree(_1column);
00113         StrFree(_values);
00114         StrFree(_1value);
00115         StrCat(_update,2,_set,_where);
00116         StrFree(_set);
00117         StrFree(_where);
00118         if (_databaseConnection == NULL)
00119                 throw ObjLibException_ConnectionError();
00120         _retval = _databaseConnection -> _Sql(_update);
00121         StrFree(_update);
00122         return _retval;
00123 };
00124 
00125 bool OneToManyRelationBase::DeleteCouple(RefBase &left, RefBase &right)
00126 {
00127         if (left.IsTransient() || right.IsTransient())
00128                 return false;
00129         ProtoBase *_right_prototype=Class[_rightClassName];
00130 
00131         //UPDATE RTAB SET REL_KEY = NULL WHERE (REL_KEY = LKEY) AND (KEY = RKEY)
00132 
00133         bool _retval;
00134         char *_update = StrCpy(_update = NULL, _right_prototype->From());
00135         StrClause(_update,"UPDATE");
00136         char *_columns = StrCpy(_columns = NULL, _leftColumnName);
00137         char *_1column = NULL;
00138         char *_values = left._KeyValues();
00139         char *_1value = NULL;
00140         char *_set = NULL;
00141         char *_separator = NULL;
00142         while (StrSplit(_columns,',',_1column) && StrSplit(_values,',',_1value)) {
00143                 StrCat(_set,3,_separator,_1column," = NULL");
00144                 _separator = ", ";
00145                 };
00146         StrClause(_set,"SET");
00147         StrCpy(_columns,_leftColumnName);
00148         StrCat(_columns,2,", ",_right_prototype->KeySelect());
00149         StrFree(_1column);
00150         StrFree(_values);
00151         _values = left._KeyValues();
00152         StrFree(_1value);
00153         StrCat(_values,2,", ",_1value = right._KeyValues());
00154         StrFree(_1value); //temporary used for all right key values
00155         char *_where = NULL;
00156         _separator = "(";
00157         while (StrSplit(_columns,',',_1column) && StrSplit(_values,',',_1value)) {
00158                 StrPrefixCut(_1column,'.');
00159                 StrCat(_where,4,_separator,_1column," = ",_1value);
00160                 _separator = ") AND (";
00161                 };
00162         StrCat(_where,")");
00163         StrClause(_where,"WHERE");
00164         StrFree(_columns);
00165         StrFree(_1column);
00166         StrFree(_values);
00167         StrFree(_1value);
00168         StrCat(_update,2,_set,_where);
00169         StrFree(_set);
00170         StrFree(_where);
00171         if (_databaseConnection == NULL)
00172                 throw ObjLibException_ConnectionError();
00173         _retval = _databaseConnection -> _Sql(_update);
00174         StrFree(_update);
00175         return _retval;
00176 };
00177 
00178 bool OneToManyRelationBase::LDeleteAll(class RefBase &right)
00179         //Deletes all couples <X, LastRight>
00180 {
00181         if (right.IsTransient())
00182                 return false;
00183         ProtoBase *_right_prototype=Class[_rightClassName];
00184 
00185         //UPDATE RTAB SET REL_KEY = NULL WHERE KEY = RKEY
00186 
00187         bool _retval;
00188         char *_update = StrCpy(_update = NULL, _right_prototype -> From());
00189         StrClause(_update,"UPDATE");
00190         char *_columns = StrCpy(_columns = NULL, _leftColumnName);
00191         char *_1column = NULL;
00192         char *_values = NULL;
00193         char *_1value = NULL;
00194         char *_set = NULL;
00195         char *_separator = NULL;
00196         while (StrSplit(_columns,',',_1column)) {
00197                 StrCat(_set,3,_separator,_1column," = NULL");
00198                 _separator = ", ";
00199                 };
00200         StrClause(_set,"SET");
00201         StrCpy(_columns,_right_prototype->KeySelect());
00202         StrFree(_1column);
00203         StrFree(_values);
00204         _values = right._KeyValues();
00205         StrFree(_1value);
00206         char *_where = NULL;
00207         _separator = "(";
00208         while (StrSplit(_columns,',',_1column) && StrSplit(_values,',',_1value)) {
00209                 StrPrefixCut(_1column,'.');
00210                 StrCat(_where,4,_separator,_1column," = ",_1value);
00211                 _separator = ") AND (";
00212                 };
00213         StrCat(_where,")");
00214         StrClause(_where,"WHERE");
00215         StrFree(_columns);
00216         StrFree(_1column);
00217         StrFree(_values);
00218         StrFree(_1value);
00219         StrCat(_update,2,_set,_where);
00220         StrFree(_set);
00221         StrFree(_where);
00222         if (_databaseConnection == NULL)
00223                 throw ObjLibException_ConnectionError();
00224         _retval = _databaseConnection -> _Sql(_update);
00225         StrFree(_update);
00226         return _retval;
00227 };
00228 
00229 bool OneToManyRelationBase::RDeleteAll(class RefBase &left)
00230         //Deletes all couples <LastLeft, X>
00231 {
00232         if (left.IsTransient())
00233                 return false;
00234         ProtoBase *_right_prototype=Class[_rightClassName];
00235 
00236         //UPDATE RTAB SET REL_KEY = NULL WHERE REL_KEY = LKEY
00237 
00238         bool _retval;
00239         char *_update = StrCpy(_update = NULL, _right_prototype -> From());
00240         StrClause(_update,"UPDATE");
00241         char *_columns = StrCpy(_columns = NULL, _leftColumnName);
00242         char *_1column = NULL;
00243         char *_values = NULL;
00244         char *_1value = NULL;
00245         char *_set = NULL;
00246         char *_separator = NULL;
00247         while (StrSplit(_columns,',',_1column)) {
00248                 StrCat(_set,3,_separator,_1column," = NULL");
00249                 _separator = ", ";
00250                 };
00251         StrClause(_set,"SET");
00252         StrCpy(_columns,_leftColumnName);
00253         StrFree(_1column);
00254         StrFree(_values);
00255         _values = left._KeyValues();
00256         StrFree(_1value);
00257         char *_where = NULL;
00258         _separator = "(";
00259         while (StrSplit(_columns,',',_1column) && StrSplit(_values,',',_1value)) {
00260                 StrPrefixCut(_1column,'.');
00261                 StrCat(_where,4,_separator,_1column," = ",_1value);
00262                 _separator = ") AND (";
00263                 };
00264         StrCat(_where,")");
00265         StrClause(_where,"WHERE");
00266         StrFree(_columns);
00267         StrFree(_1column);
00268         StrFree(_values);
00269         StrFree(_1value);
00270         StrCat(_update,2,_set,_where);
00271         StrFree(_set);
00272         StrFree(_where);
00273         if (_databaseConnection == NULL)
00274                 throw ObjLibException_ConnectionError();
00275         _retval = _databaseConnection -> _Sql(_update);
00276         StrFree(_update);
00277         return _retval;
00278 };
00279 
00280 ResultBase *OneToManyRelationBase::_LGetAll(
00281         ResultBase *rb,
00282         const class RefBase &right,
00283         const class QueRefProto &query
00284         )
00285 //Gets all objects connected to object "right"
00286 {
00287         #ifdef GC_REL1N_TRACE
00288         logmsg("OneToManyRelationBase::LGetAll(...) invoked");
00289         #endif
00290 
00291         if (right.IsTransient())
00292                 return NULL;
00293         ProtoBase *_left_prototype=Class[_leftClassName];
00294         ProtoBase *_right_prototype=Class[_rightClassName];
00295         RefBase r = right;
00296 
00297         //SELECT REL_lKEY INTO :lVAR FROM lALL, rTAB WHERE ...
00298 
00299         char *_Select = StrCpy(_Select=NULL,_leftColumnName);
00300         char *_Columns = StrCpy(
00301                 _Columns=NULL,
00302                 _left_prototype->KeySelect()
00303                 );
00304         char *_Values = r._KeyValues();
00305         char *_1Select = NULL;
00306         char *_1Column = NULL;
00307         char *_1Value = NULL;
00308         char *_JoinCondition = NULL;
00309         char *_KeyCondition = NULL;
00310         char *_Separator = "(";
00311         char *_Alias = NULL;    //table name containing relation column(s)
00312                                                                 // including alias
00313         while (
00314                 StrSplit(_Select,',',_1Select)
00315                 && StrSplit(_Columns,',',_1Column)
00316                 ) {
00317                 StrCat(_JoinCondition,6,_Separator,_tableName,".",_1Select," = ",_1Column);
00318                 _Separator = ") AND (";
00319                 };
00320         StrCat(_JoinCondition,")");
00321         StrFree(_Select);
00322         StrFree(_Columns);
00323         StrFree(_1Select);
00324         StrFree(_1Column);
00325 
00326         _Select = StrCpy(_Select,_right_prototype->KeySelect());
00327         _Separator = "(";
00328 
00329         while (
00330                 StrSplit(_Select,',',_1Select)
00331                 && StrSplit(_Values,',',_1Value)
00332                 ) {
00333                 StrPrefixCut(_1Select,'.');
00334                 StrCat(_KeyCondition,6,_Separator,_tableName,".",_1Select," = ",_1Value);
00335                 _Separator = ") AND (";
00336                 };
00337         StrCat(_KeyCondition,")");
00338         StrFree(_Select);
00339         StrFree(_Values);
00340         StrFree(_1Select);
00341         StrFree(_1Value);
00342 
00343         StrAnd(_JoinCondition,_KeyCondition);
00344         StrFree(_KeyCondition);
00345 
00346         ComplexQuery CQ(
00347                 _JoinCondition, //No additional condition
00348                 NULL,
00349                 _leftColumnName, //select different columns (foreign key)
00350                 StrCat(_Alias,3,_right_prototype->From()," ",_tableName) //additional table in query
00351                 );
00352         CQ.And(query);
00353         CQ._order_by = query._OrderBy();
00354 
00355         rb = _left_prototype->ExecuteQuery(CQ,_databaseConnection,1,rb);
00356 
00357         #ifdef GC_REL1N_TRACE
00358         logmsg("OneToManyRelationBase::LGetAll() finished");
00359         #endif
00360 
00361         return rb;
00362 };
00363 
00364 ResultBase *OneToManyRelationBase::_RGetAll(
00365         ResultBase *rb,
00366         const class RefBase &left,
00367         const class QueRefProto &query
00368         )
00369 //Gets all objects connected to object "left"
00370 {
00371         #ifdef GC_REL1N_TRACE
00372         logmsg("OneToManyRelationBase::RGetAll(...) invoked");
00373         #endif
00374 
00375         if (left.IsTransient())
00376                 return NULL;
00377         ProtoBase *_right_prototype=Class[_rightClassName];
00378         RefBase l = left;
00379 
00380         //SELECT rKEY INTO :rVAR FROM rALL WHERE ...
00381 
00382         char *_Columns = StrCpy(
00383                 _Columns=NULL,
00384                 _leftColumnName
00385                 );
00386         char *_Values = l._KeyValues();
00387         char *_1Column = NULL;
00388         char *_1Value = NULL;
00389         char *_KeyCondition = NULL;
00390         char *_Separator = "(";
00391 
00392         while (
00393                 StrSplit(_Columns,',',_1Column)
00394                 && StrSplit(_Values,',',_1Value)
00395                 ) {
00396                 StrCat(_KeyCondition,4,_Separator,_1Column," = ",_1Value);
00397                 _Separator = ") AND (";
00398                 };
00399         StrCat(_KeyCondition,")");
00400         StrFree(_Columns);
00401         StrFree(_Values);
00402         StrFree(_1Column);
00403         StrFree(_1Value);
00404 
00405         ComplexQuery CQ(
00406                 _KeyCondition, //additional condition
00407                 NULL,
00408                 NULL, //select standard columns
00409                 NULL  //No additional tables in query
00410                 );
00411         CQ.And(query);
00412 
00413         CQ._order_by = query._OrderBy();
00414 
00415         rb = _right_prototype -> ExecuteQuery(CQ,_databaseConnection,1,rb);
00416 
00417         #ifdef GC_REL1N_TRACE
00418         logmsg("OneToManyRelationBase::RGetAll() finished");
00419         #endif
00420 
00421         return rb;
00422 };
00423 
00424 bool OneToManyRelationBase::ExistsCouple(
00425                 const class RefBase &left,
00426                 const class RefBase &right
00427         )
00428 //Tests if exists relation between the given objects
00429 {
00430 // SELECT 0
00431 // FROM RIGHT_TABLE
00432 // WHERE (KEY = RIGHT.VAL) AND (LEFT_KEY = LEFT.VAL)
00433 
00434         bool _retval = false;
00435         ProtoBase *_right_prototype=Class[_rightClassName];
00436         RefBase l = left;
00437         RefBase r = right;
00438         int _sql_result_buffer = 0;
00439 
00440         if (left.IsTransient() || right.IsTransient())
00441                 return false;
00442         char *_select = StrCpy(_select = NULL, "0");
00443         StrClause(_select,"SELECT");
00444         char *_from = StrCpy(_from = NULL, _right_prototype->From());
00445         StrClause(_from, "FROM");
00446         char *_1column = NULL;
00447         char *_columns = StrCpy(_columns = NULL, _right_prototype->KeySelect());
00448         StrCat(_columns,2,", ",_leftColumnName);
00449         char *_1value = NULL;
00450         char *_values = r._KeyValues();
00451         StrCat(_values,2,", ",_1value = l._KeyValues());
00452         StrFree(_1value); //temporary used to hold all right values
00453         char *_where = NULL;
00454         char *_separator = "(";
00455         while (StrSplit(_columns,',',_1column) && StrSplit(_values,',',_1value)) {
00456                 StrPrefixCut(_1column,'.');
00457                 StrCat(_where,4,_separator,_1column," = ",_1value);
00458                 _separator = ") AND (";
00459                 };
00460         StrCat(_where,")");
00461         StrClause(_where,"WHERE");
00462         StrFree(_columns);
00463         StrFree(_1column);
00464         StrFree(_values);
00465         StrFree(_1value);
00466         StrCat(_select,2,_from,_where);
00467         StrFree(_from);
00468         StrFree(_where);
00469         if (_databaseConnection == NULL)
00470                 throw ObjLibException_ConnectionError();
00471         if (_databaseConnection -> _Open())
00472                 {
00473                 if (_databaseConnection -> _Prepare(_select))
00474                         {
00475                         if (_databaseConnection -> _Execute())
00476                                 {
00477                                 if (_databaseConnection -> _PreFetchBind(
00478                                                 1,
00479                                                 &_sql_result_buffer,
00480                                                 0,
00481                                                 'i'
00482                                                 )
00483                                         )
00484                                         {
00485                                         if (_databaseConnection -> _FetchNext())
00486                                                 {
00487                                                 _retval = true;
00488                                                 };
00489                                         };
00490                                 };
00491                         };
00492                 _databaseConnection -> _Close();
00493                 };
00494         StrFree(_select);
00495         return _retval;
00496 };
00497 
00498 /*
00499 ManyToOneRelation OneToManyRelationBase::operator -() const
00500 //Returns inverse relation
00501 {
00502         return ManyToOneRelation(_right_prototype, _left_prototype, _table_name,
00503         _databaseConnection , _rightColumnName, _leftColumnName);
00504 };
00505 */
00506 
00507 /*
00508 OneToManyRelationBase &OneToManyRelationBase::operator =(const OneToManyRelationBase &const R)
00509 //Returns copy of relation
00510 {
00511         if (this != &R) {
00512         _left_prototype = R._left_prototype;
00513         _right_prototype = R._right_prototype;
00514         StrCpy(_table_name,R._table_name);
00515         _databaseConnection = R._databaseConnection;
00516         StrCpy(_leftColumnName,R._leftColumnName);
00517         StrCpy(_rightColumnName,R._rightColumnName);
00518         };
00519         return *this;
00520 };
00521 */
00522 
00523 const char *OneToManyRelationBase::_TableName() const {
00524         return Class[_rightClassName]->From();
00525         };
00526 // Returns a table name, where both sets of foreign keys are
00527 // it is NOT a _table_name column for all types of relations!
00528 
00529 bool OneToManyRelationBase::WriteDDL(ofstream &S, class Database &Db)
00530 // generates DDL stements nedded for the library to run
00531 {
00532         if (!S.rdbuf()->is_open())
00533                 return false;
00534         ProtoBase *_left_prototype=Class[_leftClassName];
00535         ProtoBase *_right_prototype=Class[_rightClassName];
00536         char *_pk = NULL;
00537         char *_pk1 = NULL;
00538         char *_pklt = NULL;
00539         char *_fk = NULL;
00540         char *_fk1 = NULL;
00541         char *_fklt = NULL;
00542         char *typ = NULL;
00543         int c;
00544         const char *delimcols = "";
00545         const char *delimkeys = "";
00546         S << "-- One to many relation " << _tableName << " between classes " << _leftClassName << " and " << _rightClassName << endl;
00547 
00548         // Begin of alter table statement
00549         S << "ALTER TABLE " << _right_prototype->From() << " ADD(";
00550         // Left columns
00551         c = 0;
00552         StrCpy(_pk,_left_prototype->KeySelect());
00553         StrCpy(_fk,_leftColumnName);
00554         delimkeys = "";
00555         while (StrSplit(_fk,',',_fk1) && StrSplit(_pk,',',_pk1))
00556         {
00557                 StrPrefixCut(_pk1,'.');
00558                 StrPrefixCut(_fk1,'.');
00559                 StrCat(_pklt,2,delimkeys,_pk1);
00560                 StrCat(_fklt,2,delimkeys,_fk1);
00561                 delimkeys = ",";
00562                 typ = _left_prototype->ColumnTypeDDL(c,Db);
00563                 S << delimcols << endl << _fk1 << " " << typ;
00564                 StrFree(typ);
00565                 delimcols = ",";
00566                 c++;
00567         };
00568         StrFree(_pk);
00569         StrFree(_pk1);
00570         StrFree(_fk);
00571         StrFree(_fk1);
00572         // Foreign keys
00573         S << delimcols << endl << "CONSTRAINT " << _tableName << "_FK_L FOREIGN KEY(" << _fklt << ") REFERENCES " << _left_prototype->From() << "(" << _pklt << ")";
00574         delimcols = ",";
00575         // End of alter table statement
00576         S << endl << ");"<< endl << endl;
00577         // Reverse index (left and right columns swapped)
00578         S << "CREATE INDEX " << _tableName << "_RK_L ON " << _right_prototype->From() << "(" << _fklt << ");" << endl << endl;
00579         S.flush();
00580         StrFree(_pklt);
00581         StrFree(_fklt);
00582         return true;
00583 };

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