1 /* $Id: dbapi_driver_conn_params.cpp 556250 2018-01-29 14:12:00Z 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 */
29
30 #include <ncbi_pch.hpp>
31
32 #include <corelib/ncbifile.hpp>
33 #include <dbapi/driver/dbapi_driver_conn_params.hpp>
34 #include <dbapi/driver/dbapi_driver_conn_mgr.hpp>
35
36 BEGIN_NCBI_SCOPE
37
38
39 NCBI_PARAM_DEF(bool, dbapi, can_use_kerberos, false);
40
41
42 ///////////////////////////////////////////////////////////////////////////////
43 namespace impl {
44
CDBConnParamsBase(void)45 CDBConnParamsBase::CDBConnParamsBase(void)
46 : m_ProtocolVersion(0)
47 , m_Encoding(eEncoding_Unknown)
48 , m_ServerType(eUnknown)
49 , m_Host(0)
50 , m_PortNumber(0)
51 {
52 SetParam("secure_login", "false");
53 SetParam("is_pooled", "false");
54 SetParam("do_not_connect", "false");
55 }
56
~CDBConnParamsBase(void)57 CDBConnParamsBase::~CDBConnParamsBase(void)
58 {
59 }
60
GetDriverName(void) const61 string CDBConnParamsBase::GetDriverName(void) const
62 {
63 if (m_DriverName.empty()) {
64 // Return a blessed driver name ...
65 switch (GetThis().GetServerType()) {
66 case eSybaseOpenServer:
67 case eSybaseSQLServer:
68 #ifdef HAVE_LIBSYBASE
69 return "ctlib";
70 #else
71 return "ftds";
72 #endif
73 case eMSSqlServer:
74 return "ftds";
75 default:
76 return "unknown_driver";
77 }
78 }
79
80 return m_DriverName;
81 }
82
GetProtocolVersion(void) const83 Uint4 CDBConnParamsBase::GetProtocolVersion(void) const
84 {
85 if (!m_ProtocolVersion) {
86 const string driver_name = GetThis().GetDriverName();
87
88 // Artificial intelligence ...
89 switch (GetThis().GetServerType()) {
90 case eSybaseOpenServer:
91 if (NStr::Compare(driver_name, "ftds") == 0) {
92 return 125;
93 }
94 default:
95 break;
96 }
97 }
98
99 return m_ProtocolVersion;
100 }
101
102
103 EEncoding
GetEncoding(void) const104 CDBConnParamsBase::GetEncoding(void) const
105 {
106 if (m_Encoding == eEncoding_Unknown) {
107 return eEncoding_ISO8859_1;
108 }
109
110 return m_Encoding;
111 }
112
113
114 string
GetServerName(void) const115 CDBConnParamsBase::GetServerName(void) const
116 {
117 return m_ServerName;
118 }
119
GetDatabaseName(void) const120 string CDBConnParamsBase::GetDatabaseName(void) const
121 {
122 return m_DatabaseName;
123 }
124
125 string
GetUserName(void) const126 CDBConnParamsBase::GetUserName(void) const
127 {
128 if (m_UserName.empty() && !TDbapi_CanUseKerberos::GetDefault()) {
129 return "anyone";
130 }
131
132 return m_UserName;
133 }
134
135 string
GetPassword(void) const136 CDBConnParamsBase::GetPassword(void) const
137 {
138 if (m_Password.empty() && !TDbapi_CanUseKerberos::GetDefault()) {
139 return "allowed";
140 }
141
142 return m_Password;
143 }
144
145 CDBConnParams::EServerType
GetServerType(void) const146 CDBConnParamsBase::GetServerType(void) const
147 {
148 return m_ServerType;
149 }
150
151 Uint4
GetHost(void) const152 CDBConnParamsBase::GetHost(void) const
153 {
154 return m_Host;
155 }
156
157 Uint2
GetPort(void) const158 CDBConnParamsBase::GetPort(void) const
159 {
160 if (!m_PortNumber) {
161 // Artificial intelligence ...
162 switch (GetThis().GetServerType()) {
163 case eSybaseOpenServer:
164 return 2133U;
165 case eSybaseSQLServer:
166 return 2158U;
167 case eMSSqlServer:
168 return 1433U;
169 default:
170 break;
171 }
172 }
173
174 return m_PortNumber;
175 }
176
177 CRef<IConnValidator>
GetConnValidator(void) const178 CDBConnParamsBase::GetConnValidator(void) const
179 {
180 return m_Validator;
181 }
182
GetOpeningMsgHandlers(void) const183 const CDBHandlerStack& CDBConnParamsBase::GetOpeningMsgHandlers(void) const
184 {
185 return m_OpeningMsgHandlers;
186 }
187
188 string
GetParam(const string & key) const189 CDBConnParamsBase::GetParam(const string& key) const
190 {
191 TUnclassifiedParamMap::const_iterator it = m_UnclassifiedParamMap.find(key);
192
193 if (it != m_UnclassifiedParamMap.end()) {
194 return it->second;
195 }
196
197 return string();
198 }
199
200
201 }
202
203 ///////////////////////////////////////////////////////////////////////////////
CDBDefaultConnParams(const string & srv_name,const string & user_name,const string & passwd,I_DriverContext::TConnectionMode mode,bool reusable,const string & pool_name)204 CDBDefaultConnParams::CDBDefaultConnParams(
205 const string& srv_name,
206 const string& user_name,
207 const string& passwd,
208 I_DriverContext::TConnectionMode mode,
209 bool reusable,
210 const string& pool_name)
211 {
212 SetServerName(srv_name);
213 SetUserName(user_name);
214 SetPassword(passwd);
215
216 SetParam(
217 "pool_name",
218 pool_name
219 );
220
221 SetParam(
222 "secure_login",
223 ((mode & I_DriverContext::fPasswordEncrypted) != 0) ? "true" : "false"
224 );
225
226 SetParam(
227 "is_pooled",
228 reusable ? "true" : "false"
229 );
230
231 SetParam(
232 "do_not_connect",
233 (mode & I_DriverContext::fDoNotConnect) != 0 ? "true" : "false"
234 );
235 }
236
237
~CDBDefaultConnParams(void)238 CDBDefaultConnParams::~CDBDefaultConnParams(void)
239 {
240 }
241
242
243
244 ///////////////////////////////////////////////////////////////////////////////
CDBUriConnParams(const string & params)245 CDBUriConnParams::CDBUriConnParams(const string& params)
246 {
247 string::size_type pos = 0;
248 string::size_type cur_pos = 0;
249
250 // Check for 'dbapi:' ...
251 pos = params.find_first_of(":", pos);
252 if (pos == string::npos) {
253 DATABASE_DRIVER_ERROR("Invalid database locator format, should start with 'dbapi:'", 20001);
254 }
255
256 if (! NStr::StartsWith(params, "dbapi:", NStr::eNocase)) {
257 DATABASE_DRIVER_ERROR("Invalid database locator format, should start with 'dbapi:'", 20001);
258 }
259
260 cur_pos = pos + 1;
261
262 // Check for driver name ...
263 pos = params.find("//", cur_pos);
264 if (pos == string::npos) {
265 DATABASE_DRIVER_ERROR("Invalid database locator format, should contain driver name", 20001);
266 }
267
268 if (pos != cur_pos) {
269 string driver_name = params.substr(cur_pos, pos - cur_pos - 1);
270 SetDriverName(driver_name);
271 }
272
273 cur_pos = pos + 2;
274
275 // Check for user name and password ...
276 pos = params.find_first_of(":@", cur_pos);
277 if (pos != string::npos) {
278 string user_name = params.substr(cur_pos, pos - cur_pos);
279
280 if (params[pos] == '@') {
281 SetUserName(user_name);
282
283 cur_pos = pos + 1;
284
285 ParseServer(params, cur_pos);
286 } else {
287 // Look ahead, we probably found a host name ...
288 cur_pos = pos + 1;
289
290 pos = params.find_first_of("@", cur_pos);
291
292 if (pos != string::npos) {
293 // Previous value was an user name ...
294 SetUserName(user_name);
295
296 string password = params.substr(cur_pos, pos - cur_pos);
297 SetPassword(password);
298
299 cur_pos = pos + 1;
300 }
301
302 ParseServer(params, cur_pos);
303 }
304 } else {
305 ParseServer(params, cur_pos);
306 }
307
308 }
309
310
~CDBUriConnParams(void)311 CDBUriConnParams::~CDBUriConnParams(void)
312 {
313 }
314
315
ParseServer(const string & params,size_t cur_pos)316 void CDBUriConnParams::ParseServer(const string& params, size_t cur_pos)
317 {
318 string::size_type pos = 0;
319 pos = params.find_first_of(":/?", cur_pos);
320
321 if (pos != string::npos) {
322 string param_pairs;
323 string server_name = params.substr(cur_pos, pos - cur_pos);
324 SetServerName(server_name);
325
326 switch (params[pos]) {
327 case ':':
328 cur_pos = pos + 1;
329 pos = params.find_first_of("/?", cur_pos);
330
331 if (pos != string::npos) {
332 string port = params.substr(cur_pos, pos - cur_pos);
333 SetPort(static_cast<Uint2>(NStr::StringToInt(port)));
334
335 switch (params[pos]) {
336 case '/':
337 cur_pos = pos + 1;
338 ParseSlash(params, cur_pos);
339
340 break;
341 case '?':
342 param_pairs = params.substr(cur_pos);
343 break;
344 }
345 } else {
346 string port = params.substr(cur_pos);
347 SetPort(static_cast<Uint2>(NStr::StringToInt(port)));
348 }
349
350 break;
351 case '/':
352 cur_pos = pos + 1;
353 ParseSlash(params, cur_pos);
354
355 break;
356 case '?':
357 param_pairs = params.substr(cur_pos);
358
359 break;
360 default:
361 break;
362 }
363 } else {
364 string server_name = params.substr(cur_pos);
365 SetServerName(server_name);
366 // No parameter pairs. We are at the end ...
367 }
368 }
369
ParseSlash(const string & params,size_t cur_pos)370 void CDBUriConnParams::ParseSlash(const string& params, size_t cur_pos)
371 {
372 string::size_type pos = 0;
373 string param_pairs;
374
375 pos = params.find_first_of("?", cur_pos);
376 if (pos != string::npos) {
377 string database_name = params.substr(cur_pos, pos - cur_pos);
378
379 SetDatabaseName(database_name);
380
381 cur_pos = pos + 1;
382 param_pairs = params.substr(cur_pos);
383 } else {
384 string database_name = params.substr(cur_pos);
385
386 SetDatabaseName(database_name);
387 }
388 }
389
ParseParamPairs(const string & param_pairs,size_t cur_pos)390 void CDBUriConnParams::ParseParamPairs(const string& param_pairs, size_t cur_pos)
391 {
392 vector<string> arr_param;
393 string key;
394 string value;
395
396 NStr::Split(param_pairs, "&", arr_param);
397
398 ITERATE(vector<string>, it, arr_param) {
399 if (NStr::SplitInTwo(*it, "=", key, value)) {
400 NStr::TruncateSpacesInPlace(key);
401 NStr::TruncateSpacesInPlace(value);
402 SetParam(key, value);
403 } else {
404 key = *it;
405 NStr::TruncateSpacesInPlace(key);
406 SetParam(key, key);
407 }
408 }
409 }
410
411 ///////////////////////////////////////////////////////////////////////////////
CDB_ODBC_ConnParams(const string & params)412 CDB_ODBC_ConnParams::CDB_ODBC_ConnParams(const string& params)
413 {
414 vector<string> arr_param;
415 string key;
416 string value;
417
418 NStr::Split(params, ";", arr_param);
419
420 ITERATE(vector<string>, it, arr_param) {
421 if (NStr::SplitInTwo(*it, "=", key, value)) {
422 NStr::TruncateSpacesInPlace(key);
423 NStr::TruncateSpacesInPlace(value);
424 x_MapPairToParam(key, value);
425 } else {
426 key = *it;
427 NStr::TruncateSpacesInPlace(key);
428 x_MapPairToParam(key, key);
429 }
430 }
431 }
432
433
x_MapPairToParam(const string & key,const string & value)434 void CDB_ODBC_ConnParams::x_MapPairToParam(const string& key, const string& value)
435 {
436 // MS SQL Server related attributes ...
437 if (NStr::Equal(key, "SERVER", NStr::eNocase)) {
438 SetServerName(value);
439 } else if (NStr::Equal(key, "UID", NStr::eNocase)) {
440 SetUserName(value);
441 } else if (NStr::Equal(key, "PWD", NStr::eNocase)) {
442 SetPassword(value);
443 } else if (NStr::Equal(key, "DRIVER", NStr::eNocase)) {
444 SetDriverName(value);
445 } else if (NStr::Equal(key, "DATABASE", NStr::eNocase)) {
446 SetDatabaseName(value);
447 } else if (NStr::Equal(key, "ADDRESS", NStr::eNocase)) {
448 string host;
449 string port;
450
451 NStr::SplitInTwo(value, ",", host, port);
452 NStr::TruncateSpacesInPlace(host);
453 NStr::TruncateSpacesInPlace(port);
454
455 // SetHost(host);
456 SetPort(static_cast<Uint2>(NStr::StringToInt(port)));
457 } else {
458 SetParam(key, value);
459 }
460 }
461
462
~CDB_ODBC_ConnParams(void)463 CDB_ODBC_ConnParams::~CDB_ODBC_ConnParams(void)
464 {
465 }
466
467
468 /////////////////////////////////////////////////////////////////////////////
CDBEnvConnParams(const CDBConnParams & other,const string & server_name_env,const string & database_name_env,const string & user_name_env,const string & passwd_env)469 CDBEnvConnParams::CDBEnvConnParams(
470 const CDBConnParams& other,
471 const string& server_name_env,
472 const string& database_name_env,
473 const string& user_name_env,
474 const string& passwd_env
475 )
476 : CDBConnParamsDelegate(other)
477 , m_ServerNameEnv(server_name_env)
478 , m_DatabaseNameEnv(database_name_env)
479 , m_UserNameEnv(user_name_env)
480 , m_PasswordEnv(passwd_env)
481 {
482 }
483
~CDBEnvConnParams(void)484 CDBEnvConnParams::~CDBEnvConnParams(void)
485 {
486 }
487
488
GetServerName(void) const489 string CDBEnvConnParams::GetServerName(void) const
490 {
491 const string& value = m_Env.Get(m_ServerNameEnv);
492
493 if (!value.empty()) {
494 return value;
495 }
496
497 return CDBConnParamsDelegate::GetServerName();
498 }
499
GetDatabaseName(void) const500 string CDBEnvConnParams::GetDatabaseName(void) const
501 {
502 const string& value = m_Env.Get(m_DatabaseNameEnv);
503
504 if (!value.empty()) {
505 return value;
506 }
507
508 return CDBConnParamsDelegate::GetDatabaseName();
509 }
510
GetUserName(void) const511 string CDBEnvConnParams::GetUserName(void) const
512 {
513 const string& value = m_Env.Get(m_UserNameEnv);
514
515 if (!value.empty()) {
516 return value;
517 }
518
519 return CDBConnParamsDelegate::GetUserName();
520 }
521
GetPassword(void) const522 string CDBEnvConnParams::GetPassword(void) const
523 {
524 const string& value = m_Env.Get(m_PasswordEnv);
525
526 if (!value.empty()) {
527 return value;
528 }
529
530 return CDBConnParamsDelegate::GetPassword();
531 }
532
533
534
535 /////////////////////////////////////////////////////////////////////////////
CDBInterfacesFileConnParams(const CDBConnParams & other,const string & file)536 CDBInterfacesFileConnParams::CDBInterfacesFileConnParams(
537 const CDBConnParams& other,
538 const string& file
539 )
540 : CDBConnParamsDelegate(other)
541 {
542 string file_name;
543
544 if (!file.empty() && CFile(file).Exists()) {
545 file_name = file;
546 } else {
547 const CNcbiEnvironment env;
548
549 // Get it from a default place ...
550 file_name = env.Get("SYBASE") + "/interfaces";
551 if (!CFile(file_name).Exists()) {
552 file_name = env.Get("HOME") + "/.interfaces";
553 if (!CFile(file_name).Exists()) {
554 return;
555 }
556 }
557 }
558
559 CNcbiIfstream istr(file_name.c_str());
560
561 if (!istr) {
562 return;
563 }
564
565 string line;
566 string key;
567 string host_str;
568 string port_str;
569
570 vector<string> arr_param;
571 enum EState {eInitial, eKeyRead, eValueRead};
572 EState state = eInitial;
573 bool tli_format = false;
574
575 while (NcbiGetlineEOL(istr, line)) {
576 if (line[0] == '#' || line.empty()) {
577 continue;
578 } else if (line[0] == '\t') {
579 if (state == eKeyRead) {
580 NStr::TruncateSpacesInPlace(line);
581 arr_param.clear();
582 NStr::Split(line, "\t ", arr_param);
583
584 if (NStr::Equal(arr_param[0], "query")) {
585 if (NStr::Equal(arr_param[1], "tli")) {
586 tli_format = true;
587 const string tli_str = arr_param[arr_param.size() - 1];
588 host_str = tli_str.substr(10 - 1, 8);
589 port_str = tli_str.substr(6 - 1, 4);
590 } else {
591 host_str = arr_param[arr_param.size() - 2];
592 port_str = arr_param[arr_param.size() - 1];
593 }
594
595 state = eValueRead;
596 }
597 } else {
598 // Skip all values except the first one ...
599 continue;
600 }
601 } else {
602 if (state == eInitial) {
603 key = line;
604 NStr::TruncateSpacesInPlace(key);
605 state = eKeyRead;
606 } else {
607 // Error ...
608 DATABASE_DRIVER_ERROR("Invalid interfaces file line: " + line, 20001);
609 }
610 }
611
612 if (state == eValueRead) {
613 Uint4 host = 0;
614 unsigned char* b = (unsigned char*) &host;
615
616 if (!host_str.empty() && !port_str.empty()) {
617 if (tli_format) {
618 b[0] = NStr::StringToUInt(host_str.substr(0, 2), 0, 16);
619 b[1] = NStr::StringToUInt(host_str.substr(2, 2), 0, 16);
620 b[2] = NStr::StringToUInt(host_str.substr(4, 2), 0, 16);
621 b[3] = NStr::StringToUInt(host_str.substr(6, 2), 0, 16);
622
623 m_Records[key] = SIRecord(host, NStr::StringToUInt(port_str, 0, 16));
624 } else {
625 NStr::TruncateSpacesInPlace(host_str);
626 arr_param.clear();
627 NStr::Split(host_str, ".", arr_param);
628
629 b[0] = NStr::StringToUInt(arr_param[0]);
630 b[1] = NStr::StringToUInt(arr_param[1]);
631 b[2] = NStr::StringToUInt(arr_param[2]);
632 b[3] = NStr::StringToUInt(arr_param[3]);
633
634 m_Records[key] = SIRecord(host, NStr::StringToUInt(port_str));
635 }
636 }
637
638 state = eInitial;
639 }
640 }
641 }
642
~CDBInterfacesFileConnParams(void)643 CDBInterfacesFileConnParams::~CDBInterfacesFileConnParams(void)
644 {
645 }
646
647
648 CDBConnParams::EServerType
GetServerType(void) const649 CDBInterfacesFileConnParams::GetServerType(void) const
650 {
651 const string server_name = GetThis().GetServerName();
652 records_type::const_iterator it = m_Records.find(server_name);
653
654 if (it != m_Records.end()) {
655 switch(it->second.m_Port) {
656 case 2133U:
657 return eSybaseOpenServer;
658 case 2158U:
659 return eSybaseSQLServer;
660 case 1433:
661 return eMSSqlServer;
662 default:
663 break;
664 }
665 }
666
667 return CDBConnParamsDelegate::GetServerType();
668 }
669
GetHost(void) const670 Uint4 CDBInterfacesFileConnParams::GetHost(void) const
671 {
672 const string server_name = GetThis().GetServerName();
673 records_type::const_iterator it = m_Records.find(server_name);
674
675 if (it != m_Records.end()) {
676 return it->second.m_Host;
677 }
678
679 return CDBConnParamsDelegate::GetHost();
680 }
681
GetPort(void) const682 Uint2 CDBInterfacesFileConnParams::GetPort(void) const
683 {
684 const string server_name = GetThis().GetServerName();
685 records_type::const_iterator it = m_Records.find(server_name);
686
687 if (it != m_Records.end()) {
688 return it->second.m_Port;
689 }
690
691 return CDBConnParamsDelegate::GetPort();
692 }
693
694
695 ////////////////////////////////////////////////////////////////////////////
CCPPToolkitConnParams(const CDBConnParams & other)696 CCPPToolkitConnParams::CCPPToolkitConnParams(const CDBConnParams& other)
697 : CDBConnParamsDelegate(other)
698 {
699 }
700
701
~CCPPToolkitConnParams(void)702 CCPPToolkitConnParams::~CCPPToolkitConnParams(void)
703 {
704 }
705
706
707 CDBConnParams::EServerType
GetServerType(void) const708 CCPPToolkitConnParams::GetServerType(void) const
709 {
710 EServerType type = GetServerType(GetThis().GetServerName());
711 return (type == eUnknown) ? CDBConnParamsDelegate::GetServerType() : type;
712 }
713
714
715 CDBConnParams::EServerType
GetServerType(const CTempString & server_name)716 CCPPToolkitConnParams::GetServerType(const CTempString& server_name)
717 {
718 // Artificial intelligence ...
719 if (NStr::CompareNocase(server_name, 0, 8, "DBAPI_MS") == 0
720 || NStr::CompareNocase(server_name, 0, 5, "MSSQL") == 0
721 || NStr::CompareNocase(server_name, 0, 5, "MSDEV") == 0
722 || NStr::CompareNocase(server_name, 0, 9, "MS2008DEV") == 0
723 || NStr::CompareNocase(server_name, 0, 7, "OAMSDEV") == 0
724 || NStr::CompareNocase(server_name, 0, 6, "QMSSQL") == 0
725 || NStr::CompareNocase(server_name, 0, 6, "BLASTQ") == 0
726 || NStr::CompareNocase(server_name, 0, 4, "GENE") == 0
727 || NStr::CompareNocase(server_name, 0, 5, "GPIPE") == 0
728 || NStr::CompareNocase(server_name, 0, 7, "MAPVIEW") == 0
729 || NStr::CompareNocase(server_name, 0, 5, "MSSNP") == 0
730 )
731 {
732 return eMSSqlServer;
733 } else if ( NStr::CompareNocase(server_name, 0, 5, "GLUCK") == 0
734 || NStr::CompareNocase(server_name, 0, 8, "SCHUMANN") == 0
735 || NStr::CompareNocase(server_name, 0, 9, "DBAPI_DEV") == 0
736 || NStr::CompareNocase(server_name, 0, 8, "SCHUBERT") == 0
737 || NStr::CompareNocase(server_name, 0, 9, "DBAPI_SYB") == 0
738 || NStr::CompareNocase(server_name, 0, 7, "STRAUSS") == 0
739 || NStr::CompareNocase(server_name, 0, 6, "MOZART") == 0
740 || NStr::CompareNocase(server_name, 0, 6, "OBERON") == 0
741 || NStr::CompareNocase(server_name, 0, 8, "THALBERG") == 0
742 || NStr::CompareNocase(server_name, 0, 6, "BARTOK") == 0
743 )
744 {
745 return eSybaseSQLServer;
746 } else if ( NStr::CompareNocase(server_name, 0, 7, "LINK_OS") == 0
747 || NStr::CompareNocase(server_name, 0, 7, "MAIL_OS") == 0
748 || NStr::CompareNocase(server_name, 0, 9, "PUBSEQ_OS") == 0
749 || NStr::CompareNocase(server_name, 0, 6, "IDFLOW") == 0
750 || NStr::CompareNocase(server_name, 0, 6, "IDLOAD") == 0
751 || NStr::CompareNocase(server_name, 0, 6, "IDPROD") == 0
752 || NStr::CompareNocase(server_name, 0, 4, "IDQA") == 0
753 )
754 {
755 return eSybaseOpenServer;
756 }
757
758 return eUnknown;
759 }
760
761
762
763 END_NCBI_SCOPE
764
765