NCBI C++ ToolKit
sdbapi.cpp
Go to the documentation of this file.

Go to the SVN repository for this file.

1 /* $Id: sdbapi.cpp 102170 2024-04-09 14:51:33Z 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: Pavel Ivanov
27  *
28  */
29 
30 #include <ncbi_pch.hpp>
31 
34 #include <connect/ext/ncbi_crypt.h>
35 #ifdef HAVE_LIBNCBICRYPT
36 # include <ncbi_key_lookup.h>
37 #endif
38 
41 #include <dbapi/driver/drivers.hpp>
44 #include <dbapi/error_codes.hpp>
45 
46 #include "sdbapi_impl.hpp"
47 #include "../rw_impl.hpp"
48 
49 
50 #define NCBI_USE_ERRCODE_X Dbapi_Sdbapi
51 
52 
54 
55 
56 #define SDBAPI_CATCH_LOWLEVEL() \
57  catch (CDB_DeadlockEx& ex) { \
58  NCBI_RETHROW(ex, CSDB_DeadlockException, eLowLevel, ""); \
59  } catch (CDB_Exception& ex) { \
60  NCBI_RETHROW(ex, CSDB_Exception, eLowLevel, ""); \
61  }
62 
63 #define SDBAPI_THROW(code, msg) \
64  NCBI_THROW(CSDB_Exception, code, \
65  CDB_Exception::SMessageInContext(msg, x_GetContext()))
66 
67 
68 
69 const char*
71 {
72  switch (GetErrCode()) {
73  case eURLFormat: return "eURLFormat";
74  case eClosed: return "eClosed";
75  case eStarted: return "eStarted";
76  case eNotInOrder: return "eNotInOrder";
77  case eInconsistent: return "eInconsistent";
78  case eUnsupported: return "eUnsupported";
79  case eNotExist: return "eNotExist";
80  case eOutOfBounds: return "eOutOfBounds";
81  case eLowLevel: return "eLowLevel";
82  case eWrongParams: return "eWrongParams";
83  default: return CException::GetErrCodeString();
84  }
85 }
86 
88 
89 void CSDB_Exception::ReportExtra(ostream& os) const
90 {
91  os << *m_Context;
92 }
93 
94 void CSDB_Exception::x_Init(const CDiagCompileInfo&, const string&,
95  const CException* prev, EDiagSev)
96 {
97  const CDB_Exception* dbex = dynamic_cast<const CDB_Exception*>(prev);
98  if (dbex == NULL) {
99  if (m_Context.Empty()) {
100  m_Context.Reset(&kEmptyContext.Get());
101  }
102  } else if (m_Context.Empty()) {
103  m_Context.Reset(&dbex->GetContext());
104  } else {
105  const_cast<CDB_Exception::SContext&>(*m_Context)
106  .UpdateFrom(dbex->GetContext());
107  }
108 }
109 
111 {
113  const CSDB_Exception* sdb_src = dynamic_cast<const CSDB_Exception*>(&src);
114  _ASSERT(sdb_src != NULL);
115  m_Context = sdb_src->m_Context;
116 }
117 
119 {
120  ERetriable retriable = CException::GetRetriable();
121 
122  if (retriable == eRetriable_Unknown) {
123  const CException* predecessor = GetPredecessor();
124  if (predecessor)
125  return predecessor->GetRetriable();
126  }
127  return retriable;
128 }
129 
130 
131 static EDB_Type
133 {
134  switch (type)
135  {
136  case eSDB_Byte:
137  return eDB_TinyInt;
138  case eSDB_Short:
139  return eDB_SmallInt;
140  case eSDB_Int4:
141  return eDB_Int;
142  case eSDB_Int8:
143  return eDB_BigInt;
144  case eSDB_Float:
145  return eDB_Float;
146  case eSDB_Double:
147  return eDB_Double;
148  case eSDB_String:
149  case eSDB_StringUCS2:
150  return eDB_VarChar;
151  case eSDB_Binary:
152  return eDB_VarBinary;
153  case eSDB_DateTime:
154  return eDB_DateTime;
155  case eSDB_BigDateTime:
156  return eDB_BigDateTime;
157  case eSDB_Text:
158  case eSDB_TextUCS2:
159  return eDB_Text;
160  case eSDB_Image:
161  return eDB_Image;
162  case eSDB_StringMax:
163  case eSDB_StringMaxUCS2:
164  return eDB_VarCharMax;
165  case eSDB_BinaryMax:
166  return eDB_VarBinaryMax;
167  case eSDB_Bit:
168  return eDB_Bit;
169  }
170  return eDB_UnsupportedType;
171 }
172 
173 static ESDB_Type
175 {
176  switch (type) {
177  case eDB_Int:
178  return eSDB_Int4;
179  case eDB_SmallInt:
180  return eSDB_Short;
181  case eDB_TinyInt:
182  return eSDB_Byte;
183  case eDB_BigInt:
184  return eSDB_Int8;
185  case eDB_Numeric:
186  case eDB_VarChar:
187  case eDB_Char:
188  case eDB_LongChar:
189  return eSDB_String;
190  case eDB_VarBinary:
191  case eDB_Binary:
192  case eDB_LongBinary:
193  return eSDB_Binary;
194  case eDB_Float:
195  return eSDB_Float;
196  case eDB_Double:
197  return eSDB_Double;
198  case eDB_DateTime:
199  case eDB_SmallDateTime:
200  return eSDB_DateTime;
201  case eDB_BigDateTime:
202  return eSDB_BigDateTime;
203  case eDB_Text:
204  return eSDB_Text;
205  case eDB_Image:
206  return eSDB_Image;
207  case eDB_VarCharMax:
208  return eSDB_StringMax;
209  case eDB_VarBinaryMax:
210  return eSDB_BinaryMax;
211  case eDB_Bit:
212  return eSDB_Bit;
213  case eDB_UnsupportedType:
214  break;
215  }
216  _ASSERT(false);
217  return eSDB_String;
218 }
219 
220 static IBulkInsert::EHints
222 {
223  switch (hints) {
226  }
227  _ASSERT(false);
228  return IBulkInsert::EHints(hints);
229 }
230 
231 static IBulkInsert::EHints
233 {
234  switch (hints) {
238  }
239  _ASSERT(false);
240  return IBulkInsert::EHints(hints);
241 }
242 
243 static void
244 s_ConvertionNotSupported(const char* one_type, EDB_Type other_type)
245 {
247  "Conversion between " + string(one_type) + " and "
248  + CDB_Object::GetTypeName(other_type, false)
249  + " is not supported");
250 }
251 
252 #ifdef NCBI_COMPILER_WORKSHOP
253 #define CONVERTVALUE_STATIC
254 #else
255 #define CONVERTVALUE_STATIC static
256 #endif
257 
259 s_ConvertValue(const CTime& from_val, CVariant& to_var)
260 {
261  switch (to_var.GetType()) {
262  case eDB_DateTime:
263  case eDB_SmallDateTime:
264  case eDB_BigDateTime:
265  to_var = from_val;
266  break;
267  case eDB_VarChar:
268  case eDB_Char:
269  case eDB_LongChar:
270  to_var = from_val.AsString();
271  break;
272  case eDB_Text:
273  case eDB_VarCharMax:
274  {
275  string str_val = from_val.AsString();
276  to_var.Truncate();
277  to_var.Append(str_val.data(), str_val.size());
278  break;
279  }
280  default:
281  s_ConvertionNotSupported("CTime", to_var.GetType());
282  }
283 }
284 
286 s_ConvertValue(Int8 from_val, CVariant& to_var)
287 {
288  switch (to_var.GetType()) {
289  case eDB_BigInt:
290  to_var = Int8(from_val);
291  break;
292  case eDB_VarChar:
293  case eDB_Char:
294  case eDB_LongChar:
295  to_var = NStr::Int8ToString(from_val);
296  break;
297  case eDB_Text:
298  case eDB_VarCharMax:
299  {
300  string str_val = NStr::Int8ToString(from_val);
301  to_var.Truncate();
302  to_var.Append(str_val.data(), str_val.size());
303  break;
304  }
305  default:
306  s_ConvertionNotSupported("Int8", to_var.GetType());
307  }
308 }
309 
311 s_ConvertValue(Int4 from_val, CVariant& to_var)
312 {
313  switch (to_var.GetType()) {
314  case eDB_BigInt:
315  to_var = Int8(from_val);
316  break;
317  case eDB_Int:
318  to_var = Int4(from_val);
319  break;
320  case eDB_VarChar:
321  case eDB_Char:
322  case eDB_LongChar:
323  to_var = NStr::IntToString(from_val);
324  break;
325  case eDB_Text:
326  case eDB_VarCharMax:
327  {
328  string str_val = NStr::IntToString(from_val);
329  to_var.Truncate();
330  to_var.Append(str_val.data(), str_val.size());
331  break;
332  }
333  default:
334  s_ConvertionNotSupported("Int4", to_var.GetType());
335  }
336 }
337 
339 s_ConvertValue(short from_val, CVariant& to_var)
340 {
341  switch (to_var.GetType()) {
342  case eDB_BigInt:
343  to_var = Int8(from_val);
344  break;
345  case eDB_Int:
346  to_var = Int4(from_val);
347  break;
348  case eDB_SmallInt:
349  to_var = Int2(from_val);
350  break;
351  case eDB_VarChar:
352  case eDB_Char:
353  case eDB_LongChar:
354  to_var = NStr::IntToString(from_val);
355  break;
356  case eDB_Text:
357  case eDB_VarCharMax:
358  {
359  string str_val = NStr::IntToString(from_val);
360  to_var.Truncate();
361  to_var.Append(str_val.data(), str_val.size());
362  break;
363  }
364  default:
365  s_ConvertionNotSupported("short", to_var.GetType());
366  }
367 }
368 
370 s_ConvertValue(unsigned char from_val, CVariant& to_var)
371 {
372  switch (to_var.GetType()) {
373  case eDB_BigInt:
374  to_var = Int8(from_val);
375  break;
376  case eDB_Int:
377  to_var = Int4(from_val);
378  break;
379  case eDB_SmallInt:
380  to_var = Int2(from_val);
381  break;
382  case eDB_TinyInt:
383  to_var = Uint1(from_val);
384  break;
385  case eDB_VarChar:
386  case eDB_Char:
387  case eDB_LongChar:
388  to_var = NStr::IntToString(from_val);
389  break;
390  case eDB_Text:
391  case eDB_VarCharMax:
392  {
393  string str_val = NStr::IntToString(from_val);
394  to_var.Truncate();
395  to_var.Append(str_val.data(), str_val.size());
396  break;
397  }
398  default:
399  s_ConvertionNotSupported("unsigned char", to_var.GetType());
400  }
401 }
402 
404 s_ConvertValue(bool from_val, CVariant& to_var)
405 {
406  switch (to_var.GetType()) {
407  case eDB_BigInt:
408  to_var = Int8(from_val);
409  break;
410  case eDB_Int:
411  to_var = Int4(from_val);
412  break;
413  case eDB_SmallInt:
414  to_var = Int2(from_val);
415  break;
416  case eDB_TinyInt:
417  to_var = Uint1(from_val);
418  break;
419  case eDB_Bit:
420  to_var = bool(from_val);
421  break;
422  case eDB_VarChar:
423  case eDB_Char:
424  case eDB_LongChar:
425  to_var = NStr::BoolToString(from_val);
426  break;
427  case eDB_Text:
428  case eDB_VarCharMax:
429  {
430  string str_val = NStr::BoolToString(from_val);
431  to_var.Truncate();
432  to_var.Append(str_val.data(), str_val.size());
433  break;
434  }
435  default:
436  s_ConvertionNotSupported("bool", to_var.GetType());
437  }
438 }
439 
441 s_ConvertValue(const float& from_val, CVariant& to_var)
442 {
443  switch (to_var.GetType()) {
444  case eDB_Float:
445  to_var = float(from_val);
446  break;
447  case eDB_Double:
448  to_var = double(from_val);
449  break;
450  case eDB_VarChar:
451  case eDB_Char:
452  case eDB_LongChar:
453  to_var = NStr::DoubleToString(from_val);
454  break;
455  case eDB_Text:
456  case eDB_VarCharMax:
457  {
458  string str_val = NStr::DoubleToString(from_val);
459  to_var.Truncate();
460  to_var.Append(str_val.data(), str_val.size());
461  break;
462  }
463  default:
464  s_ConvertionNotSupported("float", to_var.GetType());
465  }
466 }
467 
469 s_ConvertValue(const double& from_val, CVariant& to_var)
470 {
471  switch (to_var.GetType()) {
472  case eDB_Double:
473  to_var = double(from_val);
474  break;
475  case eDB_VarChar:
476  case eDB_Char:
477  case eDB_LongChar:
478  to_var = NStr::DoubleToString(from_val);
479  break;
480  case eDB_Text:
481  case eDB_VarCharMax:
482  {
483  string str_val = NStr::DoubleToString(from_val);
484  to_var.Truncate();
485  to_var.Append(str_val.data(), str_val.size());
486  break;
487  }
488  default:
489  s_ConvertionNotSupported("double", to_var.GetType());
490  }
491 }
492 
494 s_ConvertValue(const string& from_val, CVariant& to_var)
495 {
496  switch (to_var.GetType()) {
497  case eDB_Char:
498  case eDB_VarChar:
499  case eDB_LongChar:
500  to_var = from_val;
501  break;
502  case eDB_Binary:
503  case eDB_LongBinary:
504  case eDB_VarBinary:
505  to_var = CVariant::VarBinary(from_val.data(), from_val.size());
506  break;
507  case eDB_Text:
508  case eDB_VarCharMax:
509  to_var.Truncate();
510  to_var.Append(from_val);
511  break;
512  case eDB_Image:
513  case eDB_VarBinaryMax:
514  to_var.Truncate();
515  to_var.Append(from_val.data(), from_val.size());
516  break;
517  case eDB_Bit:
518  to_var = NStr::StringToBool(from_val);
519  break;
520  case eDB_Int:
521  to_var = NStr::StringToInt(from_val);
522  break;
523  case eDB_SmallInt:
524  to_var = NStr::StringToNumeric<Int2>(from_val);
525  break;
526  case eDB_TinyInt:
527  to_var = NStr::StringToNumeric<Uint1>(from_val);
528  break;
529  case eDB_BigInt:
530  to_var = NStr::StringToInt8(from_val);
531  break;
532  case eDB_Double:
533  to_var = NStr::StringToDouble(from_val);
534  break;
535  case eDB_DateTime:
536  case eDB_SmallDateTime:
537  case eDB_BigDateTime:
538  to_var = CTime(from_val);
539  break;
540  default:
541  s_ConvertionNotSupported("string", to_var.GetType());
542  }
543 }
544 
546 s_ConvertValue(const char* from_val, CVariant& to_var)
547 {
548  s_ConvertValue(string(from_val), to_var);
549 }
550 
552 s_ConvertValue(const TStringUCS2& from_val, CVariant& to_var)
553 {
554  switch (to_var.GetType()) {
555  case eDB_Char:
556  case eDB_VarChar:
557  case eDB_LongChar:
558  to_var = from_val;
559  break;
560  case eDB_Binary:
561  case eDB_LongBinary:
562  case eDB_VarBinary:
563  s_ConvertValue(string(reinterpret_cast<const char*>(from_val.data()),
564  from_val.size() * sizeof(TCharUCS2)),
565  to_var);
566  break;
567  case eDB_Text:
568  case eDB_VarCharMax:
569  to_var.Truncate();
570  to_var.Append(from_val);
571  break;
572  case eDB_Image:
573  case eDB_VarBinaryMax:
574  to_var.Truncate();
575  to_var.Append(reinterpret_cast<const char*>(from_val.data()),
576  from_val.size() * sizeof(TCharUCS2));
577  break;
578  case eDB_Bit:
579  case eDB_Int:
580  case eDB_BigInt:
581  case eDB_Double:
582  case eDB_DateTime:
583  case eDB_SmallDateTime:
584  case eDB_BigDateTime:
585  s_ConvertValue(CUtf8::AsUTF8(from_val), to_var);
586  break;
587  default:
588  s_ConvertionNotSupported("UCS2 string", to_var.GetType());
589  }
590 }
591 
592 #undef CONVERTVALUE_STATIC
593 
594 static void
595 s_ConvertValue(const CVariant& from_var, CTime& to_val)
596 {
597  switch (from_var.GetType()) {
598  case eDB_DateTime:
599  case eDB_SmallDateTime:
600  case eDB_BigDateTime:
601  to_val = from_var.GetCTime();
602  break;
603  case eDB_VarChar:
604  case eDB_Char:
605  case eDB_LongChar:
606  case eDB_Text:
607  case eDB_VarCharMax:
608  {
609  string s = from_var.GetString();
610  try {
611  to_val = CTime(s);
612  } catch (CTimeException&) {
613  auto id = CDB_BigDateTime::Identify(s);
615  id.second));
616  }
617  break;
618  }
619  default:
620  s_ConvertionNotSupported("CTime", from_var.GetType());
621  }
622 }
623 
624 static void
625 s_ConvertValue(const CVariant& from_var, Int8& to_val)
626 {
627  switch (from_var.GetType()) {
628  case eDB_BigInt:
629  case eDB_Int:
630  case eDB_SmallInt:
631  case eDB_TinyInt:
632  to_val = from_var.GetInt8();
633  break;
634  case eDB_Bit:
635  to_val = Int8(from_var.GetBit());
636  break;
637  case eDB_VarChar:
638  case eDB_Char:
639  case eDB_LongChar:
640  case eDB_Text:
641  case eDB_VarCharMax:
642  to_val = NStr::StringToInt8(from_var.GetString());
643  break;
644  default:
645  s_ConvertionNotSupported("Int8", from_var.GetType());
646  }
647 }
648 
649 static void
650 s_ConvertValue(const CVariant& from_var, Int4& to_val)
651 {
652  Int8 temp_val;
653  switch (from_var.GetType()) {
654  case eDB_BigInt:
655  temp_val = from_var.GetInt8();
656  break;
657  case eDB_Int:
658  case eDB_SmallInt:
659  case eDB_TinyInt:
660  to_val = from_var.GetInt4();
661  return;
662  case eDB_Bit:
663  to_val = Int4(from_var.GetBit());
664  return;
665  case eDB_VarChar:
666  case eDB_Char:
667  case eDB_LongChar:
668  case eDB_Text:
669  case eDB_VarCharMax:
670  temp_val = NStr::StringToInt8(from_var.GetString());
671  break;
672  default:
673  s_ConvertionNotSupported("Int4", from_var.GetType());
674  return;
675  }
676  if (temp_val < numeric_limits<Int4>::min()
677  || temp_val > numeric_limits<Int4>::max())
678  {
680  "Value for Int4 is out of bounds: "
681  + NStr::NumericToString(temp_val));
682  }
683  to_val = Int4(temp_val);
684 }
685 
686 static void
687 s_ConvertValue(const CVariant& from_var, short& to_val)
688 {
689  Int8 temp_val;
690  switch (from_var.GetType()) {
691  case eDB_BigInt:
692  case eDB_Int:
693  temp_val = from_var.GetInt8();
694  break;
695  case eDB_SmallInt:
696  case eDB_TinyInt:
697  to_val = from_var.GetInt2();
698  return;
699  case eDB_Bit:
700  to_val = Int2(from_var.GetBit());
701  return;
702  case eDB_VarChar:
703  case eDB_Char:
704  case eDB_LongChar:
705  case eDB_Text:
706  case eDB_VarCharMax:
707  temp_val = NStr::StringToInt8(from_var.GetString());
708  break;
709  default:
710  s_ConvertionNotSupported("short", from_var.GetType());
711  return;
712  }
713  if (temp_val < numeric_limits<short>::min()
714  || temp_val > numeric_limits<short>::max())
715  {
717  "Value for short is out of bounds: "
718  + NStr::NumericToString(temp_val));
719  }
720  to_val = short(temp_val);
721 }
722 
723 static void
724 s_ConvertValue(const CVariant& from_var, unsigned char& to_val)
725 {
726  Int8 temp_val;
727  switch (from_var.GetType()) {
728  case eDB_BigInt:
729  case eDB_Int:
730  case eDB_SmallInt:
731  temp_val = from_var.GetInt8();
732  break;
733  case eDB_TinyInt:
734  to_val = from_var.GetByte();
735  return;
736  case eDB_Bit:
737  to_val = static_cast<unsigned char>(from_var.GetBit());
738  return;
739  case eDB_VarChar:
740  case eDB_Char:
741  case eDB_LongChar:
742  case eDB_Text:
743  case eDB_VarCharMax:
744  temp_val = NStr::StringToInt8(from_var.GetString());
745  break;
746  default:
747  s_ConvertionNotSupported("unsigned char", from_var.GetType());
748  return;
749  }
750  if (temp_val < numeric_limits<unsigned char>::min()
751  || temp_val > numeric_limits<unsigned char>::max())
752  {
754  "Value for unsigned char is out of bounds: "
755  + NStr::NumericToString(temp_val));
756  }
757  to_val = static_cast<unsigned char>(temp_val);
758 }
759 
760 static void
761 s_ConvertValue(const CVariant& from_var, bool& to_val)
762 {
763  Int8 temp_val;
764  switch (from_var.GetType()) {
765  case eDB_BigInt:
766  case eDB_Int:
767  case eDB_SmallInt:
768  case eDB_TinyInt:
769  temp_val = from_var.GetInt8();
770  break;
771  case eDB_Bit:
772  to_val = from_var.GetBit();
773  return;
774  case eDB_VarChar:
775  case eDB_Char:
776  case eDB_LongChar:
777  case eDB_Text:
778  case eDB_VarCharMax:
779  temp_val = NStr::StringToInt8(from_var.GetString());
780  break;
781  default:
782  s_ConvertionNotSupported("bool", from_var.GetType());
783  return;
784  }
785  if (temp_val != 0 && temp_val != 1)
786  {
788  "Value for bool is out of bounds: "
789  + NStr::NumericToString(temp_val));
790  }
791  to_val = temp_val == 1;
792 }
793 
794 static void
795 s_ConvertValue(const CVariant& from_var, float& to_val)
796 {
797  switch (from_var.GetType()) {
798  case eDB_Float:
799  to_val = from_var.GetFloat();
800  break;
801  case eDB_VarChar:
802  case eDB_Char:
803  case eDB_LongChar:
804  case eDB_Text:
805  case eDB_VarCharMax:
806  to_val = float(NStr::StringToDouble(from_var.GetString()));
807  break;
808  default:
809  s_ConvertionNotSupported("float", from_var.GetType());
810  }
811 }
812 
813 static void
814 s_ConvertValue(const CVariant& from_var, double& to_val)
815 {
816  switch (from_var.GetType()) {
817  case eDB_Float:
818  case eDB_Double:
819  to_val = from_var.GetDouble();
820  break;
821  case eDB_VarChar:
822  case eDB_Char:
823  case eDB_LongChar:
824  case eDB_Text:
825  case eDB_VarCharMax:
826  to_val = NStr::StringToDouble(from_var.GetString());
827  break;
828  default:
829  s_ConvertionNotSupported("double", from_var.GetType());
830  }
831 }
832 
833 static void
834 s_ConvertValue(const CVariant& from_var, string& to_val)
835 {
836  switch (from_var.GetType()) {
837  case eDB_BigInt:
838  case eDB_Int:
839  case eDB_SmallInt:
840  case eDB_TinyInt:
841  to_val = NStr::Int8ToString(from_var.GetInt8());
842  break;
843  case eDB_Bit:
844  to_val = NStr::BoolToString(from_var.GetBit());
845  break;
846  case eDB_Float:
847  case eDB_Double:
848  to_val = NStr::DoubleToString(from_var.GetDouble());
849  break;
850  case eDB_DateTime:
851  case eDB_SmallDateTime:
852  case eDB_BigDateTime:
853  to_val = from_var.GetCTime().AsString();
854  break;
855  case eDB_VarChar:
856  case eDB_Char:
857  case eDB_LongChar:
858  case eDB_Text:
859  case eDB_VarBinary:
860  case eDB_Binary:
861  case eDB_LongBinary:
862  case eDB_Image:
863  case eDB_Numeric:
864  case eDB_VarCharMax:
865  case eDB_VarBinaryMax:
866  to_val = from_var.GetString();
867  break;
868  default:
869  s_ConvertionNotSupported("string", from_var.GetType());
870  }
871 }
872 
873 
875 {
876  if ((flags & (fNBS_ZLib | fNBS_BZLib)) == (fNBS_ZLib | fNBS_BZLib)) {
877  NCBI_THROW(CSDB_Exception, eWrongParams,
878  "fNBS_ZLib and fNBS_BZLib are mutually incompatible; "
879  "please specify at most one compression algorithm.");
880  } else if ((flags & fNBS_ZLib) != 0) {
881  return eZLib;
882  } else if ((flags & fNBS_BZLib) != 0) {
883  return eBZLib;
884  } else {
885  return eNone;
886  }
887 }
888 
889 
890 static
891 CSimpleBlobStore::TFlags s_TranslateBlobStoreFlags(TNewBlobStoreFlags flags)
892 {
893  CSimpleBlobStore::TFlags result = CSimpleBlobStore::kDefaults;
894  if ((flags & fNBS_LogIt) != 0) {
896  }
897  if ((flags & fNBS_IsText) != 0) {
899  }
900  if ((flags & fNBS_Preallocated) != 0) {
902  }
903  return result;
904 }
905 
906 
907 static const char kDefaultDriverName[] = "ftds";
909 
911 {
912 public:
914  {
919 
920  if (s_DriverName.get() == NULL) {
922  }
923 
924  {{
926  if (app != NULL) {
927  string driver_name
928  = app->GetConfig().GetString("sdbapi", "use_driver",
929  s_DriverName.get());
930  if (driver_name == kDefaultDriverName
931  || driver_name == "ftds100"
932  || driver_name == "ftds14") {
933  s_DriverName.reset(strdup(driver_name.c_str()));
934  } else {
935  ERR_POST_X(15, "Unsupported driver name " << driver_name
936  << "; sticking with " << s_DriverName.get());
937  }
938  }
939  }}
940 
941  CDBConnParamsBase params;
942  params.SetDriverName(s_DriverName.get());
943  params.SetEncoding(eEncoding_UTF8);
944  IDataSource* ds
945  = CDriverManager::GetInstance().MakeDs(params, ".sdbapi");
947  ctx->PushCntxMsgHandler(new CDB_UserHandler_Exception, eTakeOwnership);
948  ctx->PushDefConnMsgHandler(new CDB_UserHandler_Exception, eTakeOwnership);
949  }
950 };
951 
952 
954 
955 inline
957 {
958  ds_init.Get();
960  (s_DriverName.get(), ".sdbapi");
961 }
962 
963 inline
965 {
967  return static_cast<impl::CDriverContext*>(ds->GetDriverContext());
968 }
969 
970 
971 string CSDB_Decryptor::x_Decrypt(const string& ciphertext, const string& key)
972 {
973  CRYPT_Key bin_key = CRYPT_Init(key.c_str());
974  AutoPtr<char, CDeleter<char> > plaintext
975  (CRYPT_DecodeString(bin_key, ciphertext.c_str()));
976  CRYPT_Free(bin_key);
977  if (plaintext.get() == NULL) {
979  "Password decryption failed.");
980  }
981  return string(plaintext.get());
982 }
983 
984 
986 {
987  string key;
989  if (app != NULL) {
990  key = app->GetConfig().GetString("DBAPI_key", key_id, kEmptyStr);
991  }
992 
993 #ifdef HAVE_LIBNCBICRYPT
994  if (key.empty()) {
995  key = NCBICRYPT_FindBuiltinKey(string(key_id).c_str());;
996  }
997 #endif
998  if (key.empty()) {
1000  "Unknown password decryption key ID " + string(key_id));
1001  }
1002  return key;
1003 }
1004 
1005 
1006 DEFINE_STATIC_FAST_MUTEX(s_DecryptorMutex);
1008 static bool s_DecryptorInitialized = false;
1009 
1011 {
1012  CFastMutexGuard GUARD(s_DecryptorMutex);
1013  s_Decryptor->Reset(decryptor);
1014  s_DecryptorInitialized = true;
1015 }
1016 
1018 {
1019  CFastMutexGuard GUARD(s_DecryptorMutex);
1020  if ( !s_DecryptorInitialized ) {
1021  s_Decryptor->Reset(new CSDB_Decryptor);
1022  s_DecryptorInitialized = true;
1023  }
1024  return *s_Decryptor;
1025 }
1026 
1027 
1028 string
1030 {
1031  if ((flags & fThrowIfIncomplete) != 0
1032  && (m_Url.GetHost().empty() || m_Url.GetUser().empty()
1033  || (m_Url.GetPassword().empty() && Get(ePasswordFile).empty())
1034  || m_Url.GetPath().empty() || m_Url.GetPath() == "/"))
1035  {
1038  "Connection parameters miss at least one essential part"
1039  " (host, user, password, or database [as \"path\"]): "
1040  + ComposeUrl(fl));
1041  }
1042 
1043  if ((flags & fHidePassword) != 0 && !m_Url.GetPassword().empty()) {
1044  CUrl redactee = m_Url;
1045  redactee.SetPassword("(redacted)");
1046  return redactee.ComposeUrl(CUrlArgs::eAmp_Char);
1047  }
1049 }
1050 
1052 {
1053  // Can't use m_Url.IsEmpty(), because the URL will still have a
1054  // scheme ("dbapi").
1055  if ( !m_Url.GetUser().empty() || !m_Url.GetPassword().empty()
1056  || !m_Url.GetHost().empty() || !m_Url.GetPort().empty()
1057  || !m_Url.GetPath().empty() ) {
1058  return false;
1059  } else if ( !m_Url.HaveArgs() ) {
1060  return true;
1061  }
1062 
1064  if ( !it->value.empty() ) {
1065  return false;
1066  }
1067  }
1068  return true;
1069 }
1070 
1073  TSetFlags flags)
1074 {
1075  for (int i = eUsername; i <= eArgsString; ++i) {
1076  EParam ii = static_cast<EParam>(i);
1077  Set(ii, param.Get(ii), flags);
1078  }
1079  return *this;
1080 }
1081 
1083 {
1084  static const char* kDefault = "default";
1085  m_ParamMap.clear();
1086 
1087  impl::SDBConfParams conf_params;
1088  try {
1089  s_GetDBContext()->ReadDBConfParams(m_Url.GetHost(), &conf_params);
1091 
1092 #define COPY_PARAM_EX(en, gn, fn) \
1093  if (conf_params.Is##gn##Set()) \
1094  m_ParamMap[e##en] = conf_params.fn
1095 #define COPY_PARAM(en, fn) COPY_PARAM_EX(en, en, fn)
1096 #define COPY_BOOL_PARAM(en, gn, fn) \
1097  if (conf_params.Is##gn##Set()) \
1098  m_ParamMap[e##en] = conf_params.fn.empty() ? "default" \
1099  : NStr::StringToBool(conf_params.fn) ? "true" : "false"
1100 #define COPY_NUM_PARAM(en, gn, fn) \
1101  if (conf_params.Is##gn##Set()) \
1102  m_ParamMap[e##en] = conf_params.fn.empty() ? kDefault : conf_params.fn
1103 
1104  COPY_PARAM_EX(Service, Server, server);
1105 
1106  COPY_PARAM(Username, username);
1107  COPY_PARAM(Password, password);
1108  COPY_PARAM(Port, port);
1109  COPY_PARAM(Database, database);
1110  COPY_PARAM(PasswordFile, password_file);
1111  COPY_PARAM_EX(PasswordKeyID, PasswordKey, password_key_id);
1112 
1113  COPY_NUM_PARAM (LoginTimeout, LoginTimeout, login_timeout);
1114  COPY_NUM_PARAM (IOTimeout, IOTimeout, io_timeout);
1115  COPY_BOOL_PARAM(ExclusiveServer, SingleServer, single_server);
1116  COPY_BOOL_PARAM(UseConnPool, Pooled, is_pooled);
1117  COPY_NUM_PARAM (ConnPoolMinSize, PoolMinSize, pool_minsize);
1118  COPY_NUM_PARAM (ConnPoolMaxSize, PoolMaxSize, pool_maxsize);
1119  COPY_NUM_PARAM (ConnPoolIdleTime, PoolIdleTime, pool_idle_time);
1120  COPY_NUM_PARAM (ConnPoolWaitTime, PoolWaitTime, pool_wait_time);
1121  COPY_BOOL_PARAM(ConnPoolAllowTempOverflow, PoolAllowTempOverflow,
1122  pool_allow_temp_overflow);
1123  COPY_BOOL_PARAM(ContinueAfterRaiserror, ContinueAfterRaiserror,
1124  continue_after_raiserror);
1125  COPY_NUM_PARAM (ConnPoolMaxConnUse, PoolMaxConnUse, pool_max_conn_use);
1126  COPY_BOOL_PARAM(LogMinorMessages, LogMinorMessages, log_minor_messages);
1127 
1128 #undef COPY_PARAM_EX
1129 #undef COPY_PARAM
1130 #undef COPY_BOOL_PARAM
1131 #undef COPY_NUM_PARAM
1132 
1133  if ( !conf_params.args.empty() ) {
1134  m_ParamMap[eArgsString] = conf_params.args;
1135  }
1136 
1137  // Check for overridden settings
1138  ITERATE (TParamMap, it, m_ParamMap) {
1139  string s = Get(it->first, eWithoutOverrides);
1140  if ( !s.empty() ) {
1141  x_ReportOverride(x_GetName(it->first), s, it->second);
1142  }
1143  }
1144 
1145  if (conf_params.IsPasswordSet() && conf_params.IsPasswordFileSet()) {
1147  '[' + m_Url.GetHost() + ".dbservice] password and"
1148  " password_file parameters are mutually exclusive.");
1149  }
1150 }
1151 
1153 {
1154  string password;
1155 
1156  // Account for possible indirection. Formal search order:
1157  // 1. Password directly in configuration file.
1158  // 2. Password filename in configuration file.
1159  // 3. Password filename in URL.
1160  // 4. Password directly in URL.
1161  // However, if either the configuration file or the URL supplies
1162  // both a direct password and a password filename, SDBAPI will
1163  // throw an exception, so it doesn't matter that 3 and 4 are
1164  // backward relative to 1 and 2.
1166  if (it != m_ParamMap.end()) {
1167  password = it->second;
1168  } else {
1169  string pwfile = Get(ePasswordFile, eWithOverrides);
1170  if (pwfile.empty()) {
1171  password = Get(ePassword);
1172  } else {
1173  CNcbiIfstream in(pwfile.c_str(), IOS_BASE::in | IOS_BASE::binary);
1174  if ( !in ) {
1176  eNotExist | Retriable(eRetriable_No), // eWrongParams?
1177  "Unable to open password file " + pwfile + ": " +
1179  }
1180  NcbiGetline(in, password, "\r\n");
1181  }
1182  }
1183 
1184  // Account for possible encryption.
1185  string key_id = Get(ePasswordKeyID, eWithOverrides);
1186  if ( !key_id.empty() ) {
1188  if (decryptor.NotEmpty()) {
1189  password = decryptor->Decrypt(password, key_id);
1190  ITERATE (string, pit, password) {
1191  if ( !isprint((unsigned char)*pit) ) {
1193  eWrongParams | Retriable(eRetriable_No),
1194  "Invalid character in supposedly decrypted"
1195  " password.");
1196  }
1197  }
1198  }
1199  }
1200 
1201  return password;
1202 }
1203 
1204 void
1206 {
1209  params->SetPassword (x_GetPassword());
1211 
1212  string port = Get(ePort, eWithOverrides);
1213  if ( !port.empty() ) {
1214  params->SetPort(NStr::StringToInt(port));
1215  }
1216 
1217  params->SetParam("login_timeout", Get(eLoginTimeout, eWithOverrides));
1218  params->SetParam("io_timeout", Get(eIOTimeout, eWithOverrides));
1219  x_FillBoolParam(params, "single_server", eExclusiveServer);
1220  x_FillBoolParam(params, "is_pooled", eUseConnPool);
1221  if (params->GetParam("is_pooled") == "true") { // canonicalized above
1222  params->SetParam("pool_name", params->GetServerName() + ".pool");
1223  }
1224  string explicit_pool_name = Get(eConnPoolName, eWithOverrides);
1225  if ( !explicit_pool_name.empty() ) {
1226  params->SetParam("pool_name", explicit_pool_name);
1227  }
1228  params->SetParam("pool_minsize", Get(eConnPoolMinSize, eWithOverrides));
1229  params->SetParam("pool_maxsize", Get(eConnPoolMaxSize, eWithOverrides));
1230  params->SetParam("pool_idle_time", Get(eConnPoolIdleTime, eWithOverrides));
1231  params->SetParam("pool_wait_time", Get(eConnPoolWaitTime, eWithOverrides));
1232  params->SetParam("pool_max_conn_use",
1234 
1235  x_FillBoolParam(params, "pool_allow_temp_overflow",
1237  x_FillBoolParam(params, "continue_after_raiserror",
1239  x_FillBoolParam(params, "log_minor_messages", eLogMinorMessages);
1240 
1241  // Generic named parameters. The historic version of this logic
1242  // had two quirks, which I [AMU] have not carried over:
1243  // * A setting found in the configuration file counted only when
1244  // the original URL mentioned the same parameter.
1245  // * If a key appeared more than once in either list, the old code
1246  // favored the last appearance in the URL but the first one in
1247  // the configuration file. It now always favors the last one.
1248  typedef vector<CUrlArgs*> TAllArgs;
1249  TAllArgs all_args;
1250  all_args.push_back(&m_Url.GetArgs());
1251 
1252  unique_ptr<CUrlArgs> conf_args;
1253  {{
1255  if (it != m_ParamMap.end()) {
1256  conf_args.reset(new CUrlArgs(it->second));
1257  all_args.push_back(conf_args.get());
1258  }
1259  }}
1260 
1261  ITERATE (TAllArgs, ait, all_args) {
1262  const CUrlArgs::TArgs& args = (*ait)->GetArgs();
1263  ITERATE (CUrlArgs::TArgs, uit, args) {
1264  const string& param_name = uit->name;
1265  const string& param_value = uit->value;
1266  if ( !x_IsKnownArg(param_name) ) {
1267  params->SetParam(param_name, param_value);
1268  }
1269  }
1270  }
1271 
1272  params->SetParam("do_not_read_conf", "true");
1273 }
1274 
1275 void
1277  const string& name, EParam id) const
1278 {
1279  string value = Get(id, eWithOverrides);
1280  if ( !value.empty() && value != "default") {
1282  }
1283  params->SetParam(name, value);
1284 }
1285 
1286 
1288  CTempString code_value,
1289  CTempString reg_value) const
1290 {
1291  if (code_value == reg_value) {
1292  return;
1293  } else if (name == x_GetName(eArgsString)) {
1294  // Analyze individually
1295  typedef map<string, string> TConfMap;
1296  TConfMap conf_map;
1297  CUrlArgs conf_args(reg_value);
1298  ITERATE (CUrlArgs::TArgs, it, conf_args.GetArgs()) {
1299  if ( !x_IsKnownArg(it->name) ) {
1300  conf_map[it->name] = it->value;
1301  }
1302  }
1304  TConfMap::const_iterator cmit = conf_map.find(uait->name);
1305  if (cmit != conf_map.end()) {
1306  x_ReportOverride(uait->name, uait->value, cmit->second);
1307  }
1308  }
1309  } else if (name == x_GetName(eService)) {
1310  ERR_POST_X(18, Info << "Using privately configured service alias "
1311  << code_value << " -> " << reg_value);
1312  } else {
1313  if (name == x_GetName(ePassword)) {
1314  code_value = "(redacted)";
1315  reg_value = "(redacted)";
1316  }
1317  ERR_POST_X(17, Warning << "Ignoring program-defined " << name
1318  << " parameter value " << code_value << " for "
1319  << m_Url.GetHost() << " in favor of configured value "
1320  << reg_value);
1321  }
1322 }
1323 
1324 
1325 bool
1327 {
1329  if (!app)
1330  return true;
1331  const IRegistry& reg = app->GetConfig();
1332  bool result = true;
1333  list<string> sections;
1334  reg.EnumerateSections(&sections);
1335  ITERATE(list<string>, it, sections) {
1336  const string& name = *it;
1337  if (name.size() <= 10
1338  || NStr::CompareCase(name, name.size() - 10, 10, ".dbservice") != 0)
1339  {
1340  continue;
1341  }
1343  CDBConnParamsBase lower_params;
1344  CSDB_ConnectionParam conn_params(name.substr(0, name.size() - 10));
1345  conn_params.x_FillLowerParams(&lower_params);
1346  if (lower_params.GetParam("is_pooled") == "true") {
1347  result &= ctx->SatisfyPoolMinimum(lower_params);
1348  }
1349  }
1350  return result;
1351 }
1352 
1353 
1355 {
1357 }
1358 
1360 {
1361  return s_GetDataSource()->GetApplicationName();
1362 }
1363 
1364 
1366 {
1367  if (s_DriverName.get() != NULL) {
1369  "CSDBAPI::UseDriver called with SDBAPI already in use.");
1370  }
1371  switch (driver) {
1372  case eDriver_FTDS100: s_DriverName.reset(strdup("ftds100")); break;
1373  case eDriver_FTDS14: s_DriverName.reset(strdup("ftds14")); break;
1374  }
1375 }
1376 
1377 
1382 };
1383 
1385 {
1386  string server_name;
1389 };
1390 
1391 typedef list< AutoPtr<SMirrorServInfo> > TMirrorServList;
1392 
1394 {
1397  string master;
1398 };
1399 
1402 
1403 
1405 {
1406 public:
1408  : m_Other(other)
1409  {}
1410 
1412  {}
1413 
1414  virtual Uint4 GetProtocolVersion(void) const
1415  {
1416  return m_Other.GetProtocolVersion();
1417  }
1418 
1419  virtual EEncoding GetEncoding(void) const
1420  {
1421  return m_Other.GetEncoding();
1422  }
1423 
1424  virtual string GetServerName(void) const
1425  {
1427  }
1428 
1429  virtual string GetDatabaseName(void) const
1430  {
1431  return kEmptyStr;
1432  }
1433 
1434  virtual string GetUserName(void) const
1435  {
1436  return m_Other.GetUserName();
1437  }
1438 
1439  virtual string GetPassword(void) const
1440  {
1441  return m_Other.GetPassword();
1442  }
1443 
1444  virtual EServerType GetServerType(void) const
1445  {
1446  return m_Other.GetServerType();
1447  }
1448 
1449  virtual Uint4 GetHost(void) const
1450  {
1451  return m_Other.GetHost();
1452  }
1453 
1454  virtual Uint2 GetPort(void) const
1455  {
1456  return m_Other.GetPort();
1457  }
1458 
1460  {
1461  return m_Other.GetConnValidator();
1462  }
1463 
1464  virtual string GetParam(const string& key) const
1465  {
1467  if (result.empty())
1468  return m_Other.GetParam(key);
1469  else
1470  return result;
1471  }
1472 
1473 private:
1475 };
1476 
1477 
1479 CSDBAPI::UpdateMirror(const string& dbservice,
1480  list<string>* servers /* = NULL */,
1481  string* error_message /* = NULL */)
1482 {
1483  if (dbservice.empty()) {
1485  "Mirrored database service name cannot be empty");
1486  }
1487 
1488  bool first_execution = false;
1489  SMirrorInfo& mir_info = (*s_MirrorsData)[dbservice];
1490  if (!mir_info.conn_params.get()) {
1491  mir_info.conn_params.reset(new CDBConnParamsBase);
1492  first_execution = true;
1493  }
1494  CDBConnParamsBase& conn_params = *mir_info.conn_params.get();
1495  TMirrorServList& serv_list = mir_info.servers;
1496 
1497  ds_init.Get();
1498  IDBConnectionFactory* i_factory
1500  if (conn_params.GetServerName().empty()) {
1501  first_execution = true;
1502  CSDB_ConnectionParam sdb_params(dbservice);
1503  sdb_params.x_FillLowerParams(&conn_params);
1504  if (conn_params.GetParam("single_server") != "true") {
1506  "UpdateMirror cannot be used when configuration file "
1507  "doesn't have exclusive_server=true (for " + dbservice
1508  + ')');
1509  }
1510  CDBConnectionFactory* factory
1511  = dynamic_cast<CDBConnectionFactory*>(i_factory);
1512  if (!factory) {
1514  "UpdateMirror cannot work with non-standard "
1515  "connection factory");
1516  }
1517  }
1518  if (servers)
1519  servers->clear();
1520  if (error_message)
1521  error_message->clear();
1522 
1523  CDBConnectionFactory* factory = static_cast<CDBConnectionFactory*>(i_factory);
1524  string service_name(conn_params.GetServerName());
1525  string db_name(conn_params.GetDatabaseName());
1526  bool need_reread_servers = false;
1527  bool servers_reread = false;
1528  bool has_master = false;
1529  int cnt_switches = 0;
1530 
1531  do {
1532  if (serv_list.empty()) {
1533  list<string> servers;
1534  factory->GetServersList(db_name, service_name, &servers);
1535  ITERATE(list<string>, it, servers) {
1536  serv_list.push_back(new SMirrorServInfo());
1537  serv_list.back()->server_name = *it;
1538  serv_list.back()->state = eConnInitializing;
1539  }
1540  servers_reread = true;
1541  }
1542  else if (need_reread_servers) {
1543  list<string> new_serv_info;
1544  factory->GetServersList(db_name, service_name, &new_serv_info);
1545  ERASE_ITERATE(TMirrorServList, old_it, serv_list) {
1546  bool found = false;
1547  ITERATE(list<string>, it, new_serv_info) {
1548  if (*it == (*old_it)->server_name) {
1549  found = true;
1550  break;
1551  }
1552  }
1553  if (!found) {
1554  serv_list.erase(old_it);
1555  }
1556  }
1557  ITERATE(list<string>, new_it, new_serv_info) {
1558  bool found = false;
1559  ITERATE(TMirrorServList, old_it, serv_list) {
1560  if ((*old_it)->server_name == *new_it) {
1561  found = true;
1562  break;
1563  }
1564  }
1565  if (!found) {
1566  serv_list.push_back(new SMirrorServInfo());
1567  serv_list.back()->server_name = *new_it;
1568  serv_list.back()->state = eConnInitializing;
1569  }
1570  }
1571  servers_reread = true;
1572  }
1573  if (serv_list.empty()) {
1574  factory->WorkWithSingleServer("", service_name, kEmptyStr);
1575  ERR_POST_X(3, "No servers for service '" << service_name
1576  << "' are available");
1577  if (error_message) {
1578  *error_message = "No servers for service '" + service_name
1579  + "' are available";
1580  }
1581  return eMirror_Unavailable;
1582  }
1583 
1584  for (TMirrorServList::iterator it = serv_list.end(); it != serv_list.begin(); )
1585  {
1586  --it;
1587  AutoPtr<IConnection>& conn = (*it)->conn;
1588  const string& server_name = (*it)->server_name;
1589  EMirrorConnState& state = (*it)->state;
1590  if (!conn.get()) {
1592  }
1593  if (!conn->IsAlive()) {
1594  if (state == eConnEstablished) {
1595  ERR_POST_X(7, "Connection to server '" << server_name
1596  << "' for service '" << service_name
1597  << "' is lost.");
1599  }
1600  CUpdMirrorServerParams serv_params(conn_params);
1601  serv_params.SetServerName(server_name);
1602  serv_params.SetParam("is_pooled", "false");
1603  serv_params.SetParam("do_not_dispatch", "true");
1604  try {
1605  conn->Close();
1606  conn->Connect(serv_params);
1607  if (state == eConnNotConnected) {
1608  ERR_POST_X(8, "Connection to server '" << server_name
1609  << "' for service '" << service_name
1610  << "' is restored.");
1611  }
1613  }
1614  catch (CDB_Exception& /*ex*/) {
1615  //ERR_POST_X(1, Info << "Error connecting to the server '"
1616  // << server_name << "': " << ex);
1617  if (state == eConnInitializing) {
1618  ERR_POST_X(9, "Cannot establish connection to server '"
1619  << server_name << "' for service '"
1620  << service_name << "'.");
1622  }
1623  conn->Close();
1624  need_reread_servers = true;
1625  }
1626  }
1627  bool success = false;
1628  if (conn->IsAlive()) {
1629  try {
1630  AutoPtr<IStatement> stmt(conn->GetStatement());
1631  stmt->ExecuteUpdate("use " + db_name);
1632  success = true;
1633  }
1634  catch (CDB_Exception& /*ex*/) {
1635  // success is already false
1636  //ERR_POST_X(2, Info << "Check for mirror principal state failed: "
1637  // << ex);
1638  }
1639  }
1640  if (!success && server_name == mir_info.master) {
1641  factory->WorkWithSingleServer("", service_name, kEmptyStr);
1642  string pool_name = conn_params.GetParam("pool_name");
1643  size_t invalidated_count = s_GetDBContext()->CloseConnsForPool(pool_name);
1644  ERR_POST_X(4, "The master for database '" << db_name <<
1645  "' (service '" << service_name <<
1646  "') has become inaccessible. Because of this " <<
1647  invalidated_count <<
1648  " active connections got invalidated in the pool '" <<
1649  pool_name << "'.");
1650  mir_info.master.clear();
1651  need_reread_servers = true;
1652  }
1653  else if (success && server_name != mir_info.master) {
1654  factory->WorkWithSingleServer("", service_name, server_name);
1655  string pool_name = conn_params.GetParam("pool_name");
1656  size_t invalidated_count =
1658  pool_name,
1659  conn->GetCDB_Connection()->Host(),
1660  conn->GetCDB_Connection()->Port());
1661  string msg_start = "The master for database '" + db_name +
1662  "' (for service '" + service_name +
1663  "') switched to '" + server_name + "' from ";
1664  string msg_end = ". Because of this " +
1665  NStr::NumericToString(invalidated_count) +
1666  " active connections got invalidated in the pool '" +
1667  pool_name + "'.";
1668 
1669  if (mir_info.master.empty()) {
1670  // Switching from no master to something => Message
1671  ERR_POST_X(5, Message << msg_start << "NONE" << msg_end);
1672  } else {
1673  // Switching from one master to another => Warning
1674  ERR_POST_X(5, Warning << msg_start << "'" <<
1675  mir_info.master << "'" << msg_end);
1676  }
1677  s_GetDBContext()->SatisfyPoolMinimum(conn_params);
1678 
1679  has_master = true;
1680  mir_info.master = server_name;
1681  serv_list.push_front(*it);
1682  TMirrorServList::iterator it_del = it++;
1683  serv_list.erase(it_del);
1684  need_reread_servers = true;
1685 
1686  if (++cnt_switches == 10) {
1688  eInconsistent | Retriable(eRetriable_No),
1689  "Mirror database switches too frequently or "
1690  "it isn't mirrored: " + service_name);
1691  }
1692  }
1693  else if (success && server_name == mir_info.master) {
1694  has_master = true;
1695  }
1696  }
1697  }
1698  while (need_reread_servers && !servers_reread);
1699 
1700  if (first_execution && !has_master) {
1701  factory->WorkWithSingleServer("", service_name, kEmptyStr);
1702  string pool_name = conn_params.GetParam("pool_name");
1703  size_t invalidated_count = s_GetDBContext()->CloseConnsForPool(pool_name);
1704  ERR_POST_X(10, "The master for database '" << db_name <<
1705  "' (service '" << service_name <<
1706  "') is not accessible. Because of this " <<
1707  invalidated_count <<
1708  " active connections got invalidated in the pool '" <<
1709  pool_name << "'.");
1710  }
1711 
1712  if (servers) {
1713  ITERATE(TMirrorServList, it, serv_list) {
1714  servers->push_back((*it)->server_name);
1715  }
1716  }
1717  if (!has_master) {
1718  if (error_message)
1719  *error_message = "All database instances are inaccessible";
1720  return eMirror_Unavailable;
1721  }
1722  return cnt_switches == 0? eMirror_Steady: eMirror_NewMaster;
1723 }
1724 
1726  const string& table_name,
1727  TNewBlobStoreFlags flags,
1728  size_t image_limit)
1729 {
1731  if ((flags & fNBS_IsText) != 0) {
1732  ERR_POST_X_ONCE(20, Warning << "Explicit fNBS_IsText flag passed to a"
1733  " variant of NewBlobStore that inspects column types"
1734  " itself.");
1735  }
1736  return new CBlobStoreDynamic(s_GetDBContext(),
1740  table_name, cm, image_limit,
1742 }
1743 
1744 
1746 {
1747  if (ex == nullptr) {
1748  return true;
1749  } else if (ex->GetSeverity() == eDiag_Info && m_Conn.m_LogMinorMessages) {
1750  ERR_POST_X(21, Info << *ex);
1751  return true;
1752  } else {
1754  }
1755 }
1756 
1757 
1758 bool CSDB_UserHandler::HandleMessage(int severity, int msgnum,
1759  const string& message)
1760 {
1761  if (severity < 10 || (severity == 10 && msgnum == 0)) {
1762  if (severity == 0 || (severity == 10 && msgnum == 0)) {
1763  m_Conn.m_PrintOutput.push_back(message);
1764  return !m_Conn.m_LogMinorMessages;
1765  } else if (m_Conn.m_LogMinorMessages) {
1766  return false;
1767  }
1768  }
1770  && (severity == 16 || (severity == 10 && msgnum > 0))) {
1771  // Sybase servers use severity 16 for all user-defined messages,
1772  // even if they're not intended to abort execution. Also, some
1773  // standard minor errors (such as Duplicate key was ignored, #3604)
1774  // normally map to DBAPI exceptions with severity warning.
1775  // Optionally intercept all of these messages and report them as
1776  // warnings (vs. exceptions).
1778  eDiag_Error, msgnum);
1779  ERR_POST_X(19, Warning << ex);
1780  return true;
1781  } else {
1783  (severity, msgnum, message);
1784  }
1785 }
1786 
1787 
1788 inline
1790  : m_Conn(conn),
1791  m_DefaultTimeout(0),
1792  m_HasCustomTimeout(false),
1793  m_ContinueAfterRaiserror
1794  (params.Get(CSDB_ConnectionParam::eContinueAfterRaiserror) == "true"),
1795  m_LogMinorMessages
1796  (params.Get(CSDB_ConnectionParam::eLogMinorMessages,
1797  CSDB_ConnectionParam::eWithOverrides) == "true"),
1798  m_CntOpen(0),
1799  m_Context(new CDB_Exception::SContext),
1800  m_Handler(new CSDB_UserHandler(*this))
1801 {
1802  if (conn != NULL) {
1803  m_DefaultTimeout = conn->GetTimeout();
1804  m_Context->server_name = conn->GetCDB_Connection()->ServerName();
1805  m_Context->username = conn->GetCDB_Connection()->UserName();
1806  m_Context->database_name = conn->GetDatabase();
1807  conn->GetCDB_Connection()->PushMsgHandler(&*m_Handler, eNoOwnership);
1808  }
1809 }
1810 
1812 {
1813  delete m_Conn;
1814 }
1815 
1816 inline IConnection*
1818 {
1819  return m_Conn;
1820 }
1821 
1822 inline void
1824 {
1825  CMutexGuard mg(m_Mutex);
1826  ++m_CntOpen;
1827 }
1828 
1829 inline void
1831 {
1832  CMutexGuard mg(m_Mutex);
1833  if (--m_CntOpen == 0) {
1835  m_Conn->Close();
1836  }
1837 }
1838 
1839 void CConnHolder::SetTimeout(const CTimeout& timeout)
1840 {
1841  CMutexGuard mg(m_Mutex);
1842  if (timeout.IsDefault()) {
1843  ResetTimeout();
1844  } else if (m_CntOpen > 0) {
1845  unsigned int sec, nanosec;
1846  timeout.GetNano(&sec, &nanosec);
1847  if (nanosec > 0 && sec != kMax_UInt) { // round up as appropriate
1848  ++sec;
1849  }
1850  m_HasCustomTimeout = true;
1851  m_Conn->SetTimeout(sec);
1852  }
1853 }
1854 
1856 {
1857  CMutexGuard mg(m_Mutex);
1858  if (m_HasCustomTimeout && m_CntOpen > 0) {
1860  }
1861  m_HasCustomTimeout = false;
1862 }
1863 
1864 inline
1865 const list<string>& CConnHolder::GetPrintOutput(void) const
1866 {
1867  return m_PrintOutput;
1868 }
1869 
1870 inline
1872 {
1873  CMutexGuard mg(m_Mutex);
1874  m_PrintOutput.clear();
1875 }
1876 
1877 inline
1879 {
1880  return *m_Context;
1881 }
1882 
1883 
1884 inline void
1886 {
1887  CDBConnParamsBase lower_params;
1888  params.x_FillLowerParams(&lower_params);
1890  conn->Connect(lower_params);
1891  m_Conn.Reset(new CConnHolder(conn.release(), params));
1892  m_IsOpen = m_EverConnected = true;
1893  m_Conn->AddOpenRef();
1894 }
1895 
1896 inline
1898  : m_IsOpen(false), m_EverConnected(false)
1899 {
1900 }
1901 
1902 inline
1904  : m_Conn(other.m_Conn),
1905  m_IsOpen(other.m_IsOpen),
1906  m_EverConnected(other.m_EverConnected)
1907 {
1908  if (m_IsOpen)
1909  m_Conn->AddOpenRef();
1910 }
1911 
1912 inline void
1914 {
1915  if (m_IsOpen) {
1916  m_IsOpen = false;
1917  m_Conn->CloseRef();
1918  }
1919 }
1920 
1921 inline
1923 {
1924  try {
1925  Close();
1926  }
1927  STD_CATCH_ALL_X(11, "CDatabaseImpl::~CDatabaseImpl")
1928 }
1929 
1930 inline bool
1932 {
1933  return m_IsOpen;
1934 }
1935 
1936 inline bool
1938 {
1939  return m_EverConnected;
1940 }
1941 
1942 inline IConnection*
1944 {
1945  return m_Conn->GetConn();
1946 }
1947 
1948 inline void
1950 {
1951  m_Conn->SetTimeout(timeout);
1952 }
1953 
1954 inline void
1956 {
1957  m_Conn->ResetTimeout();
1958 }
1959 
1960 inline
1961 const list<string>& CDatabaseImpl::GetPrintOutput(void) const
1962 {
1963  return m_Conn->GetPrintOutput();
1964 }
1965 
1966 inline
1968 {
1970 }
1971 
1972 inline
1975 {
1976  return m_Conn->GetContext();
1977 }
1978 
1979 
1981  : m_Impl(new CDatabaseImpl)
1982 {}
1983 
1985  : m_Params(params), m_Impl(new CDatabaseImpl)
1986 {}
1987 
1988 CDatabase::CDatabase(const string& url_string)
1989  : m_Params(url_string), m_Impl(new CDatabaseImpl)
1990 {}
1991 
1993 {
1994  operator= (db);
1995 }
1996 
1997 CDatabase&
1999 {
2000  m_Params = db.m_Params;
2001  m_Impl = db.m_Impl;
2002  return *this;
2003 }
2004 
2006 {
2007  if (m_Impl->IsOpen()) {
2008  try {
2009  m_Impl.Reset();
2010  }
2011  STD_CATCH_ALL_X(12, "CDatabase::~CDatabase");
2012  }
2013 }
2014 
2015 void
2017 {
2018  try {
2019  if (m_Impl->EverConnected()) {
2020  m_Impl.Reset(new CDatabaseImpl);
2021  }
2023  }
2025 }
2026 
2027 void
2029 {
2030  if ( !m_Impl->IsOpen() )
2031  return;
2032  try {
2033  m_Impl->Close();
2034  }
2036 }
2037 
2038 bool
2040 {
2041  if ( !m_Impl->IsOpen() ) {
2042  return false;
2043  } else if (check_method == eNoCheck) {
2044  return true;
2045  }
2046 
2048  _ASSERT(conn != NULL);
2049  if ( !conn->IsAlive() ) {
2050  Close();
2051  return false;
2052  } else if (check_method == eFastCheck) {
2053  return true;
2054  }
2055 
2056  _ASSERT(check_method == eFullCheck);
2057  try {
2058  CQuery query = NewQuery("SELECT 1");
2059  query.Execute();
2060  query.RequireRowCount(1);
2061  CQuery::CRowIterator row = query.begin();
2062  bool ok = (row != query.end() && row.GetTotalColumns() == 1
2063  && row[1].AsInt4() == 1);
2064  query.VerifyDone();
2065  return ok;
2066  } catch (exception&) {
2067  Close();
2068  return false;
2069  }
2070 }
2071 
2072 CDatabase
2074 {
2076  if (IsConnected(eNoCheck)) {
2077  result.Connect();
2078  }
2079  return result;
2080 }
2081 
2082 #define CONNECT_AS_NEEDED() x_ConnectAsNeeded(NCBI_CURRENT_FUNCTION)
2083 
2084 CQuery
2086 {
2088  return CQuery(m_Impl);
2089 }
2090 
2092 CDatabase::NewBulkInsert(const string& table_name, int autoflush)
2093 {
2095  return CBulkInsert(m_Impl, table_name, autoflush);
2096 }
2097 
2099 CDatabase::NewBookmark(const string& table_name, const string& column_name,
2100  const string& search_conditions,
2101  CBlobBookmark::EBlobType column_type,
2102  ETriState has_legacy_type)
2103 {
2105 
2107  switch (column_type) {
2108  case CBlobBookmark::eText:
2109  desc_type = CDB_BlobDescriptor::eText;
2110  break;
2112  desc_type = CDB_BlobDescriptor::eBinary;
2113  break;
2114  default:
2115  desc_type = CDB_BlobDescriptor::eUnknown;
2116  break;
2117  }
2118 
2119  unique_ptr<I_BlobDescriptor> desc
2120  (new CDB_BlobDescriptor(table_name, column_name, search_conditions,
2121  desc_type, has_legacy_type));
2122 
2123  CRef<CBlobBookmarkImpl> bm(new CBlobBookmarkImpl(m_Impl, desc.release()));
2124  return CBlobBookmark(bm);
2125 }
2126 
2127 
2129  TNewBlobStoreFlags flags,
2130  size_t image_limit)
2131 {
2133  if ((flags & fNBS_IsText) != 0) {
2134  ERR_POST_X_ONCE(20, Warning << "Explicit fNBS_IsText flag passed to a"
2135  " variant of NewBlobStore that inspects column types"
2136  " itself.");
2137  }
2140  table_name, cm, image_limit,
2142 }
2143 
2144 
2146  const string& key_col_name,
2147  const string& num_col_name,
2148  const vector<string> blob_col_names,
2149  TNewBlobStoreFlags flags,
2150  size_t image_limit)
2151 {
2155  table_name, key_col_name, num_col_name,
2156  &blob_col_names[0], blob_col_names.size(),
2158  image_limit);
2159 }
2160 
2161 
2163 {
2164  if ( !m_Impl->EverConnected() ) {
2165  _TRACE(operation << ": connecting on demand.");
2166  Connect();
2167  } else if ( !IsConnected(eNoCheck) ) {
2169  string("Cannot call ") + operation
2170  + " when not connected.");
2171  }
2172 }
2173 
2174 
2175 inline
2177  const string& table_name,
2178  int autoflush)
2179  : m_DBImpl(db_impl),
2180  m_BI(NULL),
2181  m_Autoflush(autoflush),
2182  m_RowsWritten(0),
2183  m_ColsWritten(0),
2184  m_WriteStarted(false),
2185  m_Context(new CDB_Exception::SContext(db_impl->GetContext()))
2186 {
2187  m_BI = db_impl->GetConnection()->GetBulkInsert(table_name);
2188  m_Context->extra_msg = "Bulk insertion into " + table_name;
2189 }
2190 
2192 {
2193  try {
2194  if (m_BI && m_RowsWritten != 0) {
2195  m_BI->Complete();
2196  }
2197  }
2198  STD_CATCH_ALL_X(13, "Error destroying CBulkInsert");
2199  delete m_BI;
2200 }
2201 
2202 inline
2204 {
2205  return *m_Context;
2206 }
2207 
2208 void
2210 {
2211  if (!m_BI) {
2213  "Cannot write into completed CBulkInsert");
2214  }
2215  if (!m_DBImpl->IsOpen()) {
2216  m_BI->Cancel();
2217  delete m_BI;
2218  m_BI = NULL;
2220  "Cannot write into CBulkInsert when CDatabase was closed");
2221  }
2222  if (col != 0 && col > int(m_Cols.size())) {
2223  SDBAPI_THROW(eInconsistent | Retriable(eRetriable_No),
2224  "Too many values were written to CBulkInsert: "
2225  + NStr::NumericToString(col) + " > "
2226  + NStr::NumericToString(m_Cols.size()));
2227  }
2228 }
2229 
2230 void
2232 {
2233  x_CheckCanWrite(0);
2234  m_BI->SetHints(hints);
2235 }
2236 
2237 void
2239 {
2240  x_CheckCanWrite(0);
2241  m_BI->AddHint(hint, value);
2242 }
2243 
2244 void
2246 {
2247  x_CheckCanWrite(0);
2249 }
2250 
2251 inline void
2253 {
2254  x_CheckCanWrite(0);
2255  if (m_WriteStarted) {
2256  SDBAPI_THROW(eStarted | Retriable(eRetriable_No),
2257  "Cannot bind columns when already started to insert");
2258  }
2259  if (col - 1 != int(m_Cols.size())) {
2260  SDBAPI_THROW(eNotInOrder | Retriable(eRetriable_No),
2261  "Cannot bind columns in CBulkInsert randomly");
2262  }
2263  m_Cols.push_back(CVariant(s_ConvertType(type)));
2264  if (type == eSDB_StringUCS2 || type == eSDB_TextUCS2
2265  || type == eSDB_StringMaxUCS2) {
2266  m_Cols.back().SetBulkInsertionEnc(eBulkEnc_UCS2FromChar);
2267  }
2268 }
2269 
2270 inline void
2272 {
2273  x_CheckCanWrite(0);
2274  if (m_ColsWritten != int(m_Cols.size())) {
2275  SDBAPI_THROW(eInconsistent | Retriable(eRetriable_No),
2276  "Not enough values were written to CBulkInsert: "
2278  + NStr::NumericToString(m_Cols.size()));
2279  }
2280  try {
2281  m_BI->AddRow();
2282  if (++m_RowsWritten == m_Autoflush) {
2283  m_BI->StoreBatch();
2284  m_RowsWritten = 0;
2285  }
2286  m_ColsWritten = 0;
2287  }
2289 }
2290 
2291 inline void
2293 {
2294  if (m_BI == NULL) {
2295  // Make idempotent, rather than letting x_CheckCanWrite throw.
2296  return;
2297  }
2298  x_CheckCanWrite(0);
2299  try {
2300  unique_ptr<IBulkInsert> bi(m_BI);
2301  m_BI = NULL;
2302  bi->Complete();
2303  }
2305 }
2306 
2307 inline void
2309 {
2311  if (!m_WriteStarted) {
2312  m_WriteStarted = true;
2313  try {
2314  for (unsigned int i = 0; i < m_Cols.size(); ++i) {
2315  m_BI->Bind(i + 1, &m_Cols[i]);
2316  }
2317  }
2319  }
2320 }
2321 
2322 inline void
2324 {
2326  m_Cols[m_ColsWritten++].SetNull();
2327 }
2328 
2329 template <class T>
2330 inline void
2332 {
2335 }
2336 
2337 
2339 {}
2340 
2342  const string& table_name,
2343  int autoflush)
2344 {
2345  m_Impl.Reset(new CBulkInsertImpl(db_impl, table_name, autoflush));
2346 }
2347 
2349  : m_Impl(bi.m_Impl)
2350 {}
2351 
2353 {}
2354 
2355 CBulkInsert&
2357 {
2358  m_Impl = bi.m_Impl;
2359  return *this;
2360 }
2361 
2362 void
2364 {
2365  m_Impl->SetHints(hints);
2366 }
2367 
2368 void
2370 {
2371  try {
2372  m_Impl->AddHint(s_ConvertHints(hint), 0);
2373  }
2375 }
2376 
2377 void
2379 {
2380  try {
2382  }
2384 }
2385 
2386 void
2388 {
2390 }
2391 
2392 void
2394 {
2395  m_Impl->Bind(col, type);
2396 }
2397 
2398 void
2400 {
2401  m_Impl->Complete();
2402 }
2403 
2405 CBulkInsert::operator<<(const string& val)
2406 {
2407  m_Impl->WriteVal(val);
2408  return *this;
2409 }
2410 
2413 {
2414  m_Impl->WriteVal(val);
2415  return *this;
2416 }
2417 
2419 CBulkInsert::operator<<(const char* val)
2420 {
2421  m_Impl->WriteVal(val);
2422  return *this;
2423 }
2424 
2426 CBulkInsert::operator<<(unsigned char val)
2427 {
2428  m_Impl->WriteVal(val);
2429  return *this;
2430 }
2431 
2433 CBulkInsert::operator<<(short val)
2434 {
2435  m_Impl->WriteVal(val);
2436  return *this;
2437 }
2438 
2441 {
2442  m_Impl->WriteVal(val);
2443  return *this;
2444 }
2445 
2448 {
2449  m_Impl->WriteVal(val);
2450  return *this;
2451 }
2452 
2453 #if !NCBI_INT8_IS_LONG
2455 CBulkInsert::operator<<(long val)
2456 {
2457 #if SIZEOF_LONG == 8
2458  m_Impl->WriteVal(static_cast<Int8>(val));
2459 #else
2460  m_Impl->WriteVal(static_cast<Int4>(val));
2461 #endif
2462  return *this;
2463 }
2464 #endif
2465 
2467 CBulkInsert::operator<<(float val)
2468 {
2469  m_Impl->WriteVal(val);
2470  return *this;
2471 }
2472 
2474 CBulkInsert::operator<<(double val)
2475 {
2476  m_Impl->WriteVal(val);
2477  return *this;
2478 }
2479 
2481 CBulkInsert::operator<<(bool val)
2482 {
2483  m_Impl->WriteVal(val);
2484  return *this;
2485 }
2486 
2488 CBulkInsert::operator<<(const CTime& val)
2489 {
2490  m_Impl->WriteVal(val);
2491  return *this;
2492 }
2493 
2496 {
2497  return f(*this);
2498 }
2499 
2500 CBulkInsert&
2502 {
2503  bi.m_Impl->WriteNull();
2504  return bi;
2505 }
2506 
2507 CBulkInsert&
2509 {
2510  bi.m_Impl->EndRow();
2511  return bi;
2512 }
2513 
2514 
2515 const CVariant* CRemoteQFB::GetValue(void) const
2516 {
2517  return &m_Query.GetFieldValue(m_ColNum);
2518 }
2519 
2521 {
2522  return m_Query.x_GetContext();
2523 }
2524 
2525 
2526 inline
2528  ESP_ParamType param_type)
2529  : m_Basis(new CParamQFB(v, q->x_GetContext(), param_type))
2530 {}
2531 
2532 inline
2534  : m_Basis(new CRemoteQFB(*q, col_num))
2535 {}
2536 
2537 inline
2539  : m_Basis(qf.m_Basis.release())
2540 {}
2541 
2542 inline
2544  : CQueryFieldImpl(qb) // don't try to copy extra fields
2545 {}
2546 
2547 inline
2549  ESP_ParamType param_type)
2550  : CQueryFieldImpl(q, v, param_type)
2551 {}
2552 
2553 inline
2555  : CQueryFieldImpl(q, col_num)
2556 {}
2557 
2558 
2560  : m_Impl(f.m_Impl)
2561 {}
2562 
2563 inline
2565 {
2566  if (CDB_Object::IsBlobType(v->GetType())) {
2567  m_Impl.Reset(new CQueryBlobImpl(q, v, param_type));
2568  } else {
2569  m_Impl.Reset(new CQueryFieldImpl(q, v, param_type));
2570  }
2571 }
2572 
2573 inline
2574 CQuery::CField::CField(CQueryImpl* q, unsigned int col_num)
2575 {
2576  switch (q->GetColumnType(col_num)) {
2577  case eSDB_Text:
2578  case eSDB_TextUCS2:
2579  case eSDB_Image:
2580  case eSDB_StringMax:
2581  case eSDB_StringMaxUCS2:
2582  case eSDB_BinaryMax:
2583  m_Impl.Reset(new CQueryBlobImpl(q, col_num));
2584  break;
2585  default:
2586  m_Impl.Reset(new CQueryFieldImpl(q, col_num));
2587  break;
2588  }
2589 }
2590 
2592 {}
2593 
2595 {}
2596 
2598  : m_Fields(r.m_Fields), m_MetaData(r.m_MetaData)
2599 {}
2600 
2602 {}
2603 
2604 
2605 inline
2606 void CQuery::CRow::x_CheckColumnNumber(unsigned int col) const
2607 {
2608  if (col == 0 || col > m_Fields.size()) {
2610  eNotExist | Retriable(eRetriable_No),
2611  "No such column in the result set: "
2612  + NStr::NumericToString(col) + ". " + x_GetContext());
2613  }
2614 }
2615 
2616 const CQuery::CField& CQuery::CRow::operator[](unsigned int col) const
2617 {
2618  x_CheckColumnNumber(col);
2619  return m_Fields[col - 1];
2620 }
2621 
2623 {
2625  = m_MetaData->col_nums.find(col);
2626  if (it == m_MetaData->col_nums.end()) {
2628  eNotExist | Retriable(eRetriable_No),
2629  "No such column in the result set: " + col + ". "
2630  + x_GetContext());
2631  } else {
2632  return m_Fields[it->second - 1];
2633  }
2634 }
2635 
2636 unsigned int CQuery::CRow::GetTotalColumns(void) const
2637 {
2638  return m_Fields.size();
2639 }
2640 
2641 const string& CQuery::CRow::GetColumnName(unsigned int col) const
2642 {
2643  x_CheckColumnNumber(col);
2644  return m_MetaData->col_names[col - 1];
2645 }
2646 
2648 {
2649  x_CheckColumnNumber(col);
2650  return m_MetaData->col_types[col - 1];
2651 }
2652 
2654 {
2655  m_Fields.clear();
2656  m_MetaData.Reset(new SQueryRSMetaData);
2657  m_MetaData->exception_context.Reset(&q.x_GetContext());
2658 
2659  unsigned int cols_cnt = rs.GetTotalColumns();
2660  const IResultSetMetaData* meta = rs.GetMetaData();
2661  m_Fields.clear();
2662  m_Fields.reserve(cols_cnt);
2663  for (unsigned int i = 1; i <= cols_cnt; ++i) {
2664  m_Fields.emplace_back(CQuery::CField(&q, i));
2665  m_MetaData->col_nums[meta->GetName(i)] = i;
2666  m_MetaData->col_names.emplace_back(meta->GetName(i));
2667  m_MetaData->col_types.emplace_back(s_ConvertType(meta->GetType(i)));
2668  }
2669 }
2670 
2671 // NB: x_InitBeforeExec resets many of these fields.
2672 inline
2674  : m_DBImpl(db_impl),
2675  m_Stmt(NULL),
2676  m_CallStmt(NULL),
2677  m_CurRS(NULL),
2678  m_IgnoreBounds(true),
2679  m_HasExplicitMode(false),
2680  m_RSBeginned(false),
2681  m_RSFinished(true),
2682  m_Executed(false),
2683  m_ReportedWrongRowCount(false),
2684  m_IsSP(false),
2685  m_RowUnderConstruction(false),
2686  m_CurRSNo(0),
2687  m_CurRowNo(0),
2688  m_CurRelRowNo(0),
2689  m_MinRowCount(0),
2690  m_MaxRowCount(kMax_Auto),
2691  m_RowCount(-1),
2692  m_Status(-1),
2693  m_Context(new CDB_Exception::SContext(m_DBImpl->GetContext()))
2694 {
2695  m_Stmt = db_impl->GetConnection()->GetStatement();
2696 }
2697 
2699 {
2700  try {
2701  x_Close();
2702  }
2703  STD_CATCH_ALL_X(6, "Error destroying CQuery");
2704  x_ClearAllParams();
2705  delete m_Stmt;
2706 }
2707 
2710 {
2711  if ( !m_Context->extra_msg.empty() ) {
2712  return *m_Context;
2713  }
2714 
2715  CNcbiOstrstream oss;
2716  oss << (m_IsSP ? "RPC: " : "SQL: ");
2717  oss << m_Sql;
2718  if ( !m_Params.empty() ) {
2719  string delim;
2720  oss << "; input parameter(s): ";
2721  ITERATE (TParamsMap, it, m_Params) {
2722  const CVariant* value = it->second.m_Impl->GetValue();
2723  oss << delim;
2724  oss << it->first << " = ";
2725  if (value == NULL || value->IsNull()) {
2726  oss << "NULL";
2727  } else {
2728  oss << value->GetData()->GetLogString();
2729  }
2730  delim = ", ";
2731  }
2732  }
2734  return *m_Context;
2735 }
2736 
2737 void
2738 CQueryImpl::x_CheckCanWork(bool need_rs /* = false */) const
2739 {
2740  if (!m_DBImpl->IsOpen()) {
2742  "CQuery is not operational because CDatabase was closed");
2743  }
2744  if (need_rs && !m_CurRS
2745  && !const_cast<CQueryImpl*>(this)->HasMoreResultSets())
2746  {
2748  "CQuery is closed or never executed");
2749  }
2750 }
2751 
2752 template <class T>
2753 inline void
2755  const T& value,
2756  ESDB_Type type,
2757  ESP_ParamType param_type)
2758 {
2759  x_CheckCanWork();
2760  m_Context->extra_msg.clear();
2761 
2762  EDB_Type var_type = s_ConvertType(type);
2763  TParamsMap::iterator it = m_Params.find(name);
2764  if (it == m_Params.end()) {
2765  CQuery::CField field(this, new CVariant(var_type), param_type);
2766  it = m_Params.insert(make_pair(name, field)).first;
2767  } else {
2768  it->second.x_Detach();
2769  static_cast<CParamQFB&>(*it->second.m_Impl->m_Basis)
2770  .SetParamType(param_type);
2771  }
2772  CQueryFieldImpl& field = *it->second.m_Impl;
2773  if (field.GetValue() == NULL
2774  || field.GetValue()->GetType() != var_type) {
2775  it->second = CQuery::CField(this, new CVariant(var_type), param_type);
2776  }
2778  const_cast<CVariant&>(*it->second.m_Impl->GetValue()));
2779 }
2780 
2781 inline void
2783  ESDB_Type type,
2784  ESP_ParamType param_type)
2785 {
2786  x_CheckCanWork();
2787  m_Context->extra_msg.clear();
2788 
2789  EDB_Type var_type = s_ConvertType(type);
2790  TParamsMap::iterator it = m_Params.find(name);
2791  if (it == m_Params.end()) {
2792  CQuery::CField field(this, new CVariant(var_type), param_type);
2793  it = m_Params.insert(make_pair(name, field)).first;
2794  } else {
2795  it->second.x_Detach();
2796  static_cast<CParamQFB&>(*it->second.m_Impl->m_Basis)
2797  .SetParamType(param_type);
2798  }
2799  CQueryFieldImpl& field = *it->second.m_Impl;
2800  if (field.GetValue() == NULL
2801  || field.GetValue()->GetType() != var_type) {
2802  it->second = CQuery::CField(this, new CVariant(var_type), param_type);
2803  } else {
2804  const_cast<CVariant*>(field.GetValue())->SetNull();
2805  }
2806 }
2807 
2808 inline void
2809 CQueryImpl::x_SetOutParameter(const string& name, const CVariant& value)
2810 {
2811  m_Context->extra_msg.clear();
2812  TParamsMap::iterator it = m_Params.find(name);
2813  if (it == m_Params.end()) {
2814  CQuery::CField field(this, new CVariant(value), eSP_InOut);
2815  m_Params.insert(make_pair(name, field));
2816  } else {
2817  it->second.x_Detach();
2818  CQueryFieldImpl& field = *it->second.m_Impl;
2819  try {
2820  const_cast<CVariant&>(*field.GetValue()) = value;
2821  } catch (CDB_ClientEx&) {
2822  it->second = CQuery::CField(this, new CVariant(value), eSP_InOut);
2823  }
2824  }
2825 }
2826 
2827 inline const CVariant&
2828 CQueryImpl::GetFieldValue(unsigned int col_num)
2829 {
2830  return m_CurRS->GetVariant(col_num);
2831 }
2832 
2833 inline const CQuery::CField&
2835 {
2836  x_CheckCanWork();
2837 
2838  TParamsMap::iterator it = m_Params.find(name);
2839  if (it == m_Params.end()) {
2841  eNotExist | Retriable(eRetriable_No),
2842  "Parameter '" + string(name) + "' doesn't exist. "
2843  + x_GetContext());
2844  } else if (static_cast<const CParamQFB&>(*it->second.m_Impl->m_Basis)
2845  .GetParamType() == eSP_InOut
2848  eInconsistent | Retriable(eRetriable_No),
2849  "CQuery::GetParameter called with some results still"
2850  " unread. " + x_GetContext());
2851  }
2852 
2853  return it->second;
2854 }
2855 
2856 inline void
2858 {
2859  x_CheckCanWork();
2860  m_Context->extra_msg.clear();
2861 
2862  TParamsMap::iterator it = m_Params.find(name);
2863  if (it != m_Params.end()) {
2864  it->second.x_Detach();
2865  m_Params.erase(it);
2866  }
2867 }
2868 
2869 void
2871 {
2872  m_Context->extra_msg.clear();
2873  for (auto& p : m_Params) {
2874  p.second.x_Detach();
2875  }
2876  m_Params.clear();
2877 }
2878 
2879 inline void
2881 {
2882  x_CheckCanWork();
2883  x_ClearAllParams();
2884  m_Context->extra_msg.clear();
2885 }
2886 
2887 inline void
2889 {
2890  x_CheckCanWork();
2891 
2892  m_Context->extra_msg.clear();
2893  m_Sql = sql.empty() ? CTempString(" ") : sql;
2894  m_Executed = false;
2895  m_IsSP = false;
2896 }
2897 
2899 {
2900  for (auto& f : m_Row.m_Fields) {
2901  f.x_Detach();
2902  }
2903 }
2904 
2905 void
2907 {
2909  if (m_CurRS != NULL) {
2910  auto orig_row_no = m_CurRowNo;
2911  try {
2913  } catch (CSDB_Exception& e) {
2914  ERR_POST_X(14, Critical << e <<
2915  "Problem while closing DB query "
2916  "(result was at row number " << orig_row_no <<
2917  " and is now at row number " << m_CurRowNo << ").");
2918  }
2919  if (m_CurRSNo != 0) {
2920  _TRACE(m_CurRowNo << " row(s) from query.");
2921  }
2922  }
2923 
2924  delete m_CurRS;
2925  m_CurRS = NULL;
2926  if (m_CallStmt) {
2927  if (m_DBImpl->IsOpen())
2929  delete m_CallStmt;
2930  m_CallStmt = NULL;
2931  }
2932  if (m_DBImpl->IsOpen()) {
2933  m_Stmt->PurgeResults();
2934  m_Stmt->Close();
2935  }
2936 }
2937 
2938 inline void
2940 {
2941  m_IgnoreBounds = true;
2942  m_HasExplicitMode = false;
2943  m_RSBeginned = false;
2944  m_RSFinished = true;
2945  m_ReportedWrongRowCount = false;
2946  m_CurRSNo = 0;
2947  m_CurRowNo = 0;
2948  m_CurRelRowNo = 0;
2949  m_RowCount = 0;
2950  m_MinRowCount = 0;
2952  m_Status = -1;
2954 }
2955 
2956 inline void
2958 {
2959  if (m_IsSP || m_Sql.empty()) {
2960  SDBAPI_THROW(eInconsistent | Retriable(eRetriable_No),
2961  "No statement to execute.");
2962  }
2963 
2964  x_CheckCanWork();
2965 
2966  try {
2967  x_Close();
2968  x_InitBeforeExec();
2969 
2971  ITERATE(TParamsMap, it, m_Params) {
2972  const CQueryFieldImpl& field = *it->second.m_Impl;
2973  m_Stmt->SetParam(*field.GetValue(), it->first);
2974  }
2975  if ( !timeout.IsDefault() ) {
2976  m_DBImpl->SetTimeout(timeout);
2977  }
2978  m_Executed = true;
2979  m_Stmt->SendSql(m_Sql);
2981  }
2983 }
2984 
2985 inline void
2987 {
2988  x_CheckCanWork();
2989 
2990  m_Context->extra_msg.clear();
2991  m_Sql = sp;
2992  m_IsSP = true;
2993 
2994  try {
2995  x_Close();
2996  x_InitBeforeExec();
2997 
2999  ITERATE(TParamsMap, it, m_Params) {
3000  const CParamQFB& pqfb
3001  = static_cast<const CParamQFB&>(*it->second.m_Impl->m_Basis);
3002  if (pqfb.GetParamType() == eSP_InOut) {
3003  m_CallStmt->SetOutputParam(*pqfb.GetValue(), it->first);
3004  } else {
3005  m_CallStmt->SetParam(*pqfb.GetValue(), it->first);
3006  }
3007  }
3008  if ( !timeout.IsDefault() ) {
3009  m_DBImpl->SetTimeout(timeout);
3010  }
3011  m_Executed = true;
3012  m_CallStmt->Execute();
3014  }
3016 }
3017 
3018 inline void
3020 {
3022  x_CheckCanWork();
3024  stmt->Cancel();
3025 }
3026 
3027 inline void
3029 {
3030  x_CheckCanWork();
3031  m_IgnoreBounds = is_ignore;
3032  m_HasExplicitMode = true;
3033  x_CheckRowCount();
3034 }
3035 
3036 inline unsigned int
3038 {
3039  x_CheckCanWork();
3040  return m_CurRSNo;
3041 }
3042 
3043 inline unsigned int
3045 {
3046  x_CheckCanWork();
3047  if (m_IgnoreBounds || how_much == CQuery::eAllResultSets) {
3048  return m_CurRowNo;
3049  } else {
3050  return m_CurRelRowNo;
3051  }
3052 }
3053 
3054 inline int
3056 {
3057  x_CheckCanWork();
3060  "CQuery::GetRowCount called with some results still"
3061  " unread. " + x_GetContext());
3062  } else {
3063  return m_RowCount;
3064  }
3065 }
3066 
3067 inline int
3069 {
3070  x_CheckCanWork();
3073  "CQuery::GetStatus called with some results still"
3074  " unread. " + x_GetContext());
3075  } else {
3076  return m_Status;
3077  }
3078 }
3079 
3081 {
3083  return;
3084  }
3085 
3086  unsigned int n;
3087  if ( !m_IgnoreBounds ) {
3088  n = m_CurRelRowNo;
3089 #if 0 // Counts rows affected by INSERT and the like.
3090  } else if (m_RowCount > 0) {
3091  n = m_RowCount;
3092 #endif
3093  } else {
3094  n = m_CurRowNo;
3095  }
3096 
3097  if (n > m_MaxRowCount) {
3098  m_ReportedWrongRowCount = true;
3100  "Too many rows returned (limited to "
3102  + x_GetContext());
3103  } else if (m_RSFinished && n < m_MinRowCount) {
3104  m_ReportedWrongRowCount = true;
3106  "Not enough rows returned ("
3109  + x_GetContext());
3110  }
3111 }
3112 
3113 inline bool
3115 {
3116  try {
3118  if (m_CurRS->Next()) {
3119  ++m_CurRowNo;
3120  ++m_CurRelRowNo;
3121  x_CheckRowCount();
3122  return true;
3123  }
3124  else {
3125  m_RSFinished = true;
3126  _TRACE(m_CurRelRowNo << " row(s) in set.");
3127  x_CheckRowCount();
3128  return false;
3129  }
3130  }
3132 }
3133 
3134 inline void
3136 {
3138  m_RowUnderConstruction = true;
3139  m_Row.x_Reset(*this, *m_CurRS);
3140  m_RowUnderConstruction = false;
3141 }
3142 
3143 bool
3145 {
3146  x_CheckCanWork();
3147  if (m_CurRS && !m_RSBeginned)
3148  return true;
3149  while (m_CurRS && !m_RSFinished) {
3150  x_Fetch();
3151  }
3152  delete m_CurRS;
3153  m_CurRS = NULL;
3154  m_RSBeginned = m_RSFinished = false;
3155 
3157  try {
3158  while (stmt->HasMoreResults()) {
3159  m_CurRS = stmt->GetResultSet();
3160  if (!m_CurRS)
3161  continue;
3162  switch (m_CurRS->GetResultType()) {
3163  case eDB_StatusResult:
3164  delete m_CurRS;
3165  m_CurRS = NULL;
3166  break;
3167  case eDB_ParamResult:
3168  if (m_CallStmt) {
3169  m_CurRS->Next();
3170  unsigned int col_cnt = m_CurRS->GetTotalColumns();
3171  const IResultSetMetaData* meta = m_CurRS->GetMetaData();
3172  for (unsigned int i = 1; i <= col_cnt; ++i) {
3173  x_SetOutParameter(meta->GetName(i),
3174  m_CurRS->GetVariant(i));
3175  }
3176  }
3177  delete m_CurRS;
3178  m_CurRS = NULL;
3179  break;
3180  case eDB_RowResult:
3181  if (++m_CurRSNo == 2 && !m_HasExplicitMode ) {
3182  ERR_POST_X(16, Info
3183  << "Multiple SDBAPI result sets found, but"
3184  " neither SingleSet nor MultiSet explicitly"
3185  " requested. Now defaulting to SingleSet. "
3186  << x_GetContext());
3187  }
3188  if ( !m_IgnoreBounds ) {
3189  m_ReportedWrongRowCount = false;
3190  }
3191  m_CurRelRowNo = 0;
3192  x_InitRSFields();
3193  return true;
3194  case eDB_ComputeResult:
3195  case eDB_CursorResult:
3196  _ASSERT(false);
3197  }
3198  }
3199  }
3201 
3203 
3204  _TRACE(m_CurRowNo << " row(s) from query.");
3205 
3206  if (m_CallStmt) {
3207  try {
3209  } catch (CDB_ClientEx&) {
3210  }
3211  }
3212  if (m_RowCount == 0) {
3213  if (m_CurRowNo != 0) {
3215  // m_CurRowNo = 0;
3216  }
3217  else {
3218  m_RowCount = stmt->GetRowCount();
3219  }
3220  }
3221  m_CurRSNo = 0;
3222  m_RSFinished = true;
3223  return false;
3224 }
3225 
3226 void
3228 {
3229  x_CheckCanWork();
3230  bool has_more_rs = HasMoreResultSets();
3231  if ( !has_more_rs && !m_Executed ) {
3232  // Check has_more_rs in addition to m_Executed because SetSql
3233  // resets the latter.
3235  has_more_rs = HasMoreResultSets();
3236  }
3237  if ( !has_more_rs ) {
3238  if (m_IgnoreBounds && m_CurRowNo == 0) {
3239  // OK to have no results whatsoever in SingleSet mode.
3240  return;
3241  }
3243  "All result sets in CQuery were already iterated through. "
3244  + x_GetContext());
3245  }
3246  if (m_RSFinished) {
3247  // Complete recovering from a premature call to GetStatus or
3248  // GetRowCount.
3249  m_RSFinished = false;
3250  m_CurRelRowNo = 0;
3251  try {
3252  x_InitRSFields();
3254  }
3255  while (HasMoreResultSets() && !x_Fetch() && m_IgnoreBounds)
3256  m_RSBeginned = true;
3257  m_RSBeginned = true;
3258 }
3259 
3260 inline void
3262 {
3263  x_CheckCanWork();
3264  m_HasExplicitMode = true; // Doesn't particularly matter at this point!
3265  bool has_more = true;
3266  while (has_more) {
3267  try {
3268  if ((has_more = HasMoreResultSets())) {
3269  BeginNewRS();
3270  }
3271  } catch (CSDB_Exception& e) {
3272  IResultSet* rs = NULL;
3273  while (has_more && rs != m_CurRS) {
3274  try {
3275  rs = m_CurRS;
3276  if ((has_more = HasMoreResultSets())) {
3277  BeginNewRS();
3278  }
3279  } catch (CSDB_Exception& e2) {
3280  has_more = true;
3281  // Not technically the correct relationship, but by far
3282  // the simplest way to consolidate the exceptions.
3283  e.AddPrevious(&e2);
3284  }
3285  }
3286  throw;
3287  }
3288  }
3289 }
3290 
3291 inline
3292 unsigned int
3294 {
3295  x_CheckCanWork(true);
3296  return m_Row.GetTotalColumns();
3297 }
3298 
3299 inline string
3300 CQueryImpl::GetColumnName(unsigned int col) const
3301 {
3302  x_CheckCanWork(true);
3303  return m_Row.GetColumnName(col);
3304 }
3305 
3306 inline ESDB_Type
3307 CQueryImpl::GetColumnType(unsigned int col) const
3308 {
3309  x_CheckCanWork(true);
3310  if (m_RowUnderConstruction) {
3311  try {
3312  return s_ConvertType(m_CurRS->GetMetaData()->GetType(col));
3313  }
3315  } else {
3316  return m_Row.GetColumnType(col);
3317  }
3318 }
3319 
3320 inline void
3322 {
3323  while (!x_Fetch() && m_IgnoreBounds && HasMoreResultSets())
3324  m_RSBeginned = true;
3325  m_RSBeginned = true;
3326 }
3327 
3328 inline void
3329 CQueryImpl::RequireRowCount(unsigned int min_rows, unsigned int max_rows)
3330 {
3331  if ( !m_Executed ) {
3332  SDBAPI_THROW(eInconsistent | Retriable(eRetriable_No),
3333  "RequireRowCount must follow Execute or ExecuteSP,"
3334  " which reset any requirements.");
3335  }
3336  if (min_rows > max_rows) {
3337  SDBAPI_THROW(eWrongParams | Retriable(eRetriable_No),
3338  "Inconsistent row-count constraints: "
3339  + NStr::NumericToString(min_rows) + " > "
3340  + NStr::NumericToString(max_rows));
3341  }
3342  x_CheckCanWork();
3343  _TRACE("RequireRowCount(" << min_rows << ", " << max_rows << ')');
3344  m_MinRowCount = min_rows;
3345  m_MaxRowCount = max_rows;
3346  if (m_CurRS != NULL) {
3347  x_CheckRowCount();
3348  }
3349 }
3350 
3351 inline void
3353 {
3354  x_CheckCanWork();
3355 
3356  bool missed_results = false;
3357  bool want_all = m_IgnoreBounds || how_much == CQuery::eAllResultSets;
3358 
3359  for (;;) {
3360  try {
3361  if (m_RSFinished) {
3362  x_CheckRowCount();
3363  } else if (m_CurRS) {
3364  // Tolerate having read just enough rows, unless that number
3365  // was zero but not necessarily required to be.
3366  missed_results
3367  = x_Fetch() || ( !m_RSBeginned && m_MaxRowCount > 0);
3368  }
3369  } catch (...) {
3370  if (want_all) {
3371  PurgeResults();
3372  } else {
3374  }
3375  throw;
3376  }
3377 
3378  // We always want the effect of HasMoreResultSets.
3379  if (HasMoreResultSets() && want_all) {
3380  BeginNewRS();
3381  } else {
3382  break;
3383  }
3384  }
3385 
3386  if (missed_results) {
3388  "Result set had unread rows. " + x_GetContext());
3389  }
3390 }
3391 
3392 inline bool
3394 {
3395  if ( !m_RSFinished ) {
3396  return false;
3397  } else if (how_much == CQuery::eThisResultSet
3398  || ( !m_CurRS && !m_Stmt->HasMoreResults())) {
3399  return true;
3400  }
3401 
3402  // Check whether any further result sets actually exist, in which
3403  // case some state (saved here) will need to be rolled back.
3404  // m_CurRS will have to remain advanced, but HasMoreResultSets
3405  // knows not to advance it again until BeginNewRS has run.
3406  CQuery::CRow saved_row = m_Row;
3407  unsigned int saved_rel_row_no = m_CurRelRowNo;
3408  CQueryImpl& nc_self = const_cast<CQueryImpl&>(*this);
3409 
3410  nc_self.m_Row.m_Fields.clear();
3411  nc_self.m_Row.m_MetaData.Reset();
3412  if (nc_self.HasMoreResultSets()) {
3413  nc_self.m_RSFinished = true; // still match end()
3414  nc_self.m_CurRelRowNo = saved_rel_row_no;
3415  nc_self.m_Row = saved_row;
3416  return false;
3417  }
3418 
3419  return true;
3420 }
3421 
3422 inline
3424 {
3425  x_CheckCanWork(true);
3426  return m_Row;
3427 }
3428 
3429 inline const CQuery::CField&
3431 {
3432  x_CheckCanWork(true);
3433  return c.IsPositional() ? m_Row[c.GetPosition()] : m_Row[c.GetName()];
3434 }
3435 
3436 inline CDatabaseImpl*
3438 {
3439  return m_DBImpl.GetNCPointer();
3440 }
3441 
3442 inline IConnection*
3444 {
3445  return m_DBImpl->GetConnection();
3446 }
3447 
3448 inline
3449 const list<string>& CQueryImpl::GetPrintOutput(void) const
3450 {
3451  return m_DBImpl->GetPrintOutput();
3452 }
3453 
3454 
3455 inline
3457  I_BlobDescriptor* descr)
3458  : m_DBImpl(db_impl),
3459  m_Descr(descr)
3460 {}
3461 
3462 CNcbiOstream&
3464 {
3465  try {
3467  m_OStream.reset(new CWStream
3468  (new CxBlobWriter(db_conn, *m_Descr, blob_size,
3469  flags, false),
3470  0, 0,
3473  return *m_OStream;
3474  }
3476 }
3477 
3478 
3480 {}
3481 
3483  : m_Impl(bm_impl)
3484 {}
3485 
3487  : m_Impl(bm.m_Impl)
3488 {}
3489 
3492 {
3493  m_Impl = bm.m_Impl;
3494  return *this;
3495 }
3496 
3498 {}
3499 
3500 CNcbiOstream&
3502 {
3503  return m_Impl.GetNCPointer()->GetOStream(blob_size, flags);
3504 }
3505 
3506 CNcbiOstream&
3507 CBlobBookmark::GetOStream(size_t blob_size, CQuery::EAllowLog log_it) const
3508 {
3509  return GetOStream(blob_size,
3510  (log_it == CQuery::eDisableLog) ? fBOS_SkipLogging : 0);
3511 }
3512 
3514 {
3515  return DBAPI_MakeTrans(*db.m_Impl->GetConnection());
3516 }
3517 
3519 {
3520  return DBAPI_MakeTrans(*query.m_Impl->GetConnection());
3521 }
3522 
3523 inline
3525 {
3526  return *m_MetaData->exception_context;
3527 }
3528 
3530  : m_IsEnd(false)
3531 {}
3532 
3533 inline
3535  : m_Query(q),
3536  m_IsEnd(is_end)
3537 {}
3538 
3540  : m_Query(ri.m_Query),
3541  m_IsEnd(ri.m_IsEnd)
3542 {}
3543 
3546 {
3547  m_Query = ri.m_Query;
3548  m_IsEnd = ri.m_IsEnd;
3549  return *this;
3550 }
3551 
3553 {}
3554 
3555 inline
3557 {
3558  return m_Query->x_GetContext();
3559 }
3560 
3561 unsigned int
3563 {
3564  return m_Query->GetResultSetNo();
3565 }
3566 
3567 unsigned int
3569 {
3570  return m_Query->GetRowNo();
3571 }
3572 
3573 unsigned int
3575 {
3576  return m_Query->GetTotalColumns();
3577 }
3578 
3579 string
3581 {
3582  return m_Query->GetColumnName(col);
3583 }
3584 
3585 ESDB_Type
3587 {
3588  return m_Query->GetColumnType(col);
3589 }
3590 
3591 bool
3593 {
3594  if (m_Query != ri.m_Query)
3595  return false;
3596  else if (m_IsEnd ^ ri.m_IsEnd) {
3597  return m_Query->IsFinished();
3598  }
3599  else
3600  return true;
3601 }
3602 
3605 {
3606  if (m_IsEnd || m_Query->IsFinished()) {
3607  SDBAPI_THROW(eInconsistent | Retriable(eRetriable_No),
3608  "Cannot increase end() iterator");
3609  }
3610  m_Query->Next();
3611  return *this;
3612 }
3613 
3614 const CQuery::CField&
3615 CQuery::CRowIterator::operator[](unsigned int col) const
3616 {
3617  return m_Query->GetRow()[col];
3618 }
3619 
3620 const CQuery::CField&
3622 {
3623  return m_Query->GetRow()[col];
3624 }
3625 
3627 {
3628  return m_Query->GetRow();
3629 }
3630 
3631 
3633 {
3634  unique_ptr<IQueryFieldBasis> new_basis
3635  (new CLocalQFB(new CVariant(*GetValue()), x_GetContext()));
3636  CRef<CQueryFieldImpl> replacement(new CQueryFieldImpl(*this));
3637  m_Basis.reset(new_basis.release());
3638  return replacement;
3639 }
3640 
3642 {
3643  unique_ptr<IQueryFieldBasis> new_basis
3644  (new CLocalQFB(new CVariant(*GetValue()), x_GetContext()));
3645  CRef<CQueryFieldImpl> replacement(new CQueryBlobImpl(*this));
3646  m_Basis.reset(new_basis.release());
3647  return replacement;
3648 }
3649 
3651 {
3652  if ( m_Impl.NotEmpty() && !m_Impl->ReferencedOnlyOnce() ) {
3653  m_Impl.Reset(m_Impl->Detach());
3654  }
3655 }
3656 
3657 inline
3659 {
3660  return m_Basis->x_GetContext();
3661 }
3662 
3663 inline
3665 {
3666  return m_Basis->GetValue();
3667 }
3668 
3669 string
3671 {
3672  string value;
3673  s_ConvertValue(*m_Impl->GetValue(), value);
3674  return value;
3675 }
3676 
3677 unsigned char
3679 {
3680  unsigned char value = 0;
3681  s_ConvertValue(*m_Impl->GetValue(), value);
3682  return value;
3683 }
3684 
3685 short
3687 {
3688  short value = 0;
3689  s_ConvertValue(*m_Impl->GetValue(), value);
3690  return value;
3691 }
3692 
3693 Int4
3695 {
3696  Int4 value = 0;
3697  s_ConvertValue(*m_Impl->GetValue(), value);
3698  return value;
3699 }
3700 
3701 Int8
3703 {
3704  Int8 value = 0;
3705  s_ConvertValue(*m_Impl->GetValue(), value);
3706  return value;
3707 }
3708 
3709 float
3711 {
3712  float value = 0;
3713  s_ConvertValue(*m_Impl->GetValue(), value);
3714  return value;
3715 }
3716 
3717 double
3719 {
3720  double value = 0;
3721  s_ConvertValue(*m_Impl->GetValue(), value);
3722  return value;
3723 }
3724 
3725 bool
3727 {
3728  bool value = false;
3729  s_ConvertValue(*m_Impl->GetValue(), value);
3730  return value;
3731 }
3732 
3733 CTime
3735 {
3736  CTime value;
3737  s_ConvertValue(*m_Impl->GetValue(), value);
3738  return value;
3739 }
3740 
3741 const vector<unsigned char>&
3743 {
3744  SDBAPI_THROW(eUnsupported | Retriable(eRetriable_No),
3745  string("Method is unsupported for this type of data: ")
3746  + CDB_Object::GetTypeName(GetValue()->GetType(), false));
3747 }
3748 
3749 const vector<unsigned char>&
3751 {
3752  const CVariant& var_val = *GetValue();
3753  string value = var_val.GetString();
3754  // WorkShop cannot eat string::iterators in vector<>::insert (although due
3755  // to STL he has to eat any iterator-like type) but is okay with pointers
3756  // to unsigned char here.
3757  const unsigned char* data
3758  = reinterpret_cast<const unsigned char*>(value.data());
3759  m_Vector.clear();
3760  m_Vector.insert(m_Vector.begin(), data, data + value.size());
3761  return m_Vector;
3762 }
3763 
3764 const vector<unsigned char>&
3766 {
3767  return m_Impl->AsVector();
3768 }
3769 
3770 CNcbiIstream&
3772 {
3773  SDBAPI_THROW(eUnsupported | Retriable(eRetriable_No),
3774  string("Method is unsupported for this type of data: ")
3775  + CDB_Object::GetTypeName(GetValue()->GetType(), false));
3776 }
3777 
3778 CNcbiIstream&
3780 {
3781  const CVariant& var_val = *GetValue();
3782  m_ValueForStream = var_val.GetString();
3783  m_IStream.reset
3784  (new CNcbiIstrstream(m_ValueForStream));
3785  return *m_IStream;
3786 }
3787 
3788 CNcbiIstream&
3790 {
3791  return m_Impl->AsIStream();
3792 }
3793 
3794 bool
3796 {
3797  return m_Impl->GetValue()->IsNull();
3798 }
3799 
3801 {
3802  SDBAPI_THROW(eUnsupported | Retriable(eRetriable_No),
3803  "Method requires a live field");
3804 }
3805 
3807  TBlobOStreamFlags flags) const
3808 {
3809  const CVariant& var_val = *GetValue();
3810  try {
3811  IConnection* conn = m_Query.GetConnection()->CloneConnection();
3812  CDB_Connection* db_conn = conn->GetCDB_Connection();
3813  return new CWStream
3814  (new CxBlobWriter(db_conn, var_val.GetBlobDescriptor(),
3815  blob_size, flags, false),
3816  0, 0,
3819  }
3821 }
3822 
3824 {
3825  SDBAPI_THROW(eUnsupported | Retriable(eRetriable_No),
3826  string("Method is unsupported for this type of data: ")
3827  + CDB_Object::GetTypeName(GetValue()->GetType(), false));
3828 }
3829 
3831  TBlobOStreamFlags flags) const
3832 {
3833  m_OStream.reset(m_Basis->GetOStream(blob_size, flags));
3834  return *m_OStream;
3835 }
3836 
3837 CNcbiOstream&
3839 {
3840  return m_Impl->GetOStream(blob_size, flags);
3841 }
3842 
3843 CNcbiOstream&
3844 CQuery::CField::GetOStream(size_t blob_size, EAllowLog log_it) const
3845 {
3846  return GetOStream(blob_size,
3847  (log_it == eDisableLog) ? fBOS_SkipLogging : 0);
3848 }
3849 
3851 {
3852  SDBAPI_THROW(eUnsupported | Retriable(eRetriable_No),
3853  "Method requires a live field");
3854 }
3855 
3857 {
3858  const CVariant& var_val = *GetValue();
3860  (new CBlobBookmarkImpl(m_Query.GetDatabase(),
3861  var_val.ReleaseBlobDescriptor()));
3862  return CBlobBookmark(bm);
3863 }
3864 
3866 {
3867  SDBAPI_THROW(eUnsupported | Retriable(eRetriable_No),
3868  string("Method is unsupported for this type of data: ")
3869  + CDB_Object::GetTypeName(GetValue()->GetType(), false));
3870 }
3871 
3873 {
3874  return m_Basis->GetBookmark();
3875 }
3876 
3879 {
3880  return m_Impl->GetBookmark();
3881 }
3882 
3883 
3885 {}
3886 
3888 {
3889  m_Impl.Reset(new CQueryImpl(db_impl));
3890 }
3891 
3893  : m_Impl(q.m_Impl)
3894 {}
3895 
3897 {}
3898 
3899 CQuery &
3901 {
3902  m_Impl = q.m_Impl;
3903  return *this;
3904 }
3905 
3906 CQuery&
3908  const string& value,
3909  ESDB_Type type /* = eSDB_String */,
3910  ESP_ParamType param_type /* = eSP_In */)
3911 {
3912  m_Impl->SetParameter(name, value, type, param_type);
3913  return *this;
3914 }
3915 
3916 CQuery&
3918  const char* value,
3919  ESDB_Type type /* = eSDB_String */,
3920  ESP_ParamType param_type /* = eSP_In */)
3921 {
3922  m_Impl->SetParameter(name, value, type, param_type);
3923  return *this;
3924 }
3925 
3926 CQuery&
3928  Int8 value,
3929  ESDB_Type type /* = eSDB_Int8 */,
3930  ESP_ParamType param_type /* = eSP_In */)
3931 {
3932  m_Impl->SetParameter(name, value, type, param_type);
3933  return *this;
3934 }
3935 
3936 CQuery&
3938  Int4 value,
3939  ESDB_Type type /* = eSDB_Int4 */,
3940  ESP_ParamType param_type /* = eSP_In */)
3941 {
3942  m_Impl->SetParameter(name, value, type, param_type);
3943  return *this;
3944 }
3945 
3946 CQuery&
3948  short value,
3949  ESDB_Type type /* = eSDB_Short */,
3950  ESP_ParamType param_type /* = eSP_In */)
3951 {
3952  m_Impl->SetParameter(name, value, type, param_type);
3953  return *this;
3954 }
3955 
3956 CQuery&
3958  unsigned char value,
3959  ESDB_Type type /* = eSDB_Byte */,
3960  ESP_ParamType param_type /* = eSP_In */)
3961 {
3962  m_Impl->SetParameter(name, value, type, param_type);
3963  return *this;
3964 }
3965 
3966 CQuery&
3968  float value,
3969  ESDB_Type type /* = eSDB_Float */,
3970  ESP_ParamType param_type /* = eSP_In */)
3971 {
3972  m_Impl->SetParameter(name, value, type, param_type);
3973  return *this;
3974 }
3975 
3976 CQuery&
3978  double value,
3979  ESDB_Type type /* = eSDB_Double */,
3980  ESP_ParamType param_type /* = eSP_In */)
3981 {
3982  m_Impl->SetParameter(name, value, type, param_type);
3983  return *this;
3984 }
3985 
3986 CQuery&
3988  const CTime& value,
3989  ESDB_Type type /* = eSDB_DateTime */,
3990  ESP_ParamType param_type /*= eSP_In */)
3991 {
3992  m_Impl->SetParameter(name, value, type, param_type);
3993  return *this;
3994 }
3995 
3996 CQuery&
3998  bool value,
3999  ESDB_Type type /* = eSDB_Bit */,
4000  ESP_ParamType param_type /* = eSP_In */)
4001 {
4002  m_Impl->SetParameter(name, value, type, param_type);
4003  return *this;
4004 }
4005 
4006 CQuery&
4008  ESDB_Type type,
4009  ESP_ParamType param_type /* = eSP_In */)
4010 {
4011  m_Impl->SetNullParameter(name, type, param_type);
4012  return *this;
4013 }
4014 
4015 const CQuery::CField&
4017 {
4018  return m_Impl->GetParameter(name);
4019 }
4020 
4021 CQuery&
4023 {
4024  m_Impl->ClearParameter(name);
4025  return *this;
4026 }
4027 
4028 CQuery&
4030 {
4032  return *this;
4033 }
4034 
4035 CQuery&
4037 {
4038  m_Impl->SetSql(sql);
4039  return *this;
4040 }
4041 
4042 CQuery&
4043 CQuery::Execute(const CTimeout& timeout)
4044 {
4045  m_Impl->Execute(timeout);
4046  return *this;
4047 }
4048 
4049 CQuery&
4051 {
4052  m_Impl->ExecuteSP(sp, timeout);
4053  return *this;
4054 }
4055 
4056 void
4058 {
4059  m_Impl->Cancel();
4060 }
4061 
4062 CQuery&
4064 {
4065  m_Impl->SetIgnoreBounds(true);
4066  return *this;
4067 }
4068 
4069 CQuery&
4071 {
4072  m_Impl->SetIgnoreBounds(false);
4073  return *this;
4074 }
4075 
4078 {
4079  // Check prerequisite that the requested number of rows includes 1
4080  if (m_Impl->GetMinRowCount() > 1)
4082  "Exactly one row requested while RequireRowCount() set "
4083  "the minimum to " +
4085  if (m_Impl->GetMaxRowCount() < 1)
4087  "Exactly one row requested while RequireRowCount() set "
4088  "the maximum to " +
4090 
4091  CQuery::iterator q_it = begin();
4092  if (q_it == end())
4094  "Expected exactly one row, but none are available");
4095 
4096  CQuery::CRow row(*q_it);
4097 
4098  ++q_it;
4099  if (q_it != end())
4101  "Expected exactly one row, but more than one are available");
4102 
4103  VerifyDone();
4104  return row;
4105 }
4106 
4107 unsigned int
4109 {
4110  return m_Impl->GetResultSetNo();
4111 }
4112 
4113 unsigned int
4115 {
4116  return m_Impl->GetRowNo(how_much);
4117 }
4118 
4119 int
4121 {
4122  return m_Impl->GetRowCount();
4123 }
4124 
4125 int
4127 {
4128  return m_Impl->GetStatus();
4129 }
4130 
4131 const list<string>&
4133 {
4134  return m_Impl->GetPrintOutput();
4135 }
4136 
4137 bool
4139 {
4140  return m_Impl->HasMoreResultSets();
4141 }
4142 
4143 void
4145 {
4146  m_Impl->PurgeResults();
4147 }
4148 
4149 void
4151 {
4153 }
4154 
4155 void
4156 CQuery::RequireRowCount(unsigned int min_rows, unsigned int max_rows)
4157 {
4158  m_Impl->RequireRowCount(min_rows, max_rows);
4159 }
4160 
4161 void
4163 {
4164  m_Impl->VerifyDone(how_much);
4165 }
4166 
4167 unsigned int
4169 {
4170  return m_Impl->GetTotalColumns();
4171 }
4172 
4173 string
4174 CQuery::GetColumnName(unsigned int col) const
4175 {
4176  return m_Impl->GetColumnName(col);
4177 }
4178 
4179 ESDB_Type
4180 CQuery::GetColumnType(unsigned int col) const
4181 {
4182  return m_Impl->GetColumnType(col);
4183 }
4184 
4186 CQuery::begin(void) const
4187 {
4189  return CRowIterator(m_Impl.GetNCPointer(), false);
4190 }
4191 
4193 CQuery::end(void) const
4194 {
4195  return CRowIterator(m_Impl.GetNCPointer(), true);
4196 }
4197 
4198 inline
4200  const CException* prev_exception, EDiagSev)
4201 {
4202  _ASSERT(dynamic_cast<const CDB_DeadlockEx*>(prev_exception));
4203 }
4204 
4205 inline
4207 {
4209 }
4210 
4211 
@ eNone
None specified.
Definition: blast_def.h:326
ECompressMethod
Definition: blobstore.hpp:40
@ eZLib
Definition: blobstore.hpp:42
@ eBZLib
Definition: blobstore.hpp:43
AutoPtr –.
Definition: ncbimisc.hpp:401
Helper class to allow safe initialization from higher-layer objects.
Definition: public.hpp:1056
unique_ptr< I_BlobDescriptor > m_Descr
CRef< CDatabaseImpl > m_DBImpl
unique_ptr< CWStream > m_OStream
CNcbiOstream & GetOStream(size_t blob_size, TBlobOStreamFlags flags)
Definition: sdbapi.cpp:3463
CBlobBookmarkImpl(CDatabaseImpl *db_impl, I_BlobDescriptor *descr)
Definition: sdbapi.cpp:3456
Object used to store bookmarks to blobs to be changed later.
Definition: sdbapi.hpp:766
CBlobBookmark & operator=(const CBlobBookmark &bm)
Definition: sdbapi.cpp:3491
~CBlobBookmark(void)
Definition: sdbapi.cpp:3497
CNcbiOstream & GetOStream(size_t blob_size, TBlobOStreamFlags flags=0) const
Get Blob output stream.
Definition: sdbapi.cpp:3501
CRef< CBlobBookmarkImpl > m_Impl
Bookmark implementation object.
Definition: sdbapi.hpp:810
CBlobBookmark(void)
Empty constructor of bookmark object.
Definition: sdbapi.cpp:3479
EBlobType
Blob type (if known).
Definition: sdbapi.hpp:769
void WriteNull(void)
Definition: sdbapi.cpp:2323
void x_CheckCanWrite(int col)
Definition: sdbapi.cpp:2209
CRef< CDB_Exception::SContext > m_Context
void Bind(int col, ESDB_Type type)
Definition: sdbapi.cpp:2252
void Complete(void)
Definition: sdbapi.cpp:2292
void AddOrderHint(CTempString columns)
Definition: sdbapi.cpp:2245
void x_CheckWriteStarted(void)
Definition: sdbapi.cpp:2308
void EndRow(void)
Definition: sdbapi.cpp:2271
CBulkInsertImpl(CDatabaseImpl *db_impl, const string &tableName, int autoflush)
Definition: sdbapi.cpp:2176
const CDB_Exception::SContext & x_GetContext(void) const
Definition: sdbapi.cpp:2203
~CBulkInsertImpl(void)
Definition: sdbapi.cpp:2191
void WriteVal(const T &val)
Definition: sdbapi.cpp:2331
void SetHints(CTempString hints)
Definition: sdbapi.cpp:2231
CRef< CDatabaseImpl > m_DBImpl
void AddHint(IBulkInsert::EHints hint, unsigned int value)
Definition: sdbapi.cpp:2238
IBulkInsert * m_BI
vector< CVariant > m_Cols
Object used to perform bulk-inserting operations to database.
Definition: sdbapi.hpp:816
CBulkInsert & operator<<(const string &val)
Put values of different type into bulk-insert row.
Definition: sdbapi.cpp:2405
EHints
Type of hint that can be set for bulk insert.
Definition: sdbapi.hpp:832
@ eFireTriggers
Definition: sdbapi.hpp:835
@ eCheckConstraints
Definition: sdbapi.hpp:834
void AddHint(EHints hint)
Add hint to the bulk insert.
Definition: sdbapi.cpp:2369
void Complete()
Complete bulk insert.
Definition: sdbapi.cpp:2399
void Bind(int col, ESDB_Type type)
Bind column for bulk insert.
Definition: sdbapi.cpp:2393
void AddOrderHint(CTempString columns)
Add "ORDER" hint.
Definition: sdbapi.cpp:2387
EHintsWithValue
Type of hint that requires some value to be provided with it.
Definition: sdbapi.hpp:842
@ eRowsPerBatch
Definition: sdbapi.hpp:843
@ eKilobytesPerBatch
Definition: sdbapi.hpp:844
void SetHints(CTempString hints)
Set hints by one call. Resets everything that was set by Add*Hint().
Definition: sdbapi.cpp:2363
CRef< CBulkInsertImpl > m_Impl
Bulk-insert implementation object.
Definition: sdbapi.hpp:903
CBulkInsert(void)
Empty constructor of bulk-insert object.
Definition: sdbapi.cpp:2338
CBulkInsert & operator=(const CBulkInsert &bi)
Definition: sdbapi.cpp:2356
~CBulkInsert(void)
Definition: sdbapi.cpp:2352
void SetTimeout(const CTimeout &timeout)
Definition: sdbapi.cpp:1839
CMutex m_Mutex
Definition: sdbapi_impl.hpp:86
void ResetTimeout(void)
Definition: sdbapi.cpp:1855
CRef< CDB_Exception::SContext > m_Context
Definition: sdbapi_impl.hpp:84
virtual ~CConnHolder(void)
Definition: sdbapi.cpp:1811
bool m_ContinueAfterRaiserror
Definition: sdbapi_impl.hpp:80
list< string > m_PrintOutput
Definition: sdbapi_impl.hpp:83
void CloseRef(void)
Definition: sdbapi.cpp:1830
CRef< CSDB_UserHandler > m_Handler
Definition: sdbapi_impl.hpp:85
void ResetPrintOutput()
Definition: sdbapi.cpp:1871
Uint4 m_CntOpen
Definition: sdbapi_impl.hpp:82
IConnection * GetConn(void) const
Definition: sdbapi.cpp:1817
bool m_HasCustomTimeout
Definition: sdbapi_impl.hpp:79
void AddOpenRef(void)
Definition: sdbapi.cpp:1823
CConnHolder(IConnection *conn, const CSDB_ConnectionParam &params)
Definition: sdbapi.cpp:1789
bool m_LogMinorMessages
Definition: sdbapi_impl.hpp:81
const CDB_Exception::SContext & GetContext(void) const
Definition: sdbapi.cpp:1878
size_t m_DefaultTimeout
Definition: sdbapi_impl.hpp:78
IConnection * m_Conn
Definition: sdbapi_impl.hpp:77
const list< string > & GetPrintOutput(void) const
Definition: sdbapi.cpp:1865
Helper hook-up class that installs default logging/registry/locking (but only if they have not yet be...
void SetEncoding(EEncoding encoding)
void SetPassword(const string &passwd)
void SetDriverName(const string &name)
void SetParam(const string &key, const string &value)
void SetServerName(const string &name)
void SetDatabaseName(const string &name)
void SetUserName(const string &name)
CDBConnParams::
Definition: interfaces.hpp:258
void GetServersList(const string &validator_name, const string &service_name, list< string > *serv_list)
void WorkWithSingleServer(const string &validator_name, const string &service_name, const string &server)
CDB_Exception –.
Definition: exception.hpp:118
CDataSourceInitializer(void)
Definition: sdbapi.cpp:913
void ResetPrintOutput()
Definition: sdbapi.cpp:1967
void Connect(const CSDB_ConnectionParam &params)
Definition: sdbapi.cpp:1885
~CDatabaseImpl(void)
Definition: sdbapi.cpp:1922
CRef< CConnHolder > m_Conn
const list< string > & GetPrintOutput(void) const
Definition: sdbapi.cpp:1961
IConnection * GetConnection(void)
Definition: sdbapi.cpp:1943
void ResetTimeout(void)
Definition: sdbapi.cpp:1955
CDatabaseImpl(void)
Definition: sdbapi.cpp:1897
bool IsOpen() const
Definition: sdbapi.cpp:1931
const CDB_Exception::SContext & GetContext(void) const
Definition: sdbapi.cpp:1974
bool EverConnected() const
Definition: sdbapi.cpp:1937
void Close()
Definition: sdbapi.cpp:1913
void SetTimeout(const CTimeout &timeout)
Definition: sdbapi.cpp:1949
Database connection object.
Definition: sdbapi.hpp:1137
void Close(void)
Close database object.
Definition: sdbapi.cpp:2028
CDatabase & operator=(const CDatabase &db)
Definition: sdbapi.cpp:1998
void Connect(void)
Explicitly (re)connect to the database server.
Definition: sdbapi.cpp:2016
CQuery NewQuery(void)
Get new CQuery object for this database.
Definition: sdbapi.cpp:2085
CDatabase Clone(void)
Clone database object.
Definition: sdbapi.cpp:2073
CBlobBookmark NewBookmark(const string &table_name, const string &column_name, const string &search_conditions, CBlobBookmark::EBlobType column_type=CBlobBookmark::eUnknown, ETriState has_legacy_type=eTriState_Unknown)
Get new CBlobBookmark object.
Definition: sdbapi.cpp:2099
CBulkInsert NewBulkInsert(const string &table_name, int autoflush)
Get new CBulkInsert object.
Definition: sdbapi.cpp:2092
EConnectionCheckMethod
How thoroughly IsConnected should actually check the connection.
Definition: sdbapi.hpp:1140
@ eFastCheck
Definition: sdbapi.hpp:1142
@ eFullCheck
Definition: sdbapi.hpp:1143
CRef< CDatabaseImpl > m_Impl
Database implementation object.
Definition: sdbapi.hpp:1284
CBlobStoreStatic * NewBlobStore(const string &table_name, TNewBlobStoreFlags flags=TNewBlobStoreFlags(0), size_t image_limit=1<< 24)
Get new CBlobStoreStatic object (to be owned by caller).
Definition: sdbapi.cpp:2128
~CDatabase(void)
Definition: sdbapi.cpp:2005
bool IsConnected(EConnectionCheckMethod check_method=eNoCheck)
Check if database object was already connected to database server.
Definition: sdbapi.cpp:2039
CSDB_ConnectionParam m_Params
Database parameters.
Definition: sdbapi.hpp:1282
void x_ConnectAsNeeded(const char *operation)
Definition: sdbapi.cpp:2162
CDatabase(void)
Empty constructor of database object.
Definition: sdbapi.cpp:1980
CRef< IDBConnectionFactory > GetConnectionFactory(void) const
Retrieve a connection factory.
static CDbapiConnMgr & Instance(void)
Get access to the class instance.
Incapsulate compile time information such as __FILE__, __LINE__, NCBI_MODULE, current function.
Definition: ncbidiag.hpp:65
const CVariant * GetValue(void) const override
static CNcbiApplication * Instance(void)
Singleton method.
Definition: ncbiapp.cpp:264
CNcbiOstrstreamToString class helps convert CNcbiOstrstream to a string Sample usage:
Definition: ncbistre.hpp:802
ESP_ParamType GetParamType(void) const
CRef< CQueryFieldImpl > Detach(void) override
Definition: sdbapi.cpp:3641
const vector< unsigned char > & AsVector(void) const override
Definition: sdbapi.cpp:3750
CNcbiOstream & GetOStream(size_t blob_size, TBlobOStreamFlags flags) const override
Definition: sdbapi.cpp:3830
CBlobBookmark GetBookmark(void) const override
Definition: sdbapi.cpp:3872
CQueryBlobImpl(CQueryImpl *q, unsigned int col_num)
Definition: sdbapi.cpp:2554
CNcbiIstream & AsIStream(void) const override
Definition: sdbapi.cpp:3779
const CDB_Exception::SContext & x_GetContext(void) const
Definition: sdbapi.cpp:3658
virtual CNcbiOstream & GetOStream(size_t blob_size, TBlobOStreamFlags flags) const
Definition: sdbapi.cpp:3823
virtual CNcbiIstream & AsIStream(void) const
Definition: sdbapi.cpp:3771
const CVariant * GetValue(void) const
Definition: sdbapi.cpp:3664
virtual CRef< CQueryFieldImpl > Detach(void)
Definition: sdbapi.cpp:3632
virtual const vector< unsigned char > & AsVector(void) const
Definition: sdbapi.cpp:3742
CQueryFieldImpl(CQueryImpl *q, unsigned int col_num)
Definition: sdbapi.cpp:2533
virtual CBlobBookmark GetBookmark(void) const
Definition: sdbapi.cpp:3865
void Next(void)
Definition: sdbapi.cpp:3321
unsigned int GetRowNo(CQuery::EHowMuch how_much=CQuery::eAllResultSets) const
Definition: sdbapi.cpp:3044
const list< string > & GetPrintOutput(void) const
Definition: sdbapi.cpp:3449
void SetSql(CTempString sql)
Definition: sdbapi.cpp:2888
ICallableStatement * m_CallStmt
unsigned int GetResultSetNo(void) const
Definition: sdbapi.cpp:3037
void x_InitRSFields(void)
Definition: sdbapi.cpp:3135
void ClearParameter(CTempString name)
Definition: sdbapi.cpp:2857
unsigned int m_MaxRowCount
unsigned int GetMaxRowCount(void) const
bool x_Fetch(void)
Definition: sdbapi.cpp:3114
void x_CheckCanWork(bool need_rs=false) const
Definition: sdbapi.cpp:2738
void SetNullParameter(CTempString name, ESDB_Type type, ESP_ParamType param_type)
Definition: sdbapi.cpp:2782
void x_SetOutParameter(const string &name, const CVariant &value)
Definition: sdbapi.cpp:2809
void BeginNewRS(void)
Definition: sdbapi.cpp:3227
void Cancel(void)
Definition: sdbapi.cpp:3019
IStatement * m_Stmt
void SetParameter(CTempString name, const T &value, ESDB_Type type, ESP_ParamType param_type)
Definition: sdbapi.cpp:2754
CRef< CDatabaseImpl > m_DBImpl
bool m_RSFinished
int GetStatus(void) const
Definition: sdbapi.cpp:3068
void x_InitBeforeExec(void)
Definition: sdbapi.cpp:2939
void Execute(const CTimeout &timeout)
Definition: sdbapi.cpp:2957
void ExecuteSP(CTempString sp, const CTimeout &timeout)
Definition: sdbapi.cpp:2986
unsigned int GetMinRowCount(void) const
string m_Sql
CDatabaseImpl * GetDatabase(void) const
Definition: sdbapi.cpp:3437
bool m_HasExplicitMode
void SetIgnoreBounds(bool is_ignore)
Definition: sdbapi.cpp:3028
bool m_ReportedWrongRowCount
void x_Close(void)
Definition: sdbapi.cpp:2906
CQueryImpl(CDatabaseImpl *db_impl)
Definition: sdbapi.cpp:2673
unsigned int m_MinRowCount
void x_ClearAllParams(void)
Definition: sdbapi.cpp:2870
unsigned int GetTotalColumns(void) const
Definition: sdbapi.cpp:3293
CRef< CDB_Exception::SContext > m_Context
string GetColumnName(unsigned int col) const
Definition: sdbapi.cpp:3300
bool m_IgnoreBounds
const CQuery::CField & GetParameter(CTempString name)
Definition: sdbapi.cpp:2834
void ClearParameters(void)
Definition: sdbapi.cpp:2880
IConnection * GetConnection(void)
Definition: sdbapi.cpp:3443
const CQuery::CRow & GetRow(void) const
Definition: sdbapi.cpp:3423
CQuery::CRow m_Row
bool HasMoreResultSets(void)
Definition: sdbapi.cpp:3144
void PurgeResults(void)
Definition: sdbapi.cpp:3261
TParamsMap m_Params
bool m_RowUnderConstruction
~CQueryImpl(void)
Definition: sdbapi.cpp:2698
void x_DetachAllFields(void)
Definition: sdbapi.cpp:2898
ESDB_Type GetColumnType(unsigned int col) const
Definition: sdbapi.cpp:3307
unsigned int m_CurRelRowNo
IResultSet * m_CurRS
void RequireRowCount(unsigned int min_rows, unsigned int max_rows)
Definition: sdbapi.cpp:3329
unsigned int m_CurRSNo
const CQuery::CField & GetColumn(const CDBParamVariant &col) const
Definition: sdbapi.cpp:3430
void x_CheckRowCount(void)
Definition: sdbapi.cpp:3080
bool IsFinished(CQuery::EHowMuch how_much=CQuery::eThisResultSet) const
Definition: sdbapi.cpp:3393
void VerifyDone(CQuery::EHowMuch how_much=CQuery::eThisResultSet)
Definition: sdbapi.cpp:3352
const CDB_Exception::SContext & x_GetContext(void) const
Definition: sdbapi.cpp:2709
unsigned int m_CurRowNo
int GetRowCount(void) const
Definition: sdbapi.cpp:3055
bool m_RSBeginned
const CVariant & GetFieldValue(unsigned int col_num)
Definition: sdbapi.cpp:2828
Class representing value in result set or output parameter of stored procedure.
Definition: sdbapi.hpp:258
CNcbiOstream & GetOStream(size_t blob_size, TBlobOStreamFlags flags=0) const
Get a blob output stream, on top of a cloned connection.
Definition: sdbapi.cpp:3838
bool IsNull(void) const
Check if value is NULL.
Definition: sdbapi.cpp:3795
bool AsBool(void) const
Get value as bool.
Definition: sdbapi.cpp:3726
Int8 AsInt8(void) const
Get value as 8-byte integer.
Definition: sdbapi.cpp:3702
const vector< unsigned char > & AsVector(void) const
Get value as vector of bytes.
Definition: sdbapi.cpp:3765
CField(const CField &f)
Definition: sdbapi.cpp:2559
Int4 AsInt4(void) const
Get value as 4-byte integer.
Definition: sdbapi.cpp:3694
CNcbiIstream & AsIStream(void) const
Get value as input stream.
Definition: sdbapi.cpp:3789
unsigned char AsByte(void) const
Get value as single byte.
Definition: sdbapi.cpp:3678
CTime AsDateTime(void) const
Get value as CTime.
Definition: sdbapi.cpp:3734
void x_Detach(void)
Definition: sdbapi.cpp:3650
string AsString(void) const
Get value as UTF-8 string.
Definition: sdbapi.cpp:3670
short AsShort(void) const
Get value as short integer.
Definition: sdbapi.cpp:3686
double AsDouble(void) const
Get value as double.
Definition: sdbapi.cpp:3718
CBlobBookmark GetBookmark(void) const
Get bookmark for the blob.
Definition: sdbapi.cpp:3878
float AsFloat(void) const
Get value as float.
Definition: sdbapi.cpp:3710
Iterator class doing main navigation through result sets.
Definition: sdbapi.hpp:419
ESDB_Type GetColumnType(unsigned int col) const
Get type of the column with given number in the current result set.
Definition: sdbapi.cpp:3586
bool operator==(const CRowIterator &ri) const
Comparison of iterators.
Definition: sdbapi.cpp:3592
unsigned int GetResultSetNo(void) const
Get number of currently active result set.
Definition: sdbapi.cpp:3562
unsigned int GetTotalColumns(void) const
Get number of columns in the current result set.
Definition: sdbapi.cpp:3574
const CDB_Exception::SContext & x_GetContext(void) const
Definition: sdbapi.cpp:3556
CRowIterator(void)
Empty constructor of iterator.
Definition: sdbapi.cpp:3529
const CRow & operator*(void) const
Get the full row. (The caller is welcome to keep a copy.)
Definition: sdbapi.cpp:3626
CRowIterator & operator=(const CRowIterator &ri)
Definition: sdbapi.cpp:3545
bool m_IsEnd
Flag showing whether this is constant pointer to the end or pointer to some particular row.
Definition: sdbapi.hpp:491
CRowIterator & operator++(void)
Advance iterator to the next row in the result set.
Definition: sdbapi.cpp:3604
unsigned int GetRowNo(void) const
Get row number currently active.
Definition: sdbapi.cpp:3568
string GetColumnName(unsigned int col) const
Get name of the column with given number in the current result set.
Definition: sdbapi.cpp:3580
const CField & operator[](unsigned int col) const
Get column value by its number.
Definition: sdbapi.cpp:3615
CRef< CQueryImpl > m_Query
Query iterator was created for.
Definition: sdbapi.hpp:488
A full row of result data.
Definition: sdbapi.hpp:384
void x_CheckColumnNumber(unsigned int col) const
Definition: sdbapi.cpp:2606
CRef< SQueryRSMetaData > m_MetaData
Definition: sdbapi.hpp:414
ESDB_Type GetColumnType(unsigned int col) const
Get type of the column with given number in the row.
Definition: sdbapi.cpp:2647
vector< CField > m_Fields
Definition: sdbapi.hpp:413
unsigned int GetTotalColumns(void) const
Get number of columns in the row.
Definition: sdbapi.cpp:2636
const string & GetColumnName(unsigned int col) const
Get name of the column with given number in the row.
Definition: sdbapi.cpp:2641
CRow(void)
Definition: sdbapi.cpp:2594
const CField & operator[](unsigned int col) const
Get column value by its number.
Definition: sdbapi.cpp:2616
void x_Reset(CQueryImpl &q, IResultSet &rs)
Definition: sdbapi.cpp:2653
const CDB_Exception::SContext & x_GetContext(void) const
Definition: sdbapi.cpp:3524
Object used to execute queries and stored procedures on the database server and retrieve result sets.
Definition: sdbapi.hpp:232
bool HasMoreResultSets(void)
Check if any more result sets are available for reading.
Definition: sdbapi.cpp:4138
CQuery & SetSql(CTempString sql)
Set current sql statement.
Definition: sdbapi.cpp:4036
int GetStatus(void) const
Get return status of stored procedure.
Definition: sdbapi.cpp:4126
CQuery & MultiSet(void)
Convert this query to not merge different result sets, i.e.
Definition: sdbapi.cpp:4070
CRow GetTheOnlyRow(void)
Provides the only row for the executed query.
Definition: sdbapi.cpp:4077
CQuery & ClearParameters(void)
Remove all parameters from parameter list.
Definition: sdbapi.cpp:4029
unsigned int GetTotalColumns(void) const
Get total number of columns in the current result set.
Definition: sdbapi.cpp:4168
EAllowLog
Allow transaction log (general, to avoid using bools).
Definition: sdbapi.hpp:248
@ eDisableLog
Disables log.
Definition: sdbapi.hpp:249
CRowIterator end(void) const
Get iterator pointing to the end of the current result set or to the end of all result sets (dependin...
Definition: sdbapi.cpp:4193
ESDB_Type GetColumnType(unsigned int col) const
Get type of the column with given number in the current result set All columns are numbered starting ...
Definition: sdbapi.cpp:4180
EHowMuch
Whether to consider just the current result set or all result sets, in MultiSet mode.
Definition: sdbapi.hpp:662
@ eAllResultSets
Definition: sdbapi.hpp:664
@ eThisResultSet
Definition: sdbapi.hpp:663
~CQuery(void)
Definition: sdbapi.cpp:3896
void VerifyDone(EHowMuch how_much=eThisResultSet)
Ensure that no unread rows or parameter results remain, and that the total number of rows satisfies a...
Definition: sdbapi.cpp:4162
CRef< CQueryImpl > m_Impl
Query implementation object.
Definition: sdbapi.hpp:758
void Cancel(void)
Cancel the current statement or procedure call.
Definition: sdbapi.cpp:4057
CQuery & SetNullParameter(CTempString name, ESDB_Type type, ESP_ParamType param_type=eSP_In)
Assign null value to the parameter.
Definition: sdbapi.cpp:4007
CRowIterator begin(void) const
Start iterating through next result set.
Definition: sdbapi.cpp:4186
const CField & GetParameter(CTempString name)
Get value of the parameter.
Definition: sdbapi.cpp:4016
CQuery & ClearParameter(CTempString name)
Remove parameter with given name from parameter list.
Definition: sdbapi.cpp:4022
CQuery & Execute(const CTimeout &timeout=CTimeout(CTimeout::eDefault))
Explicitly execute sql statement.
Definition: sdbapi.cpp:4043
const list< string > & GetPrintOutput(void) const
Get any PRINT output from the latest procedure call (or statement).
Definition: sdbapi.cpp:4132
void RequireRowCount(unsigned int n)
Indicate precisely how many rows the active query should return.
Definition: sdbapi.cpp:4150
CQuery(void)
Empty constructor of query object.
Definition: sdbapi.cpp:3884
CQuery & SetParameter(CTempString name, const string &value, ESDB_Type type=eSDB_String, ESP_ParamType param_type=eSP_In)
Assign string value to the parameter.
Definition: sdbapi.cpp:3907
unsigned int GetRowNo(EHowMuch how_much=eAllResultSets) const
Get row number currently active.
Definition: sdbapi.cpp:4114
CQuery & ExecuteSP(CTempString sp, const CTimeout &timeout=CTimeout(CTimeout::eDefault))
Execute stored procedure with given name.
Definition: sdbapi.cpp:4050
int GetRowCount(void) const
Get number of rows read after statement execution.
Definition: sdbapi.cpp:4120
unsigned int GetResultSetNo(void) const
Get number of currently active result set.
Definition: sdbapi.cpp:4108
void PurgeResults(void)
Purge all remaining result sets; fill in all remaining parameter results.
Definition: sdbapi.cpp:4144
CQuery & SingleSet(void)
Convert this query to work like only one result set was returned effectively merging all result sets ...
Definition: sdbapi.cpp:4063
string GetColumnName(unsigned int col) const
Get name of the column with given number in the current result set.
Definition: sdbapi.cpp:4174
CQuery & operator=(const CQuery &q)
Definition: sdbapi.cpp:3900
@ fLogExceptions
Exceptions logged only.
Definition: rwstreambuf.hpp:71
@ fOwnWriter
Own the underlying writer.
Definition: rwstreambuf.hpp:67
CRef –.
Definition: ncbiobj.hpp:618
CBlobBookmark GetBookmark(void) const override
Definition: sdbapi.cpp:3856
CQueryImpl & m_Query
unsigned int m_ColNum
const CDB_Exception::SContext & x_GetContext(void) const override
Definition: sdbapi.cpp:2520
const CVariant * GetValue(void) const override
Definition: sdbapi.cpp:2515
CNcbiOstream * GetOStream(size_t blob_size, TBlobOStreamFlags flags) const override
Definition: sdbapi.cpp:3806
EMirrorStatus
Definition: sdbapi.hpp:1324
@ eMirror_Unavailable
All databases in the mirror are unavailable.
Definition: sdbapi.hpp:1327
@ eMirror_Steady
Mirror is working on the same server as before.
Definition: sdbapi.hpp:1325
@ eMirror_NewMaster
Switched to a new master.
Definition: sdbapi.hpp:1326
static void UseDriver(EDriver driver)
Use the specified driver for all connections.
Definition: sdbapi.cpp:1365
static EMirrorStatus UpdateMirror(const string &dbservice, list< string > *servers=NULL, string *error_message=NULL)
Check for master/mirror switch.
Definition: sdbapi.cpp:1479
static CBlobStoreDynamic * NewBlobStore(const CSDB_ConnectionParam &param, const string &table_name, TNewBlobStoreFlags flags=TNewBlobStoreFlags(0), size_t image_limit=1<< 24)
Get new CBlobStoreDynamic object (to be owned by caller).
Definition: sdbapi.cpp:1725
static bool Init(void)
Initialize SDBAPI.
Definition: sdbapi.cpp:1326
static void SetApplicationName(const CTempString &name)
Report the specified application name to servers.
Definition: sdbapi.cpp:1354
static string GetApplicationName(void)
Check SDBAPI's application name setting.
Definition: sdbapi.cpp:1359
@ eDriver_FTDS14
Definition: sdbapi.hpp:1314
@ eDriver_FTDS100
Definition: sdbapi.hpp:1313
Convenience class to initialize database connection parameters from URL-like strings and/or applicati...
Definition: sdbapi.hpp:933
CSDB_ConnectionParam & Set(EParam param, const string &value, TSetFlags flags=0)
Set one of the "essential" database connection parameters, unless overridden in a configuration file.
Definition: sdbapi.hpp:1601
static CRef< CSDB_Decryptor > GetGlobalDecryptor(void)
Get the current password decryptor, if any.
Definition: sdbapi.cpp:1017
EParam
"Essential" (e.g.
Definition: sdbapi.hpp:1006
@ eService
Named service, interfaces-file alias, or raw server name, per http://ncbi.github.io/cxx-toolkit/pages...
Definition: sdbapi.hpp:1016
@ ePort
DB server's port (when not using an alias or named service)
Definition: sdbapi.hpp:1017
void x_FillParamMap(void)
Populate m_ParamMap according to the current server or service name.
Definition: sdbapi.cpp:1082
void x_FillLowerParams(CDBConnParamsBase *params) const
Fill parameters for low-level DBAPI from what is set here and in the configuration file.
Definition: sdbapi.cpp:1205
static void SetGlobalDecryptor(CRef< CSDB_Decryptor > decryptor)
Use the specified password decryptor.
Definition: sdbapi.cpp:1010
CUrl m_Url
URL storing all parameters set in code.
Definition: sdbapi.hpp:1126
void x_FillBoolParam(CDBConnParamsBase *params, const string &name, EParam id) const
Definition: sdbapi.cpp:1276
string ComposeUrl(TComposeUrlFlags flags=0) const
Compose database connection URL string out of this class.
Definition: sdbapi.cpp:1029
static bool x_IsKnownArg(const string &name)
Definition: sdbapi.hpp:1532
@ fThrowIfIncomplete
Throw an exception if missing any "essential" parameters.
Definition: sdbapi.hpp:988
bool IsEmpty(void) const
Definition: sdbapi.cpp:1051
string x_GetPassword() const
Determine what password to use, accounting for possible encryption or indirection.
Definition: sdbapi.cpp:1152
void x_ReportOverride(const CTempString &name, CTempString code_value, CTempString reg_value) const
Definition: sdbapi.cpp:1287
static const char * x_GetName(EParam param)
Definition: sdbapi.hpp:1499
string Get(EParam param, EWithOverrides with_overrides=eWithoutOverrides) const
Get one of the "essential" database connection parameters.
Definition: sdbapi.hpp:1543
TParamMap m_ParamMap
Definition: sdbapi.hpp:1131
void x_InitErrCode(CException::EErrCode err_code) override
Helper method for initializing error code.
Definition: sdbapi.cpp:4206
void x_Init(const CDiagCompileInfo &info, const string &message, const CException *prev_exception, EDiagSev severity) override
Helper method for initializing exception data.
Definition: sdbapi.cpp:4199
Database password decryptor.
Definition: sdbapi.hpp:920
virtual string x_GetKey(const CTempString &key_id)
Definition: sdbapi.cpp:985
virtual string x_Decrypt(const string &ciphertext, const string &key)
Definition: sdbapi.cpp:971
Exception class used throughout the API.
Definition: sdbapi.hpp:68
virtual const char * GetErrCodeString(void) const override
Translate from the error code value to its string representation.
Definition: sdbapi.cpp:70
void x_Assign(const CException &src) override
Helper method for copying exception data.
Definition: sdbapi.cpp:110
void x_Init(const CDiagCompileInfo &info, const string &message, const CException *prev_exception, EDiagSev severity) override
Helper method for initializing exception data.
Definition: sdbapi.cpp:94
CConstRef< CDB_Exception::SContext > m_Context
Definition: sdbapi.hpp:153
virtual ERetriable GetRetriable(void) const override
Retrieve info about ability to retry an action caused the exception.
Definition: sdbapi.cpp:118
@ eOutOfBounds
Conversion of string to integer type exceeded limits of requested type.
Definition: sdbapi.hpp:82
@ eWrongParams
Wrong parameters provided to the method.
Definition: sdbapi.hpp:88
@ eLowLevel
Exception from low level DBAPI was re-thrown with this exception class.
Definition: sdbapi.hpp:86
@ eInconsistent
Operation logically incorrect is attempted to be made (increase past end() iterator,...
Definition: sdbapi.hpp:78
@ eStarted
CBulkInsert has already started to send data, no changes in meta-information can be made.
Definition: sdbapi.hpp:75
@ eNotExist
Field/parameter with given name/position does not exist.
Definition: sdbapi.hpp:84
@ eClosed
CDatabase/CQuery/CBulkInsert is tried to be used when no connection is opened.
Definition: sdbapi.hpp:73
@ eURLFormat
Incorrectly formated URL is used to create CSDB_ConnectionParam.
Definition: sdbapi.hpp:71
@ eUnsupported
Unsupported data type conversion is requested.
Definition: sdbapi.hpp:81
@ eNotInOrder
Columns cannot be bound to CBulkInsert randomly.
Definition: sdbapi.hpp:77
void ReportExtra(ostream &os) const override
Report "non-standard" attributes.
Definition: sdbapi.cpp:89
bool HandleIt(CDB_Exception *ex)
Handle the exceptions resulting from a native API call, one-by-one.
Definition: sdbapi.cpp:1745
bool HandleMessage(int severity, int msgnum, const string &message)
Handle message resulting from a native API call.
Definition: sdbapi.cpp:1758
CConnHolder & m_Conn
Definition: sdbapi_impl.hpp:54
CSafeStatic<>::
static const TFlags kDefaults
Definition: blobstore.hpp:206
@ fIsText
(N)TEXT or (N)VARCHAR(MAX)
Definition: blobstore.hpp:201
@ fLogBlobs
Enable server-side logging.
Definition: blobstore.hpp:202
@ fPreallocated
Don't create rows or clean up excess rows.
Definition: blobstore.hpp:203
CTempString implements a light-weight string on top of a storage buffer whose lifetime management is ...
Definition: tempstr.hpp:65
CTimeException –.
Definition: ncbitime.hpp:2076
CTime –.
Definition: ncbitime.hpp:296
CTimeout – Timeout interval.
Definition: ncbitime.hpp:1693
CUpdMirrorServerParams(const CDBConnParams &other)
Definition: sdbapi.cpp:1407
virtual string GetServerName(void) const
Definition: sdbapi.cpp:1424
virtual string GetPassword(void) const
Definition: sdbapi.cpp:1439
virtual EEncoding GetEncoding(void) const
Definition: sdbapi.cpp:1419
virtual string GetUserName(void) const
Definition: sdbapi.cpp:1434
virtual Uint4 GetHost(void) const
Definition: sdbapi.cpp:1449
const CDBConnParams & m_Other
Definition: sdbapi.cpp:1474
virtual string GetParam(const string &key) const
Parameters, which are not listed above explicitly, should be retrieved via SetParam() method.
Definition: sdbapi.cpp:1464
virtual CRef< IConnValidator > GetConnValidator(void) const
Definition: sdbapi.cpp:1459
virtual EServerType GetServerType(void) const
Definition: sdbapi.cpp:1444
virtual Uint4 GetProtocolVersion(void) const
Definition: sdbapi.cpp:1414
virtual string GetDatabaseName(void) const
Definition: sdbapi.cpp:1429
virtual Uint2 GetPort(void) const
Definition: sdbapi.cpp:1454
CUrlArgs::
Definition: ncbi_url.hpp:240
CUrl –.
Definition: ncbi_url.hpp:353
CVariant –.
Definition: variant.hpp:99
Writer-based output stream.
Definition: rwstream.hpp:171
IDBConnectionFactory.
IDataSource –.
Definition: dbapi.hpp:963
virtual CBlobBookmark GetBookmark(void) const
Definition: sdbapi.cpp:3850
virtual CNcbiOstream * GetOStream(size_t blob_size, TBlobOStreamFlags flags) const
Definition: sdbapi.cpp:3800
IRegistry –.
Definition: ncbireg.hpp:73
IResultSetMetaData –.
Definition: dbapi.hpp:108
I_BlobDescriptor::
Definition: interfaces.hpp:369
Retriable manipulator.
Definition: ncbiexpt.hpp:1237
virtual string GetDatabaseName(void) const
virtual string GetParam(const string &key) const
Parameters, which are not listed above explicitly, should be retrieved via SetParam() method.
virtual string GetServerName(void) const
size_t CloseConnsForPool(const string &pool_name, Uint4 keep_host_ip=0, Uint2 keep_port=0)
void ReadDBConfParams(const string &service_name, SDBConfParams *params)
bool SatisfyPoolMinimum(const CDBConnParams &params)
void erase(iterator pos)
Definition: map.hpp:167