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

Go to the SVN repository for this file.

1 /* $Id: sdbapi.cpp 100450 2023-08-01 15:08:56Z 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  {
918 
919  if (s_DriverName.get() == NULL) {
921  }
922 
923  {{
925  if (app != NULL) {
926  string driver_name
927  = app->GetConfig().GetString("sdbapi", "use_driver",
928  s_DriverName.get());
929  if (driver_name == kDefaultDriverName
930  || driver_name == "ftds100") {
931  s_DriverName.reset(strdup(driver_name.c_str()));
932  } else {
933  ERR_POST_X(15, "Unsupported driver name " << driver_name
934  << "; sticking with " << s_DriverName.get());
935  }
936  }
937  }}
938 
939  CDBConnParamsBase params;
940  params.SetDriverName(s_DriverName.get());
941  params.SetEncoding(eEncoding_UTF8);
942  IDataSource* ds
943  = CDriverManager::GetInstance().MakeDs(params, ".sdbapi");
945  ctx->PushCntxMsgHandler(new CDB_UserHandler_Exception, eTakeOwnership);
946  ctx->PushDefConnMsgHandler(new CDB_UserHandler_Exception, eTakeOwnership);
947  }
948 };
949 
950 
952 
953 inline
955 {
956  ds_init.Get();
958  (s_DriverName.get(), ".sdbapi");
959 }
960 
961 inline
963 {
965  return static_cast<impl::CDriverContext*>(ds->GetDriverContext());
966 }
967 
968 
969 string CSDB_Decryptor::x_Decrypt(const string& ciphertext, const string& key)
970 {
971  CRYPT_Key bin_key = CRYPT_Init(key.c_str());
972  AutoPtr<char, CDeleter<char> > plaintext
973  (CRYPT_DecodeString(bin_key, ciphertext.c_str()));
974  CRYPT_Free(bin_key);
975  if (plaintext.get() == NULL) {
977  "Password decryption failed.");
978  }
979  return string(plaintext.get());
980 }
981 
982 
984 {
985  string key;
987  if (app != NULL) {
988  key = app->GetConfig().GetString("DBAPI_key", key_id, kEmptyStr);
989  }
990 
991 #ifdef HAVE_LIBNCBICRYPT
992  if (key.empty()) {
993  key = NCBICRYPT_FindBuiltinKey(string(key_id).c_str());;
994  }
995 #endif
996  if (key.empty()) {
998  "Unknown password decryption key ID " + string(key_id));
999  }
1000  return key;
1001 }
1002 
1003 
1004 DEFINE_STATIC_FAST_MUTEX(s_DecryptorMutex);
1006 static bool s_DecryptorInitialized = false;
1007 
1009 {
1010  CFastMutexGuard GUARD(s_DecryptorMutex);
1011  s_Decryptor->Reset(decryptor);
1012  s_DecryptorInitialized = true;
1013 }
1014 
1016 {
1017  CFastMutexGuard GUARD(s_DecryptorMutex);
1018  if ( !s_DecryptorInitialized ) {
1019  s_Decryptor->Reset(new CSDB_Decryptor);
1020  s_DecryptorInitialized = true;
1021  }
1022  return *s_Decryptor;
1023 }
1024 
1025 
1026 string
1028 {
1029  if ((flags & fThrowIfIncomplete) != 0
1030  && (m_Url.GetHost().empty() || m_Url.GetUser().empty()
1031  || (m_Url.GetPassword().empty() && Get(ePasswordFile).empty())
1032  || m_Url.GetPath().empty() || m_Url.GetPath() == "/"))
1033  {
1036  "Connection parameters miss at least one essential part"
1037  " (host, user, password, or database [as \"path\"]): "
1038  + ComposeUrl(fl));
1039  }
1040 
1041  if ((flags & fHidePassword) != 0 && !m_Url.GetPassword().empty()) {
1042  CUrl redactee = m_Url;
1043  redactee.SetPassword("(redacted)");
1044  return redactee.ComposeUrl(CUrlArgs::eAmp_Char);
1045  }
1047 }
1048 
1050 {
1051  // Can't use m_Url.IsEmpty(), because the URL will still have a
1052  // scheme ("dbapi").
1053  if ( !m_Url.GetUser().empty() || !m_Url.GetPassword().empty()
1054  || !m_Url.GetHost().empty() || !m_Url.GetPort().empty()
1055  || !m_Url.GetPath().empty() ) {
1056  return false;
1057  } else if ( !m_Url.HaveArgs() ) {
1058  return true;
1059  }
1060 
1062  if ( !it->value.empty() ) {
1063  return false;
1064  }
1065  }
1066  return true;
1067 }
1068 
1071  TSetFlags flags)
1072 {
1073  for (int i = eUsername; i <= eArgsString; ++i) {
1074  EParam ii = static_cast<EParam>(i);
1075  Set(ii, param.Get(ii), flags);
1076  }
1077  return *this;
1078 }
1079 
1081 {
1082  static const char* kDefault = "default";
1083  m_ParamMap.clear();
1084 
1085  impl::SDBConfParams conf_params;
1086  try {
1087  s_GetDBContext()->ReadDBConfParams(m_Url.GetHost(), &conf_params);
1089 
1090 #define COPY_PARAM_EX(en, gn, fn) \
1091  if (conf_params.Is##gn##Set()) \
1092  m_ParamMap[e##en] = conf_params.fn
1093 #define COPY_PARAM(en, fn) COPY_PARAM_EX(en, en, fn)
1094 #define COPY_BOOL_PARAM(en, gn, fn) \
1095  if (conf_params.Is##gn##Set()) \
1096  m_ParamMap[e##en] = conf_params.fn.empty() ? "default" \
1097  : NStr::StringToBool(conf_params.fn) ? "true" : "false"
1098 #define COPY_NUM_PARAM(en, gn, fn) \
1099  if (conf_params.Is##gn##Set()) \
1100  m_ParamMap[e##en] = conf_params.fn.empty() ? kDefault : conf_params.fn
1101 
1102  COPY_PARAM_EX(Service, Server, server);
1103 
1104  COPY_PARAM(Username, username);
1105  COPY_PARAM(Password, password);
1106  COPY_PARAM(Port, port);
1107  COPY_PARAM(Database, database);
1108  COPY_PARAM(PasswordFile, password_file);
1109  COPY_PARAM_EX(PasswordKeyID, PasswordKey, password_key_id);
1110 
1111  COPY_NUM_PARAM (LoginTimeout, LoginTimeout, login_timeout);
1112  COPY_NUM_PARAM (IOTimeout, IOTimeout, io_timeout);
1113  COPY_BOOL_PARAM(ExclusiveServer, SingleServer, single_server);
1114  COPY_BOOL_PARAM(UseConnPool, Pooled, is_pooled);
1115  COPY_NUM_PARAM (ConnPoolMinSize, PoolMinSize, pool_minsize);
1116  COPY_NUM_PARAM (ConnPoolMaxSize, PoolMaxSize, pool_maxsize);
1117  COPY_NUM_PARAM (ConnPoolIdleTime, PoolIdleTime, pool_idle_time);
1118  COPY_NUM_PARAM (ConnPoolWaitTime, PoolWaitTime, pool_wait_time);
1119  COPY_BOOL_PARAM(ConnPoolAllowTempOverflow, PoolAllowTempOverflow,
1120  pool_allow_temp_overflow);
1121  COPY_BOOL_PARAM(ContinueAfterRaiserror, ContinueAfterRaiserror,
1122  continue_after_raiserror);
1123  COPY_NUM_PARAM (ConnPoolMaxConnUse, PoolMaxConnUse, pool_max_conn_use);
1124  COPY_BOOL_PARAM(LogMinorMessages, LogMinorMessages, log_minor_messages);
1125 
1126 #undef COPY_PARAM_EX
1127 #undef COPY_PARAM
1128 #undef COPY_BOOL_PARAM
1129 #undef COPY_NUM_PARAM
1130 
1131  if ( !conf_params.args.empty() ) {
1132  m_ParamMap[eArgsString] = conf_params.args;
1133  }
1134 
1135  // Check for overridden settings
1136  ITERATE (TParamMap, it, m_ParamMap) {
1137  string s = Get(it->first, eWithoutOverrides);
1138  if ( !s.empty() ) {
1139  x_ReportOverride(x_GetName(it->first), s, it->second);
1140  }
1141  }
1142 
1143  if (conf_params.IsPasswordSet() && conf_params.IsPasswordFileSet()) {
1145  '[' + m_Url.GetHost() + ".dbservice] password and"
1146  " password_file parameters are mutually exclusive.");
1147  }
1148 }
1149 
1151 {
1152  string password;
1153 
1154  // Account for possible indirection. Formal search order:
1155  // 1. Password directly in configuration file.
1156  // 2. Password filename in configuration file.
1157  // 3. Password filename in URL.
1158  // 4. Password directly in URL.
1159  // However, if either the configuration file or the URL supplies
1160  // both a direct password and a password filename, SDBAPI will
1161  // throw an exception, so it doesn't matter that 3 and 4 are
1162  // backward relative to 1 and 2.
1164  if (it != m_ParamMap.end()) {
1165  password = it->second;
1166  } else {
1167  string pwfile = Get(ePasswordFile, eWithOverrides);
1168  if (pwfile.empty()) {
1169  password = Get(ePassword);
1170  } else {
1171  CNcbiIfstream in(pwfile.c_str(), IOS_BASE::in | IOS_BASE::binary);
1172  if ( !in ) {
1174  eNotExist | Retriable(eRetriable_No), // eWrongParams?
1175  "Unable to open password file " + pwfile + ": " +
1177  }
1178  NcbiGetline(in, password, "\r\n");
1179  }
1180  }
1181 
1182  // Account for possible encryption.
1183  string key_id = Get(ePasswordKeyID, eWithOverrides);
1184  if ( !key_id.empty() ) {
1186  if (decryptor.NotEmpty()) {
1187  password = decryptor->Decrypt(password, key_id);
1188  ITERATE (string, pit, password) {
1189  if ( !isprint((unsigned char)*pit) ) {
1191  eWrongParams | Retriable(eRetriable_No),
1192  "Invalid character in supposedly decrypted"
1193  " password.");
1194  }
1195  }
1196  }
1197  }
1198 
1199  return password;
1200 }
1201 
1202 void
1204 {
1207  params->SetPassword (x_GetPassword());
1209 
1210  string port = Get(ePort, eWithOverrides);
1211  if ( !port.empty() ) {
1212  params->SetPort(NStr::StringToInt(port));
1213  }
1214 
1215  params->SetParam("login_timeout", Get(eLoginTimeout, eWithOverrides));
1216  params->SetParam("io_timeout", Get(eIOTimeout, eWithOverrides));
1217  x_FillBoolParam(params, "single_server", eExclusiveServer);
1218  x_FillBoolParam(params, "is_pooled", eUseConnPool);
1219  if (params->GetParam("is_pooled") == "true") { // canonicalized above
1220  params->SetParam("pool_name", params->GetServerName() + ".pool");
1221  }
1222  string explicit_pool_name = Get(eConnPoolName, eWithOverrides);
1223  if ( !explicit_pool_name.empty() ) {
1224  params->SetParam("pool_name", explicit_pool_name);
1225  }
1226  params->SetParam("pool_minsize", Get(eConnPoolMinSize, eWithOverrides));
1227  params->SetParam("pool_maxsize", Get(eConnPoolMaxSize, eWithOverrides));
1228  params->SetParam("pool_idle_time", Get(eConnPoolIdleTime, eWithOverrides));
1229  params->SetParam("pool_wait_time", Get(eConnPoolWaitTime, eWithOverrides));
1230  params->SetParam("pool_max_conn_use",
1232 
1233  x_FillBoolParam(params, "pool_allow_temp_overflow",
1235  x_FillBoolParam(params, "continue_after_raiserror",
1237  x_FillBoolParam(params, "log_minor_messages", eLogMinorMessages);
1238 
1239  // Generic named parameters. The historic version of this logic
1240  // had two quirks, which I [AMU] have not carried over:
1241  // * A setting found in the configuration file counted only when
1242  // the original URL mentioned the same parameter.
1243  // * If a key appeared more than once in either list, the old code
1244  // favored the last appearance in the URL but the first one in
1245  // the configuration file. It now always favors the last one.
1246  typedef vector<CUrlArgs*> TAllArgs;
1247  TAllArgs all_args;
1248  all_args.push_back(&m_Url.GetArgs());
1249 
1250  unique_ptr<CUrlArgs> conf_args;
1251  {{
1253  if (it != m_ParamMap.end()) {
1254  conf_args.reset(new CUrlArgs(it->second));
1255  all_args.push_back(conf_args.get());
1256  }
1257  }}
1258 
1259  ITERATE (TAllArgs, ait, all_args) {
1260  const CUrlArgs::TArgs& args = (*ait)->GetArgs();
1261  ITERATE (CUrlArgs::TArgs, uit, args) {
1262  const string& param_name = uit->name;
1263  const string& param_value = uit->value;
1264  if ( !x_IsKnownArg(param_name) ) {
1265  params->SetParam(param_name, param_value);
1266  }
1267  }
1268  }
1269 
1270  params->SetParam("do_not_read_conf", "true");
1271 }
1272 
1273 void
1275  const string& name, EParam id) const
1276 {
1277  string value = Get(id, eWithOverrides);
1278  if ( !value.empty() && value != "default") {
1280  }
1281  params->SetParam(name, value);
1282 }
1283 
1284 
1286  CTempString code_value,
1287  CTempString reg_value) const
1288 {
1289  if (code_value == reg_value) {
1290  return;
1291  } else if (name == x_GetName(eArgsString)) {
1292  // Analyze individually
1293  typedef map<string, string> TConfMap;
1294  TConfMap conf_map;
1295  CUrlArgs conf_args(reg_value);
1296  ITERATE (CUrlArgs::TArgs, it, conf_args.GetArgs()) {
1297  if ( !x_IsKnownArg(it->name) ) {
1298  conf_map[it->name] = it->value;
1299  }
1300  }
1302  TConfMap::const_iterator cmit = conf_map.find(uait->name);
1303  if (cmit != conf_map.end()) {
1304  x_ReportOverride(uait->name, uait->value, cmit->second);
1305  }
1306  }
1307  } else if (name == x_GetName(eService)) {
1308  ERR_POST_X(18, Info << "Using privately configured service alias "
1309  << code_value << " -> " << reg_value);
1310  } else {
1311  if (name == x_GetName(ePassword)) {
1312  code_value = "(redacted)";
1313  reg_value = "(redacted)";
1314  }
1315  ERR_POST_X(17, Warning << "Ignoring program-defined " << name
1316  << " parameter value " << code_value << " for "
1317  << m_Url.GetHost() << " in favor of configured value "
1318  << reg_value);
1319  }
1320 }
1321 
1322 
1323 bool
1325 {
1327  if (!app)
1328  return true;
1329  const IRegistry& reg = app->GetConfig();
1330  bool result = true;
1331  list<string> sections;
1332  reg.EnumerateSections(&sections);
1333  ITERATE(list<string>, it, sections) {
1334  const string& name = *it;
1335  if (name.size() <= 10
1336  || NStr::CompareCase(name, name.size() - 10, 10, ".dbservice") != 0)
1337  {
1338  continue;
1339  }
1341  CDBConnParamsBase lower_params;
1342  CSDB_ConnectionParam conn_params(name.substr(0, name.size() - 10));
1343  conn_params.x_FillLowerParams(&lower_params);
1344  if (lower_params.GetParam("is_pooled") == "true") {
1345  result &= ctx->SatisfyPoolMinimum(lower_params);
1346  }
1347  }
1348  return result;
1349 }
1350 
1351 
1353 {
1355 }
1356 
1358 {
1359  return s_GetDataSource()->GetApplicationName();
1360 }
1361 
1362 
1364 {
1365  if (s_DriverName.get() != NULL) {
1367  "CSDBAPI::UseDriver called with SDBAPI already in use.");
1368  }
1369  switch (driver) {
1370  case eDriver_FTDS100: s_DriverName.reset(strdup("ftds100")); break;
1371  }
1372 }
1373 
1374 
1379 };
1380 
1382 {
1383  string server_name;
1386 };
1387 
1388 typedef list< AutoPtr<SMirrorServInfo> > TMirrorServList;
1389 
1391 {
1394  string master;
1395 };
1396 
1399 
1400 
1402 {
1403 public:
1405  : m_Other(other)
1406  {}
1407 
1409  {}
1410 
1411  virtual Uint4 GetProtocolVersion(void) const
1412  {
1413  return m_Other.GetProtocolVersion();
1414  }
1415 
1416  virtual EEncoding GetEncoding(void) const
1417  {
1418  return m_Other.GetEncoding();
1419  }
1420 
1421  virtual string GetServerName(void) const
1422  {
1424  }
1425 
1426  virtual string GetDatabaseName(void) const
1427  {
1428  return kEmptyStr;
1429  }
1430 
1431  virtual string GetUserName(void) const
1432  {
1433  return m_Other.GetUserName();
1434  }
1435 
1436  virtual string GetPassword(void) const
1437  {
1438  return m_Other.GetPassword();
1439  }
1440 
1441  virtual EServerType GetServerType(void) const
1442  {
1443  return m_Other.GetServerType();
1444  }
1445 
1446  virtual Uint4 GetHost(void) const
1447  {
1448  return m_Other.GetHost();
1449  }
1450 
1451  virtual Uint2 GetPort(void) const
1452  {
1453  return m_Other.GetPort();
1454  }
1455 
1457  {
1458  return m_Other.GetConnValidator();
1459  }
1460 
1461  virtual string GetParam(const string& key) const
1462  {
1464  if (result.empty())
1465  return m_Other.GetParam(key);
1466  else
1467  return result;
1468  }
1469 
1470 private:
1472 };
1473 
1474 
1476 CSDBAPI::UpdateMirror(const string& dbservice,
1477  list<string>* servers /* = NULL */,
1478  string* error_message /* = NULL */)
1479 {
1480  if (dbservice.empty()) {
1482  "Mirrored database service name cannot be empty");
1483  }
1484 
1485  bool first_execution = false;
1486  SMirrorInfo& mir_info = (*s_MirrorsData)[dbservice];
1487  if (!mir_info.conn_params.get()) {
1488  mir_info.conn_params.reset(new CDBConnParamsBase);
1489  first_execution = true;
1490  }
1491  CDBConnParamsBase& conn_params = *mir_info.conn_params.get();
1492  TMirrorServList& serv_list = mir_info.servers;
1493 
1494  ds_init.Get();
1495  IDBConnectionFactory* i_factory
1497  if (conn_params.GetServerName().empty()) {
1498  first_execution = true;
1499  CSDB_ConnectionParam sdb_params(dbservice);
1500  sdb_params.x_FillLowerParams(&conn_params);
1501  if (conn_params.GetParam("single_server") != "true") {
1503  "UpdateMirror cannot be used when configuration file "
1504  "doesn't have exclusive_server=true (for " + dbservice
1505  + ')');
1506  }
1507  CDBConnectionFactory* factory
1508  = dynamic_cast<CDBConnectionFactory*>(i_factory);
1509  if (!factory) {
1511  "UpdateMirror cannot work with non-standard "
1512  "connection factory");
1513  }
1514  }
1515  if (servers)
1516  servers->clear();
1517  if (error_message)
1518  error_message->clear();
1519 
1520  CDBConnectionFactory* factory = static_cast<CDBConnectionFactory*>(i_factory);
1521  string service_name(conn_params.GetServerName());
1522  string db_name(conn_params.GetDatabaseName());
1523  bool need_reread_servers = false;
1524  bool servers_reread = false;
1525  bool has_master = false;
1526  int cnt_switches = 0;
1527 
1528  do {
1529  if (serv_list.empty()) {
1530  list<string> servers;
1531  factory->GetServersList(db_name, service_name, &servers);
1532  ITERATE(list<string>, it, servers) {
1533  serv_list.push_back(new SMirrorServInfo());
1534  serv_list.back()->server_name = *it;
1535  serv_list.back()->state = eConnInitializing;
1536  }
1537  servers_reread = true;
1538  }
1539  else if (need_reread_servers) {
1540  list<string> new_serv_info;
1541  factory->GetServersList(db_name, service_name, &new_serv_info);
1542  ERASE_ITERATE(TMirrorServList, old_it, serv_list) {
1543  bool found = false;
1544  ITERATE(list<string>, it, new_serv_info) {
1545  if (*it == (*old_it)->server_name) {
1546  found = true;
1547  break;
1548  }
1549  }
1550  if (!found) {
1551  serv_list.erase(old_it);
1552  }
1553  }
1554  ITERATE(list<string>, new_it, new_serv_info) {
1555  bool found = false;
1556  ITERATE(TMirrorServList, old_it, serv_list) {
1557  if ((*old_it)->server_name == *new_it) {
1558  found = true;
1559  break;
1560  }
1561  }
1562  if (!found) {
1563  serv_list.push_back(new SMirrorServInfo());
1564  serv_list.back()->server_name = *new_it;
1565  serv_list.back()->state = eConnInitializing;
1566  }
1567  }
1568  servers_reread = true;
1569  }
1570  if (serv_list.empty()) {
1571  factory->WorkWithSingleServer("", service_name, kEmptyStr);
1572  ERR_POST_X(3, "No servers for service '" << service_name
1573  << "' are available");
1574  if (error_message) {
1575  *error_message = "No servers for service '" + service_name
1576  + "' are available";
1577  }
1578  return eMirror_Unavailable;
1579  }
1580 
1581  for (TMirrorServList::iterator it = serv_list.end(); it != serv_list.begin(); )
1582  {
1583  --it;
1584  AutoPtr<IConnection>& conn = (*it)->conn;
1585  const string& server_name = (*it)->server_name;
1586  EMirrorConnState& state = (*it)->state;
1587  if (!conn.get()) {
1589  }
1590  if (!conn->IsAlive()) {
1591  if (state == eConnEstablished) {
1592  ERR_POST_X(7, "Connection to server '" << server_name
1593  << "' for service '" << service_name
1594  << "' is lost.");
1596  }
1597  CUpdMirrorServerParams serv_params(conn_params);
1598  serv_params.SetServerName(server_name);
1599  serv_params.SetParam("is_pooled", "false");
1600  serv_params.SetParam("do_not_dispatch", "true");
1601  try {
1602  conn->Close();
1603  conn->Connect(serv_params);
1604  if (state == eConnNotConnected) {
1605  ERR_POST_X(8, "Connection to server '" << server_name
1606  << "' for service '" << service_name
1607  << "' is restored.");
1608  }
1610  }
1611  catch (CDB_Exception& /*ex*/) {
1612  //ERR_POST_X(1, Info << "Error connecting to the server '"
1613  // << server_name << "': " << ex);
1614  if (state == eConnInitializing) {
1615  ERR_POST_X(9, "Cannot establish connection to server '"
1616  << server_name << "' for service '"
1617  << service_name << "'.");
1619  }
1620  conn->Close();
1621  need_reread_servers = true;
1622  }
1623  }
1624  bool success = false;
1625  if (conn->IsAlive()) {
1626  try {
1627  AutoPtr<IStatement> stmt(conn->GetStatement());
1628  stmt->ExecuteUpdate("use " + db_name);
1629  success = true;
1630  }
1631  catch (CDB_Exception& /*ex*/) {
1632  // success is already false
1633  //ERR_POST_X(2, Info << "Check for mirror principal state failed: "
1634  // << ex);
1635  }
1636  }
1637  if (!success && server_name == mir_info.master) {
1638  factory->WorkWithSingleServer("", service_name, kEmptyStr);
1639  string pool_name = conn_params.GetParam("pool_name");
1640  size_t invalidated_count = s_GetDBContext()->CloseConnsForPool(pool_name);
1641  ERR_POST_X(4, "The master for database '" << db_name <<
1642  "' (service '" << service_name <<
1643  "') has become inaccessible. Because of this " <<
1644  invalidated_count <<
1645  " active connections got invalidated in the pool '" <<
1646  pool_name << "'.");
1647  mir_info.master.clear();
1648  need_reread_servers = true;
1649  }
1650  else if (success && server_name != mir_info.master) {
1651  factory->WorkWithSingleServer("", service_name, server_name);
1652  string pool_name = conn_params.GetParam("pool_name");
1653  size_t invalidated_count =
1655  pool_name,
1656  conn->GetCDB_Connection()->Host(),
1657  conn->GetCDB_Connection()->Port());
1658  string msg_start = "The master for database '" + db_name +
1659  "' (for service '" + service_name +
1660  "') switched to '" + server_name + "' from ";
1661  string msg_end = ". Because of this " +
1662  NStr::NumericToString(invalidated_count) +
1663  " active connections got invalidated in the pool '" +
1664  pool_name + "'.";
1665 
1666  if (mir_info.master.empty()) {
1667  // Switching from no master to something => Message
1668  ERR_POST_X(5, Message << msg_start << "NONE" << msg_end);
1669  } else {
1670  // Switching from one master to another => Warning
1671  ERR_POST_X(5, Warning << msg_start << "'" <<
1672  mir_info.master << "'" << msg_end);
1673  }
1674  s_GetDBContext()->SatisfyPoolMinimum(conn_params);
1675 
1676  has_master = true;
1677  mir_info.master = server_name;
1678  serv_list.push_front(*it);
1679  TMirrorServList::iterator it_del = it++;
1680  serv_list.erase(it_del);
1681  need_reread_servers = true;
1682 
1683  if (++cnt_switches == 10) {
1685  eInconsistent | Retriable(eRetriable_No),
1686  "Mirror database switches too frequently or "
1687  "it isn't mirrored: " + service_name);
1688  }
1689  }
1690  else if (success && server_name == mir_info.master) {
1691  has_master = true;
1692  }
1693  }
1694  }
1695  while (need_reread_servers && !servers_reread);
1696 
1697  if (first_execution && !has_master) {
1698  factory->WorkWithSingleServer("", service_name, kEmptyStr);
1699  string pool_name = conn_params.GetParam("pool_name");
1700  size_t invalidated_count = s_GetDBContext()->CloseConnsForPool(pool_name);
1701  ERR_POST_X(10, "The master for database '" << db_name <<
1702  "' (service '" << service_name <<
1703  "') is not accessible. Because of this " <<
1704  invalidated_count <<
1705  " active connections got invalidated in the pool '" <<
1706  pool_name << "'.");
1707  }
1708 
1709  if (servers) {
1710  ITERATE(TMirrorServList, it, serv_list) {
1711  servers->push_back((*it)->server_name);
1712  }
1713  }
1714  if (!has_master) {
1715  if (error_message)
1716  *error_message = "All database instances are inaccessible";
1717  return eMirror_Unavailable;
1718  }
1719  return cnt_switches == 0? eMirror_Steady: eMirror_NewMaster;
1720 }
1721 
1723  const string& table_name,
1724  TNewBlobStoreFlags flags,
1725  size_t image_limit)
1726 {
1728  if ((flags & fNBS_IsText) != 0) {
1729  ERR_POST_X_ONCE(20, Warning << "Explicit fNBS_IsText flag passed to a"
1730  " variant of NewBlobStore that inspects column types"
1731  " itself.");
1732  }
1733  return new CBlobStoreDynamic(s_GetDBContext(),
1737  table_name, cm, image_limit,
1739 }
1740 
1741 
1743 {
1744  if (ex == nullptr) {
1745  return true;
1746  } else if (ex->GetSeverity() == eDiag_Info && m_Conn.m_LogMinorMessages) {
1747  ERR_POST_X(21, Info << *ex);
1748  return true;
1749  } else {
1751  }
1752 }
1753 
1754 
1755 bool CSDB_UserHandler::HandleMessage(int severity, int msgnum,
1756  const string& message)
1757 {
1758  if (severity < 10 || (severity == 10 && msgnum == 0)) {
1759  if (severity == 0 || (severity == 10 && msgnum == 0)) {
1760  m_Conn.m_PrintOutput.push_back(message);
1761  return !m_Conn.m_LogMinorMessages;
1762  } else if (m_Conn.m_LogMinorMessages) {
1763  return false;
1764  }
1765  }
1767  && (severity == 16 || (severity == 10 && msgnum > 0))) {
1768  // Sybase servers use severity 16 for all user-defined messages,
1769  // even if they're not intended to abort execution. Also, some
1770  // standard minor errors (such as Duplicate key was ignored, #3604)
1771  // normally map to DBAPI exceptions with severity warning.
1772  // Optionally intercept all of these messages and report them as
1773  // warnings (vs. exceptions).
1775  eDiag_Error, msgnum);
1776  ERR_POST_X(19, Warning << ex);
1777  return true;
1778  } else {
1780  (severity, msgnum, message);
1781  }
1782 }
1783 
1784 
1785 inline
1787  : m_Conn(conn),
1788  m_DefaultTimeout(0),
1789  m_HasCustomTimeout(false),
1790  m_ContinueAfterRaiserror
1791  (params.Get(CSDB_ConnectionParam::eContinueAfterRaiserror) == "true"),
1792  m_LogMinorMessages
1793  (params.Get(CSDB_ConnectionParam::eLogMinorMessages,
1794  CSDB_ConnectionParam::eWithOverrides) == "true"),
1795  m_CntOpen(0),
1796  m_Context(new CDB_Exception::SContext),
1797  m_Handler(new CSDB_UserHandler(*this))
1798 {
1799  if (conn != NULL) {
1800  m_DefaultTimeout = conn->GetTimeout();
1801  m_Context->server_name = conn->GetCDB_Connection()->ServerName();
1802  m_Context->username = conn->GetCDB_Connection()->UserName();
1803  m_Context->database_name = conn->GetDatabase();
1804  conn->GetCDB_Connection()->PushMsgHandler(&*m_Handler, eNoOwnership);
1805  }
1806 }
1807 
1809 {
1810  delete m_Conn;
1811 }
1812 
1813 inline IConnection*
1815 {
1816  return m_Conn;
1817 }
1818 
1819 inline void
1821 {
1822  CMutexGuard mg(m_Mutex);
1823  ++m_CntOpen;
1824 }
1825 
1826 inline void
1828 {
1829  CMutexGuard mg(m_Mutex);
1830  if (--m_CntOpen == 0) {
1832  m_Conn->Close();
1833  }
1834 }
1835 
1836 void CConnHolder::SetTimeout(const CTimeout& timeout)
1837 {
1838  CMutexGuard mg(m_Mutex);
1839  if (timeout.IsDefault()) {
1840  ResetTimeout();
1841  } else if (m_CntOpen > 0) {
1842  unsigned int sec, nanosec;
1843  timeout.GetNano(&sec, &nanosec);
1844  if (nanosec > 0 && sec != kMax_UInt) { // round up as appropriate
1845  ++sec;
1846  }
1847  m_HasCustomTimeout = true;
1848  m_Conn->SetTimeout(sec);
1849  }
1850 }
1851 
1853 {
1854  CMutexGuard mg(m_Mutex);
1855  if (m_HasCustomTimeout && m_CntOpen > 0) {
1857  }
1858  m_HasCustomTimeout = false;
1859 }
1860 
1861 inline
1862 const list<string>& CConnHolder::GetPrintOutput(void) const
1863 {
1864  return m_PrintOutput;
1865 }
1866 
1867 inline
1869 {
1870  CMutexGuard mg(m_Mutex);
1871  m_PrintOutput.clear();
1872 }
1873 
1874 inline
1876 {
1877  return *m_Context;
1878 }
1879 
1880 
1881 inline void
1883 {
1884  CDBConnParamsBase lower_params;
1885  params.x_FillLowerParams(&lower_params);
1887  conn->Connect(lower_params);
1888  m_Conn.Reset(new CConnHolder(conn.release(), params));
1889  m_IsOpen = m_EverConnected = true;
1890  m_Conn->AddOpenRef();
1891 }
1892 
1893 inline
1895  : m_IsOpen(false), m_EverConnected(false)
1896 {
1897 }
1898 
1899 inline
1901  : m_Conn(other.m_Conn),
1902  m_IsOpen(other.m_IsOpen),
1903  m_EverConnected(other.m_EverConnected)
1904 {
1905  if (m_IsOpen)
1906  m_Conn->AddOpenRef();
1907 }
1908 
1909 inline void
1911 {
1912  if (m_IsOpen) {
1913  m_IsOpen = false;
1914  m_Conn->CloseRef();
1915  }
1916 }
1917 
1918 inline
1920 {
1921  try {
1922  Close();
1923  }
1924  STD_CATCH_ALL_X(11, "CDatabaseImpl::~CDatabaseImpl")
1925 }
1926 
1927 inline bool
1929 {
1930  return m_IsOpen;
1931 }
1932 
1933 inline bool
1935 {
1936  return m_EverConnected;
1937 }
1938 
1939 inline IConnection*
1941 {
1942  return m_Conn->GetConn();
1943 }
1944 
1945 inline void
1947 {
1948  m_Conn->SetTimeout(timeout);
1949 }
1950 
1951 inline void
1953 {
1954  m_Conn->ResetTimeout();
1955 }
1956 
1957 inline
1958 const list<string>& CDatabaseImpl::GetPrintOutput(void) const
1959 {
1960  return m_Conn->GetPrintOutput();
1961 }
1962 
1963 inline
1965 {
1967 }
1968 
1969 inline
1972 {
1973  return m_Conn->GetContext();
1974 }
1975 
1976 
1978  : m_Impl(new CDatabaseImpl)
1979 {}
1980 
1982  : m_Params(params), m_Impl(new CDatabaseImpl)
1983 {}
1984 
1985 CDatabase::CDatabase(const string& url_string)
1986  : m_Params(url_string), m_Impl(new CDatabaseImpl)
1987 {}
1988 
1990 {
1991  operator= (db);
1992 }
1993 
1994 CDatabase&
1996 {
1997  m_Params = db.m_Params;
1998  m_Impl = db.m_Impl;
1999  return *this;
2000 }
2001 
2003 {
2004  if (m_Impl->IsOpen()) {
2005  try {
2006  m_Impl.Reset();
2007  }
2008  STD_CATCH_ALL_X(12, "CDatabase::~CDatabase");
2009  }
2010 }
2011 
2012 void
2014 {
2015  try {
2016  if (m_Impl->EverConnected()) {
2017  m_Impl.Reset(new CDatabaseImpl);
2018  }
2020  }
2022 }
2023 
2024 void
2026 {
2027  if ( !m_Impl->IsOpen() )
2028  return;
2029  try {
2030  m_Impl->Close();
2031  }
2033 }
2034 
2035 bool
2037 {
2038  if ( !m_Impl->IsOpen() ) {
2039  return false;
2040  } else if (check_method == eNoCheck) {
2041  return true;
2042  }
2043 
2045  _ASSERT(conn != NULL);
2046  if ( !conn->IsAlive() ) {
2047  Close();
2048  return false;
2049  } else if (check_method == eFastCheck) {
2050  return true;
2051  }
2052 
2053  _ASSERT(check_method == eFullCheck);
2054  try {
2055  CQuery query = NewQuery("SELECT 1");
2056  query.Execute();
2057  query.RequireRowCount(1);
2058  CQuery::CRowIterator row = query.begin();
2059  bool ok = (row != query.end() && row.GetTotalColumns() == 1
2060  && row[1].AsInt4() == 1);
2061  query.VerifyDone();
2062  return ok;
2063  } catch (exception&) {
2064  Close();
2065  return false;
2066  }
2067 }
2068 
2069 CDatabase
2071 {
2073  if (IsConnected(eNoCheck)) {
2074  result.Connect();
2075  }
2076  return result;
2077 }
2078 
2079 #define CONNECT_AS_NEEDED() x_ConnectAsNeeded(NCBI_CURRENT_FUNCTION)
2080 
2081 CQuery
2083 {
2085  return CQuery(m_Impl);
2086 }
2087 
2089 CDatabase::NewBulkInsert(const string& table_name, int autoflush)
2090 {
2092  return CBulkInsert(m_Impl, table_name, autoflush);
2093 }
2094 
2096 CDatabase::NewBookmark(const string& table_name, const string& column_name,
2097  const string& search_conditions,
2098  CBlobBookmark::EBlobType column_type,
2099  ETriState has_legacy_type)
2100 {
2102 
2104  switch (column_type) {
2105  case CBlobBookmark::eText:
2106  desc_type = CDB_BlobDescriptor::eText;
2107  break;
2109  desc_type = CDB_BlobDescriptor::eBinary;
2110  break;
2111  default:
2112  desc_type = CDB_BlobDescriptor::eUnknown;
2113  break;
2114  }
2115 
2116  unique_ptr<I_BlobDescriptor> desc
2117  (new CDB_BlobDescriptor(table_name, column_name, search_conditions,
2118  desc_type, has_legacy_type));
2119 
2120  CRef<CBlobBookmarkImpl> bm(new CBlobBookmarkImpl(m_Impl, desc.release()));
2121  return CBlobBookmark(bm);
2122 }
2123 
2124 
2126  TNewBlobStoreFlags flags,
2127  size_t image_limit)
2128 {
2130  if ((flags & fNBS_IsText) != 0) {
2131  ERR_POST_X_ONCE(20, Warning << "Explicit fNBS_IsText flag passed to a"
2132  " variant of NewBlobStore that inspects column types"
2133  " itself.");
2134  }
2137  table_name, cm, image_limit,
2139 }
2140 
2141 
2143  const string& key_col_name,
2144  const string& num_col_name,
2145  const vector<string> blob_col_names,
2146  TNewBlobStoreFlags flags,
2147  size_t image_limit)
2148 {
2152  table_name, key_col_name, num_col_name,
2153  &blob_col_names[0], blob_col_names.size(),
2155  image_limit);
2156 }
2157 
2158 
2160 {
2161  if ( !m_Impl->EverConnected() ) {
2162  _TRACE(operation << ": connecting on demand.");
2163  Connect();
2164  } else if ( !IsConnected(eNoCheck) ) {
2166  string("Cannot call ") + operation
2167  + " when not connected.");
2168  }
2169 }
2170 
2171 
2172 inline
2174  const string& table_name,
2175  int autoflush)
2176  : m_DBImpl(db_impl),
2177  m_BI(NULL),
2178  m_Autoflush(autoflush),
2179  m_RowsWritten(0),
2180  m_ColsWritten(0),
2181  m_WriteStarted(false),
2182  m_Context(new CDB_Exception::SContext(db_impl->GetContext()))
2183 {
2184  m_BI = db_impl->GetConnection()->GetBulkInsert(table_name);
2185  m_Context->extra_msg = "Bulk insertion into " + table_name;
2186 }
2187 
2189 {
2190  try {
2191  if (m_BI && m_RowsWritten != 0) {
2192  m_BI->Complete();
2193  }
2194  }
2195  STD_CATCH_ALL_X(13, "Error destroying CBulkInsert");
2196  delete m_BI;
2197 }
2198 
2199 inline
2201 {
2202  return *m_Context;
2203 }
2204 
2205 void
2207 {
2208  if (!m_BI) {
2210  "Cannot write into completed CBulkInsert");
2211  }
2212  if (!m_DBImpl->IsOpen()) {
2213  m_BI->Cancel();
2214  delete m_BI;
2215  m_BI = NULL;
2217  "Cannot write into CBulkInsert when CDatabase was closed");
2218  }
2219  if (col != 0 && col > int(m_Cols.size())) {
2220  SDBAPI_THROW(eInconsistent | Retriable(eRetriable_No),
2221  "Too many values were written to CBulkInsert: "
2222  + NStr::NumericToString(col) + " > "
2223  + NStr::NumericToString(m_Cols.size()));
2224  }
2225 }
2226 
2227 void
2229 {
2230  x_CheckCanWrite(0);
2231  m_BI->SetHints(hints);
2232 }
2233 
2234 void
2236 {
2237  x_CheckCanWrite(0);
2238  m_BI->AddHint(hint, value);
2239 }
2240 
2241 void
2243 {
2244  x_CheckCanWrite(0);
2245  m_BI->AddOrderHint(columns);
2246 }
2247 
2248 inline void
2250 {
2251  x_CheckCanWrite(0);
2252  if (m_WriteStarted) {
2253  SDBAPI_THROW(eStarted | Retriable(eRetriable_No),
2254  "Cannot bind columns when already started to insert");
2255  }
2256  if (col - 1 != int(m_Cols.size())) {
2257  SDBAPI_THROW(eNotInOrder | Retriable(eRetriable_No),
2258  "Cannot bind columns in CBulkInsert randomly");
2259  }
2260  m_Cols.push_back(CVariant(s_ConvertType(type)));
2261  if (type == eSDB_StringUCS2 || type == eSDB_TextUCS2
2262  || type == eSDB_StringMaxUCS2) {
2263  m_Cols.back().SetBulkInsertionEnc(eBulkEnc_UCS2FromChar);
2264  }
2265 }
2266 
2267 inline void
2269 {
2270  x_CheckCanWrite(0);
2271  if (m_ColsWritten != int(m_Cols.size())) {
2272  SDBAPI_THROW(eInconsistent | Retriable(eRetriable_No),
2273  "Not enough values were written to CBulkInsert: "
2275  + NStr::NumericToString(m_Cols.size()));
2276  }
2277  try {
2278  m_BI->AddRow();
2279  if (++m_RowsWritten == m_Autoflush) {
2280  m_BI->StoreBatch();
2281  m_RowsWritten = 0;
2282  }
2283  m_ColsWritten = 0;
2284  }
2286 }
2287 
2288 inline void
2290 {
2291  if (m_BI == NULL) {
2292  // Make idempotent, rather than letting x_CheckCanWrite throw.
2293  return;
2294  }
2295  x_CheckCanWrite(0);
2296  try {
2297  unique_ptr<IBulkInsert> bi(m_BI);
2298  m_BI = NULL;
2299  bi->Complete();
2300  }
2302 }
2303 
2304 inline void
2306 {
2308  if (!m_WriteStarted) {
2309  m_WriteStarted = true;
2310  try {
2311  for (unsigned int i = 0; i < m_Cols.size(); ++i) {
2312  m_BI->Bind(i + 1, &m_Cols[i]);
2313  }
2314  }
2316  }
2317 }
2318 
2319 inline void
2321 {
2323  m_Cols[m_ColsWritten++].SetNull();
2324 }
2325 
2326 template <class T>
2327 inline void
2329 {
2332 }
2333 
2334 
2336 {}
2337 
2339  const string& table_name,
2340  int autoflush)
2341 {
2342  m_Impl.Reset(new CBulkInsertImpl(db_impl, table_name, autoflush));
2343 }
2344 
2346  : m_Impl(bi.m_Impl)
2347 {}
2348 
2350 {}
2351 
2352 CBulkInsert&
2354 {
2355  m_Impl = bi.m_Impl;
2356  return *this;
2357 }
2358 
2359 void
2361 {
2362  m_Impl->SetHints(hints);
2363 }
2364 
2365 void
2367 {
2368  try {
2369  m_Impl->AddHint(s_ConvertHints(hint), 0);
2370  }
2372 }
2373 
2374 void
2376 {
2377  try {
2379  }
2381 }
2382 
2383 void
2385 {
2386  m_Impl->AddOrderHint(columns);
2387 }
2388 
2389 void
2391 {
2392  m_Impl->Bind(col, type);
2393 }
2394 
2395 void
2397 {
2398  m_Impl->Complete();
2399 }
2400 
2402 CBulkInsert::operator<<(const string& val)
2403 {
2404  m_Impl->WriteVal(val);
2405  return *this;
2406 }
2407 
2410 {
2411  m_Impl->WriteVal(val);
2412  return *this;
2413 }
2414 
2416 CBulkInsert::operator<<(const char* val)
2417 {
2418  m_Impl->WriteVal(val);
2419  return *this;
2420 }
2421 
2423 CBulkInsert::operator<<(unsigned char val)
2424 {
2425  m_Impl->WriteVal(val);
2426  return *this;
2427 }
2428 
2430 CBulkInsert::operator<<(short val)
2431 {
2432  m_Impl->WriteVal(val);
2433  return *this;
2434 }
2435 
2438 {
2439  m_Impl->WriteVal(val);
2440  return *this;
2441 }
2442 
2445 {
2446  m_Impl->WriteVal(val);
2447  return *this;
2448 }
2449 
2450 #if !NCBI_INT8_IS_LONG
2452 CBulkInsert::operator<<(long val)
2453 {
2454 #if SIZEOF_LONG == 8
2455  m_Impl->WriteVal(static_cast<Int8>(val));
2456 #else
2457  m_Impl->WriteVal(static_cast<Int4>(val));
2458 #endif
2459  return *this;
2460 }
2461 #endif
2462 
2464 CBulkInsert::operator<<(float val)
2465 {
2466  m_Impl->WriteVal(val);
2467  return *this;
2468 }
2469 
2471 CBulkInsert::operator<<(double val)
2472 {
2473  m_Impl->WriteVal(val);
2474  return *this;
2475 }
2476 
2478 CBulkInsert::operator<<(bool val)
2479 {
2480  m_Impl->WriteVal(val);
2481  return *this;
2482 }
2483 
2485 CBulkInsert::operator<<(const CTime& val)
2486 {
2487  m_Impl->WriteVal(val);
2488  return *this;
2489 }
2490 
2493 {
2494  return f(*this);
2495 }
2496 
2497 CBulkInsert&
2499 {
2500  bi.m_Impl->WriteNull();
2501  return bi;
2502 }
2503 
2504 CBulkInsert&
2506 {
2507  bi.m_Impl->EndRow();
2508  return bi;
2509 }
2510 
2511 
2512 const CVariant* CRemoteQFB::GetValue(void) const
2513 {
2514  return &m_Query.GetFieldValue(m_ColNum);
2515 }
2516 
2518 {
2519  return m_Query.x_GetContext();
2520 }
2521 
2522 
2523 inline
2525  ESP_ParamType param_type)
2526  : m_Basis(new CParamQFB(v, q->x_GetContext(), param_type))
2527 {}
2528 
2529 inline
2531  : m_Basis(new CRemoteQFB(*q, col_num))
2532 {}
2533 
2534 inline
2536  : m_Basis(qf.m_Basis.release())
2537 {}
2538 
2539 inline
2541  : CQueryFieldImpl(qb) // don't try to copy extra fields
2542 {}
2543 
2544 inline
2546  ESP_ParamType param_type)
2547  : CQueryFieldImpl(q, v, param_type)
2548 {}
2549 
2550 inline
2552  : CQueryFieldImpl(q, col_num)
2553 {}
2554 
2555 
2557  : m_Impl(f.m_Impl)
2558 {}
2559 
2560 inline
2562 {
2563  if (CDB_Object::IsBlobType(v->GetType())) {
2564  m_Impl.Reset(new CQueryBlobImpl(q, v, param_type));
2565  } else {
2566  m_Impl.Reset(new CQueryFieldImpl(q, v, param_type));
2567  }
2568 }
2569 
2570 inline
2571 CQuery::CField::CField(CQueryImpl* q, unsigned int col_num)
2572 {
2573  switch (q->GetColumnType(col_num)) {
2574  case eSDB_Text:
2575  case eSDB_TextUCS2:
2576  case eSDB_Image:
2577  case eSDB_StringMax:
2578  case eSDB_StringMaxUCS2:
2579  case eSDB_BinaryMax:
2580  m_Impl.Reset(new CQueryBlobImpl(q, col_num));
2581  break;
2582  default:
2583  m_Impl.Reset(new CQueryFieldImpl(q, col_num));
2584  break;
2585  }
2586 }
2587 
2589 {}
2590 
2592 {}
2593 
2595  : m_Fields(r.m_Fields), m_MetaData(r.m_MetaData)
2596 {}
2597 
2599 {}
2600 
2601 
2602 inline
2603 void CQuery::CRow::x_CheckColumnNumber(unsigned int col) const
2604 {
2605  if (col == 0 || col > m_Fields.size()) {
2607  eNotExist | Retriable(eRetriable_No),
2608  "No such column in the result set: "
2609  + NStr::NumericToString(col) + ". " + x_GetContext());
2610  }
2611 }
2612 
2613 const CQuery::CField& CQuery::CRow::operator[](unsigned int col) const
2614 {
2615  x_CheckColumnNumber(col);
2616  return m_Fields[col - 1];
2617 }
2618 
2620 {
2622  = m_MetaData->col_nums.find(col);
2623  if (it == m_MetaData->col_nums.end()) {
2625  eNotExist | Retriable(eRetriable_No),
2626  "No such column in the result set: " + col + ". "
2627  + x_GetContext());
2628  } else {
2629  return m_Fields[it->second - 1];
2630  }
2631 }
2632 
2633 unsigned int CQuery::CRow::GetTotalColumns(void) const
2634 {
2635  return m_Fields.size();
2636 }
2637 
2638 const string& CQuery::CRow::GetColumnName(unsigned int col) const
2639 {
2640  x_CheckColumnNumber(col);
2641  return m_MetaData->col_names[col - 1];
2642 }
2643 
2645 {
2646  x_CheckColumnNumber(col);
2647  return m_MetaData->col_types[col - 1];
2648 }
2649 
2651 {
2652  m_Fields.clear();
2653  m_MetaData.Reset(new SQueryRSMetaData);
2654  m_MetaData->exception_context.Reset(&q.x_GetContext());
2655 
2656  unsigned int cols_cnt = rs.GetTotalColumns();
2657  const IResultSetMetaData* meta = rs.GetMetaData();
2658  m_Fields.clear();
2659  m_Fields.reserve(cols_cnt);
2660  for (unsigned int i = 1; i <= cols_cnt; ++i) {
2661  m_Fields.emplace_back(CQuery::CField(&q, i));
2662  m_MetaData->col_nums[meta->GetName(i)] = i;
2663  m_MetaData->col_names.emplace_back(meta->GetName(i));
2664  m_MetaData->col_types.emplace_back(s_ConvertType(meta->GetType(i)));
2665  }
2666 }
2667 
2668 // NB: x_InitBeforeExec resets many of these fields.
2669 inline
2671  : m_DBImpl(db_impl),
2672  m_Stmt(NULL),
2673  m_CallStmt(NULL),
2674  m_CurRS(NULL),
2675  m_IgnoreBounds(true),
2676  m_HasExplicitMode(false),
2677  m_RSBeginned(false),
2678  m_RSFinished(true),
2679  m_Executed(false),
2680  m_ReportedWrongRowCount(false),
2681  m_IsSP(false),
2682  m_RowUnderConstruction(false),
2683  m_CurRSNo(0),
2684  m_CurRowNo(0),
2685  m_CurRelRowNo(0),
2686  m_MinRowCount(0),
2687  m_MaxRowCount(kMax_Auto),
2688  m_RowCount(-1),
2689  m_Status(-1),
2690  m_Context(new CDB_Exception::SContext(m_DBImpl->GetContext()))
2691 {
2692  m_Stmt = db_impl->GetConnection()->GetStatement();
2693 }
2694 
2696 {
2697  try {
2698  x_Close();
2699  }
2700  STD_CATCH_ALL_X(6, "Error destroying CQuery");
2701  x_ClearAllParams();
2702  delete m_Stmt;
2703 }
2704 
2707 {
2708  if ( !m_Context->extra_msg.empty() ) {
2709  return *m_Context;
2710  }
2711 
2712  CNcbiOstrstream oss;
2713  oss << (m_IsSP ? "RPC: " : "SQL: ");
2714  oss << m_Sql;
2715  if ( !m_Params.empty() ) {
2716  string delim;
2717  oss << "; input parameter(s): ";
2718  ITERATE (TParamsMap, it, m_Params) {
2719  const CVariant* value = it->second.m_Impl->GetValue();
2720  oss << delim;
2721  oss << it->first << " = ";
2722  if (value == NULL || value->IsNull()) {
2723  oss << "NULL";
2724  } else {
2725  oss << value->GetData()->GetLogString();
2726  }
2727  delim = ", ";
2728  }
2729  }
2731  return *m_Context;
2732 }
2733 
2734 void
2735 CQueryImpl::x_CheckCanWork(bool need_rs /* = false */) const
2736 {
2737  if (!m_DBImpl->IsOpen()) {
2739  "CQuery is not operational because CDatabase was closed");
2740  }
2741  if (need_rs && !m_CurRS
2742  && !const_cast<CQueryImpl*>(this)->HasMoreResultSets())
2743  {
2745  "CQuery is closed or never executed");
2746  }
2747 }
2748 
2749 template <class T>
2750 inline void
2752  const T& value,
2753  ESDB_Type type,
2754  ESP_ParamType param_type)
2755 {
2756  x_CheckCanWork();
2757  m_Context->extra_msg.clear();
2758 
2759  EDB_Type var_type = s_ConvertType(type);
2760  TParamsMap::iterator it = m_Params.find(name);
2761  if (it == m_Params.end()) {
2762  CQuery::CField field(this, new CVariant(var_type), param_type);
2763  it = m_Params.insert(make_pair(name, field)).first;
2764  } else {
2765  it->second.x_Detach();
2766  static_cast<CParamQFB&>(*it->second.m_Impl->m_Basis)
2767  .SetParamType(param_type);
2768  }
2769  CQueryFieldImpl& field = *it->second.m_Impl;
2770  if (field.GetValue() == NULL
2771  || field.GetValue()->GetType() != var_type) {
2772  it->second = CQuery::CField(this, new CVariant(var_type), param_type);
2773  }
2775  const_cast<CVariant&>(*it->second.m_Impl->GetValue()));
2776 }
2777 
2778 inline void
2780  ESDB_Type type,
2781  ESP_ParamType param_type)
2782 {
2783  x_CheckCanWork();
2784  m_Context->extra_msg.clear();
2785 
2786  EDB_Type var_type = s_ConvertType(type);
2787  TParamsMap::iterator it = m_Params.find(name);
2788  if (it == m_Params.end()) {
2789  CQuery::CField field(this, new CVariant(var_type), param_type);
2790  it = m_Params.insert(make_pair(name, field)).first;
2791  } else {
2792  it->second.x_Detach();
2793  static_cast<CParamQFB&>(*it->second.m_Impl->m_Basis)
2794  .SetParamType(param_type);
2795  }
2796  CQueryFieldImpl& field = *it->second.m_Impl;
2797  if (field.GetValue() == NULL
2798  || field.GetValue()->GetType() != var_type) {
2799  it->second = CQuery::CField(this, new CVariant(var_type), param_type);
2800  } else {
2801  const_cast<CVariant*>(field.GetValue())->SetNull();
2802  }
2803 }
2804 
2805 inline void
2806 CQueryImpl::x_SetOutParameter(const string& name, const CVariant& value)
2807 {
2808  m_Context->extra_msg.clear();
2809  TParamsMap::iterator it = m_Params.find(name);
2810  if (it == m_Params.end()) {
2811  CQuery::CField field(this, new CVariant(value), eSP_InOut);
2812  m_Params.insert(make_pair(name, field));
2813  } else {
2814  it->second.x_Detach();
2815  CQueryFieldImpl& field = *it->second.m_Impl;
2816  try {
2817  const_cast<CVariant&>(*field.GetValue()) = value;
2818  } catch (CDB_ClientEx&) {
2819  it->second = CQuery::CField(this, new CVariant(value), eSP_InOut);
2820  }
2821  }
2822 }
2823 
2824 inline const CVariant&
2825 CQueryImpl::GetFieldValue(unsigned int col_num)
2826 {
2827  return m_CurRS->GetVariant(col_num);
2828 }
2829 
2830 inline const CQuery::CField&
2832 {
2833  x_CheckCanWork();
2834 
2835  TParamsMap::iterator it = m_Params.find(name);
2836  if (it == m_Params.end()) {
2838  eNotExist | Retriable(eRetriable_No),
2839  "Parameter '" + string(name) + "' doesn't exist. "
2840  + x_GetContext());
2841  } else if (static_cast<const CParamQFB&>(*it->second.m_Impl->m_Basis)
2842  .GetParamType() == eSP_InOut
2845  eInconsistent | Retriable(eRetriable_No),
2846  "CQuery::GetParameter called with some results still"
2847  " unread. " + x_GetContext());
2848  }
2849 
2850  return it->second;
2851 }
2852 
2853 inline void
2855 {
2856  x_CheckCanWork();
2857  m_Context->extra_msg.clear();
2858 
2859  TParamsMap::iterator it = m_Params.find(name);
2860  if (it != m_Params.end()) {
2861  it->second.x_Detach();
2862  m_Params.erase(it);
2863  }
2864 }
2865 
2866 void
2868 {
2869  m_Context->extra_msg.clear();
2870  for (auto& p : m_Params) {
2871  p.second.x_Detach();
2872  }
2873  m_Params.clear();
2874 }
2875 
2876 inline void
2878 {
2879  x_CheckCanWork();
2880  x_ClearAllParams();
2881  m_Context->extra_msg.clear();
2882 }
2883 
2884 inline void
2886 {
2887  x_CheckCanWork();
2888 
2889  m_Context->extra_msg.clear();
2890  m_Sql = sql.empty() ? CTempString(" ") : sql;
2891  m_Executed = false;
2892  m_IsSP = false;
2893 }
2894 
2896 {
2897  for (auto& f : m_Row.m_Fields) {
2898  f.x_Detach();
2899  }
2900 }
2901 
2902 void
2904 {
2906  if (m_CurRS != NULL) {
2907  auto orig_row_no = m_CurRowNo;
2908  try {
2910  } catch (CSDB_Exception& e) {
2911  ERR_POST_X(14, Critical << e <<
2912  "Problem while closing DB query "
2913  "(result was at row number " << orig_row_no <<
2914  " and is now at row number " << m_CurRowNo << ").");
2915  }
2916  if (m_CurRSNo != 0) {
2917  _TRACE(m_CurRowNo << " row(s) from query.");
2918  }
2919  }
2920 
2921  delete m_CurRS;
2922  m_CurRS = NULL;
2923  if (m_CallStmt) {
2924  if (m_DBImpl->IsOpen())
2926  delete m_CallStmt;
2927  m_CallStmt = NULL;
2928  }
2929  if (m_DBImpl->IsOpen()) {
2930  m_Stmt->PurgeResults();
2931  m_Stmt->Close();
2932  }
2933 }
2934 
2935 inline void
2937 {
2938  m_IgnoreBounds = true;
2939  m_HasExplicitMode = false;
2940  m_RSBeginned = false;
2941  m_RSFinished = true;
2942  m_ReportedWrongRowCount = false;
2943  m_CurRSNo = 0;
2944  m_CurRowNo = 0;
2945  m_CurRelRowNo = 0;
2946  m_RowCount = 0;
2947  m_MinRowCount = 0;
2949  m_Status = -1;
2951 }
2952 
2953 inline void
2955 {
2956  if (m_IsSP || m_Sql.empty()) {
2957  SDBAPI_THROW(eInconsistent | Retriable(eRetriable_No),
2958  "No statement to execute.");
2959  }
2960 
2961  x_CheckCanWork();
2962 
2963  try {
2964  x_Close();
2965  x_InitBeforeExec();
2966 
2968  ITERATE(TParamsMap, it, m_Params) {
2969  const CQueryFieldImpl& field = *it->second.m_Impl;
2970  m_Stmt->SetParam(*field.GetValue(), it->first);
2971  }
2972  if ( !timeout.IsDefault() ) {
2973  m_DBImpl->SetTimeout(timeout);
2974  }
2975  m_Executed = true;
2976  m_Stmt->SendSql(m_Sql);
2978  }
2980 }
2981 
2982 inline void
2984 {
2985  x_CheckCanWork();
2986 
2987  m_Context->extra_msg.clear();
2988  m_Sql = sp;
2989  m_IsSP = true;
2990 
2991  try {
2992  x_Close();
2993  x_InitBeforeExec();
2994 
2996  ITERATE(TParamsMap, it, m_Params) {
2997  const CParamQFB& pqfb
2998  = static_cast<const CParamQFB&>(*it->second.m_Impl->m_Basis);
2999  if (pqfb.GetParamType() == eSP_InOut) {
3000  m_CallStmt->SetOutputParam(*pqfb.GetValue(), it->first);
3001  } else {
3002  m_CallStmt->SetParam(*pqfb.GetValue(), it->first);
3003  }
3004  }
3005  if ( !timeout.IsDefault() ) {
3006  m_DBImpl->SetTimeout(timeout);
3007  }
3008  m_Executed = true;
3009  m_CallStmt->Execute();
3011  }
3013 }
3014 
3015 inline void
3017 {
3019  x_CheckCanWork();
3021  stmt->Cancel();
3022 }
3023 
3024 inline void
3026 {
3027  x_CheckCanWork();
3028  m_IgnoreBounds = is_ignore;
3029  m_HasExplicitMode = true;
3030  x_CheckRowCount();
3031 }
3032 
3033 inline unsigned int
3035 {
3036  x_CheckCanWork();
3037  return m_CurRSNo;
3038 }
3039 
3040 inline unsigned int
3042 {
3043  x_CheckCanWork();
3044  if (m_IgnoreBounds || how_much == CQuery::eAllResultSets) {
3045  return m_CurRowNo;
3046  } else {
3047  return m_CurRelRowNo;
3048  }
3049 }
3050 
3051 inline int
3053 {
3054  x_CheckCanWork();
3057  "CQuery::GetRowCount called with some results still"
3058  " unread. " + x_GetContext());
3059  } else {
3060  return m_RowCount;
3061  }
3062 }
3063 
3064 inline int
3066 {
3067  x_CheckCanWork();
3070  "CQuery::GetStatus called with some results still"
3071  " unread. " + x_GetContext());
3072  } else {
3073  return m_Status;
3074  }
3075 }
3076 
3078 {
3080  return;
3081  }
3082 
3083  unsigned int n;
3084  if ( !m_IgnoreBounds ) {
3085  n = m_CurRelRowNo;
3086 #if 0 // Counts rows affected by INSERT and the like.
3087  } else if (m_RowCount > 0) {
3088  n = m_RowCount;
3089 #endif
3090  } else {
3091  n = m_CurRowNo;
3092  }
3093 
3094  if (n > m_MaxRowCount) {
3095  m_ReportedWrongRowCount = true;
3097  "Too many rows returned (limited to "
3099  + x_GetContext());
3100  } else if (m_RSFinished && n < m_MinRowCount) {
3101  m_ReportedWrongRowCount = true;
3103  "Not enough rows returned ("
3106  + x_GetContext());
3107  }
3108 }
3109 
3110 inline bool
3112 {
3113  try {
3115  if (m_CurRS->Next()) {
3116  ++m_CurRowNo;
3117  ++m_CurRelRowNo;
3118  x_CheckRowCount();
3119  return true;
3120  }
3121  else {
3122  m_RSFinished = true;
3123  _TRACE(m_CurRelRowNo << " row(s) in set.");
3124  x_CheckRowCount();
3125  return false;
3126  }
3127  }
3129 }
3130 
3131 inline void
3133 {
3135  m_RowUnderConstruction = true;
3136  m_Row.x_Reset(*this, *m_CurRS);
3137  m_RowUnderConstruction = false;
3138 }
3139 
3140 bool
3142 {
3143  x_CheckCanWork();
3144  if (m_CurRS && !m_RSBeginned)
3145  return true;
3146  while (m_CurRS && !m_RSFinished) {
3147  x_Fetch();
3148  }
3149  delete m_CurRS;
3150  m_CurRS = NULL;
3151  m_RSBeginned = m_RSFinished = false;
3152 
3154  try {
3155  while (stmt->HasMoreResults()) {
3156  m_CurRS = stmt->GetResultSet();
3157  if (!m_CurRS)
3158  continue;
3159  switch (m_CurRS->GetResultType()) {
3160  case eDB_StatusResult:
3161  delete m_CurRS;
3162  m_CurRS = NULL;
3163  break;
3164  case eDB_ParamResult:
3165  if (m_CallStmt) {
3166  m_CurRS->Next();
3167  unsigned int col_cnt = m_CurRS->GetTotalColumns();
3168  const IResultSetMetaData* meta = m_CurRS->GetMetaData();
3169  for (unsigned int i = 1; i <= col_cnt; ++i) {
3170  x_SetOutParameter(meta->GetName(i),
3171  m_CurRS->GetVariant(i));
3172  }
3173  }
3174  delete m_CurRS;
3175  m_CurRS = NULL;
3176  break;
3177  case eDB_RowResult:
3178  if (++m_CurRSNo == 2 && !m_HasExplicitMode ) {
3179  ERR_POST_X(16, Info
3180  << "Multiple SDBAPI result sets found, but"
3181  " neither SingleSet nor MultiSet explicitly"
3182  " requested. Now defaulting to SingleSet. "
3183  << x_GetContext());
3184  }
3185  if ( !m_IgnoreBounds ) {
3186  m_ReportedWrongRowCount = false;
3187  }
3188  m_CurRelRowNo = 0;
3189  x_InitRSFields();
3190  return true;
3191  case eDB_ComputeResult:
3192  case eDB_CursorResult:
3193  _ASSERT(false);
3194  }
3195  }
3196  }
3198 
3200 
3201  _TRACE(m_CurRowNo << " row(s) from query.");
3202 
3203  if (m_CallStmt) {
3204  try {
3206  } catch (CDB_ClientEx&) {
3207  }
3208  }
3209  if (m_RowCount == 0) {
3210  if (m_CurRowNo != 0) {
3212  // m_CurRowNo = 0;
3213  }
3214  else {
3215  m_RowCount = stmt->GetRowCount();
3216  }
3217  }
3218  m_CurRSNo = 0;
3219  m_RSFinished = true;
3220  return false;
3221 }
3222 
3223 void
3225 {
3226  x_CheckCanWork();
3227  bool has_more_rs = HasMoreResultSets();
3228  if ( !has_more_rs && !m_Executed ) {
3229  // Check has_more_rs in addition to m_Executed because SetSql
3230  // resets the latter.
3232  has_more_rs = HasMoreResultSets();
3233  }
3234  if ( !has_more_rs ) {
3235  if (m_IgnoreBounds && m_CurRowNo == 0) {
3236  // OK to have no results whatsoever in SingleSet mode.
3237  return;
3238  }
3240  "All result sets in CQuery were already iterated through. "
3241  + x_GetContext());
3242  }
3243  if (m_RSFinished) {
3244  // Complete recovering from a premature call to GetStatus or
3245  // GetRowCount.
3246  m_RSFinished = false;
3247  m_CurRelRowNo = 0;
3248  try {
3249  x_InitRSFields();
3251  }
3252  while (HasMoreResultSets() && !x_Fetch() && m_IgnoreBounds)
3253  m_RSBeginned = true;
3254  m_RSBeginned = true;
3255 }
3256 
3257 inline void
3259 {
3260  x_CheckCanWork();
3261  m_HasExplicitMode = true; // Doesn't particularly matter at this point!
3262  bool has_more = true;
3263  while (has_more) {
3264  try {
3265  if ((has_more = HasMoreResultSets())) {
3266  BeginNewRS();
3267  }
3268  } catch (CSDB_Exception& e) {
3269  IResultSet* rs = NULL;
3270  while (has_more && rs != m_CurRS) {
3271  try {
3272  rs = m_CurRS;
3273  if ((has_more = HasMoreResultSets())) {
3274  BeginNewRS();
3275  }
3276  } catch (CSDB_Exception& e2) {
3277  has_more = true;
3278  // Not technically the correct relationship, but by far
3279  // the simplest way to consolidate the exceptions.
3280  e.AddPrevious(&e2);
3281  }
3282  }
3283  throw;
3284  }
3285  }
3286 }
3287 
3288 inline
3289 unsigned int
3291 {
3292  x_CheckCanWork(true);
3293  return m_Row.GetTotalColumns();
3294 }
3295 
3296 inline string
3297 CQueryImpl::GetColumnName(unsigned int col) const
3298 {
3299  x_CheckCanWork(true);
3300  return m_Row.GetColumnName(col);
3301 }
3302 
3303 inline ESDB_Type
3304 CQueryImpl::GetColumnType(unsigned int col) const
3305 {
3306  x_CheckCanWork(true);
3307  if (m_RowUnderConstruction) {
3308  try {
3309  return s_ConvertType(m_CurRS->GetMetaData()->GetType(col));
3310  }
3312  } else {
3313  return m_Row.GetColumnType(col);
3314  }
3315 }
3316 
3317 inline void
3319 {
3320  while (!x_Fetch() && m_IgnoreBounds && HasMoreResultSets())
3321  m_RSBeginned = true;
3322  m_RSBeginned = true;
3323 }
3324 
3325 inline void
3326 CQueryImpl::RequireRowCount(unsigned int min_rows, unsigned int max_rows)
3327 {
3328  if ( !m_Executed ) {
3329  SDBAPI_THROW(eInconsistent | Retriable(eRetriable_No),
3330  "RequireRowCount must follow Execute or ExecuteSP,"
3331  " which reset any requirements.");
3332  }
3333  if (min_rows > max_rows) {
3334  SDBAPI_THROW(eWrongParams | Retriable(eRetriable_No),
3335  "Inconsistent row-count constraints: "
3336  + NStr::NumericToString(min_rows) + " > "
3337  + NStr::NumericToString(max_rows));
3338  }
3339  x_CheckCanWork();
3340  _TRACE("RequireRowCount(" << min_rows << ", " << max_rows << ')');
3341  m_MinRowCount = min_rows;
3342  m_MaxRowCount = max_rows;
3343  if (m_CurRS != NULL) {
3344  x_CheckRowCount();
3345  }
3346 }
3347 
3348 inline void
3350 {
3351  x_CheckCanWork();
3352 
3353  bool missed_results = false;
3354  bool want_all = m_IgnoreBounds || how_much == CQuery::eAllResultSets;
3355 
3356  for (;;) {
3357  try {
3358  if (m_RSFinished) {
3359  x_CheckRowCount();
3360  } else if (m_CurRS) {
3361  // Tolerate having read just enough rows, unless that number
3362  // was zero but not necessarily required to be.
3363  missed_results
3364  = x_Fetch() || ( !m_RSBeginned && m_MaxRowCount > 0);
3365  }
3366  } catch (...) {
3367  if (want_all) {
3368  PurgeResults();
3369  } else {
3371  }
3372  throw;
3373  }
3374 
3375  // We always want the effect of HasMoreResultSets.
3376  if (HasMoreResultSets() && want_all) {
3377  BeginNewRS();
3378  } else {
3379  break;
3380  }
3381  }
3382 
3383  if (missed_results) {
3385  "Result set had unread rows. " + x_GetContext());
3386  }
3387 }
3388 
3389 inline bool
3391 {
3392  if ( !m_RSFinished ) {
3393  return false;
3394  } else if (how_much == CQuery::eThisResultSet
3395  || ( !m_CurRS && !m_Stmt->HasMoreResults())) {
3396  return true;
3397  }
3398 
3399  // Check whether any further result sets actually exist, in which
3400  // case some state (saved here) will need to be rolled back.
3401  // m_CurRS will have to remain advanced, but HasMoreResultSets
3402  // knows not to advance it again until BeginNewRS has run.
3403  CQuery::CRow saved_row = m_Row;
3404  unsigned int saved_rel_row_no = m_CurRelRowNo;
3405  CQueryImpl& nc_self = const_cast<CQueryImpl&>(*this);
3406 
3407  nc_self.m_Row.m_Fields.clear();
3408  nc_self.m_Row.m_MetaData.Reset();
3409  if (nc_self.HasMoreResultSets()) {
3410  nc_self.m_RSFinished = true; // still match end()
3411  nc_self.m_CurRelRowNo = saved_rel_row_no;
3412  nc_self.m_Row = saved_row;
3413  return false;
3414  }
3415 
3416  return true;
3417 }
3418 
3419 inline
3421 {
3422  x_CheckCanWork(true);
3423  return m_Row;
3424 }
3425 
3426 inline const CQuery::CField&
3428 {
3429  x_CheckCanWork(true);
3430  return c.IsPositional() ? m_Row[c.GetPosition()] : m_Row[c.GetName()];
3431 }
3432 
3433 inline CDatabaseImpl*
3435 {
3436  return m_DBImpl.GetNCPointer();
3437 }
3438 
3439 inline IConnection*
3441 {
3442  return m_DBImpl->GetConnection();
3443 }
3444 
3445 inline
3446 const list<string>& CQueryImpl::GetPrintOutput(void) const
3447 {
3448  return m_DBImpl->GetPrintOutput();
3449 }
3450 
3451 
3452 inline
3454  I_BlobDescriptor* descr)
3455  : m_DBImpl(db_impl),
3456  m_Descr(descr)
3457 {}
3458 
3459 CNcbiOstream&
3461 {
3462  try {
3464  m_OStream.reset(new CWStream
3465  (new CxBlobWriter(db_conn, *m_Descr, blob_size,
3466  flags, false),
3467  0, 0,
3470  return *m_OStream;
3471  }
3473 }
3474 
3475 
3477 {}
3478 
3480  : m_Impl(bm_impl)
3481 {}
3482 
3484  : m_Impl(bm.m_Impl)
3485 {}
3486 
3489 {
3490  m_Impl = bm.m_Impl;
3491  return *this;
3492 }
3493 
3495 {}
3496 
3497 CNcbiOstream&
3499 {
3500  return m_Impl.GetNCPointer()->GetOStream(blob_size, flags);
3501 }
3502 
3503 CNcbiOstream&
3504 CBlobBookmark::GetOStream(size_t blob_size, CQuery::EAllowLog log_it) const
3505 {
3506  return GetOStream(blob_size,
3507  (log_it == CQuery::eDisableLog) ? fBOS_SkipLogging : 0);
3508 }
3509 
3511 {
3512  return DBAPI_MakeTrans(*db.m_Impl->GetConnection());
3513 }
3514 
3516 {
3517  return DBAPI_MakeTrans(*query.m_Impl->GetConnection());
3518 }
3519 
3520 inline
3522 {
3523  return *m_MetaData->exception_context;
3524 }
3525 
3527  : m_IsEnd(false)
3528 {}
3529 
3530 inline
3532  : m_Query(q),
3533  m_IsEnd(is_end)
3534 {}
3535 
3537  : m_Query(ri.m_Query),
3538  m_IsEnd(ri.m_IsEnd)
3539 {}
3540 
3543 {
3544  m_Query = ri.m_Query;
3545  m_IsEnd = ri.m_IsEnd;
3546  return *this;
3547 }
3548 
3550 {}
3551 
3552 inline
3554 {
3555  return m_Query->x_GetContext();
3556 }
3557 
3558 unsigned int
3560 {
3561  return m_Query->GetResultSetNo();
3562 }
3563 
3564 unsigned int
3566 {
3567  return m_Query->GetRowNo();
3568 }
3569 
3570 unsigned int
3572 {
3573  return m_Query->GetTotalColumns();
3574 }
3575 
3576 string
3578 {
3579  return m_Query->GetColumnName(col);
3580 }
3581 
3582 ESDB_Type
3584 {
3585  return m_Query->GetColumnType(col);
3586 }
3587 
3588 bool
3590 {
3591  if (m_Query != ri.m_Query)
3592  return false;
3593  else if (m_IsEnd ^ ri.m_IsEnd) {
3594  return m_Query->IsFinished();
3595  }
3596  else
3597  return true;
3598 }
3599 
3602 {
3603  if (m_IsEnd || m_Query->IsFinished()) {
3604  SDBAPI_THROW(eInconsistent | Retriable(eRetriable_No),
3605  "Cannot increase end() iterator");
3606  }
3607  m_Query->Next();
3608  return *this;
3609 }
3610 
3611 const CQuery::CField&
3612 CQuery::CRowIterator::operator[](unsigned int col) const
3613 {
3614  return m_Query->GetRow()[col];
3615 }
3616 
3617 const CQuery::CField&
3619 {
3620  return m_Query->GetRow()[col];
3621 }
3622 
3624 {
3625  return m_Query->GetRow();
3626 }
3627 
3628 
3630 {
3631  unique_ptr<IQueryFieldBasis> new_basis
3632  (new CLocalQFB(new CVariant(*GetValue()), x_GetContext()));
3633  CRef<CQueryFieldImpl> replacement(new CQueryFieldImpl(*this));
3634  m_Basis.reset(new_basis.release());
3635  return replacement;
3636 }
3637 
3639 {
3640  unique_ptr<IQueryFieldBasis> new_basis
3641  (new CLocalQFB(new CVariant(*GetValue()), x_GetContext()));
3642  CRef<CQueryFieldImpl> replacement(new CQueryBlobImpl(*this));
3643  m_Basis.reset(new_basis.release());
3644  return replacement;
3645 }
3646 
3648 {
3649  if ( m_Impl.NotEmpty() && !m_Impl->ReferencedOnlyOnce() ) {
3650  m_Impl.Reset(m_Impl->Detach());
3651  }
3652 }
3653 
3654 inline
3656 {
3657  return m_Basis->x_GetContext();
3658 }
3659 
3660 inline
3662 {
3663  return m_Basis->GetValue();
3664 }
3665 
3666 string
3668 {
3669  string value;
3670  s_ConvertValue(*m_Impl->GetValue(), value);
3671  return value;
3672 }
3673 
3674 unsigned char
3676 {
3677  unsigned char value = 0;
3678  s_ConvertValue(*m_Impl->GetValue(), value);
3679  return value;
3680 }
3681 
3682 short
3684 {
3685  short value = 0;
3686  s_ConvertValue(*m_Impl->GetValue(), value);
3687  return value;
3688 }
3689 
3690 Int4
3692 {
3693  Int4 value = 0;
3694  s_ConvertValue(*m_Impl->GetValue(), value);
3695  return value;
3696 }
3697 
3698 Int8
3700 {
3701  Int8 value = 0;
3702  s_ConvertValue(*m_Impl->GetValue(), value);
3703  return value;
3704 }
3705 
3706 float
3708 {
3709  float value = 0;
3710  s_ConvertValue(*m_Impl->GetValue(), value);
3711  return value;
3712 }
3713 
3714 double
3716 {
3717  double value = 0;
3718  s_ConvertValue(*m_Impl->GetValue(), value);
3719  return value;
3720 }
3721 
3722 bool
3724 {
3725  bool value = false;
3726  s_ConvertValue(*m_Impl->GetValue(), value);
3727  return value;
3728 }
3729 
3730 CTime
3732 {
3733  CTime value;
3734  s_ConvertValue(*m_Impl->GetValue(), value);
3735  return value;
3736 }
3737 
3738 const vector<unsigned char>&
3740 {
3741  SDBAPI_THROW(eUnsupported | Retriable(eRetriable_No),
3742  string("Method is unsupported for this type of data: ")
3743  + CDB_Object::GetTypeName(GetValue()->GetType(), false));
3744 }
3745 
3746 const vector<unsigned char>&
3748 {
3749  const CVariant& var_val = *GetValue();
3750  string value = var_val.GetString();
3751  // WorkShop cannot eat string::iterators in vector<>::insert (although due
3752  // to STL he has to eat any iterator-like type) but is okay with pointers
3753  // to unsigned char here.
3754  const unsigned char* data
3755  = reinterpret_cast<const unsigned char*>(value.data());
3756  m_Vector.clear();
3757  m_Vector.insert(m_Vector.begin(), data, data + value.size());
3758  return m_Vector;
3759 }
3760 
3761 const vector<unsigned char>&
3763 {
3764  return m_Impl->AsVector();
3765 }
3766 
3767 CNcbiIstream&
3769 {
3770  SDBAPI_THROW(eUnsupported | Retriable(eRetriable_No),
3771  string("Method is unsupported for this type of data: ")
3772  + CDB_Object::GetTypeName(GetValue()->GetType(), false));
3773 }
3774 
3775 CNcbiIstream&
3777 {
3778  const CVariant& var_val = *GetValue();
3779  m_ValueForStream = var_val.GetString();
3780  m_IStream.reset
3781  (new CNcbiIstrstream(m_ValueForStream));
3782  return *m_IStream;
3783 }
3784 
3785 CNcbiIstream&
3787 {
3788  return m_Impl->AsIStream();
3789 }
3790 
3791 bool
3793 {
3794  return m_Impl->GetValue()->IsNull();
3795 }
3796 
3798 {
3799  SDBAPI_THROW(eUnsupported | Retriable(eRetriable_No),
3800  "Method requires a live field");
3801 }
3802 
3804  TBlobOStreamFlags flags) const
3805 {
3806  const CVariant& var_val = *GetValue();
3807  try {
3808  IConnection* conn = m_Query.GetConnection()->CloneConnection();
3809  CDB_Connection* db_conn = conn->GetCDB_Connection();
3810  return new CWStream
3811  (new CxBlobWriter(db_conn, var_val.GetBlobDescriptor(),
3812  blob_size, flags, false),
3813  0, 0,
3816  }
3818 }
3819 
3821 {
3822  SDBAPI_THROW(eUnsupported | Retriable(eRetriable_No),
3823  string("Method is unsupported for this type of data: ")
3824  + CDB_Object::GetTypeName(GetValue()->GetType(), false));
3825 }
3826 
3828  TBlobOStreamFlags flags) const
3829 {
3830  m_OStream.reset(m_Basis->GetOStream(blob_size, flags));
3831  return *m_OStream;
3832 }
3833 
3834 CNcbiOstream&
3836 {
3837  return m_Impl->GetOStream(blob_size, flags);
3838 }
3839 
3840 CNcbiOstream&
3841 CQuery::CField::GetOStream(size_t blob_size, EAllowLog log_it) const
3842 {
3843  return GetOStream(blob_size,
3844  (log_it == eDisableLog) ? fBOS_SkipLogging : 0);
3845 }
3846 
3848 {
3849  SDBAPI_THROW(eUnsupported | Retriable(eRetriable_No),
3850  "Method requires a live field");
3851 }
3852 
3854 {
3855  const CVariant& var_val = *GetValue();
3857  (new CBlobBookmarkImpl(m_Query.GetDatabase(),
3858  var_val.ReleaseBlobDescriptor()));
3859  return CBlobBookmark(bm);
3860 }
3861 
3863 {
3864  SDBAPI_THROW(eUnsupported | Retriable(eRetriable_No),
3865  string("Method is unsupported for this type of data: ")
3866  + CDB_Object::GetTypeName(GetValue()->GetType(), false));
3867 }
3868 
3870 {
3871  return m_Basis->GetBookmark();
3872 }
3873 
3876 {
3877  return m_Impl->GetBookmark();
3878 }
3879 
3880 
3882 {}
3883 
3885 {
3886  m_Impl.Reset(new CQueryImpl(db_impl));
3887 }
3888 
3890  : m_Impl(q.m_Impl)
3891 {}
3892 
3894 {}
3895 
3896 CQuery &
3898 {
3899  m_Impl = q.m_Impl;
3900  return *this;
3901 }
3902 
3903 CQuery&
3905  const string& value,
3906  ESDB_Type type /* = eSDB_String */,
3907  ESP_ParamType param_type /* = eSP_In */)
3908 {
3909  m_Impl->SetParameter(name, value, type, param_type);
3910  return *this;
3911 }
3912 
3913 CQuery&
3915  const char* value,
3916  ESDB_Type type /* = eSDB_String */,
3917  ESP_ParamType param_type /* = eSP_In */)
3918 {
3919  m_Impl->SetParameter(name, value, type, param_type);
3920  return *this;
3921 }
3922 
3923 CQuery&
3925  Int8 value,
3926  ESDB_Type type /* = eSDB_Int8 */,
3927  ESP_ParamType param_type /* = eSP_In */)
3928 {
3929  m_Impl->SetParameter(name, value, type, param_type);
3930  return *this;
3931 }
3932 
3933 CQuery&
3935  Int4 value,
3936  ESDB_Type type /* = eSDB_Int4 */,
3937  ESP_ParamType param_type /* = eSP_In */)
3938 {
3939  m_Impl->SetParameter(name, value, type, param_type);
3940  return *this;
3941 }
3942 
3943 CQuery&
3945  short value,
3946  ESDB_Type type /* = eSDB_Short */,
3947  ESP_ParamType param_type /* = eSP_In */)
3948 {
3949  m_Impl->SetParameter(name, value, type, param_type);
3950  return *this;
3951 }
3952 
3953 CQuery&
3955  unsigned char value,
3956  ESDB_Type type /* = eSDB_Byte */,
3957  ESP_ParamType param_type /* = eSP_In */)
3958 {
3959  m_Impl->SetParameter(name, value, type, param_type);
3960  return *this;
3961 }
3962 
3963 CQuery&
3965  float value,
3966  ESDB_Type type /* = eSDB_Float */,
3967  ESP_ParamType param_type /* = eSP_In */)
3968 {
3969  m_Impl->SetParameter(name, value, type, param_type);
3970  return *this;
3971 }
3972 
3973 CQuery&
3975  double value,
3976  ESDB_Type type /* = eSDB_Double */,
3977  ESP_ParamType param_type /* = eSP_In */)
3978 {
3979  m_Impl->SetParameter(name, value, type, param_type);
3980  return *this;
3981 }
3982 
3983 CQuery&
3985  const CTime& value,
3986  ESDB_Type type /* = eSDB_DateTime */,
3987  ESP_ParamType param_type /*= eSP_In */)
3988 {
3989  m_Impl->SetParameter(name, value, type, param_type);
3990  return *this;
3991 }
3992 
3993 CQuery&
3995  bool value,
3996  ESDB_Type type /* = eSDB_Bit */,
3997  ESP_ParamType param_type /* = eSP_In */)
3998 {
3999  m_Impl->SetParameter(name, value, type, param_type);
4000  return *this;
4001 }
4002 
4003 CQuery&
4005  ESDB_Type type,
4006  ESP_ParamType param_type /* = eSP_In */)
4007 {
4008  m_Impl->SetNullParameter(name, type, param_type);
4009  return *this;
4010 }
4011 
4012 const CQuery::CField&
4014 {
4015  return m_Impl->GetParameter(name);
4016 }
4017 
4018 CQuery&
4020 {
4021  m_Impl->ClearParameter(name);
4022  return *this;
4023 }
4024 
4025 CQuery&
4027 {
4029  return *this;
4030 }
4031 
4032 CQuery&
4034 {
4035  m_Impl->SetSql(sql);
4036  return *this;
4037 }
4038 
4039 CQuery&
4040 CQuery::Execute(const CTimeout& timeout)
4041 {
4042  m_Impl->Execute(timeout);
4043  return *this;
4044 }
4045 
4046 CQuery&
4048 {
4049  m_Impl->ExecuteSP(sp, timeout);
4050  return *this;
4051 }
4052 
4053 void
4055 {
4056  m_Impl->Cancel();
4057 }
4058 
4059 CQuery&
4061 {
4062  m_Impl->SetIgnoreBounds(true);
4063  return *this;
4064 }
4065 
4066 CQuery&
4068 {
4069  m_Impl->SetIgnoreBounds(false);
4070  return *this;
4071 }
4072 
4075 {
4076  // Check prerequisite that the requested number of rows includes 1
4077  if (m_Impl->GetMinRowCount() > 1)
4079  "Exactly one row requested while RequireRowCount() set "
4080  "the minimum to " +
4082  if (m_Impl->GetMaxRowCount() < 1)
4084  "Exactly one row requested while RequireRowCount() set "
4085  "the maximum to " +
4087 
4088  CQuery::iterator q_it = begin();
4089  if (q_it == end())
4091  "Expected exactly one row, but none are available");
4092 
4093  CQuery::CRow row(*q_it);
4094 
4095  ++q_it;
4096  if (q_it != end())
4098  "Expected exactly one row, but more than one are available");
4099 
4100  VerifyDone();
4101  return row;
4102 }
4103 
4104 unsigned int
4106 {
4107  return m_Impl->GetResultSetNo();
4108 }
4109 
4110 unsigned int
4112 {
4113  return m_Impl->GetRowNo(how_much);
4114 }
4115 
4116 int
4118 {
4119  return m_Impl->GetRowCount();
4120 }
4121 
4122 int
4124 {
4125  return m_Impl->GetStatus();
4126 }
4127 
4128 const list<string>&
4130 {
4131  return m_Impl->GetPrintOutput();
4132 }
4133 
4134 bool
4136 {
4137  return m_Impl->HasMoreResultSets();
4138 }
4139 
4140 void
4142 {
4143  m_Impl->PurgeResults();
4144 }
4145 
4146 void
4148 {
4150 }
4151 
4152 void
4153 CQuery::RequireRowCount(unsigned int min_rows, unsigned int max_rows)
4154 {
4155  m_Impl->RequireRowCount(min_rows, max_rows);
4156 }
4157 
4158 void
4160 {
4161  m_Impl->VerifyDone(how_much);
4162 }
4163 
4164 unsigned int
4166 {
4167  return m_Impl->GetTotalColumns();
4168 }
4169 
4170 string
4171 CQuery::GetColumnName(unsigned int col) const
4172 {
4173  return m_Impl->GetColumnName(col);
4174 }
4175 
4176 ESDB_Type
4177 CQuery::GetColumnType(unsigned int col) const
4178 {
4179  return m_Impl->GetColumnType(col);
4180 }
4181 
4183 CQuery::begin(void) const
4184 {
4186  return CRowIterator(m_Impl.GetNCPointer(), false);
4187 }
4188 
4190 CQuery::end(void) const
4191 {
4192  return CRowIterator(m_Impl.GetNCPointer(), true);
4193 }
4194 
4195 inline
4197  const CException* prev_exception, EDiagSev)
4198 {
4199  _ASSERT(dynamic_cast<const CDB_DeadlockEx*>(prev_exception));
4200 }
4201 
4202 inline
4204 {
4206 }
4207 
4208 
@ eNone
None specified.
Definition: blast_def.h:326
ECompressMethod
Definition: blobstore.hpp:40
@ eZLib
Definition: blobstore.hpp:42
@ eBZLib
Definition: blobstore.hpp:43
#define true
Definition: bool.h:35
#define false
Definition: bool.h:36
#define bool
Definition: bool.h:34
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:3460
CBlobBookmarkImpl(CDatabaseImpl *db_impl, I_BlobDescriptor *descr)
Definition: sdbapi.cpp:3453
Object used to store bookmarks to blobs to be changed later.
Definition: sdbapi.hpp:766
CBlobBookmark & operator=(const CBlobBookmark &bm)
Definition: sdbapi.cpp:3488
~CBlobBookmark(void)
Definition: sdbapi.cpp:3494
CNcbiOstream & GetOStream(size_t blob_size, TBlobOStreamFlags flags=0) const
Get Blob output stream.
Definition: sdbapi.cpp:3498
CRef< CBlobBookmarkImpl > m_Impl
Bookmark implementation object.
Definition: sdbapi.hpp:810
CBlobBookmark(void)
Empty constructor of bookmark object.
Definition: sdbapi.cpp:3476
EBlobType
Blob type (if known).
Definition: sdbapi.hpp:769
void WriteNull(void)
Definition: sdbapi.cpp:2320
void x_CheckCanWrite(int col)
Definition: sdbapi.cpp:2206
CRef< CDB_Exception::SContext > m_Context
void Bind(int col, ESDB_Type type)
Definition: sdbapi.cpp:2249
void Complete(void)
Definition: sdbapi.cpp:2289
void AddOrderHint(CTempString columns)
Definition: sdbapi.cpp:2242
void x_CheckWriteStarted(void)
Definition: sdbapi.cpp:2305
void EndRow(void)
Definition: sdbapi.cpp:2268
CBulkInsertImpl(CDatabaseImpl *db_impl, const string &tableName, int autoflush)
Definition: sdbapi.cpp:2173
const CDB_Exception::SContext & x_GetContext(void) const
Definition: sdbapi.cpp:2200
~CBulkInsertImpl(void)
Definition: sdbapi.cpp:2188
void WriteVal(const T &val)
Definition: sdbapi.cpp:2328
void SetHints(CTempString hints)
Definition: sdbapi.cpp:2228
CRef< CDatabaseImpl > m_DBImpl
void AddHint(IBulkInsert::EHints hint, unsigned int value)
Definition: sdbapi.cpp:2235
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:2402
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:2366
void Complete()
Complete bulk insert.
Definition: sdbapi.cpp:2396
void Bind(int col, ESDB_Type type)
Bind column for bulk insert.
Definition: sdbapi.cpp:2390
void AddOrderHint(CTempString columns)
Add "ORDER" hint.
Definition: sdbapi.cpp:2384
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:2360
CRef< CBulkInsertImpl > m_Impl
Bulk-insert implementation object.
Definition: sdbapi.hpp:903
CBulkInsert(void)
Empty constructor of bulk-insert object.
Definition: sdbapi.cpp:2335
CBulkInsert & operator=(const CBulkInsert &bi)
Definition: sdbapi.cpp:2353
~CBulkInsert(void)
Definition: sdbapi.cpp:2349
void SetTimeout(const CTimeout &timeout)
Definition: sdbapi.cpp:1836
CMutex m_Mutex
Definition: sdbapi_impl.hpp:86
void ResetTimeout(void)
Definition: sdbapi.cpp:1852
CRef< CDB_Exception::SContext > m_Context
Definition: sdbapi_impl.hpp:84
virtual ~CConnHolder(void)
Definition: sdbapi.cpp:1808
bool m_ContinueAfterRaiserror
Definition: sdbapi_impl.hpp:80
list< string > m_PrintOutput
Definition: sdbapi_impl.hpp:83
void CloseRef(void)
Definition: sdbapi.cpp:1827
CRef< CSDB_UserHandler > m_Handler
Definition: sdbapi_impl.hpp:85
void ResetPrintOutput()
Definition: sdbapi.cpp:1868
Uint4 m_CntOpen
Definition: sdbapi_impl.hpp:82
IConnection * GetConn(void) const
Definition: sdbapi.cpp:1814
bool m_HasCustomTimeout
Definition: sdbapi_impl.hpp:79
void AddOpenRef(void)
Definition: sdbapi.cpp:1820
CConnHolder(IConnection *conn, const CSDB_ConnectionParam &params)
Definition: sdbapi.cpp:1786
bool m_LogMinorMessages
Definition: sdbapi_impl.hpp:81
const CDB_Exception::SContext & GetContext(void) const
Definition: sdbapi.cpp:1875
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:1862
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:1964
void Connect(const CSDB_ConnectionParam &params)
Definition: sdbapi.cpp:1882
~CDatabaseImpl(void)
Definition: sdbapi.cpp:1919
CRef< CConnHolder > m_Conn
const list< string > & GetPrintOutput(void) const
Definition: sdbapi.cpp:1958
IConnection * GetConnection(void)
Definition: sdbapi.cpp:1940
void ResetTimeout(void)
Definition: sdbapi.cpp:1952
CDatabaseImpl(void)
Definition: sdbapi.cpp:1894
bool IsOpen() const
Definition: sdbapi.cpp:1928
const CDB_Exception::SContext & GetContext(void) const
Definition: sdbapi.cpp:1971
bool EverConnected() const
Definition: sdbapi.cpp:1934
void Close()
Definition: sdbapi.cpp:1910
void SetTimeout(const CTimeout &timeout)
Definition: sdbapi.cpp:1946
Database connection object.
Definition: sdbapi.hpp:1137
void Close(void)
Close database object.
Definition: sdbapi.cpp:2025
CDatabase & operator=(const CDatabase &db)
Definition: sdbapi.cpp:1995
void Connect(void)
Explicitly (re)connect to the database server.
Definition: sdbapi.cpp:2013
CQuery NewQuery(void)
Get new CQuery object for this database.
Definition: sdbapi.cpp:2082
CDatabase Clone(void)
Clone database object.
Definition: sdbapi.cpp:2070
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:2096
CBulkInsert NewBulkInsert(const string &table_name, int autoflush)
Get new CBulkInsert object.
Definition: sdbapi.cpp:2089
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:2125
~CDatabase(void)
Definition: sdbapi.cpp:2002
bool IsConnected(EConnectionCheckMethod check_method=eNoCheck)
Check if database object was already connected to database server.
Definition: sdbapi.cpp:2036
CSDB_ConnectionParam m_Params
Database parameters.
Definition: sdbapi.hpp:1282
void x_ConnectAsNeeded(const char *operation)
Definition: sdbapi.cpp:2159
CDatabase(void)
Empty constructor of database object.
Definition: sdbapi.cpp:1977
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:244
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:3638
const vector< unsigned char > & AsVector(void) const override
Definition: sdbapi.cpp:3747
CNcbiOstream & GetOStream(size_t blob_size, TBlobOStreamFlags flags) const override
Definition: sdbapi.cpp:3827
CBlobBookmark GetBookmark(void) const override
Definition: sdbapi.cpp:3869
CQueryBlobImpl(CQueryImpl *q, unsigned int col_num)
Definition: sdbapi.cpp:2551
CNcbiIstream & AsIStream(void) const override
Definition: sdbapi.cpp:3776
const CDB_Exception::SContext & x_GetContext(void) const
Definition: sdbapi.cpp:3655
virtual CNcbiOstream & GetOStream(size_t blob_size, TBlobOStreamFlags flags) const
Definition: sdbapi.cpp:3820
virtual CNcbiIstream & AsIStream(void) const
Definition: sdbapi.cpp:3768
const CVariant * GetValue(void) const
Definition: sdbapi.cpp:3661
virtual CRef< CQueryFieldImpl > Detach(void)
Definition: sdbapi.cpp:3629
virtual const vector< unsigned char > & AsVector(void) const
Definition: sdbapi.cpp:3739
CQueryFieldImpl(CQueryImpl *q, unsigned int col_num)
Definition: sdbapi.cpp:2530
virtual CBlobBookmark GetBookmark(void) const
Definition: sdbapi.cpp:3862
void Next(void)
Definition: sdbapi.cpp:3318
unsigned int GetRowNo(CQuery::EHowMuch how_much=CQuery::eAllResultSets) const
Definition: sdbapi.cpp:3041
const list< string > & GetPrintOutput(void) const
Definition: sdbapi.cpp:3446
void SetSql(CTempString sql)
Definition: sdbapi.cpp:2885
ICallableStatement * m_CallStmt
unsigned int GetResultSetNo(void) const
Definition: sdbapi.cpp:3034
void x_InitRSFields(void)
Definition: sdbapi.cpp:3132
void ClearParameter(CTempString name)
Definition: sdbapi.cpp:2854
unsigned int m_MaxRowCount
unsigned int GetMaxRowCount(void) const
bool x_Fetch(void)
Definition: sdbapi.cpp:3111
void x_CheckCanWork(bool need_rs=false) const
Definition: sdbapi.cpp:2735
void SetNullParameter(CTempString name, ESDB_Type type, ESP_ParamType param_type)
Definition: sdbapi.cpp:2779
void x_SetOutParameter(const string &name, const CVariant &value)
Definition: sdbapi.cpp:2806
void BeginNewRS(void)
Definition: sdbapi.cpp:3224
void Cancel(void)
Definition: sdbapi.cpp:3016
IStatement * m_Stmt
void SetParameter(CTempString name, const T &value, ESDB_Type type, ESP_ParamType param_type)
Definition: sdbapi.cpp:2751
CRef< CDatabaseImpl > m_DBImpl
bool m_RSFinished
int GetStatus(void) const
Definition: sdbapi.cpp:3065
void x_InitBeforeExec(void)
Definition: sdbapi.cpp:2936
void Execute(const CTimeout &timeout)
Definition: sdbapi.cpp:2954
void ExecuteSP(CTempString sp, const CTimeout &timeout)
Definition: sdbapi.cpp:2983
unsigned int GetMinRowCount(void) const
string m_Sql
CDatabaseImpl * GetDatabase(void) const
Definition: sdbapi.cpp:3434
bool m_HasExplicitMode
void SetIgnoreBounds(bool is_ignore)
Definition: sdbapi.cpp:3025
bool m_ReportedWrongRowCount
void x_Close(void)
Definition: sdbapi.cpp:2903
CQueryImpl(CDatabaseImpl *db_impl)
Definition: sdbapi.cpp:2670
unsigned int m_MinRowCount
void x_ClearAllParams(void)
Definition: sdbapi.cpp:2867
unsigned int GetTotalColumns(void) const
Definition: sdbapi.cpp:3290
CRef< CDB_Exception::SContext > m_Context
string GetColumnName(unsigned int col) const
Definition: sdbapi.cpp:3297
bool m_IgnoreBounds
const CQuery::CField & GetParameter(CTempString name)
Definition: sdbapi.cpp:2831
void ClearParameters(void)
Definition: sdbapi.cpp:2877
IConnection * GetConnection(void)
Definition: sdbapi.cpp:3440
const CQuery::CRow & GetRow(void) const
Definition: sdbapi.cpp:3420
CQuery::CRow m_Row
bool HasMoreResultSets(void)
Definition: sdbapi.cpp:3141
void PurgeResults(void)
Definition: sdbapi.cpp:3258
TParamsMap m_Params
bool m_RowUnderConstruction
~CQueryImpl(void)
Definition: sdbapi.cpp:2695
void x_DetachAllFields(void)
Definition: sdbapi.cpp:2895
ESDB_Type GetColumnType(unsigned int col) const
Definition: sdbapi.cpp:3304
unsigned int m_CurRelRowNo
IResultSet * m_CurRS
void RequireRowCount(unsigned int min_rows, unsigned int max_rows)
Definition: sdbapi.cpp:3326
unsigned int m_CurRSNo
const CQuery::CField & GetColumn(const CDBParamVariant &col) const
Definition: sdbapi.cpp:3427
void x_CheckRowCount(void)
Definition: sdbapi.cpp:3077
bool IsFinished(CQuery::EHowMuch how_much=CQuery::eThisResultSet) const
Definition: sdbapi.cpp:3390
void VerifyDone(CQuery::EHowMuch how_much=CQuery::eThisResultSet)
Definition: sdbapi.cpp:3349
const CDB_Exception::SContext & x_GetContext(void) const
Definition: sdbapi.cpp:2706
unsigned int m_CurRowNo
int GetRowCount(void) const
Definition: sdbapi.cpp:3052
bool m_RSBeginned
const CVariant & GetFieldValue(unsigned int col_num)
Definition: sdbapi.cpp:2825
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:3835
bool IsNull(void) const
Check if value is NULL.
Definition: sdbapi.cpp:3792
bool AsBool(void) const
Get value as bool.
Definition: sdbapi.cpp:3723
Int8 AsInt8(void) const
Get value as 8-byte integer.
Definition: sdbapi.cpp:3699
const vector< unsigned char > & AsVector(void) const
Get value as vector of bytes.
Definition: sdbapi.cpp:3762
CField(const CField &f)
Definition: sdbapi.cpp:2556
Int4 AsInt4(void) const
Get value as 4-byte integer.
Definition: sdbapi.cpp:3691
CNcbiIstream & AsIStream(void) const
Get value as input stream.
Definition: sdbapi.cpp:3786
unsigned char AsByte(void) const
Get value as single byte.
Definition: sdbapi.cpp:3675
CTime AsDateTime(void) const
Get value as CTime.
Definition: sdbapi.cpp:3731
void x_Detach(void)
Definition: sdbapi.cpp:3647
string AsString(void) const
Get value as UTF-8 string.
Definition: sdbapi.cpp:3667
short AsShort(void) const
Get value as short integer.
Definition: sdbapi.cpp:3683
double AsDouble(void) const
Get value as double.
Definition: sdbapi.cpp:3715
CBlobBookmark GetBookmark(void) const
Get bookmark for the blob.
Definition: sdbapi.cpp:3875
float AsFloat(void) const
Get value as float.
Definition: sdbapi.cpp:3707
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:3583
bool operator==(const CRowIterator &ri) const
Comparison of iterators.
Definition: sdbapi.cpp:3589
unsigned int GetResultSetNo(void) const
Get number of currently active result set.
Definition: sdbapi.cpp:3559
unsigned int GetTotalColumns(void) const
Get number of columns in the current result set.
Definition: sdbapi.cpp:3571
const CDB_Exception::SContext & x_GetContext(void) const
Definition: sdbapi.cpp:3553
CRowIterator(void)
Empty constructor of iterator.
Definition: sdbapi.cpp:3526
const CRow & operator*(void) const
Get the full row. (The caller is welcome to keep a copy.)
Definition: sdbapi.cpp:3623
CRowIterator & operator=(const CRowIterator &ri)
Definition: sdbapi.cpp:3542
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:3601
unsigned int GetRowNo(void) const
Get row number currently active.
Definition: sdbapi.cpp:3565
string GetColumnName(unsigned int col) const
Get name of the column with given number in the current result set.
Definition: sdbapi.cpp:3577
const CField & operator[](unsigned int col) const
Get column value by its number.
Definition: sdbapi.cpp:3612
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:2603
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:2644
vector< CField > m_Fields
Definition: sdbapi.hpp:413
unsigned int GetTotalColumns(void) const
Get number of columns in the row.
Definition: sdbapi.cpp:2633
const string & GetColumnName(unsigned int col) const
Get name of the column with given number in the row.
Definition: sdbapi.cpp:2638
CRow(void)
Definition: sdbapi.cpp:2591
const CField & operator[](unsigned int col) const
Get column value by its number.
Definition: sdbapi.cpp:2613
void x_Reset(CQueryImpl &q, IResultSet &rs)
Definition: sdbapi.cpp:2650
const CDB_Exception::SContext & x_GetContext(void) const
Definition: sdbapi.cpp:3521
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:4135
CQuery & SetSql(CTempString sql)
Set current sql statement.
Definition: sdbapi.cpp:4033
int GetStatus(void) const
Get return status of stored procedure.
Definition: sdbapi.cpp:4123
CQuery & MultiSet(void)
Convert this query to not merge different result sets, i.e.
Definition: sdbapi.cpp:4067
CRow GetTheOnlyRow(void)
Provides the only row for the executed query.
Definition: sdbapi.cpp:4074
CQuery & ClearParameters(void)
Remove all parameters from parameter list.
Definition: sdbapi.cpp:4026
unsigned int GetTotalColumns(void) const
Get total number of columns in the current result set.
Definition: sdbapi.cpp:4165
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:4190
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:4177
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:3893
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:4159
CRef< CQueryImpl > m_Impl
Query implementation object.
Definition: sdbapi.hpp:758
void Cancel(void)
Cancel the current statement or procedure call.
Definition: sdbapi.cpp:4054
CQuery & SetNullParameter(CTempString name, ESDB_Type type, ESP_ParamType param_type=eSP_In)
Assign null value to the parameter.
Definition: sdbapi.cpp:4004
CRowIterator begin(void) const
Start iterating through next result set.
Definition: sdbapi.cpp:4183
const CField & GetParameter(CTempString name)
Get value of the parameter.
Definition: sdbapi.cpp:4013
CQuery & ClearParameter(CTempString name)
Remove parameter with given name from parameter list.
Definition: sdbapi.cpp:4019
CQuery & Execute(const CTimeout &timeout=CTimeout(CTimeout::eDefault))
Explicitly execute sql statement.
Definition: sdbapi.cpp:4040
const list< string > & GetPrintOutput(void) const
Get any PRINT output from the latest procedure call (or statement).
Definition: sdbapi.cpp:4129
void RequireRowCount(unsigned int n)
Indicate precisely how many rows the active query should return.
Definition: sdbapi.cpp:4147
CQuery(void)
Empty constructor of query object.
Definition: sdbapi.cpp:3881
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:3904
unsigned int GetRowNo(EHowMuch how_much=eAllResultSets) const
Get row number currently active.
Definition: sdbapi.cpp:4111
CQuery & ExecuteSP(CTempString sp, const CTimeout &timeout=CTimeout(CTimeout::eDefault))
Execute stored procedure with given name.
Definition: sdbapi.cpp:4047
int GetRowCount(void) const
Get number of rows read after statement execution.
Definition: sdbapi.cpp:4117
unsigned int GetResultSetNo(void) const
Get number of currently active result set.
Definition: sdbapi.cpp:4105
void PurgeResults(void)
Purge all remaining result sets; fill in all remaining parameter results.
Definition: sdbapi.cpp:4141
CQuery & SingleSet(void)
Convert this query to work like only one result set was returned effectively merging all result sets ...
Definition: sdbapi.cpp:4060
string GetColumnName(unsigned int col) const
Get name of the column with given number in the current result set.
Definition: sdbapi.cpp:4171
CQuery & operator=(const CQuery &q)
Definition: sdbapi.cpp:3897
@ 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:3853
CQueryImpl & m_Query
unsigned int m_ColNum
const CDB_Exception::SContext & x_GetContext(void) const override
Definition: sdbapi.cpp:2517
const CVariant * GetValue(void) const override
Definition: sdbapi.cpp:2512
CNcbiOstream * GetOStream(size_t blob_size, TBlobOStreamFlags flags) const override
Definition: sdbapi.cpp:3803
EMirrorStatus
Definition: sdbapi.hpp:1323
@ eMirror_Unavailable
All databases in the mirror are unavailable.
Definition: sdbapi.hpp:1326
@ eMirror_Steady
Mirror is working on the same server as before.
Definition: sdbapi.hpp:1324
@ eMirror_NewMaster
Switched to a new master.
Definition: sdbapi.hpp:1325
static void UseDriver(EDriver driver)
Use the specified driver for all connections.
Definition: sdbapi.cpp:1363
static EMirrorStatus UpdateMirror(const string &dbservice, list< string > *servers=NULL, string *error_message=NULL)
Check for master/mirror switch.
Definition: sdbapi.cpp:1476
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:1722
static bool Init(void)
Initialize SDBAPI.
Definition: sdbapi.cpp:1324
static void SetApplicationName(const CTempString &name)
Report the specified application name to servers.
Definition: sdbapi.cpp:1352
static string GetApplicationName(void)
Check SDBAPI's application name setting.
Definition: sdbapi.cpp:1357
@ 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:1600
static CRef< CSDB_Decryptor > GetGlobalDecryptor(void)
Get the current password decryptor, if any.
Definition: sdbapi.cpp:1015
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:1080
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:1203
static void SetGlobalDecryptor(CRef< CSDB_Decryptor > decryptor)
Use the specified password decryptor.
Definition: sdbapi.cpp:1008
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:1274
string ComposeUrl(TComposeUrlFlags flags=0) const
Compose database connection URL string out of this class.
Definition: sdbapi.cpp:1027
static bool x_IsKnownArg(const string &name)
Definition: sdbapi.hpp:1531
@ fThrowIfIncomplete
Throw an exception if missing any "essential" parameters.
Definition: sdbapi.hpp:988
bool IsEmpty(void) const
Definition: sdbapi.cpp:1049
string x_GetPassword() const
Determine what password to use, accounting for possible encryption or indirection.
Definition: sdbapi.cpp:1150
void x_ReportOverride(const CTempString &name, CTempString code_value, CTempString reg_value) const
Definition: sdbapi.cpp:1285
static const char * x_GetName(EParam param)
Definition: sdbapi.hpp:1498
string Get(EParam param, EWithOverrides with_overrides=eWithoutOverrides) const
Get one of the "essential" database connection parameters.
Definition: sdbapi.hpp:1542
TParamMap m_ParamMap
Definition: sdbapi.hpp:1131
void x_InitErrCode(CException::EErrCode err_code) override
Helper method for initializing error code.
Definition: sdbapi.cpp:4203
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:4196
Database password decryptor.
Definition: sdbapi.hpp:920
virtual string x_GetKey(const CTempString &key_id)
Definition: sdbapi.cpp:983
virtual string x_Decrypt(const string &ciphertext, const string &key)
Definition: sdbapi.cpp:969
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:1742
bool HandleMessage(int severity, int msgnum, const string &message)
Handle message resulting from a native API call.
Definition: sdbapi.cpp:1755
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:1404
virtual string GetServerName(void) const
Definition: sdbapi.cpp:1421
virtual string GetPassword(void) const
Definition: sdbapi.cpp:1436
virtual EEncoding GetEncoding(void) const
Definition: sdbapi.cpp:1416
virtual string GetUserName(void) const
Definition: sdbapi.cpp:1431
virtual Uint4 GetHost(void) const
Definition: sdbapi.cpp:1446
const CDBConnParams & m_Other
Definition: sdbapi.cpp:1471
virtual string GetParam(const string &key) const
Parameters, which are not listed above explicitly, should be retrieved via SetParam() method.
Definition: sdbapi.cpp:1461
virtual CRef< IConnValidator > GetConnValidator(void) const
Definition: sdbapi.cpp:1456
virtual EServerType GetServerType(void) const
Definition: sdbapi.cpp:1441
virtual Uint4 GetProtocolVersion(void) const
Definition: sdbapi.cpp:1411
virtual string GetDatabaseName(void) const
Definition: sdbapi.cpp:1426
virtual Uint2 GetPort(void) const
Definition: sdbapi.cpp:1451
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:3847
virtual CNcbiOstream * GetOStream(size_t blob_size, TBlobOStreamFlags flags) const
Definition: sdbapi.cpp:3797
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
container_type::const_iterator const_iterator
Definition: map.hpp:53
const_iterator end() const
Definition: map.hpp:152
iterator_bool insert(const value_type &val)
Definition: map.hpp:165
bool empty() const
Definition: map.hpp:149
void clear()
Definition: map.hpp:169
const_iterator find(const key_type &key) const
Definition: map.hpp:153
state()
Definition: sls_alp.cpp:1633
char value[7]
Definition: config.c:431
static CS_CONNECTION * conn
Definition: ct_dynamic.c:25
static uch flags
CS_CONTEXT * ctx
Definition: t0006.c:12