1 /* $Id: dbapi_unit_test_common.cpp 583697 2019-04-01 15:00:36Z ucko $
2 * ===========================================================================
3 *
4 * PUBLIC DOMAIN NOTICE
5 * National Center for Biotechnology Information
6 *
7 * This software/database is a "United States Government Work" under the
8 * terms of the United States Copyright Act. It was written as part of
9 * the author's official duties as a United States Government employee and
10 * thus cannot be copyrighted. This software/database is freely available
11 * to the public for use. The National Library of Medicine and the U.S.
12 * Government have not placed any restriction on its use or reproduction.
13 *
14 * Although all reasonable efforts have been taken to ensure the accuracy
15 * and reliability of the software and data, the NLM and the U.S.
16 * Government do not and cannot warrant the performance or results that
17 * may be obtained by using this software or data. The NLM and the U.S.
18 * Government disclaim all warranties, express or implied, including
19 * warranties of performance, merchantability or fitness for any particular
20 * purpose.
21 *
22 * Please cite the author in any work or product based on this material.
23 *
24 * ===========================================================================
25 *
26 * Author: Sergey Sikorskiy
27 *
28 * File Description: DBAPI unit-test
29 *
30 * ===========================================================================
31 */
32
33 #include "dbapi_unit_test_pch.hpp"
34
35 #include <corelib/ncbiargs.hpp>
36 //#include <corelib/ncbithr.hpp>
37 #include <corelib/expr.hpp>
38
39 #include <connect/ncbi_core_cxx.hpp>
40 #ifdef HAVE_LIBCONNEXT
41 # include <connect/ext/ncbi_crypt.h>
42 #endif
43
44 #include <dbapi/driver/drivers.hpp>
45 #include <dbapi/driver/impl/dbapi_driver_utils.hpp>
46 #include <dbapi/driver/dbapi_svc_mapper.hpp>
47 #include <dbapi/driver/impl/dbapi_impl_context.hpp>
48
49 BEGIN_NCBI_SCOPE
50
51 ///////////////////////////////////////////////////////////////////////////////
CDBSetConnParams(const string & server_name,const string & user_name,const string & password,Uint4 tds_version,const CDBConnParams & other)52 CDBSetConnParams::CDBSetConnParams(
53 const string& server_name,
54 const string& user_name,
55 const string& password,
56 Uint4 tds_version,
57 const CDBConnParams& other)
58 : CDBConnParamsDelegate(other)
59 , m_ProtocolVersion(tds_version)
60 , m_ServerName(server_name)
61 , m_UserName(user_name)
62 , m_Password(password)
63 {
64 }
65
~CDBSetConnParams(void)66 CDBSetConnParams::~CDBSetConnParams(void)
67 {
68 }
69
70 Uint4
GetProtocolVersion(void) const71 CDBSetConnParams::GetProtocolVersion(void) const
72 {
73 return m_ProtocolVersion;
74 }
75
76 string
GetServerName(void) const77 CDBSetConnParams::GetServerName(void) const
78 {
79 return m_ServerName;
80 }
81
82 string
GetUserName(void) const83 CDBSetConnParams::GetUserName(void) const
84 {
85 return m_UserName;
86 }
87
88 string
GetPassword(void) const89 CDBSetConnParams::GetPassword(void) const
90 {
91 return m_Password;
92 }
93
94
95 ////////////////////////////////////////////////////////////////////////////////
96 const char* ftds95_driver = "ftds95";
97 const char* ftds100_driver = "ftds100";
98 const char* ftds_driver = "ftds";
99
100 const char* odbc_driver = "odbc";
101 const char* ctlib_driver = "ctlib";
102
103 ////////////////////////////////////////////////////////////////////////////////
104 const char* msg_record_expected = "Record expected";
105
106 /////////////////////////////////////////////////////////////////////////////
107 const string&
GetTableName(void)108 GetTableName(void)
109 {
110 static const string s_TableName = "#dbapi_unit_table";
111 return s_TableName;
112 }
113
114 const CTestArguments&
GetArgs(void)115 GetArgs(void)
116 {
117 static CRef<CTestArguments> s_Args(new CTestArguments());
118 return *s_Args;
119 }
120
121 int
GetMaxVarcharSize(void)122 GetMaxVarcharSize(void)
123 {
124 static int s_max_varchar_size = 0;
125
126 if (s_max_varchar_size == 0) {
127 if ( GetArgs().GetServerType() == CDBConnParams::eMSSqlServer) {
128 s_max_varchar_size = 8000;
129 } else {
130 // Sybase
131 s_max_varchar_size = 1900;
132 }
133 }
134
135 return s_max_varchar_size;
136 }
137
138
139 ///////////////////////////////////////////////////////////////////////////////
140 static IDataSource* s_DS = NULL;
141
142 IDataSource&
GetDS(void)143 GetDS(void)
144 {
145 _ASSERT(s_DS);
146 return *s_DS;
147 }
148
149 static
s_CommonInit(void)150 bool s_CommonInit(void)
151 {
152 // Using old log format ...
153 // Show time (no msec.) ...
154 SetDiagPostFlag(eDPF_DateTime);
155 CONNECT_Init(&CNcbiApplication::Instance()->GetConfig());
156
157 DBLB_INSTALL_DEFAULT();
158
159 #ifndef NCBI_DLL_SUPPORT
160
161 #ifdef HAVE_LIBSYBASE
162 DBAPI_RegisterDriver_CTLIB();
163 #endif
164
165 #ifdef HAVE_ODBC
166 DBAPI_RegisterDriver_ODBC();
167 #endif
168
169 DBAPI_RegisterDriver_FTDS();
170 DBAPI_RegisterDriver_FTDS95();
171 DBAPI_RegisterDriver_FTDS100();
172
173 #else
174 CPluginManager_DllResolver::EnableGlobally(true);
175 #endif // NCBI_DLL_SUPPORT
176
177 if (false) {
178 // Two calls below will cause problems with the Sybase 12.5.1 client
179 // (No problems with the Sybase 12.5.0 client)
180 IDataSource* ds = GetDM().MakeDs(GetArgs().GetConnParams());
181 GetDM().DestroyDs(ds);
182 }
183
184 try {
185 s_DS = GetDM().MakeDs(GetArgs().GetConnParams());
186 }
187 catch (CException& ex) {
188 LOG_POST(Warning << "Error loading database driver: " << ex.what());
189 NcbiTestSetGlobalDisabled();
190 return false;
191 }
192
193 I_DriverContext* drv_context = GetDS().GetDriverContext();
194 drv_context->SetLoginTimeout(4);
195 drv_context->SetTimeout(4);
196
197 if (GetArgs().GetTestConfiguration() != CTestArguments::eWithoutExceptions) {
198 if (GetArgs().IsODBCBased()) {
199 drv_context->PushCntxMsgHandler(
200 new CDB_UserHandler_Exception_ODBC,
201 eTakeOwnership
202 );
203 drv_context->PushDefConnMsgHandler(
204 new CDB_UserHandler_Exception_ODBC,
205 eTakeOwnership
206 );
207 } else {
208 drv_context->PushCntxMsgHandler(
209 new CDB_UserHandler_Exception,
210 eTakeOwnership
211 );
212 drv_context->PushDefConnMsgHandler(
213 new CDB_UserHandler_Exception,
214 eTakeOwnership
215 );
216 }
217 }
218
219 return true;
220 }
221
222 static
s_CommonFini(void)223 void s_CommonFini(void)
224 {
225 if (s_DS) {
226 GetDM().DestroyDs(s_DS);
227 }
228 }
229
230 ///////////////////////////////////////////////////////////////////////////////
231 static AutoPtr<IConnection> s_Conn = NULL;
232
233 static void s_ResetConnection(void);
234
235 IConnection&
GetConnection(void)236 GetConnection(void)
237 {
238 _ASSERT(s_Conn.get());
239 if ( !s_Conn->IsAlive() ) {
240 s_ResetConnection();
241 }
242 return *s_Conn;
243 }
244
245
246 ///////////////////////////////////////////////////////////////////////////////
NCBITEST_AUTO_INIT()247 NCBITEST_AUTO_INIT()
248 {
249 if (!s_CommonInit())
250 return;
251
252 s_ResetConnection();
253 }
254
s_ResetConnection(void)255 static void s_ResetConnection(void)
256 {
257 s_Conn.reset(GetDS().CreateConnection( CONN_OWNERSHIP ));
258 _ASSERT(s_Conn.get());
259
260 s_Conn->Connect(GetArgs().GetConnParams());
261 //CTrivialConnValidator validator(GetArgs().GetDatabaseName());
262 //s_Conn->ConnectValidated(validator, GetArgs().GetUserName(), GetArgs().GetUserPassword(), GetArgs().GetServerName());
263 //cout << s_Conn->GetCDB_Connection()->ServerName() << endl;
264
265 unique_ptr<IStatement> auto_stmt(GetConnection().GetStatement());
266
267 // Create a test table ...
268 string sql;
269
270 sql = " CREATE TABLE " + GetTableName() + "( \n";
271 sql += " id NUMERIC(18, 0) IDENTITY NOT NULL, \n";
272 sql += " int_field INT NULL, \n";
273 sql += " vc1000_field VARCHAR(1000) NULL, \n";
274 sql += " text_field TEXT NULL, \n";
275 sql += " image_field IMAGE NULL \n";
276 sql += " )";
277
278 // Create the table
279 auto_stmt->ExecuteUpdate(sql);
280
281 sql = " CREATE UNIQUE INDEX #ind01 ON " + GetTableName() + "( id ) \n";
282
283 // Create an index
284 auto_stmt->ExecuteUpdate( sql );
285
286 sql = " CREATE TABLE #dbapi_bcp_table2 ( \n";
287 sql += " id INT NULL, \n";
288 // Identity won't work with bulk insert ...
289 // sql += " id NUMERIC(18, 0) IDENTITY NOT NULL, \n";
290 sql += " int_field INT NULL, \n";
291 sql += " vc1000_field VARCHAR(1000) NULL, \n";
292 sql += " text_field TEXT NULL \n";
293 sql += " )";
294
295 auto_stmt->ExecuteUpdate( sql );
296
297 sql = " CREATE TABLE #test_unicode_table ( \n";
298 sql += " id NUMERIC(18, 0) IDENTITY NOT NULL, \n";
299 sql += " nvc255_field NVARCHAR(255) NULL \n";
300 // sql += " nvc255_field VARCHAR(255) NULL \n";
301 sql += " )";
302
303 // Create table
304 auto_stmt->ExecuteUpdate(sql);
305 }
306
NCBITEST_AUTO_FINI()307 NCBITEST_AUTO_FINI()
308 {
309 // I_DriverContext* drv_context = GetDS().GetDriverContext();
310 //
311 // drv_context->PopDefConnMsgHandler( m_ErrHandler.get() );
312 // drv_context->PopCntxMsgHandler( m_ErrHandler.get() );
313
314 s_Conn.reset(NULL);
315 s_CommonFini();
316 }
317
318
319 ///////////////////////////////////////////////////////////////////////////////
320
GetSybaseClientVersion(void)321 string GetSybaseClientVersion(void)
322 {
323 string sybase_version;
324
325 #if defined(NCBI_OS_MSWIN)
326 sybase_version = "15.5";
327 #else
328 impl::CDriverContext::ResetEnvSybase();
329
330 CNcbiEnvironment env;
331 sybase_version = env.Get("SYBASE");
332
333 if (!sybase_version.empty()) {
334 CDirEntry dir_entry(sybase_version);
335 dir_entry.DereferenceLink();
336 sybase_version = dir_entry.GetPath();
337
338 sybase_version = sybase_version.substr(
339 sybase_version.find_last_of('/') + 1
340 );
341 } else {
342 sybase_version = "0.0";
343 }
344 #endif
345
346 return sybase_version;
347 }
348
349
NCBITEST_INIT_VARIABLES(parser)350 NCBITEST_INIT_VARIABLES(parser)
351 {
352 ////////////////////////
353 // Sybase ...
354 {
355 double syb_client_ver = 0.0;
356 const string syb_client_ver_str = GetSybaseClientVersion();
357
358 if (!syb_client_ver_str.empty()) {
359 try {
360 syb_client_ver = NStr::StringToDouble(syb_client_ver_str.substr(0, 4));
361 } catch (const CStringException&) {
362 // Conversion error
363 }
364 }
365
366 parser->AddSymbol("SYBASE_ClientVersion", syb_client_ver);
367
368 }
369
370 ///////////////////////
371 // Configuration-related ...
372 #ifdef HAVE_LIBCONNEXT
373 parser->AddSymbol("HAVE_LibConnExt", CRYPT_Version(-1) != -1);
374 #else
375 parser->AddSymbol("HAVE_LibConnExt", false);
376 #endif
377
378 #ifdef HAVE_LIBSYBASE
379 parser->AddSymbol("HAVE_Sybase", true);
380 #else
381 parser->AddSymbol("HAVE_Sybase", false);
382 #endif
383
384 #ifdef HAVE_ODBC
385 parser->AddSymbol("HAVE_ODBC", true);
386 #else
387 parser->AddSymbol("HAVE_ODBC", false);
388 #endif
389
390 #ifdef HAVE_MYSQL
391 parser->AddSymbol("HAVE_MYSQL", true);
392 #else
393 parser->AddSymbol("HAVE_MYSQL", false);
394 #endif
395
396 parser->AddSymbol("DRIVER_AllowsMultipleContexts", GetArgs().DriverAllowsMultipleContexts());
397
398 parser->AddSymbol("SERVER_MySQL", GetArgs().GetServerType() == CDBConnParams::eMySQL);
399 parser->AddSymbol("SERVER_SybaseOS", GetArgs().GetServerType() == CDBConnParams::eSybaseOpenServer);
400 parser->AddSymbol("SERVER_SybaseSQL", GetArgs().GetServerType() == CDBConnParams::eSybaseSQLServer);
401 parser->AddSymbol("SERVER_MicrosoftSQL", GetArgs().GetServerType() == CDBConnParams::eMSSqlServer);
402
403 parser->AddSymbol("DRIVER_ftds", GetArgs().IsFreeTDS());
404 parser->AddSymbol("DRIVER_ftds95", GetArgs().GetDriverName() == ftds95_driver);
405 parser->AddSymbol("DRIVER_ftds100", GetArgs().GetDriverName() == ftds100_driver);
406 parser->AddSymbol("DRIVER_odbc", GetArgs().GetDriverName() == odbc_driver);
407 parser->AddSymbol("DRIVER_ctlib", GetArgs().GetDriverName() == ctlib_driver);
408 parser->AddSymbol("DRIVER_mysql", GetArgs().GetDriverName() == "mysql");
409
410 parser->AddSymbol("DRIVER_IsBcpAvailable", GetArgs().IsBCPAvailable());
411 parser->AddSymbol("DRIVER_IsOdbcBased", GetArgs().GetDriverName() == odbc_driver);
412 }
413
414
415 ////////////////////////////////////////////////////////////////////////////////
CUnitTestParams(const CDBConnParams & other)416 CUnitTestParams::CUnitTestParams(const CDBConnParams& other)
417 : CDBConnParamsDelegate(other)
418 {
419 }
420
~CUnitTestParams(void)421 CUnitTestParams::~CUnitTestParams(void)
422 {
423 }
424
GetServerName(void) const425 string CUnitTestParams::GetServerName(void) const
426 {
427 const string server_name = CDBConnParamsDelegate::GetServerName();
428
429 if (NStr::CompareNocase(server_name, "MsSql") == 0) {
430 #ifdef HAVE_LIBCONNEXT
431 return "DBAPI_MS_TEST";
432 #else
433 return "MSDEV1";
434 #endif
435 } else if (NStr::CompareNocase(server_name, "Sybase") == 0) {
436 #ifdef HAVE_LIBCONNEXT
437 return "DBAPI_SYB160_TEST";
438 #else
439 return "DBAPI_DEV16_2K";
440 #endif
441 }
442
443 return server_name;
444 }
445
446 CDBConnParams::EServerType
GetServerType(void) const447 CUnitTestParams::GetServerType(void) const
448 {
449 return CDBConnParamsDelegate::GetServerType();
450 }
451
452 ////////////////////////////////////////////////////////////////////////////////
CTestArguments(void)453 CTestArguments::CTestArguments(void)
454 : m_TestConfiguration(eWithExceptions)
455 , m_NumOfDisabled(0)
456 , m_ReportDisabled(false)
457 , m_ReportExpected(false)
458 , m_ConnParams(m_ParamBase)
459 , m_CPPParams(m_ParamBase2)
460 , m_ConnParams2(m_CPPParams)
461 // , m_CPPParams(m_ParamBase)
462 // , m_ConnParams(m_CPPParams)
463 {
464 const CNcbiApplication* app = CNcbiApplication::Instance();
465
466 if (!app) {
467 return;
468 }
469
470 const CArgs& args = app->GetArgs();
471
472 // Get command-line arguments ...
473 m_ParamBase.SetServerName(args["S"].AsString());
474 m_ParamBase2.SetServerName(args["S"].AsString());
475 m_ParamBase.SetUserName(args["U"].AsString());
476 m_ParamBase2.SetUserName(args["U"].AsString());
477 m_ParamBase.SetPassword(args["P"].AsString());
478 m_ParamBase2.SetPassword(args["P"].AsString());
479
480 if (args["dr"].HasValue()) {
481 m_ParamBase.SetDriverName(args["dr"].AsString());
482 m_ParamBase2.SetDriverName(args["dr"].AsString());
483 if (args["dr"].AsString() == ctlib_driver) {
484 // Force the traditional C locale when using Sybase ctlib
485 // to avoid error #4847 from Sybase ASE 15.5 (reporting
486 // that character set mismatches block bulk insertion).
487 CNcbiEnvironment& env
488 = CNcbiApplication::Instance()->SetEnvironment();
489 env.Unset("LANG");
490 env.Unset("LC_ALL");
491 env.Unset("LC_CTYPE");
492 }
493 }
494
495 if (args["D"].HasValue()) {
496 m_ParamBase.SetDatabaseName(args["D"].AsString());
497 m_ParamBase2.SetDatabaseName(args["D"].AsString());
498 }
499
500 if ( args["V"].HasValue() ) {
501 m_ParamBase.SetProtocolVersion(args["V"].AsInteger());
502 m_ParamBase2.SetProtocolVersion(args["V"].AsInteger());
503 }
504
505 if (args["conf"].AsString() == "with-exceptions") {
506 m_TestConfiguration = CTestArguments::eWithExceptions;
507 } else if (args["conf"].AsString() == "without-exceptions") {
508 m_TestConfiguration = CTestArguments::eWithoutExceptions;
509 } else if (args["conf"].AsString() == "fast") {
510 m_TestConfiguration = CTestArguments::eFast;
511 }
512
513 SetDatabaseParameters();
514 }
515
516 bool
IsBCPAvailable(void) const517 CTestArguments::IsBCPAvailable(void) const
518 {
519 #if defined(NCBI_OS_SOLARIS)
520 const bool os_solaris = true;
521 #else
522 const bool os_solaris = false;
523 #endif
524
525 if (os_solaris && HOST_CPU[0] == 'i' && GetDriverName() == ctlib_driver) {
526 // Solaris Intel native Sybase drivers ...
527 // There is no apropriate client
528 return false;
529 }
530
531 return true;
532 }
533
534 bool
IsFreeTDS(void) const535 CTestArguments::IsFreeTDS(void) const
536 {
537 return NStr::StartsWith(GetDriverName(), "ftds");
538 }
539
540 bool
IsODBCBased(void) const541 CTestArguments::IsODBCBased(void) const
542 {
543 return GetDriverName() == odbc_driver;
544 }
545
DriverAllowsMultipleContexts(void) const546 bool CTestArguments::DriverAllowsMultipleContexts(void) const
547 {
548 return (GetDriverName() == ctlib_driver) || IsFreeTDS() || IsODBCBased();
549 }
550
551 void
SetDatabaseParameters(void)552 CTestArguments::SetDatabaseParameters(void)
553 {
554 if ((IsFreeTDS() /* || GetDriverName() == odbc_driver */)
555 && GetServerType() == CDBConnParams::eMSSqlServer)
556 {
557 m_ParamBase.SetEncoding(eEncoding_UTF8);
558 m_ParamBase2.SetEncoding(eEncoding_UTF8);
559 }
560
561 if (!m_GatewayHost.empty()) {
562 m_ParamBase.SetParam("host_name", m_GatewayHost);
563 m_ParamBase2.SetParam("host_name", m_GatewayHost);
564 m_ParamBase.SetParam("port_num", m_GatewayPort);
565 m_ParamBase2.SetParam("port_num", m_GatewayPort);
566 m_ParamBase.SetParam("driver_name", GetDriverName());
567 m_ParamBase2.SetParam("driver_name", GetDriverName());
568 }
569 }
570
PutMsgDisabled(const char * msg) const571 void CTestArguments::PutMsgDisabled(const char* msg) const
572 {
573 ++m_NumOfDisabled;
574
575 if (m_ReportDisabled) {
576 LOG_POST(Warning << "- " << msg << " is disabled !!!");
577 }
578 }
579
PutMsgExpected(const char * msg,const char * replacement) const580 void CTestArguments::PutMsgExpected(const char* msg, const char* replacement) const
581 {
582 if (m_ReportExpected) {
583 LOG_POST(Warning << "? " << msg << " is expected instead of " << replacement);
584 }
585 }
586
587 ////////////////////////////////////////////////////////////////////////////////
NCBITEST_INIT_CMDLINE(arg_desc)588 NCBITEST_INIT_CMDLINE(arg_desc)
589 {
590 // Describe the expected command-line arguments
591 #define FTDS_DRIVERS ftds_driver, ftds95_driver, ftds100_driver
592
593 #define DEF_SERVER "MSSQL"
594 #define DEF_DRIVER ftds_driver
595 #define ALL_DRIVERS ctlib_driver, FTDS_DRIVERS, odbc_driver
596
597 //#if defined(NCBI_OS_MSWIN)
598 //#define DEF_SERVER "MSSQL"
599 //#define DEF_DRIVER ftds_driver
600 //#define ALL_DRIVERS ctlib_driver, FTDS_DRIVERS, odbc_driver
601
602 //#elif defined(HAVE_LIBSYBASE)
603 //#define DEF_SERVER "Sybase"
604 //#define DEF_DRIVER ctlib_driver
605 //#define ALL_DRIVERS ctlib_driver, FTDS_DRIVERS
606 //#else
607 //#define DEF_SERVER "MSSQL"
608 //#define DEF_DRIVER ftds_driver
609 //#define ALL_DRIVERS FTDS_DRIVERS
610 //#endif
611
612 arg_desc->AddDefaultKey("S", "server",
613 "Name of the SQL server to connect to",
614 CArgDescriptions::eString, DEF_SERVER);
615
616 arg_desc->AddDefaultKey("dr", "driver",
617 "Name of the DBAPI driver to use",
618 CArgDescriptions::eString, DEF_DRIVER);
619 arg_desc->SetConstraint("dr", &(*new CArgAllow_Strings, ALL_DRIVERS));
620
621 arg_desc->AddDefaultKey("U", "username",
622 "User name",
623 CArgDescriptions::eString, "DBAPI_test");
624
625 arg_desc->AddDefaultKey("P", "password",
626 "Password",
627 CArgDescriptions::eString, "allowed");
628 arg_desc->AddDefaultKey("D", "database",
629 "Name of the database to connect",
630 CArgDescriptions::eString, "DBAPI_Sample");
631
632 arg_desc->AddOptionalKey("V", "version",
633 "TDS protocol version",
634 CArgDescriptions::eInteger);
635 #if BOOST_VERSION < 106000
636 arg_desc->AddAlias("v", "V");
637 #endif
638
639 arg_desc->AddDefaultKey("conf", "configuration",
640 "Configuration for testing",
641 CArgDescriptions::eString, "with-exceptions");
642 arg_desc->SetConstraint("conf", &(*new CArgAllow_Strings,
643 "with-exceptions", "without-exceptions", "fast"));
644 }
645
646
647
648 END_NCBI_SCOPE
649