00001 // File and Version Information: 00002 // $Id: CdbNTupleAlgorithms.cc,v 1.5 2004/08/06 05:54:41 bartoldu Exp $ 00003 00004 /// The implementation of the CdbNTupleAlgorithms class. 00005 /** 00006 * @see CdbNTupleAlgorithms 00007 */ 00008 00009 #include "BaBar/BaBar.hh" 00010 00011 #include "CdbTable/CdbNTupleAlgorithms.hh" 00012 #include "CdbTable/CdbNTupleFactory.hh" 00013 #include "CdbTable/CdbNTupleIsLessComparator.hh" 00014 00015 #include <iostream> 00016 using std::cout; 00017 using std::endl; 00018 00019 /* 00020 * The obsolete interface and implementation of the algorithm 00021 * 00022 template < class T, unsigned int NCOL > 00023 CdbStatus 00024 CdbNTupleMerge( CdbCPtr<CdbNTuple<T,NCOL> >& theOutputPtr, 00025 const CdbCPtr<CdbNTuple<T,NCOL> >& thePrototypePtr, 00026 const CdbCPtr<CdbNTuple<T,NCOL> >& theExtraPtr ) 00027 { 00028 const char* errorStr = "CdbNTupleMerge<T,NCOL>(output,prototype,extra) - ERROR"; 00029 00030 if( thePrototypePtr.isNull( )) return CdbStatus::IllegalParameters; 00031 if( theExtraPtr.isNull( )) return CdbStatus::IllegalParameters; 00032 00033 // Create a clone of the "prototype" tuple and initialize the resulting 00034 // pointer with this clone. Upon the successfull completion of the algorithm 00035 // the output pointer will be repointed onto this new tuple. 00036 // 00037 // NOTE; This operation will automatically copy all metadata and rows 00038 // from the "prototype" into the resulting tuple. 00039 00040 CdbCPtr<CdbNTuple<T,NCOL> > resultPtr = thePrototypePtr->clone( ); 00041 00042 // Copy over rows from the "extra" tuple and append them by the end 00043 // of the "output" one. 00044 00045 unsigned int nRows = theExtraPtr->rows( ); 00046 for( unsigned int i = 0; i < nRows; ++i ) { 00047 00048 std::vector<T> row; 00049 if( CdbStatus::Success != theExtraPtr->get_row( row, i )) { 00050 cout << errorStr << endl 00051 << " Failed to read the row number " << i << " from the \"extra\" tuple." << endl; 00052 return CdbStatus::Error; 00053 } 00054 if( CdbStatus::Success != resultPtr->append_row( row )) { 00055 cout << errorStr << endl 00056 << " Failed to append the row number " << i << " read from the \"extra\" tuple" << endl 00057 << " by the end of the resulting tuple." << endl; 00058 return CdbStatus::Error; 00059 } 00060 } 00061 00062 // Repoint the "output" tuple to point onto the newely created 00063 // resulting tuple. 00064 00065 theOutputPtr = resultPtr; 00066 00067 return CdbStatus::Success; 00068 } 00069 * 00070 * There is a better implementation below. 00071 */ 00072 00073 template < class NTUPLE > 00074 CdbStatus 00075 CdbNTupleMerge( CdbCPtr<NTUPLE>& theOutputPtr, 00076 const CdbCPtr<NTUPLE>& thePrototypePtr, 00077 const CdbCPtr<NTUPLE>& theExtraPtr ) 00078 { 00079 const char* errorStr = "CdbNTupleMerge<NTUPLE>(output,prototype,extra) - ERROR"; 00080 00081 if( thePrototypePtr.isNull( )) return CdbStatus::IllegalParameters; 00082 if( theExtraPtr.isNull( )) return CdbStatus::IllegalParameters; 00083 00084 // Create a clone of the "prototype" tuple and initialize the resulting 00085 // pointer with this clone. Upon the successfull completion of the algorithm 00086 // the output pointer will be repointed onto this new tuple. 00087 // 00088 // NOTE; This operation will automatically copy all metadata and rows 00089 // from the "prototype" into the resulting tuple. 00090 00091 CdbCPtr<NTUPLE> resultPtr = thePrototypePtr->clone( ); 00092 00093 // Copy over rows from the "extra" tuple and append them by the end 00094 // of the "output" one. 00095 00096 unsigned int nRows = theExtraPtr->rows( ); 00097 for( unsigned int i = 0; i < nRows; ++i ) { 00098 00099 std::vector<typename NTUPLE::element_type> row; 00100 if( CdbStatus::Success != theExtraPtr->get_row( row, i )) { 00101 cout << errorStr << endl 00102 << " Failed to read the row number " << i << " from the \"extra\" tuple." << endl; 00103 return CdbStatus::Error; 00104 } 00105 if( CdbStatus::Success != resultPtr->append_row( row )) { 00106 cout << errorStr << endl 00107 << " Failed to append the row number " << i << " read from the \"extra\" tuple" << endl 00108 << " by the end of the resulting tuple." << endl; 00109 return CdbStatus::Error; 00110 } 00111 } 00112 00113 // Repoint the "output" tuple to point onto the newely created 00114 // resulting tuple. 00115 00116 theOutputPtr = resultPtr; 00117 00118 return CdbStatus::Success; 00119 } 00120 00121 /* 00122 * The obsolete interface and implementation of the algorithm 00123 * 00124 template < class T, unsigned int NCOL > 00125 CdbStatus 00126 CdbNTupleAppend( CdbCPtr<CdbNTuple<T,NCOL> >& theOutputPtr, 00127 const CdbCPtr<CdbNTuple<T,NCOL> >& theInputPtr ) 00128 { 00129 const char* errorStr = "CdbNTupleAppend<T,NCOL>(output,input) - ERROR"; 00130 00131 if( theOutputPtr.isNull( )) return CdbStatus::IllegalParameters; 00132 if( theInputPtr.isNull( )) return CdbStatus::IllegalParameters; 00133 00134 // Copy over rows from the "input" tuple and append them by the end 00135 // of the "output" one. 00136 00137 unsigned int nRows = theInputPtr->rows( ); 00138 for( unsigned int i =0; i < nRows; ++i ) { 00139 std::vector<T> row; 00140 if( CdbStatus::Success != theInputPtr->get_row( row, i )) { 00141 cout << errorStr << endl 00142 << " Failed to read the row number " << i << " from the \"input\" tuple." << endl; 00143 return CdbStatus::Error; 00144 } 00145 if( CdbStatus::Success != theOutputPtr->append_row( row )) { 00146 cout << errorStr << endl 00147 << " Failed to append the row number " << i << " read from the \"input\" tuple" << endl 00148 << " by the end of the \"output\" tuple." << endl; 00149 return CdbStatus::Error; 00150 } 00151 } 00152 00153 return CdbStatus::Success; 00154 } 00155 * 00156 * There is a better implementation below. 00157 */ 00158 00159 template < class NTUPLE > 00160 CdbStatus 00161 CdbNTupleAppend( CdbCPtr<NTUPLE >& theOutputPtr, 00162 const CdbCPtr<NTUPLE >& theInputPtr ) 00163 { 00164 const char* errorStr = "CdbNTupleAppend<NTUPLE>(output,input) - ERROR"; 00165 00166 if( theOutputPtr.isNull( )) return CdbStatus::IllegalParameters; 00167 if( theInputPtr.isNull( )) return CdbStatus::IllegalParameters; 00168 00169 // Copy over rows from the "input" tuple and append them by the end 00170 // of the "output" one. 00171 00172 unsigned int nRows = theInputPtr->rows( ); 00173 for( unsigned int i =0; i < nRows; ++i ) { 00174 std::vector<typename NTUPLE::element_type> row; 00175 if( CdbStatus::Success != theInputPtr->get_row( row, i )) { 00176 cout << errorStr << endl 00177 << " Failed to read the row number " << i << " from the \"input\" tuple." << endl; 00178 return CdbStatus::Error; 00179 } 00180 if( CdbStatus::Success != theOutputPtr->append_row( row )) { 00181 cout << errorStr << endl 00182 << " Failed to append the row number " << i << " read from the \"input\" tuple" << endl 00183 << " by the end of the \"output\" tuple." << endl; 00184 return CdbStatus::Error; 00185 } 00186 } 00187 00188 return CdbStatus::Success; 00189 } 00190 00191 /* 00192 * The obsolete interface and implementation of the algorithm 00193 * 00194 template < class T, unsigned int NCOL > 00195 CdbStatus 00196 CdbNTupleCopy( CdbCPtr<CdbNTuple<T,NCOL> >& theOutputTuple, 00197 const CdbCPtr<CdbNTuple<T,NCOL> >& theInputTuple ) 00198 { 00199 if( theInputTuple.isNull( )) return CdbStatus::IllegalParameters; 00200 00201 // Create a clone of the "input" tuple and repoint the "output" pointer 00202 // onto the clone. 00203 // 00204 // NOTE; This operation will automatically copy all metadata and rows 00205 // from the "input" into the "output" tuple. 00206 00207 theOutputTuple = theInputTuple->clone( ); 00208 00209 return CdbStatus::Success; 00210 } 00211 * 00212 * There is a better implementation below. 00213 */ 00214 00215 template < class NTUPLE > 00216 CdbStatus 00217 CdbNTupleCopy( CdbCPtr<NTUPLE>& theOutputTuple, 00218 const CdbCPtr<NTUPLE>& theInputTuple ) 00219 { 00220 if( theInputTuple.isNull( )) return CdbStatus::IllegalParameters; 00221 00222 // Create a clone of the "input" tuple and repoint the "output" pointer 00223 // onto the clone. 00224 // 00225 // NOTE; This operation will automatically copy all metadata and rows 00226 // from the "input" into the "output" tuple. 00227 00228 theOutputTuple = theInputTuple->clone( ); 00229 00230 return CdbStatus::Success; 00231 } 00232 00233 /* 00234 * The obsolete interface and implementation of the algorithm 00235 * 00236 template < class T, 00237 unsigned int NCOL_OUT, 00238 unsigned int NCOL_LEFT, 00239 unsigned int NCOL_RIGHT > 00240 CdbStatus 00241 CdbNTupleGlue_utility<T,NCOL_OUT,NCOL_LEFT,NCOL_RIGHT>::glue( CdbCPtr<CdbNTuple<T,NCOL_OUT> >& theOutputPtr, 00242 const CdbCPtr<CdbNTuple<T,NCOL_LEFT> >& theLeftPtr, 00243 const CdbCPtr<CdbNTuple<T,NCOL_RIGHT> >& theRightPtr, 00244 const bool allowRenamingOfColumnsFlag ) 00245 { 00246 const char* errorStr = "CdbNTupleGlue_utility<T,NCOL_OUT,NCOL_LEFT,NCOL_RIGHT>::glue(output,left,right) - ERROR"; 00247 const char* fatalStr = "CdbNTupleGlue_utility<T,NCOL_OUT,NCOL_LEFT,NCOL_RIGHT>::glue(output,left,right) - FATAL ERROR"; 00248 00249 if( NCOL_OUT != NCOL_LEFT + NCOL_RIGHT ) return CdbStatus::ConflictOfParameters; 00250 00251 if( theLeftPtr.isNull( )) return CdbStatus::IllegalParameters; 00252 if( theRightPtr.isNull( )) return CdbStatus::IllegalParameters; 00253 00254 // Check for the column names (in-)compatibility. 00255 00256 std::vector<std::string> outputColumnNames; 00257 { 00258 std::vector<std::string> leftColumnNames; 00259 theLeftPtr->column_names( leftColumnNames ); 00260 00261 std::vector<std::string> rightColumnNames; 00262 theRightPtr->column_names( rightColumnNames ); 00263 00264 outputColumnNames = leftColumnNames; 00265 00266 for( unsigned int right = 0; right < NCOL_RIGHT; ++right ) { 00267 00268 std::string rightName = rightColumnNames[right]; 00269 00270 if( CdbNTupleBase::is_system_name( rightName )) { 00271 00272 // That's a defaul t"system" name. Then we need to force its replacement 00273 // with the right default name regardeless of the mode the algorithm 00274 // is used. This is because "system" names of columns from the right tuple 00275 // would be unsuitable when these columns will "shifted" right. 00276 00277 rightName = CdbNTupleBase::default_column_name( NCOL_LEFT + right ); 00278 00279 } else { 00280 00281 // For regular names we should check for the duplicates. 00282 00283 for( unsigned int left = 0; left < NCOL_LEFT; ++left ) { 00284 00285 if( rightName == leftColumnNames[left] ) { 00286 00287 // Replace column names at a right column with the corresponding default 00288 // value for that position if a conflict with the naming of left columns 00289 // is found, and if the algorithm is allowed so. 00290 00291 if( allowRenamingOfColumnsFlag ) { 00292 rightName = CdbNTupleBase::default_column_name( NCOL_LEFT + right ); 00293 break; 00294 } else { 00295 return CdbStatus::ConflictOfParameters; 00296 } 00297 } 00298 } 00299 } 00300 outputColumnNames.push_back( rightName ); 00301 } 00302 } 00303 00304 // Create a resulting tuple, which will be returned back to a caller 00305 // upon the successfull completion of the algorithm. 00306 // 00307 // NOTE: We've commited not to modify the value of the "output" pointer 00308 // in case of any problems. 00309 00310 CdbCPtr< CdbNTuple< T, NCOL_OUT > > resultPtr = 00311 CdbNTupleFactory< T, NCOL_OUT >::createSimple( outputColumnNames, 00312 theLeftPtr->name( ), 00313 theLeftPtr->description( )); 00314 if( resultPtr.isNull( )) { 00315 00316 cout << fatalStr << endl 00317 << " Failed to create an output tuple using the \"simple\" factory method." << endl 00318 << " It can be either a memory management problem of the current application" << endl 00319 << " or improperly implemented hierarchy of N-Tupe classes." << endl; 00320 00321 assert( 0 ); 00322 00323 return CdbStatus::Error; 00324 } 00325 00326 // Copy over rows from the both input tuples and merge them into the output 00327 // one. Fill elements with default values (using default constructor of the 00328 // current element type) for shortest tuple. 00329 00330 unsigned int nLeftRows = theLeftPtr->rows( ); 00331 unsigned int nRightRows = theRightPtr->rows( ); 00332 unsigned int nOutputRows = ( nLeftRows > nRightRows ? nLeftRows : nRightRows ); 00333 00334 for( unsigned int i = 0; i < nOutputRows; ++ i ) { 00335 00336 std::vector<T> leftRow; 00337 { 00338 00339 if( i < nLeftRows ) { 00340 00341 // Get and check the width of a row from the left tuple 00342 00343 if( CdbStatus::Success != theLeftPtr->get_row( leftRow, i )) { 00344 cout << errorStr << endl 00345 << " Failed to read the row number " << i << " from the \"left\" tuple." << endl; 00346 return CdbStatus::Error; 00347 } 00348 if( NCOL_LEFT != leftRow.size( )) { 00349 00350 cout << fatalStr << endl 00351 << " The number of elements " << leftRow.size( ) << " in a vector returned" << endl 00352 << " from the \"left\" tuple when reading the row number " << i << " does not match" << endl 00353 << " the width of the tuple. The tuple is supposed to be " << NCOL_LEFT << " in width." << endl 00354 << " This can be a problem with the actual implementation of the tuple class." << endl; 00355 00356 assert( 0 ); 00357 00358 return CdbStatus::Error; 00359 } 00360 00361 } else { 00362 00363 // Fill that row with default values by resizing the vector 00364 // 00365 // NOTE: See the specifications for the std::vector class for details. 00366 00367 leftRow.resize( NCOL_LEFT ); 00368 } 00369 } 00370 00371 // Get and check the width of a row from the right tuple 00372 00373 std::vector<T> rightRow; 00374 { 00375 if( i < nRightRows ) { 00376 00377 // Get and check the width of a row from the right tuple 00378 00379 if( CdbStatus::Success != theRightPtr->get_row( rightRow, i )) { 00380 cout << errorStr << endl 00381 << " Failed to read the row number " << i << " from the \"right\" tuple." << endl; 00382 return CdbStatus::Error; 00383 } 00384 if( NCOL_RIGHT != rightRow.size( )) { 00385 00386 cout << fatalStr << endl 00387 << " The number of elements " << rightRow.size( ) << " in a vector returned" << endl 00388 << " from the \"right\" tuple when reading the row number " << i << " does not match" << endl 00389 << " the width of the tuple. The tuple is supposed to be " << NCOL_RIGHT << " in width." << endl 00390 << " This can be a problem with the actual implementation of the tuple class." << endl; 00391 00392 assert( 0 ); 00393 00394 return CdbStatus::Error; 00395 } 00396 00397 } else { 00398 00399 // Fill that row with default values by resizing the vector. 00400 // 00401 // NOTE: See the specifications for the std::vector class for details. 00402 00403 rightRow.resize( NCOL_RIGHT ); 00404 } 00405 } 00406 00407 // Write the merged row into the resulting tuple 00408 00409 std::vector<T> resultRow = leftRow; 00410 00411 resultRow.insert( resultRow.end( ), 00412 rightRow.begin( ), 00413 rightRow.end( )); 00414 00415 if( CdbStatus::Success != resultPtr->append_row( resultRow )) { 00416 cout << errorStr << endl 00417 << " Failed to append the row number " << i << " merged from both input tuples" << endl 00418 << " by the end of the \"output\" tuple." << endl; 00419 return CdbStatus::Error; 00420 } 00421 } 00422 00423 // Substitute the original "output" pointer with the above created resulting one. 00424 00425 theOutputPtr = resultPtr; 00426 00427 return CdbStatus::Success; 00428 } 00429 * 00430 * There is a better implementation below. 00431 */ 00432 00433 template < class NTUPLE_OUT, 00434 class NTUPLE_LEFT, 00435 class NTUPLE_RIGHT > 00436 CdbStatus 00437 CdbNTupleGlue( CdbCPtr<NTUPLE_OUT>& theOutputPtr, 00438 const CdbCPtr<NTUPLE_LEFT>& theLeftPtr, 00439 const CdbCPtr<NTUPLE_RIGHT>& theRightPtr, 00440 const bool allowRenamingOfColumnsFlag ) 00441 { 00442 const char* errorStr = "CdbNTupleGlue<NTUPLE_OUT,NTUPLE_LEFT,NTUPLE_RIGHT>(output,left,right) - ERROR"; 00443 const char* fatalStr = "CdbNTupleGlue<NTUPLE_OUT,NTUPLE_LEFT,NTUPLE_RIGHT>(output,left,right) - FATAL ERROR"; 00444 00445 if( NTUPLE_OUT::ncol != NTUPLE_LEFT::ncol + NTUPLE_RIGHT::ncol ) return CdbStatus::ConflictOfParameters; 00446 00447 if( theLeftPtr.isNull( )) return CdbStatus::IllegalParameters; 00448 if( theRightPtr.isNull( )) return CdbStatus::IllegalParameters; 00449 00450 // Check for the column names (in-)compatibility. 00451 00452 std::vector<std::string> outputColumnNames; 00453 { 00454 std::vector<std::string> leftColumnNames; 00455 theLeftPtr->column_names( leftColumnNames ); 00456 00457 std::vector<std::string> rightColumnNames; 00458 theRightPtr->column_names( rightColumnNames ); 00459 00460 outputColumnNames = leftColumnNames; 00461 00462 for( unsigned int right = 0; right < NTUPLE_RIGHT::ncol; ++right ) { 00463 00464 std::string rightName = rightColumnNames[right]; 00465 00466 if( CdbNTupleBase::is_system_name( rightName )) { 00467 00468 // That's a defaul t"system" name. Then we need to force its replacement 00469 // with the right default name regardeless of the mode the algorithm 00470 // is used. This is because "system" names of columns from the right tuple 00471 // would be unsuitable when these columns will "shifted" right. 00472 00473 rightName = CdbNTupleBase::default_column_name( NTUPLE_LEFT::ncol + right ); 00474 00475 } else { 00476 00477 // For regular names we should check for the duplicates. 00478 00479 for( unsigned int left = 0; left < NTUPLE_LEFT::ncol; ++left ) { 00480 00481 if( rightName == leftColumnNames[left] ) { 00482 00483 // Replace column names at a right column with the corresponding default 00484 // value for that position if a conflict with the naming of left columns 00485 // is found, and if the algorithm is allowed so. 00486 00487 if( allowRenamingOfColumnsFlag ) { 00488 rightName = CdbNTupleBase::default_column_name( NTUPLE_LEFT::ncol + right ); 00489 break; 00490 } else { 00491 return CdbStatus::ConflictOfParameters; 00492 } 00493 } 00494 } 00495 } 00496 outputColumnNames.push_back( rightName ); 00497 } 00498 } 00499 00500 // Create a resulting tuple, which will be returned back to a caller 00501 // upon the successfull completion of the algorithm. 00502 // 00503 // NOTE: We've commited not to modify the value of the "output" pointer 00504 // in case of any problems. 00505 00506 CdbCPtr< NTUPLE_OUT > resultPtr = 00507 CdbNTupleFactory< typename NTUPLE_OUT::element_type, NTUPLE_OUT::ncol >::createSimple( outputColumnNames, 00508 theLeftPtr->name( ), 00509 theLeftPtr->description( )); 00510 if( resultPtr.isNull( )) { 00511 00512 cout << fatalStr << endl 00513 << " Failed to create an output tuple using the \"simple\" factory method." << endl 00514 << " It can be either a memory management problem of the current application" << endl 00515 << " or improperly implemented hierarchy of N-Tupe classes." << endl; 00516 00517 assert( 0 ); 00518 00519 return CdbStatus::Error; 00520 } 00521 00522 // Copy over rows from the both input tuples and merge them into the output 00523 // one. Fill elements with default values (using default constructor of the 00524 // current element type) for shortest tuple. 00525 00526 unsigned int nLeftRows = theLeftPtr->rows( ); 00527 unsigned int nRightRows = theRightPtr->rows( ); 00528 unsigned int nOutputRows = ( nLeftRows > nRightRows ? nLeftRows : nRightRows ); 00529 00530 for( unsigned int i = 0; i < nOutputRows; ++ i ) { 00531 00532 std::vector<typename NTUPLE_LEFT::element_type> leftRow; 00533 { 00534 00535 if( i < nLeftRows ) { 00536 00537 // Get and check the width of a row from the left tuple 00538 00539 if( CdbStatus::Success != theLeftPtr->get_row( leftRow, i )) { 00540 cout << errorStr << endl 00541 << " Failed to read the row number " << i << " from the \"left\" tuple." << endl; 00542 return CdbStatus::Error; 00543 } 00544 if( NTUPLE_LEFT::ncol != leftRow.size( )) { 00545 00546 cout << fatalStr << endl 00547 << " The number of elements " << leftRow.size( ) << " in a vector returned" << endl 00548 << " from the \"left\" tuple when reading the row number " << i << " does not match" << endl 00549 << " the width of the tuple. The tuple is supposed to be " << NTUPLE_LEFT::ncol << " in width." << endl 00550 << " This can be a problem with the actual implementation of the tuple class." << endl; 00551 00552 assert( 0 ); 00553 00554 return CdbStatus::Error; 00555 } 00556 00557 } else { 00558 00559 // Fill that row with default values by resizing the vector 00560 // 00561 // NOTE: See the specifications for the std::vector class for details. 00562 00563 leftRow.resize( NTUPLE_LEFT::ncol ); 00564 } 00565 } 00566 00567 // Get and check the width of a row from the right tuple 00568 00569 std::vector<typename NTUPLE_RIGHT::element_type> rightRow; 00570 { 00571 if( i < nRightRows ) { 00572 00573 // Get and check the width of a row from the right tuple 00574 00575 if( CdbStatus::Success != theRightPtr->get_row( rightRow, i )) { 00576 cout << errorStr << endl 00577 << " Failed to read the row number " << i << " from the \"right\" tuple." << endl; 00578 return CdbStatus::Error; 00579 } 00580 if( NTUPLE_RIGHT::ncol != rightRow.size( )) { 00581 00582 cout << fatalStr << endl 00583 << " The number of elements " << rightRow.size( ) << " in a vector returned" << endl 00584 << " from the \"right\" tuple when reading the row number " << i << " does not match" << endl 00585 << " the width of the tuple. The tuple is supposed to be " << NTUPLE_RIGHT::ncol << " in width." << endl 00586 << " This can be a problem with the actual implementation of the tuple class." << endl; 00587 00588 assert( 0 ); 00589 00590 return CdbStatus::Error; 00591 } 00592 00593 } else { 00594 00595 // Fill that row with default values by resizing the vector. 00596 // 00597 // NOTE: See the specifications for the std::vector class for details. 00598 00599 rightRow.resize( NTUPLE_RIGHT::ncol ); 00600 } 00601 } 00602 00603 // Write the merged row into the resulting tuple 00604 00605 std::vector<typename NTUPLE_OUT::element_type> resultRow = leftRow; 00606 00607 resultRow.insert( resultRow.end( ), 00608 rightRow.begin( ), 00609 rightRow.end( )); 00610 00611 if( CdbStatus::Success != resultPtr->append_row( resultRow )) { 00612 cout << errorStr << endl 00613 << " Failed to append the row number " << i << " merged from both input tuples" << endl 00614 << " by the end of the \"output\" tuple." << endl; 00615 return CdbStatus::Error; 00616 } 00617 } 00618 00619 // Substitute the original "output" pointer with the above created resulting one. 00620 00621 theOutputPtr = resultPtr; 00622 00623 return CdbStatus::Success; 00624 } 00625 00626 ///////////////// 00627 // End Of File // 00628 /////////////////
1.3-rc3