|
NCBI C++ ToolKit
|
00001 /* $Id: dbapi_testspeed.cpp 53326 2012-03-08 17:02:40Z ivanovp $ 00002 * =========================================================================== 00003 * 00004 * PUBLIC DOMAIN NOTICE 00005 * National Center for Biotechnology Information 00006 * 00007 * This software/database is a "United States Government Work" under the 00008 * terms of the United States Copyright Act. It was written as part of 00009 * the author's official duties as a United States Government employee and 00010 * thus cannot be copyrighted. This software/database is freely available 00011 * to the public for use. The National Library of Medicine and the U.S. 00012 * Government have not placed any restriction on its use or reproduction. 00013 * 00014 * Although all reasonable efforts have been taken to ensure the accuracy 00015 * and reliability of the software and data, the NLM and the U.S. 00016 * Government do not and cannot warrant the performance or results that 00017 * may be obtained by using this software or data. The NLM and the U.S. 00018 * Government disclaim all warranties, express or implied, including 00019 * warranties of performance, merchantability or fitness for any particular 00020 * purpose. 00021 * 00022 * Please cite the author in any work or product based on this material. 00023 * 00024 * =========================================================================== 00025 * 00026 * File Description: 00027 * Run a series of insert/update/select statement, 00028 * measure the time required for their execution. 00029 * 00030 *============================================================================ 00031 */ 00032 00033 #include <ncbi_pch.hpp> 00034 #include <corelib/ncbitime.hpp> 00035 #include <corelib/ncbifile.hpp> 00036 #include "dbapi_testspeed.hpp" 00037 #include "../dbapi_sample_base.hpp" 00038 #include <common/test_assert.h> /* This header must go last */ 00039 00040 USING_NCBI_SCOPE; 00041 00042 ///////////////////////////////////////////////////////////////////////////// 00043 // CDbapiTestBcpApp:: 00044 // 00045 00046 class CDbapiTestSpeedApp : public CDbapiSampleApp 00047 { 00048 public: 00049 CDbapiTestSpeedApp(void); 00050 virtual ~CDbapiTestSpeedApp(void); 00051 00052 protected: 00053 virtual void InitSample(CArgDescriptions& arg_desc); 00054 virtual int RunSample(void); 00055 00056 protected: 00057 /// 00058 void FetchFile (const string& table_name, bool readItems); 00059 /// 00060 void FetchResults (const string& table_name, bool readItems); 00061 string GetTableName(void) const; 00062 00063 private: 00064 string m_TableName; 00065 }; 00066 00067 CDbapiTestSpeedApp::CDbapiTestSpeedApp(void) 00068 { 00069 } 00070 00071 CDbapiTestSpeedApp::~CDbapiTestSpeedApp(void) 00072 { 00073 } 00074 00075 inline 00076 string 00077 CDbapiTestSpeedApp::GetTableName(void) const 00078 { 00079 return m_TableName; 00080 } 00081 00082 // const char usage[] = 00083 // "Run a series of BCP/insert/select commands,\n" 00084 // "measure the time required for their execution. \n" 00085 // "\n" 00086 // "USAGE: dbapi_testspeed -parameters [file]\n" 00087 // "REQUIRED PARAMETERS:\n" 00088 // " -S server\n" 00089 // " -d driver (e.g. ctlib dblib ftds odbc gateway)\n" 00090 // " -g sss_server:port for gateway database driver\n" 00091 // " (only one of -d/-g is required to be present)\n" 00092 // "OPTIONAL PARAMETERS:\n" 00093 // " -r row_count (default is 1)\n" 00094 // " -b text_blob_size in kilobytes (default is 1 kb)\n" 00095 // " -c column_count 1..5 (int_val fl_val date_val str_val txt_val)\n" 00096 // " -t table_name (default is 'TestSpeed')\n" 00097 // " -m mode_character:\n" 00098 // " r write and read as usual,\n" 00099 // " use CDB_Result->ReadItem() instead of GetItem() whenever possible\n" 00100 // " w write to the table, do not read, do not delete it\n" 00101 // " R read using ReadItem() (can be done many times after '-m w' )\n" 00102 // " G read using GetItem() (can be done many times after '-m w' )\n" 00103 // "FILE (optional):\n" 00104 // " Upload the specified file as a blob into the table,\n" 00105 // " then download it to \"./testspeed.out\".\n" 00106 // " \"diff\" can then be used to verify the data.\n" 00107 // " -r -b -c parameterss are ignored.\n" 00108 // "\n" 00109 // ; 00110 00111 void 00112 CDbapiTestSpeedApp::InitSample(CArgDescriptions& arg_desc) 00113 { 00114 arg_desc.AddOptionalKey( 00115 "g", "sss_server", 00116 "Server:port for gateway database driver\n" 00117 "(only one of -d/-g is required to be present)", 00118 CArgDescriptions::eString 00119 ); 00120 00121 arg_desc.AddDefaultKey( 00122 "r", "row_count", 00123 "Row count", 00124 CArgDescriptions::eInteger, 00125 "1" 00126 ); 00127 00128 arg_desc.AddDefaultKey( 00129 "b", "text_blob_size", 00130 "Text blob size in kilobytes", 00131 CArgDescriptions::eInteger, 00132 "1" 00133 ); 00134 00135 arg_desc.AddOptionalKey( 00136 "c", "column_count", 00137 "Column count 1..5 (int_val fl_val date_val str_val txt_val)", 00138 CArgDescriptions::eInteger 00139 ); 00140 00141 arg_desc.AddDefaultKey( 00142 "t", "table_name", 00143 "Table name", 00144 CArgDescriptions::eString, 00145 "#spd" 00146 ); 00147 00148 arg_desc.AddOptionalKey( 00149 "m", "mode_character", 00150 "Mode character \n" 00151 " r write and read as usual,\n" 00152 " use CDB_Result->ReadItem() instead of GetItem() whenever possible\n" 00153 " w write to the table, do not read, do not delete it\n" 00154 " R read using ReadItem() (can be done many times after '-m w' )\n" 00155 " G read using GetItem() (can be done many times after '-m w' )", 00156 CArgDescriptions::eString 00157 ); 00158 arg_desc.SetConstraint("m", new CArgAllow_Symbols("rwRG")); 00159 00160 arg_desc.AddOptionalKey( 00161 "FILE", "mode_character", 00162 "Upload the specified file as a blob into the table,\n" 00163 "then download it to \"./testspeed.out\" \n" 00164 "\"diff\" can then be used to verify the data.\n" 00165 "-r -b -c parameterss are ignored.\n", 00166 CArgDescriptions::eInputFile 00167 ); 00168 } 00169 00170 // Create a table with 5 columns, fill it using BCP or insert commands(1), 00171 // fetch results(2), delete the table. Execution time is measured for steps 1, 2. 00172 int 00173 CDbapiTestSpeedApp::RunSample(void) 00174 { 00175 string host_name; 00176 string port_num; 00177 int count = 0; 00178 int row_count = 1; 00179 int col_count = 5; 00180 int blob_size = 1; 00181 bool readItems = false; 00182 bool writeOnly = false; 00183 bool selectOnly = false; 00184 string fileParam; 00185 CStopWatch timer; 00186 double timeElapsed; 00187 00188 const CArgs& args = GetArgs(); 00189 00190 // Process additional arguments ... 00191 00192 // 00193 if (args["g"]) { 00194 host_name = args["g"].AsString(); 00195 00196 int i = NStr::Find(host_name, ":"); 00197 if ( i > 0 ) { 00198 port_num = host_name.substr( i + 1 ); 00199 host_name.resize(i); 00200 } 00201 00202 if ( GetDriverName().empty() ) { 00203 SetDriverName("gateway"); 00204 } 00205 } 00206 00207 // 00208 row_count = args["r"].AsInteger(); 00209 if ( row_count < 1 || row_count > 0x100000 ) { 00210 cerr << "Error -- invalid row count; valid values are 1 .. 1 Meg.\n"; 00211 return 1; 00212 } 00213 00214 // 00215 if (args["c"]) { 00216 col_count = args["g"].AsInteger(); 00217 } 00218 00219 // 00220 blob_size = args["b"].AsInteger(); 00221 if ( blob_size < 1 || blob_size > 1024000 ) { 00222 cerr << "Error -- invalid blob size; valid values are 1 (kb) to 1000 (kb)\n"; 00223 return 1; 00224 } 00225 if ( col_count < 5 ) { 00226 cerr << "Error -- blob size makes sense for '-c 5' only.\n"; 00227 return 1; 00228 } 00229 00230 // 00231 m_TableName = args["t"].AsString(); 00232 00233 // 00234 if (args["m"]) { 00235 string key_value = args["m"].AsString(); 00236 00237 switch ( *key_value.c_str() ) { 00238 case 'r': 00239 readItems = true; 00240 break; 00241 case 'w': 00242 writeOnly = true; 00243 break; 00244 case 'G': 00245 selectOnly = true; 00246 break; 00247 case 'R': 00248 selectOnly = true; 00249 readItems = true; 00250 break; 00251 default: 00252 cerr << "Error -- invalid mode character '" << key_value << "'\n"; 00253 return 1; 00254 } 00255 } 00256 00257 // 00258 if (args["FILE"]) { 00259 fileParam = args["FILE"].AsString(); 00260 } 00261 00262 // Modify connection atributes 00263 // Do it before establishing of a connection to a server ... 00264 if ( !host_name.empty() ) { 00265 SetDatabaseParameter("host", host_name); 00266 } 00267 if ( !port_num.empty() ) { 00268 SetDatabaseParameter("port", port_num); 00269 } 00270 00271 try { 00272 auto_ptr<CDB_LangCmd> set_cmd; 00273 auto_ptr<CDB_LangCmd> ins_cmd; 00274 auto_ptr<CDB_BCPInCmd> bcp; 00275 00276 string cmd_str("set textsize 1024000"); 00277 set_cmd.reset(GetConnection().LangCmd(cmd_str)); 00278 set_cmd->Send(); 00279 while ( set_cmd->HasMoreResults() ) { 00280 auto_ptr<CDB_Result> r(set_cmd->Result()); 00281 } 00282 00283 // Create table, insert data 00284 if ( !selectOnly ) { 00285 // Deletes the pre-existing table, if present 00286 CreateTable(GetTableName()); 00287 cout << ", rows " << row_count; 00288 cout << ", cols " << col_count; 00289 cout << ", blob size " << blob_size << "\n"; 00290 00291 if ( col_count > 4 ) { 00292 // "Bulk copy in" command 00293 bcp.reset(GetConnection().BCPIn(GetTableName())); 00294 } else { 00295 string s = "insert into "; 00296 s += GetTableName(); 00297 s += " (int_val"; 00298 string sv = "@i"; 00299 00300 if ( col_count > 1 ) { 00301 s += ", fl_val"; 00302 sv +=", @f"; 00303 } 00304 if ( col_count > 2 ) { 00305 s += ", date_val"; 00306 sv += ", @d"; 00307 } 00308 if ( col_count > 3 ) { 00309 s += ", str_val"; 00310 sv +=", @s"; 00311 } 00312 00313 s += ") values ("; 00314 s += sv; 00315 s += ")"; 00316 00317 ins_cmd.reset(GetConnection().LangCmd(s)); 00318 } 00319 00320 CDB_Int int_val; 00321 CDB_Float fl_val; 00322 CDB_DateTime date_val(CTime::eCurrent); 00323 CDB_VarChar str_val; 00324 CDB_Text pTxt; 00325 int i; 00326 00327 if ( !fileParam.empty() ) { 00328 CNcbiIfstream f(fileParam.c_str(), IOS_BASE::in | 00329 IOS_BASE::binary); 00330 if ( !f.is_open() ) { 00331 cerr << "Error -- cannot read '" << fileParam << "'\n"; 00332 return 1; 00333 } 00334 char buf[10240]; 00335 int sz; 00336 while ( f.good() && !f.eof() ) { 00337 f.read( buf, sizeof(buf) ); 00338 sz = (size_t)f.gcount(); 00339 if ( sz <= 0 ) break; 00340 pTxt.Append(buf, sz); 00341 if ( sz != sizeof(buf) ) break; 00342 } 00343 f.close(); 00344 00345 col_count = 5; 00346 row_count = 1; 00347 } else if ( col_count > 4 ) { 00348 for ( i = 0; i < blob_size; ++i ) { 00349 // Add 1024 chars 00350 for ( int j = 0; j < 32; ++j ) { 00351 pTxt.Append("If you want to know who we are--"); 00352 } 00353 } 00354 } 00355 00356 timer.Start(); 00357 00358 // Bind program variables as data source 00359 if ( bcp.get() ) { 00360 bcp->Bind(0, &int_val); 00361 if ( col_count > 1 ) bcp->Bind(1, &fl_val ); 00362 if ( col_count > 2 ) bcp->Bind(2, &date_val); 00363 if ( col_count > 3 ) bcp->Bind(3, &str_val ); 00364 if ( col_count > 4 ) bcp->Bind(4, &pTxt ); 00365 } else { 00366 if ( !ins_cmd->BindParam("@i", &int_val) ) { 00367 cerr << "Error in BindParam()\n"; 00368 DeleteTable(GetTableName()); 00369 return 1; 00370 } 00371 00372 if ( col_count > 1 ) ins_cmd->BindParam("@f", &fl_val ); 00373 if ( col_count > 2 ) ins_cmd->BindParam("@d", &date_val ); 00374 if ( col_count > 3 ) ins_cmd->BindParam("@s", &str_val ); 00375 } 00376 00377 for ( i = 0; i < row_count; ++i ) { 00378 int_val = i; 00379 fl_val = static_cast<float>(i + 0.999); 00380 if ( !fileParam.empty() ) { 00381 CDirEntry fileEntry(fileParam); 00382 CTime fileTime; 00383 fileEntry.GetTime(&fileTime); 00384 00385 date_val = fileTime; 00386 str_val = fileParam; 00387 } else { 00388 date_val = date_val.Value(); 00389 str_val = string("Franz Joseph Haydn symphony # ") + 00390 NStr::IntToString(i); 00391 } 00392 pTxt.MoveTo(0); 00393 00394 if ( bcp.get() ) { 00395 bcp->SendRow(); 00396 00397 if ( count == 2 ) { 00398 bcp->CompleteBatch(); 00399 count = 0; 00400 } 00401 ++count; 00402 } else { 00403 ins_cmd->Send(); 00404 while ( ins_cmd->HasMoreResults() ) { 00405 auto_ptr<CDB_Result> r(ins_cmd->Result()); 00406 } 00407 } 00408 } 00409 if ( bcp.get() ) { 00410 bcp->CompleteBCP(); 00411 } 00412 timeElapsed = timer.Elapsed(); 00413 cout << "inserting timeElapsed=" << NStr::DoubleToString(timeElapsed, 2) << "\n"; 00414 } else { 00415 cout << "\n"; 00416 } 00417 00418 if ( !writeOnly ) { 00419 // Read data 00420 timer.Start(); 00421 if ( !fileParam.empty() ) { 00422 FetchFile(GetTableName(), readItems); 00423 } else { 00424 FetchResults(GetTableName(), readItems); 00425 } 00426 timeElapsed = timer.Elapsed(); 00427 cout << "fetching timeElapsed=" << NStr::DoubleToString(timeElapsed,2) << "\n"; 00428 cout << "\n"; 00429 } 00430 00431 if ( !(selectOnly || writeOnly) ) { 00432 DeleteTable(GetTableName()); 00433 } 00434 00435 // Drop lost tables. 00436 DeleteLostTables(); 00437 } 00438 catch ( CDB_Exception& e ) { 00439 CDB_UserHandler::GetDefault().HandleIt(&e); 00440 return 1; 00441 } 00442 00443 return 0; 00444 } 00445 00446 void 00447 CDbapiTestSpeedApp::FetchFile(const string& table_name, bool readItems) 00448 { 00449 CDB_VarChar str_val; 00450 CDB_DateTime date_val; 00451 00452 string query = "select date_val,str_val,txt_val from "; 00453 query += table_name; 00454 auto_ptr<CDB_LangCmd> lcmd(GetConnection().LangCmd(query)); 00455 lcmd->Send(); 00456 00457 //CTime fileTime; 00458 while ( lcmd->HasMoreResults() ) { 00459 auto_ptr<CDB_Result> r(lcmd->Result()); 00460 if ( !r.get() ) continue; 00461 00462 if ( r->ResultType() == eDB_RowResult ) { 00463 while ( r->Fetch() ) { 00464 CNcbiOfstream f("testspeed.out", IOS_BASE::trunc|IOS_BASE::out|IOS_BASE::binary); 00465 00466 for ( unsigned int j = 0; j < r->NofItems(); j++ ) { 00467 EDB_Type rt = r->ItemDataType(j); 00468 00469 if ( readItems && rt == eDB_Text ) { 00470 bool isNull=false; 00471 char txt_buf[10240]; 00472 // cout<< "j=" << j 00473 // << " CurrentItemNo()=" << r->CurrentItemNo() << "\n"; 00474 for ( ;; ) { 00475 int len_txt = r->ReadItem(txt_buf, sizeof(txt_buf), &isNull); 00476 //cout << "len_txt=" << len_txt << " isNull=" << isNull << "\n"; 00477 if ( isNull || len_txt<=0 ) break; 00478 f.write(txt_buf, len_txt); 00479 } 00480 f.close(); 00481 continue; 00482 } 00483 00484 // Type-specific GetItem() 00485 if ( rt == eDB_Char || rt == eDB_VarChar ) { 00486 r->GetItem(&str_val); 00487 00488 } else if ( rt == eDB_DateTime || rt == eDB_SmallDateTime ) { 00489 r->GetItem(&date_val); 00490 } else if ( rt == eDB_Text ) { 00491 CDB_Text text_val; 00492 r->GetItem(&text_val); 00493 00494 if ( text_val.IsNULL() ) { 00495 // cout << "{NULL}"; 00496 } else { 00497 char txt_buf[10240]; 00498 //cout << "text_val.Size()=" << text_val.Size() << "\n"; 00499 for ( ;; ) { 00500 int len_txt = text_val.Read( txt_buf, sizeof(txt_buf) ); 00501 if ( len_txt<=0 ) break; 00502 f.write(txt_buf, len_txt); 00503 } 00504 } 00505 f.close(); 00506 } else { 00507 r->SkipItem(); 00508 // cout << "{unprintable}"; 00509 } 00510 } 00511 // cout << "</ROW>" << endl << endl; 00512 } 00513 } 00514 } 00515 00516 cout << "File " << str_val.Value() << " dated " 00517 << date_val.Value().AsString() << " was written to testspeed.out using " 00518 << (readItems?"ReadItem":"GetItem") << "\n"; 00519 } 00520 00521 void 00522 CDbapiTestSpeedApp::FetchResults (const string& table_name, bool readItems) 00523 { 00524 // char* txt_buf = NULL ; // Temporary disabled ... 00525 // long len_txt = 0; 00526 00527 00528 string query = "select int_val,fl_val,date_val,str_val,txt_val from "; 00529 query += table_name; 00530 00531 auto_ptr<CDB_LangCmd> lcmd(GetConnection().LangCmd(query)); 00532 lcmd->Send(); 00533 00534 while ( lcmd->HasMoreResults() ) { 00535 auto_ptr<CDB_Result> r(lcmd->Result()); 00536 if ( !r.get() ) continue; 00537 00538 if ( r->ResultType() == eDB_RowResult ) { 00539 while ( r->Fetch() ) { 00540 // cout << "<ROW>"<< endl; 00541 for ( unsigned int j = 0; j < r->NofItems(); ++j ) { 00542 // Determination of data type: 00543 EDB_Type rt = r->ItemDataType(j); 00544 const string iname = r->ItemName(j); 00545 00546 // cout << iname << '='; 00547 00548 if ( readItems && rt!=eDB_Numeric && 00549 rt != eDB_DateTime && rt != eDB_SmallDateTime ) { 00550 bool isNull; 00551 char buf[1024]; 00552 int sz=0; 00553 while ( j == abs(r->CurrentItemNo()) ) { 00554 sz += r->ReadItem(buf, sizeof(buf), &isNull); 00555 } 00556 continue; 00557 } 00558 00559 // Type-specific GetItem() 00560 if ( rt == eDB_Char || rt == eDB_VarChar ) { 00561 CDB_VarChar str_val; 00562 r->GetItem(&str_val); 00563 // cout << (str_val.IsNULL()? "{NULL}" : str_val.Value()) << endl << endl ; 00564 00565 } else if ( rt == eDB_Int || rt == eDB_SmallInt || rt == eDB_TinyInt ) { 00566 CDB_Int int_val; 00567 r->GetItem(&int_val); 00568 if ( int_val.IsNULL() ) { 00569 // cout << "{NULL}"; 00570 } else { 00571 // cout << int_val.Value() << endl << endl ; 00572 } 00573 } else if ( rt == eDB_Float ) { 00574 CDB_Float fl_val; 00575 r->GetItem(&fl_val); 00576 if ( fl_val.IsNULL() ) { 00577 // cout << "{NULL}"; 00578 } else { 00579 // cout << fl_val.Value() << endl<< endl ; 00580 } 00581 } else if ( rt == eDB_Double ) { 00582 CDB_Double fl_val; 00583 r->GetItem(&fl_val); 00584 if ( fl_val.IsNULL() ) { 00585 // cout << "{NULL}"; 00586 } else { 00587 // cout << fl_val.Value() << endl<< endl ; 00588 } 00589 } else if ( rt == eDB_DateTime || rt == eDB_SmallDateTime ) { 00590 CDB_DateTime date_val; 00591 r->GetItem(&date_val); 00592 if ( date_val.IsNULL() ) { 00593 // cout << "{NULL}"; 00594 } else { 00595 // cout << date_val.Value().AsString() << endl<< endl ; 00596 } 00597 } else if ( rt == eDB_Text ) { 00598 CDB_Text text_val; 00599 r->GetItem(&text_val); 00600 00601 if ( text_val.IsNULL() ) { 00602 // cout << "{NULL}"; 00603 } else { 00604 /* Do not do this at the moment ... 00605 txt_buf = ( char*) malloc (text_val.Size() + 1); 00606 len_txt = text_val.Read (( char*)txt_buf, text_val.Size()); 00607 txt_buf[text_val.Size()] = '\0'; 00608 */ 00609 // cout << txt_buf << endl<< endl ; 00610 } 00611 } else { 00612 r->SkipItem(); 00613 // cout << "{unprintable}"; 00614 } 00615 } 00616 // cout << "</ROW>" << endl << endl; 00617 } 00618 } 00619 } 00620 } 00621 00622 int main(int argc, char* argv[]) 00623 { 00624 // Execute main application function 00625 return CDbapiTestSpeedApp().AppMain(argc, argv); 00626 } 00627 00628
1.7.5.1
Modified on Wed May 23 13:33:37 2012 by modify_doxy.py rev. 337098