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 #include <cChainedRelationBase.h>
00021
00022
00023 #include <cRefBase.h>
00024 #include <cClassRegister.h>
00025 #include <cComplexQuery.h>
00026 #include <cConnection.h>
00027
00028 ChainedRelationBase::ChainedRelationBase(
00029 const char *a_left_class_name,
00030 const char *a_right_class_name,
00031 const char *a_table_name,
00032 class Connection *a_database_connection,
00033 const char *a_leftColumnName,
00034 const char *a_rightColumnName,
00035 const char *a_inner_columns,
00036 const int a_relnum,
00037 const int a_qnum,
00038 const class Query &a_left_query,
00039 const class Query &a_right_query
00040 ) :
00041 Relation(
00042 a_left_class_name,
00043 a_right_class_name,
00044 a_table_name,
00045 a_database_connection,
00046 a_leftColumnName,
00047 a_rightColumnName
00048 ),
00049 _left_query(a_left_query),
00050 _right_query(a_right_query)
00051 {
00052 _inner_columns = StrCpy(_inner_columns = NULL,a_inner_columns);
00053 _relnum = a_relnum;
00054 _qnum = a_qnum;
00055 };
00056
00057 ChainedRelationBase::ChainedRelationBase(
00058 const ChainedRelationBase &X,
00059 const ChainedRelationBase &Y
00060 ) :
00061 Relation(
00062 X._leftClassName,
00063 Y._rightClassName,
00064 NULL,
00065 X._databaseConnection ? X._databaseConnection : Y._databaseConnection,
00066 X._leftColumnName,
00067 NULL
00068 ),
00069 _left_query(X._left_query),
00070 _right_query(Y._right_query)
00071 {
00072
00073
00074 class ProtoBase *M1 = Class[X._rightClassName];
00075 class ProtoBase *M2 = Class[Y._leftClassName];
00076 class ProtoBase *ancestor = NULL;
00077
00078 if ((*M1)<=(*M2))
00079 ancestor = M1;
00080 else if ((*M2)<=(*M1))
00081 ancestor = M2;
00082 else
00083 throw ObjLibException_NotSupported();
00084
00085
00086
00087 char *_right_col_name=NULL;
00088 char *_inner_tabs=NULL;
00089 char *_inner_cols=NULL;
00090
00091 int any_query_on_join = (X._right_query._where || Y._left_query._where) ? 1 : 0;
00092
00093
00094 StrCpy(_right_col_name, Y._rightColumnName);
00095 RealiasR(_right_col_name,1,Y._relnum,X._relnum);
00096
00097
00098 StrCat(_inner_tabs,Y._tableName);
00099 RealiasR(_inner_tabs,1,Y._relnum,X._relnum);
00100
00101 RealiasQ(_inner_tabs,2,Y._qnum+1,X._qnum+any_query_on_join);
00102
00103 if (any_query_on_join)
00104 {
00105 char *q_tables = ancestor->FullFrom(X._qnum+2);
00106 StrAddPrefix(_inner_tabs,q_tables,",");
00107 StrFree(q_tables);
00108 };
00109 StrAddPrefix(_inner_tabs,X._tableName,", ");
00110
00111
00112
00113 char *_Join = NULL;
00114 char *_JoinL = StrCpy(_JoinL=NULL, X._rightColumnName);
00115 char *_JoinR = StrCpy(_JoinR=NULL, Y._leftColumnName);
00116 RealiasR(_JoinR,1,Y._relnum,X._relnum);
00117
00118 StrCpy(_inner_cols,X._inner_columns);
00119 if (any_query_on_join == 0)
00120 {
00121 StrMergeLists(_Join,_JoinL,_JoinR,',',"("," = ",") AND (",")");
00122 StrAndOnly(_inner_cols,_Join);
00123 StrFree(_Join);
00124 }
00125 else
00126 {
00127 char *key = StrCpy(key = NULL, ancestor->KeySelect());
00128 ancestor->_RealiasT(key,X._qnum+2);
00129 StrMergeLists(_Join,_JoinL,key,',',"("," = ",") AND (",")");
00130 StrAndOnly(_inner_cols,_Join);
00131 StrFree(_Join);
00132
00133 key = ancestor->FullWhere(X._qnum+2);
00134 StrAndOnly(_inner_cols,key);
00135 StrFree(key);
00136
00137 Query ancest_query(X._right_query && Y._left_query);
00138 key = (ancestor->_TranslateToSql(ancest_query))._Where();
00139 ancestor->_RealiasT(key,X._qnum+2);
00140 if (key)
00141 {
00142 StrCat(_inner_cols,3," AND (",key,")");
00143 StrFree(key);
00144 }
00145
00146 key = StrCpy(key = NULL, ancestor->KeySelect());
00147 ancestor->_RealiasT(key,X._qnum+2);
00148 StrMergeLists(_Join,key,_JoinR,',',"("," = ",") AND (",")");
00149 StrAndOnly(_inner_cols,_Join);
00150 StrFree(_Join);
00151 }
00152
00153 if (Y._inner_columns!=NULL)
00154 {
00155 char * _right_inner_cols=StrCpy(_right_inner_cols=NULL,Y._inner_columns);
00156 RealiasR(_right_inner_cols,1,Y._relnum,X._relnum);
00157 RealiasQ(_right_inner_cols,2,Y._qnum+1,X._qnum+any_query_on_join);
00158 StrCat(_inner_cols,2," AND ", _right_inner_cols);
00159 StrFree(_right_inner_cols);
00160 }
00161
00162 _tableName = _inner_tabs;
00163 _rightColumnName = _right_col_name;
00164 _inner_columns = _inner_cols;
00165 _relnum = X._relnum + Y._relnum;
00166 _qnum = X._qnum + Y._qnum + any_query_on_join;
00167 };
00168
00169 ChainedRelationBase::ChainedRelationBase(
00170 ProtoBase &X,
00171 ProtoBase &Y
00172 ) :
00173 Relation(
00174 X.ClassName(),
00175 Y.ClassName(),
00176 NULL,
00177 NULL,
00178 NULL,
00179 NULL
00180 ),
00181 _left_query(EQUERY),
00182 _right_query(EQUERY)
00183 {
00184 char *_alias1 = AliasR(1);
00185 char *_alias2 = AliasR(2);
00186 StrCat(_tableName,7,X.From()," ",_alias1,",",Y.From()," ",_alias2);
00187 char *_cols_lt = StrCpy(X.KeySelect());
00188 char *_cols_rt = StrCpy(Y.KeySelect());
00189 char *_col1_lt = NULL;
00190 char *_col1_rt = NULL;
00191 const char *delimcol="";
00192 const char *delimcond="";
00193 _inner_columns = NULL;
00194 while (StrSplit(_cols_lt,',',_col1_lt) && StrSplit(_cols_rt,',',_col1_rt))
00195 {
00196 StrPrefixCut(_col1_lt,'.');
00197 StrPrefixCut(_col1_rt,'.');
00198 StrCat(_leftColumnName,4,delimcol,_alias1,".",_col1_lt);
00199 StrCat(_rightColumnName,4,delimcol,_alias2,".",_col1_lt);
00200 delimcol=",";
00201 StrCat(_inner_columns,8,delimcond,_alias1,",",_col1_lt,"=",_alias2,",",_col1_rt);
00202 delimcond=" AND ";
00203 };
00204 StrFree(_alias1);
00205 StrFree(_alias2);
00206 StrFree(_cols_lt);
00207 StrFree(_cols_rt);
00208 StrFree(_col1_lt);
00209 StrFree(_col1_rt);
00210 _relnum = 2;
00211 _qnum = 0;
00212 };
00213
00214 ChainedRelationBase::~ChainedRelationBase()
00215
00216 {
00217 StrFree(_inner_columns);
00218 };
00219
00220 ResultBase *ChainedRelationBase::_RGetAll(
00221 ResultBase *rb,
00222 const class RefBase &left,
00223 const class QueRefProto &query
00224 )
00225
00226 {
00227 ProtoBase *_left_prototype=Class[_leftClassName];
00228 ProtoBase *_right_prototype=Class[_rightClassName];
00229 RefBase l = left;
00230
00231 #ifdef C_CHAINEDRELATION_TRACE
00232 logmsg("ChainedRelationBase::RGetAll(...) invoked");
00233 #endif
00234
00235 if (left.IsTransient())
00236 return NULL;
00237
00238 char *_Select = StrCpy(_Select=NULL,_rightColumnName);
00239 char *_Columns = StrCpy(
00240 _Columns=NULL,
00241 _right_prototype->KeySelect()
00242 );
00243 _right_prototype->_RealiasT(_Columns,1);
00244 char *_Values = l._KeyValues();
00245 char *_JoinCondition = NULL;
00246 char *_KeyCondition = NULL;
00247
00248 StrMergeLists(_JoinCondition,_Select,_Columns,',',"("," = ",") AND (",")");
00249
00250 _Select = StrCpy(_Select,_leftColumnName);
00251
00252 StrMergeLists(_KeyCondition,_Select,_Values,',',"("," = ",") AND (",")");
00253
00254 StrCat(_JoinCondition,2," AND ",_inner_columns);
00255
00256 StrAnd(_JoinCondition,_KeyCondition);
00257 StrFree(_KeyCondition);
00258
00259
00260 ComplexQuery CQ(
00261 _JoinCondition,
00262 NULL,
00263 NULL,
00264 _tableName
00265 );
00266 CQ.And(query);
00267 char *_order = query._OrderBy();
00268 _left_prototype->_RealiasT(_order,1);
00269 CQ._order_by = _order;
00270
00271 StrFree(_JoinCondition);
00272
00273 rb = _right_prototype -> ExecuteQuery(CQ,_databaseConnection,1,rb);
00274
00275 #ifdef C_CHAINEDRELATION_TRACE
00276 logmsg("ChainedRelationBase::RGetAll() finished");
00277 #endif
00278
00279 return rb;
00280 };
00281
00282 ResultBase *ChainedRelationBase::_LGetAll(
00283 ResultBase *rb,
00284 const class RefBase &right,
00285 const class QueRefProto &query
00286 )
00287
00288 {
00289 ProtoBase *_left_prototype=Class[_leftClassName];
00290 ProtoBase *_right_prototype=Class[_rightClassName];
00291 RefBase r = right;
00292
00293 #ifdef C_CHAINEDRELATION_TRACE
00294 logmsg("ChainedRelationBase::LGetAll(...) invoked");
00295 #endif
00296
00297
00298 if (right.IsTransient())
00299 return NULL;
00300
00301 char *_Select = StrCpy(_Select=NULL,_leftColumnName);
00302 char *_Columns = StrCpy(
00303 _Columns=NULL,
00304 _left_prototype->KeySelect()
00305 );
00306 _left_prototype->_RealiasT(_Columns,1);
00307 char *_Values = r._KeyValues();
00308 char *_JoinCondition = NULL;
00309 char *_KeyCondition = NULL;
00310
00311 StrMergeLists(_JoinCondition,_Select,_Columns,',',"("," = ",") AND (",")");
00312
00313 StrCat(_JoinCondition,2," AND ",_inner_columns);
00314
00315 _Select = StrCpy(_Select,_rightColumnName);
00316
00317 StrMergeLists(_KeyCondition,_Select,_Values,',',"("," = ",") AND (",")");
00318
00319 StrAnd(_JoinCondition,_KeyCondition);
00320 StrFree(_KeyCondition);
00321
00322 ComplexQuery CQ(
00323 _JoinCondition,
00324 NULL,
00325 NULL,
00326 _tableName
00327 );
00328 CQ.And(query);
00329 char *_order = query._OrderBy();
00330 _left_prototype->_RealiasT(_order,1);
00331 CQ._order_by = _order;
00332
00333 StrFree(_JoinCondition);
00334
00335 rb = _left_prototype -> ExecuteQuery(CQ,_databaseConnection,1,rb);
00336
00337 #ifdef C_CHAINEDRELATION_TRACE
00338 logmsg("ChainedRelationBase::LGetAll() finished");
00339 #endif
00340
00341 return rb;
00342 };
00343
00344
00345 bool ChainedRelationBase::ExistsCouple(
00346 const class RefBase &left,
00347 const class RefBase &right
00348 )
00349 {
00350
00351
00352
00353
00354 bool _retval = false;
00355 int _sql_result_buffer = 0;
00356 ProtoBase *_left_prototype=Class[_leftClassName];
00357 ProtoBase *_right_prototype=Class[_rightClassName];
00358 RefBase l = left;
00359 RefBase r = right;
00360
00361 if (left.IsTransient() || right.IsTransient())
00362 return false;
00363 char *_select = StrCpy(_select = NULL, "0");
00364 StrClause(_select,"SELECT");
00365 char *_from = StrCpy(_from = NULL, _tableName);
00366 StrClause(_from, "FROM");
00367 char *_columns = StrCat(_columns = NULL, 3,
00368 _leftColumnName,
00369 ", ",
00370 _rightColumnName
00371 );
00372 char *_lvalues = l._KeyValues();
00373 char *_rvalues = r._KeyValues();
00374 _left_prototype->_RealiasT(_lvalues,1);
00375 _right_prototype->_RealiasT(_rvalues,2);
00376 StrCat(_lvalues,2,", ",_rvalues);
00377 StrFree(_rvalues);
00378 char *_where = NULL;
00379 StrMergeLists(_where,_columns,_lvalues,',',"("," = ",") AND (",")");
00380 StrAndOnly(_where,_inner_columns);
00381 StrClause(_where,"WHERE");
00382 StrCat(_select,2,_from,_where);
00383 StrFree(_from);
00384 StrFree(_where);
00385 if (_databaseConnection == NULL)
00386 throw ObjLibException_ConnectionError();
00387 if (_databaseConnection->_Open())
00388 {
00389 if (_databaseConnection->_Prepare(_select))
00390 {
00391 if (_databaseConnection->_Execute())
00392 {
00393 if (_databaseConnection->_PreFetchBind(
00394 1,
00395 &_sql_result_buffer,
00396 0,
00397 'i'
00398 )
00399 )
00400 {
00401 if (_databaseConnection->_FetchNext())
00402 {
00403 _retval = true;
00404 };
00405 };
00406 };
00407 };
00408 _databaseConnection -> _Close();
00409 };
00410 StrFree(_select);
00411 return _retval;
00412 };
00413
00415
00416 void ChainedRelationBase::_Init(
00417 const char *a_left_class_name,
00418 const char *a_right_class_name,
00419 const char *a_table_name,
00420 class Connection *a_database_connection,
00421 const char *a_left_column_name,
00422 const char *a_right_column_name,
00423 const char *a_inner_columns,
00424 const int a_relnum,
00425 const int a_qnum,
00426 const class Query &a_left_query,
00427 const class Query &a_right_query
00428 )
00429 {
00430 _leftClassName = a_left_class_name;
00431 _rightClassName = a_right_class_name;
00432 _databaseConnection = a_database_connection;
00433
00434 char *_alias = AliasR(1);
00435 _inner_columns=NULL;
00436
00437 char *_list = StrCpy(_list = NULL, a_left_column_name);
00438 char *_part = NULL;
00439 char *_res = NULL;
00440 char *_Separator = "";
00441 while (
00442 StrSplit(_list,',',_part)
00443 ) {
00444 StrPrefixCut(_part,'.');
00445 StrCat(_res,4,_Separator,_alias,".",_part);
00446 _Separator = ", ";
00447 };
00448 StrCpy(_leftColumnName,_res);
00449 StrFree(_list);
00450 StrFree(_part);
00451 StrFree(_res);
00452
00453
00454 _list = StrCpy(_list, a_right_column_name);
00455 _Separator = "";
00456 while (
00457 StrSplit(_list,',',_part)
00458 ) {
00459 StrPrefixCut(_part,'.');
00460 StrCat(_res,4,_Separator,_alias,".",_part);
00461 _Separator = ", ";
00462 };
00463 StrCpy(_rightColumnName,_res);
00464 StrFree(_list);
00465 StrFree(_part);
00466 StrFree(_res);
00467
00468
00469 StrCat(_tableName,3,a_table_name," ",_alias);
00470 StrFree(_alias);
00471 _inner_columns = NULL;
00472 _relnum = 1;
00473 _qnum = 0;
00474 };
00475
00476 ChainedRelationBase::ChainedRelationBase(const ChainedRelationBase &R):
00477 Relation(
00478 R._leftClassName,
00479 R._rightClassName,
00480 R._tableName,
00481 R._databaseConnection,
00482 R._leftColumnName,
00483 R._rightColumnName),
00484 _left_query(R._left_query),
00485 _right_query(R._right_query)
00486
00487 {
00488 StrCpy(_inner_columns = NULL,R._inner_columns);
00489 _relnum = R._relnum;
00490 _qnum = R._qnum;
00491 };
00492
00493 ResultBase * ChainedRelationBase::_LGetAll(
00494 ResultBase * rb,
00495 const class QueRefProto &qL,
00496 const class QueRefProto &qR
00497 )
00498
00499
00500 {
00501 ProtoBase *_left_prototype=Class[_leftClassName];
00502 ProtoBase *_right_prototype=Class[_rightClassName];
00503
00504 #ifdef C_CHAINEDRELATION_TRACE
00505 logmsg("ChainedRelationBase::LGetAll(qL,qR) invoked");
00506 #endif
00507
00508 char *_Select = NULL;
00509 char *_LColumns = StrCpy(_LColumns=NULL,_left_prototype->KeySelect());
00510 _left_prototype->_RealiasT(_LColumns,1);
00511 char *_RColumns = StrCpy(_RColumns=NULL,_right_prototype->KeySelect());
00512 _right_prototype->_RealiasT(_RColumns,_qnum+2);
00513 char *_RightCondition = NULL;
00514 char *_LeftCondition = NULL;
00515
00516 _Select = StrCpy(_Select,_rightColumnName);
00517 StrMergeLists(_RightCondition,_Select,_RColumns,',',"("," = ",") AND (",")");
00518
00519
00520 Query rquery(_right_query && qR);
00521 char * RWhere = _right_prototype->_TranslateToSql(rquery)._Where();
00522 _right_prototype->_RealiasT(RWhere,_qnum+2);
00523
00524
00525 char * temp=StrCpy(temp=NULL,_right_prototype->FullWhere(_qnum+2));
00526 StrAndOnly(_LeftCondition,_inner_columns);
00527 StrAndOnly(_LeftCondition,_RightCondition);
00528 StrAnd(temp,RWhere);
00529 StrFree(RWhere);
00530 StrAndOnly(_LeftCondition,temp);
00531 StrFree(temp);
00532 StrFree(_RightCondition);
00533
00534 char * Rtables=NULL;
00535 StrCat(Rtables,3,_tableName,", ",_right_prototype->FullFrom(_qnum+2));
00536
00537 StrCat(temp,9,
00538 "(",_LColumns,") IN ("
00539 " SELECT ",_leftColumnName,
00540 " FROM ",Rtables,
00541 " WHERE ",_LeftCondition,
00542 ")"
00543 );
00544 ComplexQuery CQ(
00545 temp,
00546 NULL,
00547 NULL,
00548 NULL
00549 );
00550 StrFree(temp);
00551 CQ.And(_left_query && qL);
00552 _left_prototype->_TranslateToSql(CQ);
00553 char *_order = qL._OrderBy();
00554 _left_prototype->_RealiasT(_order,1);
00555 CQ._order_by = _order;
00556
00557 StrFree(_LeftCondition);
00558 StrFree(Rtables);
00559
00560 rb = _left_prototype -> ExecuteQuery(CQ,_databaseConnection,1,rb);
00561
00562 #ifdef C_CHAINEDRELATION_TRACE
00563 logmsg("ChainedRelationBase::LGetAll(qL,qR) finished");
00564 #endif
00565
00566 return rb;
00567 };
00568
00569
00570
00571
00572 ResultBase * ChainedRelationBase::_RGetAll(
00573 ResultBase * rb,
00574 const class QueRefProto &qL,
00575 const class QueRefProto &qR
00576 )
00577
00578
00579 {
00580 ProtoBase *_left_prototype=Class[_leftClassName];
00581 ProtoBase *_right_prototype=Class[_rightClassName];
00582
00583 #ifdef C_CHAINEDRELATION_TRACE
00584 logmsg("ChainedRelationBase::RGetAll(qL,qR) invoked");
00585 #endif
00586
00587 char *_Select = NULL;
00588 char *_RColumns = StrCpy(_RColumns=NULL,_right_prototype->KeySelect());
00589 _right_prototype->_RealiasT(_RColumns,1);
00590 char *_LColumns = StrCpy(_LColumns=NULL,_left_prototype->KeySelect());
00591 _left_prototype->_RealiasT(_LColumns,_qnum+2);
00592 char *_RightCondition = NULL;
00593 char *_LeftCondition = NULL;
00594
00595 _Select = StrCpy(_Select,_leftColumnName);
00596 StrMergeLists(_LeftCondition,_Select,_LColumns,',',"("," = ",") AND (",")");
00597
00598
00599 Query lquery(_left_query && qL);
00600 char * LWhere = _left_prototype->_TranslateToSql(lquery)._Where();
00601 _left_prototype->_RealiasT(LWhere,_qnum+2);
00602
00603
00604 char * temp=StrCpy(temp=NULL,_left_prototype->FullWhere(_qnum+2));
00605 StrAndOnly(_RightCondition,_inner_columns);
00606 StrAndOnly(_RightCondition,_LeftCondition);
00607 StrAnd(temp,LWhere);
00608 StrFree(LWhere);
00609 StrAndOnly(_RightCondition,temp);
00610 StrFree(temp);
00611 StrFree(_LeftCondition);
00612
00613 char * Ltables=NULL;
00614 StrCat(Ltables,3,_tableName,", ",_left_prototype->FullFrom(_qnum+2));
00615
00616 StrCat(temp,9,
00617 "(",_RColumns,") IN ("
00618 " SELECT ",_rightColumnName,
00619 " FROM ",Ltables,
00620 " WHERE ",_RightCondition,
00621 ")"
00622 );
00623 ComplexQuery CQ(
00624 temp,
00625 NULL,
00626 NULL,
00627 NULL
00628 );
00629 StrFree(temp);
00630 CQ.And(_right_query && qR);
00631 _right_prototype->_TranslateToSql(CQ);
00632 char *_order = qR._OrderBy();
00633 _right_prototype->_RealiasT(_order,1);
00634 CQ._order_by = _order;
00635
00636 StrFree(_RightCondition);
00637 StrFree(Ltables);
00638
00639 rb = _right_prototype -> ExecuteQuery(CQ,_databaseConnection,1,rb);
00640
00641 #ifdef C_CHAINEDRELATION_TRACE
00642 logmsg("ChainedRelationBase::RGetAll(qL,qR) finished");
00643 #endif
00644
00645 return rb;
00646 };
00647
00648
00649 bool ChainedRelationBase::WriteDDL(ofstream &S, class Database &Db)
00650
00651 {
00652 return true;
00653 };