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

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

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