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

cManyToManyRelationBase.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 <cManyToManyRelationBase.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 ManyToManyRelationBase::ManyToManyRelationBase(
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,".L_",_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         {
00067                 StrCpy(_str,_right_prototype->KeySelect());
00068                 _separator = NULL;
00069                 while (StrSplit(_str,',',_column)) 
00070                 {
00071                         StrPrefixCut(_column,'.');
00072                         StrCat(_rightColumnName,4,_separator,_tableName,".R_",_column);
00073                         _separator = ", ";
00074                 };
00075         }
00076         else
00077                 StrCpy(_rightColumnName=NULL,a_right_column_name);
00078 
00079         StrFree(_str);
00080 };
00081 
00082 bool ManyToManyRelationBase::InsertCouple(RefBase &left, RefBase &right)
00083         //Inserts a couple <L, R> to the OMT-relation.
00084 {
00085         if (left.IsTransient() || right.IsTransient())
00086                 return false;
00087 
00088         bool _Retval;
00089         char *_insert = StrCpy(_insert = NULL, _tableName);
00090 
00091         StrClause(_insert,"INSERT INTO");
00092         StrCat(_insert,9,
00093                 "(",
00094                 _leftColumnName,", ",_rightColumnName,
00095                 ") VALUES (",
00096                 left._KeyValues(),", ",right._KeyValues(),
00097                 ")"
00098                 );
00099         if (_databaseConnection == NULL)
00100                 throw ObjLibException_ConnectionError();
00101         _Retval = _databaseConnection -> _Sql(_insert);
00102         StrFree(_insert);
00103         return _Retval;
00104 };
00105 
00106 bool ManyToManyRelationBase::DeleteCouple(RefBase &left, RefBase &right)
00107 {
00108         bool _retval;
00109         char *_delete = StrCpy(_delete = NULL, _tableName);
00110         char *_where = NULL;
00111         char *_columns = NULL;
00112         char *_1column = NULL;
00113         char *_values = NULL;
00114         char *_1value = NULL;
00115         char *_separator;
00116 
00117         StrClause(_delete,"DELETE FROM");
00118         _separator = "(";
00119         StrCat(_columns,3,_leftColumnName,",",_rightColumnName);
00120         StrCat(_values,3,left._KeyValues(),",",right._KeyValues());
00121         while (StrSplit(_columns,',',_1column) && StrSplit(_values,',',_1value)) {
00122                 StrCat(_where,4,_separator,_1column," = ",_1value);
00123                 _separator = ") AND (";
00124                 };
00125         StrCat(_where,")");
00126         StrFree(_columns);
00127         StrFree(_1column);
00128         StrFree(_values);
00129         StrFree(_1value);
00130         StrClause(_where,"WHERE");
00131         StrCat(_delete,_where);
00132         StrFree(_where);
00133         if (_databaseConnection == NULL)
00134                 throw ObjLibException_ConnectionError();
00135         _retval = _databaseConnection -> _Sql(_delete);
00136         StrFree(_delete);
00137         return _retval;
00138 };
00139 
00140 bool ManyToManyRelationBase::LDeleteAll(class RefBase &right)
00141         //Deletes all couples <X, LastRight>
00142 {
00143         bool _retval;
00144         if (right.IsTransient())
00145                 return false;
00146 
00147         char *_delete = StrCpy(_delete = NULL, _tableName);
00148         char *_where = NULL;
00149         char *_columns = StrCpy(_columns = NULL,_rightColumnName);
00150         char *_1column = NULL;
00151         char *_values = right._KeyValues();
00152         char *_1value = NULL;
00153         char *_separator;
00154 
00155         StrClause(_delete,"DELETE FROM");
00156         _separator = "(";
00157         while (StrSplit(_columns,',',_1column) && StrSplit(_values,',',_1value)) {
00158                 StrCat(_where,4,_separator,_1column," = ",_1value);
00159                 _separator = ") AND (";
00160                 };
00161         StrCat(_where,")");
00162         StrFree(_columns);
00163         StrFree(_1column);
00164         StrFree(_values);
00165         StrFree(_1value);
00166         StrClause(_where,"WHERE");
00167         StrCat(_delete,_where);
00168         StrFree(_where);
00169         if (_databaseConnection == NULL)
00170                 throw ObjLibException_ConnectionError();
00171         _retval = _databaseConnection -> _Sql(_delete);
00172         StrFree(_delete);
00173         return _retval;
00174 };
00175 
00176 bool ManyToManyRelationBase::RDeleteAll(class RefBase &left)
00177         //Deletes all couples <LastLeft, X>
00178 {
00179         if (left.IsTransient())
00180                 return false;
00181 
00182         bool _retval;
00183         char *_delete = StrCpy(_delete = NULL, _tableName);
00184         char *_where = NULL;
00185         char *_columns = StrCpy(_columns = NULL,_leftColumnName);
00186         char *_1column = NULL;
00187         char *_values = left._KeyValues();
00188         char *_1value = NULL;
00189         char *_separator;
00190 
00191         StrClause(_delete,"DELETE FROM");
00192         _separator = "(";
00193         while (StrSplit(_columns,',',_1column) && StrSplit(_values,',',_1value)) {
00194                 StrCat(_where,4,_separator,_1column," = ",_1value);
00195                 _separator = ") AND (";
00196                 };
00197         StrCat(_where,")");
00198         StrFree(_columns);
00199         StrFree(_1column);
00200         StrFree(_values);
00201         StrFree(_1value);
00202         StrClause(_where,"WHERE");
00203         StrCat(_delete,_where);
00204         StrFree(_where);
00205         if (_databaseConnection == NULL)
00206                 throw ObjLibException_ConnectionError();
00207         _retval = _databaseConnection -> _Sql(_delete);
00208         StrFree(_delete);
00209         return _retval;
00210 };
00211 
00212 ResultBase *ManyToManyRelationBase::_LGetAll(
00213         ResultBase *rb,
00214         const class RefBase &right,
00215         const class QueRefProto &query
00216         )
00217 //Gets all objects connected to object "right"
00218 {
00219         ProtoBase *_left_prototype = Class[_leftClassName];
00220         RefBase r = right;
00221 
00222         #ifdef GC_RELNN_TRACE
00223         logmsg("ManyToManyRelationBase::LGetAll(...) invoked");
00224         #endif
00225 
00226         if (right.IsTransient())
00227                 return NULL;
00228 
00229         char *_Select = StrCpy(_Select=NULL,_leftColumnName);
00230         char *_Columns = StrCpy(
00231                 _Columns=NULL,
00232                 _left_prototype->KeySelect()
00233                 );
00234         char *_Values = r._KeyValues();
00235         char *_1Select = NULL;
00236         char *_1Column = NULL;
00237         char *_1Value = NULL;
00238         char *_JoinCondition = NULL;
00239         char *_KeyCondition = NULL;
00240         char *_Separator = "(";
00241 
00242         while (
00243                 StrSplit(_Select,',',_1Select)
00244                 && StrSplit(_Columns,',',_1Column)
00245                 ) {
00246                 StrCat(_JoinCondition,4,_Separator,_1Select," = ",_1Column);
00247                 _Separator = ") AND (";
00248                 };
00249         StrCat(_JoinCondition,")");
00250         StrFree(_Select);
00251         StrFree(_Columns);
00252         StrFree(_1Select);
00253         StrFree(_1Column);
00254 
00255         _Select = StrCpy(_Select,_rightColumnName);
00256         _Separator = "(";
00257 
00258         while (
00259                 StrSplit(_Select,',',_1Select)
00260                 && StrSplit(_Values,',',_1Value)
00261                 ) {
00262                 StrCat(_KeyCondition,4,_Separator,_1Select," = ",_1Value);
00263                 _Separator = ") AND (";
00264                 };
00265         StrCat(_KeyCondition,")");
00266         StrFree(_Select);
00267         StrFree(_Values);
00268         StrFree(_1Select);
00269         StrFree(_1Value);
00270 
00271         StrAnd(_JoinCondition,_KeyCondition);
00272         StrFree(_KeyCondition);
00273 
00274         ComplexQuery CQ(
00275                 _JoinCondition,
00276                 NULL,
00277                 NULL, //select standard key columns
00278                 _tableName
00279                 );
00280         CQ.And(query);
00281         CQ._order_by = query._OrderBy();
00282 
00283         StrFree(_JoinCondition);
00284         rb = _left_prototype -> ExecuteQuery(CQ,_databaseConnection,1,rb);
00285 
00286         #ifdef GC_RELNN_TRACE
00287         logmsg("ManyToManyRelationBase::LGetAll() finished");
00288         #endif
00289 
00290         return rb;
00291 };
00292 
00293 ResultBase *ManyToManyRelationBase::_RGetAll(
00294         ResultBase *rb,
00295         const class RefBase &left,
00296         const class QueRefProto &query
00297         )
00298 //Gets all objects connected to object "left"
00299 {
00300         ProtoBase *_right_prototype = Class[_rightClassName];
00301         RefBase l = left;
00302 
00303         #ifdef GC_RELNN_TRACE
00304         logmsg("ManyToManyRelationBase::RGetAll(...) invoked");
00305         #endif
00306 
00307         if (left.IsTransient())
00308                 return NULL;
00309 
00310         char *_Select = StrCpy(_Select=NULL,_rightColumnName);
00311         char *_Columns = StrCpy(
00312                 _Columns=NULL,
00313                 _right_prototype->KeySelect()
00314                 );
00315         char *_Values = l._KeyValues();
00316         char *_1Select = NULL;
00317         char *_1Column = NULL;
00318         char *_1Value = NULL;
00319         char *_JoinCondition = NULL;
00320         char *_KeyCondition = NULL;
00321         char *_Separator = "(";
00322 
00323         while (
00324                 StrSplit(_Select,',',_1Select)
00325                 && StrSplit(_Columns,',',_1Column)
00326                 ) {
00327                 StrCat(_JoinCondition,4,_Separator,_1Select," = ",_1Column);
00328                 _Separator = ") AND (";
00329                 };
00330         StrCat(_JoinCondition,")");
00331         StrFree(_Select);
00332         StrFree(_Columns);
00333         StrFree(_1Select);
00334         StrFree(_1Column);
00335 
00336         _Select = StrCpy(_Select,_leftColumnName);
00337         _Separator = "(";
00338 
00339         while (
00340                 StrSplit(_Select,',',_1Select)
00341                 && StrSplit(_Values,',',_1Value)
00342                 ) {
00343                 StrCat(_KeyCondition,4,_Separator,_1Select," = ",_1Value);
00344                 _Separator = ") AND (";
00345                 };
00346         StrCat(_KeyCondition,")");
00347         StrFree(_Select);
00348         StrFree(_Values);
00349         StrFree(_1Select);
00350         StrFree(_1Value);
00351 
00352         StrAnd(_JoinCondition,_KeyCondition);
00353         StrFree(_KeyCondition);
00354 
00355 
00356         ComplexQuery CQ(
00357                 _JoinCondition,
00358                 NULL,
00359                 NULL, //select standard key columns
00360                 _tableName
00361                 );
00362         CQ.And(query);
00363         CQ._order_by = query._OrderBy();
00364 
00365         StrFree(_JoinCondition);
00366 
00367         rb = _right_prototype -> ExecuteQuery(CQ,_databaseConnection,1,rb);
00368 
00369         #ifdef GC_RELNN_TRACE
00370         logmsg("ManyToManyRelationBase::RGetAll() finished");
00371         #endif
00372 
00373         return rb;
00374 };
00375 
00376 bool ManyToManyRelationBase::ExistsCouple(
00377                 const class RefBase &left,
00378                 const class RefBase &right
00379         )
00380 //Tests if exists relation between the given objects
00381 {
00382 // SELECT 0
00383 // FROM RELATION_TABLE
00384 // WHERE (LEFT_KEY = LEFT.VAL) AND (RIGHT_KEY = RIGHT.VAL)
00385 
00386         bool _retval = false;
00387         RefBase l = left;
00388         RefBase r = right;
00389         int _sql_result_buffer = 0;
00390 
00391         if (left.IsTransient() || right.IsTransient())
00392                 return false;
00393         char *_select = StrCpy(_select = NULL, "0");
00394         StrClause(_select,"SELECT");
00395         char *_from = StrCpy(_from = NULL, _tableName);
00396         StrClause(_from, "FROM");
00397         char *_1column = NULL;
00398         char *_columns = StrCat(_columns = NULL, 3,
00399                 _leftColumnName,
00400                 ", ",
00401                 _rightColumnName
00402                 );
00403         char *_1value = NULL;
00404         char *_values = l._KeyValues();
00405         StrCat(_values,2,", ",_1value = r._KeyValues());
00406         StrFree(_1value); //temporary used to hold all right values
00407         char *_where = NULL;
00408         char *_separator = "(";
00409         while (StrSplit(_columns,',',_1column) && StrSplit(_values,',',_1value)) {
00410                 StrPrefixCut(_1column,'.');
00411                 StrCat(_where,4,_separator,_1column," = ",_1value);
00412                 _separator = ") AND (";
00413                 };
00414         StrCat(_where,")");
00415         StrClause(_where,"WHERE");
00416         StrFree(_columns);
00417         StrFree(_1column);
00418         StrFree(_values);
00419         StrFree(_1value);
00420         StrCat(_select,2,_from,_where);
00421         StrFree(_from);
00422         StrFree(_where);
00423         if (_databaseConnection == NULL)
00424                 throw ObjLibException_ConnectionError();
00425         if (_databaseConnection -> _Open())
00426                 {
00427                 if (_databaseConnection -> _Prepare(_select))
00428                         {
00429                         if (_databaseConnection -> _Execute())
00430                                 {
00431                                 if (_databaseConnection -> _PreFetchBind(
00432                                                 1,
00433                                                 &_sql_result_buffer,
00434                                                 0,
00435                                                 'i'
00436                                                 )
00437                                         )
00438                                         {
00439                                         if (_databaseConnection -> _FetchNext())
00440                                                 {
00441                                                 _retval = true;
00442                                                 };
00443                                         };
00444                                 };
00445                         };
00446                 _databaseConnection -> _Close();
00447                 };
00448         StrFree(_select);
00449         return _retval;
00450 };
00451 
00452 bool ManyToManyRelationBase::WriteDDL(ofstream &S, class Database &Db)
00453 // generates DDL stements nedded for the library to run
00454 {
00455         if (!S.rdbuf()->is_open())
00456                 return false;
00457         ProtoBase *_left_prototype=Class[_leftClassName];
00458         ProtoBase *_right_prototype=Class[_rightClassName];
00459         char *_pk = NULL;
00460         char *_pk1 = NULL;
00461         char *_pklt = NULL;
00462         char *_pkrt = NULL;
00463         char *_fk = NULL;
00464         char *_fk1 = NULL;
00465         char *_fklt = NULL;
00466         char *_fkrt = NULL;
00467         char *typ = NULL;
00468         int c;
00469         const char *delimcols = "";
00470         const char *delimkeys;
00471         S << "-- Many to many relation " << _tableName << " between classes " << _leftClassName << " and " << _rightClassName << endl;
00472         // Begin of create table statement
00473         S << "CREATE TABLE " << _tableName << "(";
00474         // Left columns
00475         c = 0;
00476         StrCpy(_pk,_left_prototype->KeySelect());
00477         StrCpy(_fk,_leftColumnName);
00478         delimkeys = "";
00479         while (StrSplit(_fk,',',_fk1) && StrSplit(_pk,',',_pk1))
00480         {
00481                 StrPrefixCut(_pk1,'.');
00482                 StrPrefixCut(_fk1,'.');
00483                 StrCat(_pklt,2,delimkeys,_pk1);
00484                 StrCat(_fklt,2,delimkeys,_fk1);
00485                 delimkeys = ",";
00486                 typ = _left_prototype->ColumnTypeDDL(c,Db);
00487                 S << delimcols << endl << _fk1 << " " << typ << " NOT NULL";
00488                 StrFree(typ);
00489                 delimcols = ",";
00490                 c++;
00491         };
00492         StrFree(_pk);
00493         StrFree(_pk1);
00494         StrFree(_fk);
00495         StrFree(_fk1);
00496         // Right columns
00497         c = 0;
00498         StrCpy(_pk,_right_prototype->KeySelect());
00499         StrCpy(_fk,_rightColumnName);
00500         delimkeys = "";
00501         while (StrSplit(_fk,',',_fk1) && StrSplit(_pk,',',_pk1))
00502         {
00503                 StrPrefixCut(_pk1,'.');
00504                 StrPrefixCut(_fk1,'.');
00505                 StrCat(_pkrt,2,delimkeys,_pk1);
00506                 StrCat(_fkrt,2,delimkeys,_fk1);
00507                 delimkeys = ",";
00508                 typ = _right_prototype->ColumnTypeDDL(c,Db);
00509                 S << delimcols << endl << _fk1 << " " << typ << " NOT NULL";
00510                 StrFree(typ);
00511                 delimcols = ",";
00512                 c++;
00513         };
00514         StrFree(_pk);
00515         StrFree(_pk1);
00516         StrFree(_fk);
00517         StrFree(_fk1);
00518         // Primary key
00519         S << delimcols << endl << "CONSTRAINT " << _tableName << "_PK PRIMARY KEY(" << _fklt << "," << _fkrt << ")";
00520         delimcols = ",";
00521         // Foreign keys
00522         S << delimcols << endl << "CONSTRAINT " << _tableName << "_FK_L FOREIGN KEY(" << _fklt << ") REFERENCES " << _left_prototype->From() << "(" << _pklt << ") ON DELETE CASCADE";
00523         delimcols = ",";
00524         S << delimcols << endl << "CONSTRAINT " << _tableName << "_FK_R FOREIGN KEY(" << _fkrt << ") REFERENCES " << _right_prototype->From() << "(" << _pkrt << ") ON DELETE CASCADE";
00525         //delimcols = ",";
00526         // End of create table statement
00527         S << endl << ");"<< endl << endl;
00528         // Reverse index (left and right columns swapped)
00529         S << "CREATE UNIQUE INDEX " << _tableName << "_RK ON " << _tableName << "(" << _fkrt << "," << _fklt << ");" << endl << endl;
00530         S.flush();
00531         StrFree(_pklt);
00532         StrFree(_pkrt);
00533         StrFree(_fklt);
00534         StrFree(_fkrt);
00535         return true;
00536 };
00537 

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