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

Go to the SVN repository for this file.

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