00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include <lTrace.h>
00017 #include <lDefs.h>
00018
00019
00020
00021 #include <cManyToManyRelationBase.h>
00022
00023
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
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
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
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
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,
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
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,
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
00381 {
00382
00383
00384
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);
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
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
00473 S << "CREATE TABLE " << _tableName << "(";
00474
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
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
00519 S << delimcols << endl << "CONSTRAINT " << _tableName << "_PK PRIMARY KEY(" << _fklt << "," << _fkrt << ")";
00520 delimcols = ",";
00521
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
00526
00527 S << endl << ");"<< endl << endl;
00528
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