1 /* $Id: types.cpp 626573 2021-03-01 19:49:53Z ivanov $
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: Vladimir Soussov
27 *
28 * File Description: Type conversions
29 *
30 */
31
32 #include <ncbi_pch.hpp>
33 #include <corelib/ncbitime.hpp>
34
35 #include <dbapi/driver/interfaces.hpp>
36 #include <dbapi/driver/dbapi_object_convert.hpp>
37 #include <dbapi/driver/util/numeric_convert.hpp>
38 #include "memory_store.hpp"
39
40 #include <dbapi/driver/types.hpp>
41 #include <dbapi/error_codes.hpp>
42
43 #include <string.h>
44
45
46 #define NCBI_USE_ERRCODE_X Dbapi_DrvrTypes
47
48
49 BEGIN_NCBI_SCOPE
50
51
52 inline
s_MakeLittleEndian(TStringUCS2 & s)53 void s_MakeLittleEndian(TStringUCS2& s)
54 {
55 #ifdef WORDS_BIGENDIAN
56 NON_CONST_ITERATE (TStringUCS2, it, s) {
57 *it = (*it << 8) | (*it >> 8);
58 }
59 #endif
60 }
61
62
63 /////////////////////////////////////////////////////////////////////////////
64 template<>
operator const char*(void) const65 CGenericSqlString<char>::operator const char*(void) const
66 {
67 return this->c_str();
68 }
69
70 #ifdef HAVE_WSTRING
71 template<>
operator const wchar_t*(void) const72 CGenericSqlString<wchar_t>::operator const wchar_t*(void) const
73 {
74 return this->c_str();
75 }
76 #endif
77
78
79 /////////////////////////////////////////////////////////////////////////////
CWString(void)80 CWString::CWString(void) :
81 m_AvailableValueType(0),
82 m_StringEncoding(eEncoding_Unknown),
83 m_Char(NULL)
84 #ifdef HAVE_WSTRING
85 , m_WChar(NULL)
86 #endif
87 {
88 }
89
90
CWString(const CWString & str)91 CWString::CWString(const CWString& str) :
92 m_AvailableValueType(str.m_AvailableValueType),
93 m_StringEncoding(str.m_StringEncoding),
94 m_Char(NULL),
95 #ifdef HAVE_WSTRING
96 m_WChar(NULL),
97 #endif
98 m_String(str.m_String),
99 #ifdef HAVE_WSTRING
100 m_WString(str.m_WString),
101 #endif
102 m_UTF8String(str.m_UTF8String)
103 {
104 // Assign m_Char even if m_String is empty ...
105 m_Char = m_String.c_str();
106
107 #ifdef HAVE_WSTRING
108 // Assign m_WChar even if m_WString is empty ...
109 m_WChar = m_WString.c_str();
110 #endif
111 }
112
113
CWString(const char * str,string::size_type size,EEncoding enc)114 CWString::CWString(const char* str,
115 string::size_type size,
116 EEncoding enc) :
117 m_AvailableValueType(eChar),
118 m_StringEncoding(enc),
119 m_Char(NULL)
120 #ifdef HAVE_WSTRING
121 , m_WChar(NULL)
122 #endif
123 {
124 if (size == string::npos) {
125 m_Char = str;
126 } else {
127 if (str) {
128 m_String.assign(str, size);
129 m_Char = m_String.c_str();
130 }
131 m_AvailableValueType |= eString;
132 }
133 }
134
135
136 #ifdef HAVE_WSTRING
CWString(const wchar_t * str,wstring::size_type size)137 CWString::CWString(const wchar_t* str,
138 wstring::size_type size) :
139 m_AvailableValueType(eWChar),
140 m_StringEncoding(eEncoding_Unknown),
141 m_Char(NULL),
142 m_WChar(NULL)
143 {
144 if (size == wstring::npos) {
145 m_WChar = str;
146 } else {
147 if (str) {
148 m_WString.assign(str, size);
149 m_WChar = m_WString.c_str();
150 }
151 m_AvailableValueType |= eWString;
152 }
153 }
154 #endif
155
156
CWString(const string & str,EEncoding enc)157 CWString::CWString(const string& str, EEncoding enc) :
158 m_AvailableValueType(eString),
159 m_StringEncoding(enc),
160 m_Char(NULL),
161 #ifdef HAVE_WSTRING
162 m_WChar(NULL),
163 #endif
164 m_String(str)
165 {
166 m_Char = m_String.c_str();
167 m_AvailableValueType |= eChar;
168 }
169
170
171 #ifdef HAVE_WSTRING
CWString(const wstring & str)172 CWString::CWString(const wstring& str) :
173 m_AvailableValueType(eWString),
174 m_Char(NULL),
175 m_WChar(NULL),
176 m_WString(str)
177 {
178 m_WChar = m_WString.c_str();
179 m_AvailableValueType |= eWChar;
180 }
181 #endif
182
183
~CWString(void)184 CWString::~CWString(void)
185 {
186 }
187
188
operator =(const CWString & str)189 CWString& CWString::operator=(const CWString& str)
190 {
191 if (&str != this) {
192 m_AvailableValueType = str.m_AvailableValueType;
193 m_StringEncoding = str.m_StringEncoding;
194 m_Char = NULL;
195 m_String = str.m_String;
196 m_UTF8String = str.m_UTF8String;
197 m_Char = m_String.c_str();
198
199 #ifdef HAVE_WSTRING
200 m_WChar = NULL;
201 m_WString = str.m_WString;
202 m_WChar = m_WString.c_str();
203 #endif
204 }
205
206 return *this;
207 }
208
209 // Deprecated conversions, defined out of line to reduce warnings
operator char*(void) const210 CWString::operator char*(void) const
211 {
212 return const_cast<char*>(AsCString());
213 }
214
operator const char*(void) const215 CWString::operator const char*(void) const
216 {
217 return AsCString();
218 }
219
operator wchar_t*(void) const220 CWString::operator wchar_t*(void) const
221 {
222 return const_cast<wchar_t*>(AsCWString());
223 }
224
operator const wchar_t*(void) const225 CWString::operator const wchar_t*(void) const
226 {
227 return AsCWString();
228 }
229
230
x_CalculateEncoding(EEncoding str_enc) const231 void CWString::x_CalculateEncoding(EEncoding str_enc) const
232 {
233 if (str_enc != eEncoding_Unknown) {
234 m_StringEncoding = str_enc;
235 } else {
236 m_StringEncoding = eEncoding_ISO8859_1;
237 }
238 }
239
x_UTF8ToString(EEncoding str_enc) const240 void CWString::x_UTF8ToString(EEncoding str_enc) const
241 {
242 if (m_StringEncoding == eEncoding_Unknown) {
243 x_CalculateEncoding(str_enc);
244 }
245
246 if (m_StringEncoding == eEncoding_UTF8) {
247 m_String = m_UTF8String;
248 } else {
249 m_String = CUtf8::AsSingleByteString(m_UTF8String,m_StringEncoding);
250 }
251
252 m_AvailableValueType |= eString;
253 }
254
255
x_StringToUTF8(EEncoding str_enc) const256 void CWString::x_StringToUTF8(EEncoding str_enc) const
257 {
258 if (m_StringEncoding == eEncoding_Unknown) {
259 x_CalculateEncoding(str_enc);
260 }
261
262 if (m_AvailableValueType & eString) {
263 m_UTF8String = CUtf8::AsUTF8(m_String, m_StringEncoding);
264 } else if (m_AvailableValueType & eChar) {
265 if (m_Char) {
266 m_UTF8String = CUtf8::AsUTF8(m_Char, m_StringEncoding);
267 } else {
268 m_UTF8String.erase();
269 }
270 }
271
272 m_AvailableValueType |= eUTF8String;
273 }
274
275
x_MakeString(EEncoding str_enc) const276 void CWString::x_MakeString(EEncoding str_enc) const
277 {
278 if (m_AvailableValueType & eString) {
279 if (!(m_AvailableValueType & eChar)) {
280 if (m_String.empty()) {
281 m_Char = NULL;
282 } else {
283 m_Char = m_String.c_str();
284 }
285 m_AvailableValueType |= eChar;
286 }
287 } else if (m_AvailableValueType & eChar) {
288 if (m_Char) {
289 m_String.assign(m_Char);
290 } else {
291 m_String.erase();
292 }
293 m_AvailableValueType |= eString;
294 } else if (m_AvailableValueType & eUTF8String) {
295 x_UTF8ToString(str_enc);
296 x_MakeString(str_enc);
297 #ifdef HAVE_WSTRING
298 } else if (m_AvailableValueType & eWString) {
299 m_UTF8String = CUtf8::AsUTF8(m_WString);
300 m_AvailableValueType |= eUTF8String;
301 x_UTF8ToString(str_enc);
302 x_MakeString(str_enc);
303 } else if (m_AvailableValueType & eWChar) {
304 if (m_WChar) {
305 m_UTF8String = CUtf8::AsUTF8(m_WChar);
306 m_AvailableValueType |= eUTF8String;
307 x_UTF8ToString(str_enc);
308 } else {
309 m_String.erase();
310 m_AvailableValueType |= eString;
311 }
312 x_MakeString(str_enc);
313 #endif
314 }
315 }
316
317 #ifdef HAVE_WSTRING
x_MakeWString(EEncoding str_enc) const318 void CWString::x_MakeWString(EEncoding str_enc) const
319 {
320 if (m_AvailableValueType & eWString) {
321 if (!(m_AvailableValueType & eWChar)) {
322 if (m_WString.empty()) {
323 m_WChar = NULL;
324 } else {
325 m_WChar = m_WString.c_str();
326 }
327 m_AvailableValueType |= eWChar;
328 }
329 } else if (m_AvailableValueType & eWChar) {
330 if (m_WChar) {
331 m_WString.assign(m_WChar);
332 } else {
333 m_WString.erase();
334 }
335 m_AvailableValueType |= eWString;
336 } else if (m_AvailableValueType & eUTF8String) {
337 m_WString = CUtf8::AsBasicString<wchar_t>(m_UTF8String);
338 m_AvailableValueType |= eWString;
339 x_MakeWString(str_enc);
340 } else if (m_AvailableValueType & eString) {
341 x_StringToUTF8(str_enc);
342 x_MakeWString(str_enc);
343 } else if (m_AvailableValueType & eChar) {
344 if (m_Char) {
345 x_StringToUTF8(str_enc);
346 x_MakeWString(str_enc);
347 } else {
348 m_WString.erase();
349 m_AvailableValueType |= eWString;
350 }
351 }
352 }
353 #endif
354
x_MakeUTF8String(EEncoding str_enc) const355 void CWString::x_MakeUTF8String(EEncoding str_enc) const
356 {
357 if (m_AvailableValueType & eUTF8String) {
358 return;
359 } else if (m_AvailableValueType & eString) {
360 x_StringToUTF8(str_enc);
361 } else if (m_AvailableValueType & eChar) {
362 x_StringToUTF8(str_enc);
363 #ifdef HAVE_WSTRING
364 } else if (m_AvailableValueType & eWString) {
365 m_UTF8String = CUtf8::AsUTF8(m_WString);
366 m_AvailableValueType |= eUTF8String;
367 } else if (m_AvailableValueType & eWChar) {
368 if (m_WChar) {
369 m_UTF8String = CUtf8::AsUTF8(m_WChar);
370 } else {
371 m_UTF8String.erase();
372 }
373 m_AvailableValueType |= eUTF8String;
374 #endif
375 }
376 }
377
x_MakeUCS2LEString(EEncoding str_enc) const378 void CWString::x_MakeUCS2LEString(EEncoding str_enc) const
379 {
380 if (m_AvailableValueType & eUCS2LEString) {
381 return;
382 } else {
383 x_MakeUTF8String(str_enc);
384 m_UCS2LEString = CUtf8::AsBasicString<TCharUCS2>(m_UTF8String);
385 s_MakeLittleEndian(m_UCS2LEString);
386 m_AvailableValueType |= eUCS2LEString;
387 }
388 }
389
GetSymbolNum(void) const390 size_t CWString::GetSymbolNum(void) const
391 {
392 size_t num = 0;
393
394 if (m_AvailableValueType & eString) {
395 num = m_String.size();
396 #ifdef HAVE_WSTRING
397 } else if (m_AvailableValueType & eWString) {
398 num = m_WString.size();
399 #endif
400 } else if (m_AvailableValueType & eChar) {
401 if (m_Char) {
402 num = strlen(m_Char);
403 }
404 #ifdef HAVE_WSTRING
405 } else if (m_AvailableValueType & eWChar) {
406 if (m_WChar) {
407 // ??? Should be a better solution ...
408 x_MakeWString();
409 num = m_WString.size();
410 }
411 #endif
412 } else if (m_AvailableValueType & eUTF8String) {
413 num = CUtf8::GetSymbolCount(m_UTF8String);
414 }
415
416 return num;
417 }
418
Clear(void)419 void CWString::Clear(void)
420 {
421 m_AvailableValueType = 0;
422 m_StringEncoding = eEncoding_Unknown;
423 m_Char = NULL;
424 m_String.erase();
425 #ifdef HAVE_WSTRING
426 m_WChar = NULL;
427 m_WString.erase();
428 #endif
429 m_UTF8String.erase();
430 }
431
Assign(const char * str,string::size_type size,EEncoding enc)432 void CWString::Assign(const char* str,
433 string::size_type size,
434 EEncoding enc)
435 {
436 #ifdef HAVE_WSTRING
437 m_WChar = NULL;
438 m_WString.erase();
439 #endif
440 m_UTF8String.erase();
441
442 m_StringEncoding = enc;
443 if (size == string::npos) {
444 m_String.erase();
445 m_Char = str;
446 m_AvailableValueType = eChar;
447 } else {
448 if (str) {
449 m_String.assign(str, size);
450 m_Char = m_String.c_str();
451 } else {
452 m_Char = NULL;
453 m_String.erase();
454 }
455 m_AvailableValueType = eChar | eString;
456 }
457 }
458
459 #ifdef HAVE_WSTRING
Assign(const wchar_t * str,wstring::size_type size)460 void CWString::Assign(const wchar_t* str,
461 wstring::size_type size)
462 {
463 m_StringEncoding = eEncoding_Unknown;
464 m_Char = NULL;
465 m_String.erase();
466 m_UTF8String.erase();
467
468 if (size == wstring::npos) {
469 m_WString.erase();
470 m_WChar = str;
471 m_AvailableValueType = eWChar;
472 } else {
473 if (str) {
474 m_WString.assign(str, size);
475 m_WChar = m_WString.c_str();
476 } else {
477 m_WChar = NULL;
478 m_WString.erase();
479 }
480 m_AvailableValueType = eWChar | eWString;
481 }
482 }
483 #endif
484
Assign(const string & str,EEncoding enc)485 void CWString::Assign(const string& str,
486 EEncoding enc)
487 {
488 #ifdef HAVE_WSTRING
489 m_WChar = NULL;
490 m_WString.erase();
491 #endif
492 m_UTF8String.erase();
493
494 m_StringEncoding = enc;
495 m_String = str;
496 m_Char = m_String.c_str();
497 m_AvailableValueType = eChar | eString;
498 }
499
500 #ifdef HAVE_WSTRING
Assign(const wstring & str)501 void CWString::Assign(const wstring& str)
502 {
503 m_StringEncoding = eEncoding_Unknown;
504 m_Char = NULL;
505 m_String.erase();
506 m_UTF8String.erase();
507
508 m_WString = str;
509 m_WChar = m_WString.c_str();
510 m_AvailableValueType = eWChar | eWString;
511 }
512 #endif
513
514
515 ////////////////////////////////////////////////////////////////////////////////
516 static
CheckStringTruncation(size_t cur_len,size_t max_len)517 void CheckStringTruncation(size_t cur_len, size_t max_len)
518 {
519 if (cur_len > max_len) {
520 ERR_POST_X(1, Warning << "String of size " << cur_len <<
521 " was truncated to " << max_len << " character(s)");
522 }
523 }
524
525 ////////////////////////////////////////////////////////////////////////////////
526 static
CheckBinaryTruncation(size_t cur_len,size_t max_len)527 void CheckBinaryTruncation(size_t cur_len, size_t max_len)
528 {
529 if (cur_len > max_len) {
530 ERR_POST_X(2, Warning << "Binary data of size " << cur_len <<
531 " was truncated to " << max_len << " byte(s)");
532 }
533 }
534
535 ////////////////////////////////////////////////////////////////////////////////
536 // CDB_Object::
537 //
538
CDB_Object(bool is_null)539 CDB_Object::CDB_Object(bool is_null) :
540 m_Null(is_null)
541 {
542 return;
543 }
544
~CDB_Object()545 CDB_Object::~CDB_Object()
546 {
547 return;
548 }
549
AssignNULL()550 void CDB_Object::AssignNULL()
551 {
552 SetNULL();
553 }
554
555
Create(EDB_Type type,size_t size)556 CDB_Object* CDB_Object::Create(EDB_Type type, size_t size)
557 {
558 switch ( type ) {
559 case eDB_Int : return new CDB_Int ();
560 case eDB_SmallInt : return new CDB_SmallInt ();
561 case eDB_TinyInt : return new CDB_TinyInt ();
562 case eDB_BigInt : return new CDB_BigInt ();
563 case eDB_VarChar : return new CDB_VarChar ();
564 case eDB_Char : return new CDB_Char (size);
565 case eDB_VarBinary : return new CDB_VarBinary ();
566 case eDB_Binary : return new CDB_Binary (size);
567 case eDB_Float : return new CDB_Float ();
568 case eDB_Double : return new CDB_Double ();
569 case eDB_DateTime : return new CDB_DateTime ();
570 case eDB_BigDateTime : return new CDB_BigDateTime ();
571 case eDB_SmallDateTime : return new CDB_SmallDateTime ();
572 case eDB_Text : return new CDB_Text ();
573 case eDB_Image : return new CDB_Image ();
574 case eDB_Bit : return new CDB_Bit ();
575 case eDB_Numeric : return new CDB_Numeric ();
576 case eDB_LongBinary : return new CDB_LongBinary(size);
577 case eDB_LongChar : return new CDB_LongChar (size);
578 case eDB_VarCharMax : return new CDB_VarCharMax ();
579 case eDB_VarBinaryMax : return new CDB_VarBinaryMax ();
580 case eDB_UnsupportedType : break;
581 }
582 DATABASE_DRIVER_ERROR("unknown type " + NStr::IntToString(type), 2);
583 }
584
585
GetTypeName(EDB_Type db_type,bool throw_on_unknown)586 const char* CDB_Object::GetTypeName(EDB_Type db_type, bool throw_on_unknown)
587 {
588 switch ( db_type ) {
589 case eDB_Int : return "DB_Int";
590 case eDB_SmallInt : return "DB_SmallInt";
591 case eDB_TinyInt : return "DB_TinyInt";
592 case eDB_BigInt : return "DB_BigInt";
593 case eDB_VarChar : return "DB_VarChar";
594 case eDB_Char : return "DB_Char";
595 case eDB_VarBinary : return "DB_VarBinary";
596 case eDB_Binary : return "DB_Binary";
597 case eDB_Float : return "DB_Float";
598 case eDB_Double : return "DB_Double";
599 case eDB_DateTime : return "DB_DateTime";
600 case eDB_BigDateTime : return "DB_BigDateTime";
601 case eDB_SmallDateTime : return "DB_SmallDateTime";
602 case eDB_Text : return "DB_Text";
603 case eDB_Image : return "DB_Image";
604 case eDB_Bit : return "DB_Bit";
605 case eDB_Numeric : return "DB_Numeric";
606 case eDB_LongBinary : return "DB_LongBinary";
607 case eDB_LongChar : return "DB_LongChar";
608 case eDB_VarCharMax : return "DB_VarCharMax";
609 case eDB_VarBinaryMax : return "DB_VarBinaryMax";
610 case eDB_UnsupportedType : return "DB_UnsupportedType";
611 }
612
613 if (throw_on_unknown) {
614 DATABASE_DRIVER_ERROR("unknown type " + NStr::IntToString(db_type), 2);
615 }
616
617 return "DB_???";
618 }
619
620
621 NCBI_PARAM_DEF(unsigned int, dbapi, max_logged_param_length, 255);
622
623
GetLogString(void) const624 string CDB_Object::GetLogString(void) const
625 {
626 if (IsNULL()) {
627 return "NULL";
628 }
629
630 unsigned int max_length = TDbapi_MaxLoggedParamLength::GetDefault();
631 string result;
632
633 if (IsBlobType(GetType())) {
634 const CDB_Stream& s = static_cast<const CDB_Stream&>(*this);
635 AutoArray<char> buff(max_length + 1);
636 result.assign(buff.get(), s.PeekAt(buff.get(), 0, max_length + 1));
637 } else {
638 try {
639 result = (string)ConvertSQL(*this);
640 } catch (exception& e) {
641 ERR_POST(Warning << "Exception converting from "
642 << GetTypeName(GetType()) << ": " << e.what());
643 return "???";
644 }
645 }
646
647 if (result.length() > max_length) {
648 result.resize(max_length);
649 if (max_length > 3) {
650 result[max_length - 1] = result[max_length - 2] =
651 result[max_length - 3] = '.';
652 }
653 }
654 // XXX - retrim?
655 return NStr::PrintableString
656 (result, NStr::fNewLine_Quote | NStr::fNonAscii_Quote);
657 }
658
659
660 /////////////////////////////////////////////////////////////////////////////
661 // CDB_Int::
662 //
663
CDB_Int()664 CDB_Int::CDB_Int() :
665 CDB_Object(true),
666 m_Val(0)
667 {
668 return;
669 }
670
CDB_Int(const Int4 & i)671 CDB_Int::CDB_Int(const Int4& i) :
672 CDB_Object(false),
673 m_Val(i)
674 {
675 return;
676 }
677
~CDB_Int()678 CDB_Int::~CDB_Int()
679 {
680 return;
681 }
682
GetType() const683 EDB_Type CDB_Int::GetType() const
684 {
685 return eDB_Int;
686 }
687
Clone() const688 CDB_Object* CDB_Int::Clone() const
689 {
690 return IsNULL() ? new CDB_Int : new CDB_Int(m_Val);
691 }
692
AssignValue(const CDB_Object & v)693 void CDB_Int::AssignValue(const CDB_Object& v)
694 {
695 switch( v.GetType() ) {
696 case eDB_Int : *this = static_cast<const CDB_Int&>(v); break;
697 case eDB_SmallInt: *this = static_cast<const CDB_SmallInt&>(v).Value(); break;
698 case eDB_TinyInt : *this = static_cast<const CDB_TinyInt &>(v).Value(); break;
699 default:
700 DATABASE_DRIVER_ERROR( "wrong type of CDB_Object", 2 );
701 }
702
703 }
704
705
706 /////////////////////////////////////////////////////////////////////////////
707 // CDB_SmallInt::
708 //
709
CDB_SmallInt()710 CDB_SmallInt::CDB_SmallInt() :
711 CDB_Object(true),
712 m_Val(0)
713 {
714 return;
715 }
716
CDB_SmallInt(const Int2 & i)717 CDB_SmallInt::CDB_SmallInt(const Int2& i) :
718 CDB_Object(false),
719 m_Val(i)
720 {
721 return;
722 }
723
~CDB_SmallInt()724 CDB_SmallInt::~CDB_SmallInt()
725 {
726 return;
727 }
728
GetType() const729 EDB_Type CDB_SmallInt::GetType() const
730 {
731 return eDB_SmallInt;
732 }
733
Clone() const734 CDB_Object* CDB_SmallInt::Clone() const
735 {
736 return IsNULL() ? new CDB_SmallInt : new CDB_SmallInt(m_Val);
737 }
738
AssignValue(const CDB_Object & v)739 void CDB_SmallInt::AssignValue(const CDB_Object& v)
740 {
741 switch( v.GetType() ) {
742 case eDB_SmallInt: *this= (const CDB_SmallInt&)v; break;
743 case eDB_TinyInt : *this= ((const CDB_TinyInt &)v).Value(); break;
744 default:
745 DATABASE_DRIVER_ERROR(string("wrong type of CDB_Object: ")
746 + GetTypeName(v.GetType(), false),
747 2);
748 }
749 *this= (CDB_SmallInt&)v;
750 }
751
752 /////////////////////////////////////////////////////////////////////////////
753 // CDB_TinyInt::
754 //
755
CDB_TinyInt()756 CDB_TinyInt::CDB_TinyInt() :
757 CDB_Object(true),
758 m_Val(0)
759 {
760 return;
761 }
762
CDB_TinyInt(const Uint1 & i)763 CDB_TinyInt::CDB_TinyInt(const Uint1& i) :
764 CDB_Object(false),
765 m_Val(i)
766 {
767 return;
768 }
769
~CDB_TinyInt()770 CDB_TinyInt::~CDB_TinyInt()
771 {
772 return;
773 }
774
GetType() const775 EDB_Type CDB_TinyInt::GetType() const
776 {
777 return eDB_TinyInt;
778 }
779
Clone() const780 CDB_Object* CDB_TinyInt::Clone() const
781 {
782 return IsNULL() ? new CDB_TinyInt : new CDB_TinyInt(m_Val);
783 }
784
AssignValue(const CDB_Object & v)785 void CDB_TinyInt::AssignValue(const CDB_Object& v)
786 {
787 CHECK_DRIVER_ERROR(v.GetType() != eDB_TinyInt,
788 string("wrong type of CDB_Object: ")
789 + GetTypeName(v.GetType(), false),
790 2);
791
792 *this= (const CDB_TinyInt&)v;
793 }
794
795
796 /////////////////////////////////////////////////////////////////////////////
797 // CDB_BigInt::
798 //
799
CDB_BigInt()800 CDB_BigInt::CDB_BigInt() :
801 CDB_Object(true),
802 m_Val(0)
803 {
804 return;
805 }
806
CDB_BigInt(const Int8 & i)807 CDB_BigInt::CDB_BigInt(const Int8& i) :
808 CDB_Object(false),
809 m_Val(i)
810 {
811 return;
812 }
813
~CDB_BigInt()814 CDB_BigInt::~CDB_BigInt()
815 {
816 return;
817 }
818
GetType() const819 EDB_Type CDB_BigInt::GetType() const
820 {
821 return eDB_BigInt;
822 }
823
Clone() const824 CDB_Object* CDB_BigInt::Clone() const
825 {
826 return IsNULL() ? new CDB_BigInt : new CDB_BigInt(m_Val);
827 }
828
AssignValue(const CDB_Object & v)829 void CDB_BigInt::AssignValue(const CDB_Object& v)
830 {
831 switch( v.GetType() ) {
832 case eDB_BigInt : *this= (const CDB_BigInt&)v; break;
833 case eDB_Int : *this= ((const CDB_Int &)v).Value(); break;
834 case eDB_SmallInt: *this= ((const CDB_SmallInt&)v).Value(); break;
835 case eDB_TinyInt : *this= ((const CDB_TinyInt &)v).Value(); break;
836 default:
837 DATABASE_DRIVER_ERROR(string("wrong type of CDB_Object: ")
838 + GetTypeName(v.GetType(), false),
839 2);
840 }
841 }
842
843
844 template <typename TChar>
my_strnlen(const TChar * str,size_t maxlen)845 inline size_t my_strnlen(const TChar* str, size_t maxlen)
846 {
847 size_t len = 0;
848 while (len < maxlen && *str != 0) {
849 ++len;
850 ++str;
851 }
852 return len;
853 }
854
855
856 /////////////////////////////////////////////////////////////////////////////
857 inline
MakeString(const string & s,string::size_type size,EEncoding enc=eEncoding_Unknown)858 CRef<CWString> MakeString(const string& s, string::size_type size,
859 EEncoding enc = eEncoding_Unknown)
860 {
861 string value(s, 0, size);
862
863 if (size != string::npos) {
864 value.resize(size, ' ');
865 }
866
867 return CRef<CWString>(new CWString(value, enc));
868 }
869
870 inline
MakeString(const TStringUCS2 & s,TStringUCS2::size_type size,EEncoding enc=eEncoding_Unknown)871 CRef<CWString> MakeString(const TStringUCS2& s, TStringUCS2::size_type size,
872 EEncoding enc = eEncoding_Unknown)
873 {
874 _ASSERT(enc == eEncoding_Unknown);
875 TStringUCS2 value(s, 0, size);
876
877 if (size != TStringUCS2::npos) {
878 value.resize(size, TCharUCS2(' '));
879 }
880
881 s_MakeLittleEndian(value);
882 return CRef<CWString>(new CWString((const char*)value.data(),
883 value.size() * sizeof(TCharUCS2)));
884 }
885
886 template <typename TChar>
887 inline
MakeString(const TChar * s,typename basic_string<TChar>::size_type size,EEncoding enc=eEncoding_Unknown)888 CRef<CWString> MakeString(const TChar* s,
889 typename basic_string<TChar>::size_type size,
890 EEncoding enc = eEncoding_Unknown)
891 {
892 typedef basic_string<TChar> TStr;
893 if (s == NULL) {
894 return MakeString(TStr(), size);
895 }
896
897 TStr str;
898 if (size == TStr::npos)
899 str.assign(s);
900 else {
901 size_t str_size = my_strnlen(s, size);
902 str.assign(s, str_size);
903 }
904 return MakeString(str, size);
905 }
906
907 /////////////////////////////////////////////////////////////////////////////
908 // CDB_String::
909 //
910
CDB_String(void)911 CDB_String::CDB_String(void)
912 : CDB_Object(true), m_BulkInsertionEnc(eBulkEnc_RawBytes)
913 {
914 }
915
916
CDB_String(const CDB_String & other,bool share_data)917 CDB_String::CDB_String(const CDB_String& other, bool share_data)
918 : CDB_Object(other), m_WString(other.m_WString),
919 m_BulkInsertionEnc(other.m_BulkInsertionEnc)
920 {
921 if (other.m_WString.NotEmpty() && !share_data) {
922 m_WString.Reset(new CWString(*other.m_WString));
923 }
924 }
925
926
CDB_String(const string & s,EEncoding enc)927 CDB_String::CDB_String(const string& s, EEncoding enc)
928 : CDB_Object(false), m_WString(new CWString(s, enc)),
929 m_BulkInsertionEnc(eBulkEnc_RawBytes)
930 {
931 }
932
933
CDB_String(const char * s,string::size_type size,EEncoding enc)934 CDB_String::CDB_String(const char* s,
935 string::size_type size,
936 EEncoding enc)
937 : CDB_Object(s == NULL), m_WString(MakeString(s, size, enc)),
938 m_BulkInsertionEnc(eBulkEnc_RawBytes)
939 {
940 }
941
942
CDB_String(const string & s,string::size_type size,EEncoding enc)943 CDB_String::CDB_String(const string& s,
944 string::size_type size,
945 EEncoding enc)
946 : CDB_Object(false), m_WString(MakeString(s, size, enc)),
947 m_BulkInsertionEnc(eBulkEnc_RawBytes)
948 {
949 }
950
951
CDB_String(const TStringUCS2 & s,TStringUCS2::size_type size)952 CDB_String::CDB_String(const TStringUCS2& s, TStringUCS2::size_type size)
953 : CDB_Object(false), m_WString(MakeString(s, size)),
954 m_BulkInsertionEnc(eBulkEnc_RawUCS2)
955 {
956 }
957
958
959 /*
960 CDB_String::CDB_String(const TCharUCS2* s, string::size_type size)
961 : CDB_Object(s == NULL), m_WString(MakeString(s, size)),
962 m_BulkInsertionEnc(eBulkEnc_RawUCS2)
963 {
964 }
965 */
966
967
~CDB_String(void)968 CDB_String::~CDB_String(void)
969 {
970 }
971
972
operator =(const CDB_String & other)973 CDB_String& CDB_String::operator= (const CDB_String& other)
974 {
975 if (this != &other) {
976 Assign(other);
977 }
978
979 return *this;
980 }
981
982
operator =(const string & s)983 CDB_String& CDB_String::operator= (const string& s)
984 {
985 Assign(s);
986 return *this;
987 }
988
989
operator =(const char * s)990 CDB_String& CDB_String::operator= (const char* s)
991 {
992 Assign(s);
993 return *this;
994 }
995
996
operator =(const TStringUCS2 & s)997 CDB_String& CDB_String::operator= (const TStringUCS2& s)
998 {
999 Assign(s);
1000 return *this;
1001 }
1002
1003
operator const char*(void) const1004 CDB_String::operator const char*(void) const
1005 {
1006 return m_WString.Empty() ? kEmptyCStr : m_WString->AsCString();
1007 }
1008
1009
1010 #ifdef HAVE_WSTRING
AsUnicode(EEncoding enc) const1011 const wchar_t* CDB_String::AsUnicode(EEncoding enc) const
1012 {
1013 return IsNULL() ? NULL : m_WString->AsUnicode(enc).c_str();
1014 }
1015 #endif
1016
1017
Assign(const CDB_String & other)1018 void CDB_String::Assign(const CDB_String& other)
1019 {
1020 SetNULL(other.IsNULL());
1021 m_WString.Reset((IsNULL() || other.m_WString.Empty()) ? NULL
1022 : new CWString(*other.m_WString));
1023 m_BulkInsertionEnc = other.m_BulkInsertionEnc;
1024 }
1025
1026
Assign(const char * s,string::size_type size,EEncoding enc)1027 void CDB_String::Assign(const char* s,
1028 string::size_type size,
1029 EEncoding enc)
1030 {
1031 if ( s ) {
1032 SetNULL(false);
1033
1034 if (m_WString.NotEmpty() && size == string::npos) {
1035 m_WString->Assign(string(s), enc);
1036 } else {
1037 m_WString.Reset(MakeString(s, size, enc));
1038 }
1039 } else {
1040 SetNULL();
1041 }
1042 if (m_BulkInsertionEnc == eBulkEnc_RawUCS2) {
1043 m_BulkInsertionEnc = eBulkEnc_UCS2FromChar;
1044 }
1045 }
1046
1047
Assign(const string & s,string::size_type size,EEncoding enc)1048 void CDB_String::Assign(const string& s,
1049 string::size_type size,
1050 EEncoding enc)
1051 {
1052 SetNULL(false);
1053 m_WString.Reset(MakeString(s, size, enc));
1054 if (m_BulkInsertionEnc == eBulkEnc_RawUCS2) {
1055 m_BulkInsertionEnc = eBulkEnc_UCS2FromChar;
1056 }
1057 }
1058
1059
1060 /*
1061 void CDB_String::Assign(const TCharUCS2* s,
1062 TStringUCS2::size_type size)
1063 {
1064 if ( s ) {
1065 SetNULL(false);
1066 m_WString.Reset(MakeString(s, size));
1067 } else {
1068 SetNULL();
1069 }
1070 m_BulkInsertionEnc = eBulkEnc_RawUCS2;
1071 }
1072 */
1073
1074
Assign(const TStringUCS2 & s,TStringUCS2::size_type size)1075 void CDB_String::Assign(const TStringUCS2& s,
1076 TStringUCS2::size_type size)
1077 {
1078 SetNULL(false);
1079 m_WString.Reset(MakeString(s, size));
1080 m_BulkInsertionEnc = eBulkEnc_RawUCS2;
1081 }
1082
1083
GetBulkInsertionData(CTempString * ts,bool convert_raw_bytes) const1084 void CDB_String::GetBulkInsertionData(CTempString* ts, bool convert_raw_bytes)
1085 const
1086 {
1087 _ASSERT(ts);
1088
1089 if (IsNULL() || m_WString.Empty()) {
1090 ts->clear();
1091 return;
1092 }
1093
1094 EBulkEnc enc = m_BulkInsertionEnc;
1095 if (convert_raw_bytes && enc == eBulkEnc_RawBytes) {
1096 enc = eBulkEnc_UCS2FromChar;
1097 }
1098
1099 switch (enc) {
1100 case eBulkEnc_RawBytes:
1101 case eBulkEnc_RawUCS2:
1102 *ts = x_GetWString();
1103 break;
1104 case eBulkEnc_UCS2FromChar:
1105 {
1106 const TStringUCS2& s2 = m_WString->AsUCS2_LE();
1107 ts->assign((char*) s2.data(), s2.size() * sizeof(TCharUCS2));
1108 break;
1109 }
1110 default:
1111 _TROUBLE;
1112 }
1113 }
1114
1115 /////////////////////////////////////////////////////////////////////////////
1116 template <typename TChar>
1117 static
1118 typename basic_string<TChar>::size_type
get_string_size_varchar(const TChar * str,typename basic_string<TChar>::size_type len)1119 get_string_size_varchar(const TChar* str,
1120 typename basic_string<TChar>::size_type len)
1121 {
1122 typedef basic_string<TChar> TStr;
1123
1124 if (len == TStr::npos) {
1125 return len;
1126 } else if (str == NULL) {
1127 return 0;
1128 } else {
1129 return my_strnlen(str, len ? len : TStr::npos);
1130 }
1131 }
1132
1133 /////////////////////////////////////////////////////////////////////////////
1134 // CDB_VarChar::
1135 //
1136
CDB_VarChar(void)1137 CDB_VarChar::CDB_VarChar(void)
1138 {
1139 }
1140
1141
CDB_VarChar(const CDB_VarChar & v,bool share_data)1142 CDB_VarChar::CDB_VarChar(const CDB_VarChar& v, bool share_data)
1143 : CDB_String(v, share_data)
1144 {
1145 }
1146
1147
CDB_VarChar(const string & s,EEncoding enc)1148 CDB_VarChar::CDB_VarChar(const string& s,
1149 EEncoding enc)
1150 : CDB_String(s, enc)
1151 {
1152 }
1153
1154
CDB_VarChar(const char * s,EEncoding enc)1155 CDB_VarChar::CDB_VarChar(const char* s,
1156 EEncoding enc)
1157 : CDB_String(s, string::npos, enc)
1158 {
1159 }
1160
1161
CDB_VarChar(const char * s,size_t l,EEncoding enc)1162 CDB_VarChar::CDB_VarChar(const char* s,
1163 size_t l,
1164 EEncoding enc)
1165 : CDB_String(s, get_string_size_varchar(s, l), enc)
1166 {
1167 }
1168
1169
CDB_VarChar(const TStringUCS2 & s,size_t l)1170 CDB_VarChar::CDB_VarChar(const TStringUCS2& s, size_t l)
1171 : CDB_String(s, get_string_size_varchar(s.data(), l))
1172 {
1173 }
1174
1175
1176 /*
1177 CDB_VarChar::CDB_VarChar(const TCharUCS2* s, size_t l)
1178 : CDB_String(s, get_string_size_varchar(s, l))
1179 {
1180 }
1181 */
1182
1183
~CDB_VarChar(void)1184 CDB_VarChar::~CDB_VarChar(void)
1185 {
1186 }
1187
1188
SetValue(const string & s,EEncoding enc)1189 CDB_VarChar& CDB_VarChar::SetValue(const string& s,
1190 EEncoding enc)
1191 {
1192 Assign(s, string::npos, enc);
1193
1194 return *this;
1195 }
1196
1197
SetValue(const char * s,EEncoding enc)1198 CDB_VarChar& CDB_VarChar::SetValue(const char* s,
1199 EEncoding enc)
1200 {
1201 Assign(s, string::npos, enc);
1202
1203 return *this;
1204 }
1205
1206
SetValue(const char * s,size_t l,EEncoding enc)1207 CDB_VarChar& CDB_VarChar::SetValue(const char* s, size_t l,
1208 EEncoding enc)
1209 {
1210 Assign(s, l, enc);
1211
1212 return *this;
1213 }
1214
1215
SetValue(const TStringUCS2 & s)1216 CDB_VarChar& CDB_VarChar::SetValue(const TStringUCS2& s)
1217 {
1218 Assign(s, TStringUCS2::npos);
1219
1220 return *this;
1221 }
1222
1223
1224 /*
1225 CDB_VarChar& CDB_VarChar::SetValue(const TCharUCS2* s, size_t l)
1226 {
1227 Assign(s, l);
1228
1229 return *this;
1230 }
1231 */
1232
1233
GetType() const1234 EDB_Type CDB_VarChar::GetType() const
1235 {
1236 return eDB_VarChar;
1237 }
1238
1239
Clone() const1240 CDB_Object* CDB_VarChar::Clone() const
1241 {
1242 return IsNULL() ? new CDB_VarChar() : new CDB_VarChar(*this);
1243 }
1244
1245
ShallowClone() const1246 CDB_Object* CDB_VarChar::ShallowClone() const
1247 {
1248 return IsNULL() ? new CDB_VarChar() : new CDB_VarChar(*this, true);
1249 }
1250
1251
AssignValue(const CDB_Object & v)1252 void CDB_VarChar::AssignValue(const CDB_Object& v)
1253 {
1254 CHECK_DRIVER_ERROR(v.GetType() != eDB_VarChar,
1255 string("wrong type of CDB_Object: ")
1256 + GetTypeName(v.GetType(), false),
1257 2);
1258
1259 *this= (const CDB_VarChar&)v;
1260 }
1261
1262
1263 /////////////////////////////////////////////////////////////////////////////
1264 // CDB_Char::
1265 //
1266
1267
CDB_Char(size_t s)1268 CDB_Char::CDB_Char(size_t s)
1269 : m_Size((s < 1) ? 1 : s)
1270 {
1271 }
1272
1273
CDB_Char(size_t s,const string & v,EEncoding enc)1274 CDB_Char::CDB_Char(size_t s,
1275 const string& v,
1276 EEncoding enc) :
1277 CDB_String(v, s, enc),
1278 m_Size(CDB_String::Size())
1279 {
1280 }
1281
1282
CDB_Char(size_t s,const char * str,EEncoding enc)1283 CDB_Char::CDB_Char(size_t s,
1284 const char* str,
1285 EEncoding enc) :
1286 CDB_String(str, s, enc),
1287 m_Size(CDB_String::Size())
1288 {
1289 }
1290
1291
CDB_Char(size_t s,const TStringUCS2 & v)1292 CDB_Char::CDB_Char(size_t s, const TStringUCS2& v)
1293 : CDB_String(v, s), m_Size(CDB_String::Size())
1294 {
1295 }
1296
1297
CDB_Char(const CDB_Char & v,bool share_data)1298 CDB_Char::CDB_Char(const CDB_Char& v, bool share_data) :
1299 CDB_String(v, share_data),
1300 m_Size(v.m_Size)
1301 {
1302 }
1303
1304
operator =(const CDB_Char & v)1305 CDB_Char& CDB_Char::operator= (const CDB_Char& v)
1306 {
1307 if (this != &v) {
1308 m_Size = v.m_Size;
1309 Assign(v);
1310 }
1311
1312 return *this;
1313 }
1314
1315
operator =(const string & s)1316 CDB_Char& CDB_Char::operator= (const string& s)
1317 {
1318 // Encoding of s ???
1319 CheckStringTruncation(s.size(), m_Size);
1320 Assign(s, m_Size);
1321
1322 return *this;
1323 }
1324
1325
operator =(const char * s)1326 CDB_Char& CDB_Char::operator= (const char* s)
1327 {
1328 if (s) {
1329 // Encoding of s ???
1330 size_t len = strlen(s);
1331 CheckStringTruncation(len, m_Size);
1332 Assign(s, m_Size);
1333 }
1334
1335 return *this;
1336 }
1337
1338
operator =(const TStringUCS2 & s)1339 CDB_Char& CDB_Char::operator= (const TStringUCS2& s)
1340 {
1341 CheckStringTruncation(s.size(), m_Size);
1342 Assign(s, m_Size);
1343
1344 return *this;
1345 }
1346
1347
SetValue(const char * str,size_t len,EEncoding enc)1348 void CDB_Char::SetValue(const char* str, size_t len, EEncoding enc)
1349 {
1350 CDB_VarChar vc_value(str, len, enc);
1351 CheckStringTruncation(vc_value.Size(), m_Size);
1352
1353 Assign(vc_value.AsCString(), m_Size, enc);
1354 }
1355
1356
SetValue(const TStringUCS2 & v,size_t len)1357 void CDB_Char::SetValue(const TStringUCS2& v, size_t len)
1358 {
1359 CDB_VarChar vc_value(v, len);
1360 CheckStringTruncation(vc_value.Size(), m_Size);
1361
1362 Assign(vc_value.Data(), m_Size);
1363 }
1364
1365
GetType() const1366 EDB_Type CDB_Char::GetType() const
1367 {
1368 return eDB_Char;
1369 }
1370
Clone() const1371 CDB_Object* CDB_Char::Clone() const
1372 {
1373 return new CDB_Char(*this);
1374 }
1375
ShallowClone() const1376 CDB_Object* CDB_Char::ShallowClone() const
1377 {
1378 return new CDB_Char(*this, true);
1379 }
1380
AssignValue(const CDB_Object & v)1381 void CDB_Char::AssignValue(const CDB_Object& v)
1382 {
1383 CHECK_DRIVER_ERROR(v.GetType() != eDB_Char,
1384 string("wrong type of CDB_Object: ")
1385 + GetTypeName(v.GetType(), false),
1386 2);
1387
1388 const CDB_Char& cv = (const CDB_Char&)v;
1389 *this = cv;
1390 }
1391
~CDB_Char()1392 CDB_Char::~CDB_Char()
1393 {
1394 }
1395
1396 /////////////////////////////////////////////////////////////////////////////
1397 static
1398 string::size_type
get_string_size_longchar(const char * str,string::size_type len)1399 get_string_size_longchar(const char* str, string::size_type len)
1400 {
1401 if (len == string::npos) {
1402 return len;
1403 }
1404
1405 if (str != NULL) {
1406 if (len == 0) {
1407 return strlen(str); // Similar to string::npos ...
1408 } else {
1409 return max(len, my_strnlen(str, len)); // This line is "min(len, str_len)" in case of varchar ...
1410 }
1411 }
1412
1413 return 0;
1414 }
1415
1416 /////////////////////////////////////////////////////////////////////////////
1417 // CDB_LongChar::
1418 //
1419
1420
CDB_LongChar(size_t s)1421 CDB_LongChar::CDB_LongChar(size_t s)
1422 : m_Size((s < 1) ? 1 : s)
1423 {
1424 }
1425
1426
CDB_LongChar(size_t s,const string & v,EEncoding enc)1427 CDB_LongChar::CDB_LongChar(size_t s,
1428 const string& v,
1429 EEncoding enc) :
1430 CDB_String(v, s, enc),
1431 m_Size(CDB_String::Size())
1432 {
1433 }
1434
1435
CDB_LongChar(size_t len,const char * str,EEncoding enc)1436 CDB_LongChar::CDB_LongChar(size_t len,
1437 const char* str,
1438 EEncoding enc) :
1439 CDB_String(str, get_string_size_longchar(str, len), enc),
1440 m_Size(CDB_String::Size())
1441 {
1442 }
1443
1444
CDB_LongChar(size_t s,const TStringUCS2 & v)1445 CDB_LongChar::CDB_LongChar(size_t s,
1446 const TStringUCS2& v)
1447 : CDB_String(v, s), m_Size(CDB_String::Size())
1448 {
1449 }
1450
1451
CDB_LongChar(const CDB_LongChar & v,bool share_data)1452 CDB_LongChar::CDB_LongChar(const CDB_LongChar& v, bool share_data) :
1453 CDB_String(v, share_data),
1454 m_Size(v.m_Size)
1455 {
1456 }
1457
1458
operator =(const CDB_LongChar & v)1459 CDB_LongChar& CDB_LongChar::operator= (const CDB_LongChar& v)
1460 {
1461 if (this != &v) {
1462 m_Size = v.m_Size;
1463 Assign(v);
1464 }
1465
1466 return *this;
1467 }
1468
1469
operator =(const string & s)1470 CDB_LongChar& CDB_LongChar::operator= (const string& s)
1471 {
1472 // Encoding of s ???
1473 CheckStringTruncation(s.size(), m_Size);
1474 Assign(s, m_Size);
1475
1476 return *this;
1477 }
1478
1479
operator =(const char * s)1480 CDB_LongChar& CDB_LongChar::operator= (const char* s)
1481 {
1482 if (s) {
1483 // Encoding of s ???
1484 size_t len = strlen(s);
1485 CheckStringTruncation(len, m_Size);
1486 Assign(s, m_Size);
1487 }
1488
1489 return *this;
1490 }
1491
1492
operator =(const TStringUCS2 & s)1493 CDB_LongChar& CDB_LongChar::operator= (const TStringUCS2& s)
1494 {
1495 CheckStringTruncation(s.size(), m_Size);
1496 Assign(s, m_Size);
1497
1498 return *this;
1499 }
1500
1501
SetValue(const char * str,size_t len,EEncoding enc)1502 void CDB_LongChar::SetValue(const char* str,
1503 size_t len,
1504 EEncoding enc)
1505 {
1506 CDB_VarChar vc(str, len, enc);
1507 CheckStringTruncation(vc.Size(), m_Size);
1508
1509 Assign(vc.AsCString(), m_Size, enc);
1510 }
1511
1512
SetValue(const TStringUCS2 & str,size_t len)1513 void CDB_LongChar::SetValue(const TStringUCS2& str, size_t len)
1514 {
1515 CDB_VarChar vc(str, len);
1516 CheckStringTruncation(vc.Size(), m_Size);
1517
1518 Assign(vc.Data(), m_Size);
1519 }
1520
1521
GetType() const1522 EDB_Type CDB_LongChar::GetType() const
1523 {
1524 return eDB_LongChar;
1525 }
1526
1527
Clone() const1528 CDB_Object* CDB_LongChar::Clone() const
1529 {
1530 return new CDB_LongChar(*this);
1531 }
1532
ShallowClone() const1533 CDB_Object* CDB_LongChar::ShallowClone() const
1534 {
1535 return new CDB_LongChar(*this, true);
1536 }
1537
1538
AssignValue(const CDB_Object & v)1539 void CDB_LongChar::AssignValue(const CDB_Object& v)
1540 {
1541 CHECK_DRIVER_ERROR(v.GetType() != eDB_LongChar,
1542 string("wrong type of CDB_Object: ")
1543 + GetTypeName(v.GetType(), false),
1544 2);
1545
1546 const CDB_LongChar& cv= (const CDB_LongChar&)v;
1547 *this = cv;
1548 }
1549
1550
~CDB_LongChar()1551 CDB_LongChar::~CDB_LongChar()
1552 {
1553 }
1554
1555
1556 /////////////////////////////////////////////////////////////////////////////
1557 // CDB_VarBinary::
1558 //
1559
1560
CDB_VarBinary(void)1561 CDB_VarBinary::CDB_VarBinary(void)
1562 {
1563 }
1564
CDB_VarBinary(const CDB_VarBinary & v,bool share_data)1565 CDB_VarBinary::CDB_VarBinary(const CDB_VarBinary& v, bool share_data)
1566 : CDB_Object(v), m_Value(v.m_Value)
1567 {
1568 if (v.m_Value.NotEmpty() && !share_data) {
1569 m_Value.Reset(new TValue(*v.m_Value));
1570 }
1571 }
1572
CDB_VarBinary(const void * v,size_t l)1573 CDB_VarBinary::CDB_VarBinary(const void* v, size_t l)
1574 {
1575 SetValue(v, l);
1576 }
1577
~CDB_VarBinary(void)1578 CDB_VarBinary::~CDB_VarBinary(void)
1579 {
1580 }
1581
SetValue(const void * v,size_t l)1582 void CDB_VarBinary::SetValue(const void* v, size_t l)
1583 {
1584 if (v != NULL) {
1585 if (m_Value.Empty()) {
1586 m_Value.Reset(new TValue);
1587 }
1588 m_Value->GetData().assign(static_cast<const char*>(v), l);
1589 SetNULL(false);
1590 } else {
1591 m_Value.Reset();
1592 SetNULL();
1593 }
1594 }
1595
1596
operator =(const CDB_VarBinary & v)1597 CDB_VarBinary& CDB_VarBinary::operator= (const CDB_VarBinary& v)
1598 {
1599 if (this != &v) {
1600 SetNULL(v.IsNULL());
1601 m_Value.Reset((IsNULL() || v.m_Value.Empty()) ? NULL
1602 : new TValue(*v.m_Value));
1603 }
1604
1605 return *this;
1606 }
1607
1608
GetType() const1609 EDB_Type CDB_VarBinary::GetType() const
1610 {
1611 return eDB_VarBinary;
1612 }
1613
1614
Clone() const1615 CDB_Object* CDB_VarBinary::Clone() const
1616 {
1617 return IsNULL() ? new CDB_VarBinary : new CDB_VarBinary(*this);
1618 }
1619
ShallowClone() const1620 CDB_Object* CDB_VarBinary::ShallowClone() const
1621 {
1622 return IsNULL() ? new CDB_VarBinary : new CDB_VarBinary(*this, true);
1623 }
1624
1625
AssignValue(const CDB_Object & v)1626 void CDB_VarBinary::AssignValue(const CDB_Object& v)
1627 {
1628 CHECK_DRIVER_ERROR(v.GetType() != eDB_VarBinary,
1629 string("wrong type of CDB_Object: ")
1630 + GetTypeName(v.GetType(), false),
1631 2);
1632
1633 *this= (const CDB_VarBinary&)v;
1634 }
1635
1636 /////////////////////////////////////////////////////////////////////////////
1637 // CDB_Binary::
1638 //
1639
1640
CDB_Binary(size_t s)1641 CDB_Binary::CDB_Binary(size_t s)
1642 {
1643 m_Size = (s < 1) ? 1 : s;
1644 }
1645
1646
CDB_Binary(size_t s,const void * v,size_t v_size)1647 CDB_Binary::CDB_Binary(size_t s, const void* v, size_t v_size)
1648 {
1649 m_Size = (s == 0) ? 1 : s;
1650 SetValue(v, v_size);
1651 }
1652
1653
CDB_Binary(const CDB_Binary & v,bool share_data)1654 CDB_Binary::CDB_Binary(const CDB_Binary& v, bool share_data)
1655 : CDB_Object(v), m_Size(v.m_Size), m_Value(v.m_Value)
1656 {
1657 if (v.m_Value.NotEmpty() && !share_data) {
1658 m_Value.Reset(new TValue(*v.m_Value));
1659 }
1660 }
1661
1662
SetValue(const void * v,size_t v_size)1663 void CDB_Binary::SetValue(const void* v, size_t v_size)
1664 {
1665 if (v != NULL) {
1666 CheckBinaryTruncation(v_size, m_Size);
1667
1668 if (m_Value.Empty()) {
1669 m_Value.Reset(new TValue);
1670 }
1671 m_Value->GetData().assign(static_cast<const char*>(v),
1672 min(v_size, m_Size));
1673 m_Value->GetData().resize(m_Size, '\0');
1674 SetNULL(false);
1675 } else {
1676 m_Value.Reset();
1677 SetNULL();
1678 }
1679 }
1680
1681
operator =(const CDB_Binary & v)1682 CDB_Binary& CDB_Binary::operator= (const CDB_Binary& v)
1683 {
1684 if (this != &v) {
1685 SetNULL(v.IsNULL());
1686 m_Size = v.m_Size;
1687 m_Value.Reset((IsNULL() || v.m_Value.Empty()) ? NULL
1688 : new TValue(*v.m_Value));
1689 }
1690
1691 return *this;
1692 }
1693
1694
GetType() const1695 EDB_Type CDB_Binary::GetType() const
1696 {
1697 return eDB_Binary;
1698 }
1699
1700
Clone() const1701 CDB_Object* CDB_Binary::Clone() const
1702 {
1703 return IsNULL() ? new CDB_Binary(m_Size) : new CDB_Binary(*this);
1704 }
1705
ShallowClone() const1706 CDB_Object* CDB_Binary::ShallowClone() const
1707 {
1708 return IsNULL() ? new CDB_Binary(m_Size) : new CDB_Binary(*this, true);
1709 }
1710
1711
AssignValue(const CDB_Object & v)1712 void CDB_Binary::AssignValue(const CDB_Object& v)
1713 {
1714 CHECK_DRIVER_ERROR(v.GetType() != eDB_Binary,
1715 string("wrong type of CDB_Object: ")
1716 + GetTypeName(v.GetType(), false),
1717 2);
1718
1719 const CDB_Binary& cv = static_cast<const CDB_Binary&>(v);
1720 *this = cv;
1721 }
1722
1723
~CDB_Binary()1724 CDB_Binary::~CDB_Binary()
1725 {
1726 }
1727
1728 /////////////////////////////////////////////////////////////////////////////
1729 // CDB_LongBinary::
1730 //
1731
1732
CDB_LongBinary(size_t s)1733 CDB_LongBinary::CDB_LongBinary(size_t s)
1734 : m_Size((s < 1) ? 1 : s)
1735 , m_DataSize(0)
1736 {
1737 }
1738
1739
CDB_LongBinary(size_t s,const void * v,size_t v_size)1740 CDB_LongBinary::CDB_LongBinary(size_t s, const void* v, size_t v_size)
1741 : m_Size(s)
1742 {
1743 SetValue(v, v_size);
1744 }
1745
1746
CDB_LongBinary(const CDB_LongBinary & v,bool share_data)1747 CDB_LongBinary::CDB_LongBinary(const CDB_LongBinary& v, bool share_data)
1748 : CDB_Object(v)
1749 , m_Size(v.m_Size)
1750 , m_DataSize(v.m_DataSize)
1751 , m_Value(v.m_Value)
1752 {
1753 if (v.m_Value.NotEmpty() && !share_data) {
1754 m_Value.Reset(new TValue(*v.m_Value));
1755 }
1756 }
1757
1758
SetValue(const void * v,size_t v_size)1759 void CDB_LongBinary::SetValue(const void* v, size_t v_size)
1760 {
1761 if (v != NULL) {
1762 m_DataSize = min(v_size, m_Size);
1763 CheckBinaryTruncation(v_size, m_Size);
1764 if (m_Value.Empty()) {
1765 m_Value.Reset(new TValue);
1766 }
1767 m_Value->GetData().assign(static_cast<const char*>(v), m_DataSize);
1768 m_Value->GetData().resize(m_Size, '\0');
1769 SetNULL(false);
1770 } else {
1771 m_Value.Reset();
1772 SetNULL();
1773 m_DataSize = 0;
1774 }
1775 }
1776
1777
operator =(const CDB_LongBinary & v)1778 CDB_LongBinary& CDB_LongBinary::operator= (const CDB_LongBinary& v)
1779 {
1780 if (this != &v) {
1781 SetNULL(v.IsNULL());
1782 m_Size = v.m_Size;
1783 m_DataSize = v.m_DataSize;
1784 m_Value = v.m_Value;
1785 m_Value.Reset((IsNULL() || v.m_Value.Empty()) ? NULL
1786 : new TValue(*v.m_Value));
1787 }
1788
1789 return *this;
1790 }
1791
1792
GetType() const1793 EDB_Type CDB_LongBinary::GetType() const
1794 {
1795 return eDB_LongBinary;
1796 }
1797
1798
Clone() const1799 CDB_Object* CDB_LongBinary::Clone() const
1800 {
1801 return new CDB_LongBinary(*this);
1802 }
1803
ShallowClone() const1804 CDB_Object* CDB_LongBinary::ShallowClone() const
1805 {
1806 return new CDB_LongBinary(*this, true);
1807 }
1808
1809
AssignValue(const CDB_Object & v)1810 void CDB_LongBinary::AssignValue(const CDB_Object& v)
1811 {
1812 CHECK_DRIVER_ERROR(
1813 v.GetType() != eDB_LongBinary,
1814 string("wrong type of CDB_Object: ") + GetTypeName(v.GetType(), false),
1815 2 );
1816
1817 const CDB_LongBinary& cv = static_cast<const CDB_LongBinary&>(v);
1818 *this = cv;
1819 }
1820
1821
~CDB_LongBinary()1822 CDB_LongBinary::~CDB_LongBinary()
1823 {
1824 }
1825
1826
1827 /////////////////////////////////////////////////////////////////////////////
1828 // CDB_Float::
1829 //
1830
1831
CDB_Float()1832 CDB_Float::CDB_Float() :
1833 CDB_Object(true),
1834 m_Val(0.0)
1835 {
1836 return;
1837 }
1838
CDB_Float(float i)1839 CDB_Float::CDB_Float(float i) :
1840 CDB_Object(false),
1841 m_Val(i)
1842 {
1843 return;
1844 }
1845
~CDB_Float(void)1846 CDB_Float::~CDB_Float(void)
1847 {
1848 }
1849
1850
operator =(const float & i)1851 CDB_Float& CDB_Float::operator= (const float& i)
1852 {
1853 SetNULL(false);
1854 m_Val = i;
1855 return *this;
1856 }
1857
1858
GetType() const1859 EDB_Type CDB_Float::GetType() const
1860 {
1861 return eDB_Float;
1862 }
1863
Clone() const1864 CDB_Object* CDB_Float::Clone() const
1865 {
1866 return IsNULL() ? new CDB_Float : new CDB_Float(m_Val);
1867 }
1868
AssignValue(const CDB_Object & v)1869 void CDB_Float::AssignValue(const CDB_Object& v)
1870 {
1871 switch( v.GetType() ) {
1872 case eDB_Float : *this = (const CDB_Float&)v; break;
1873 case eDB_SmallInt: *this = ((const CDB_SmallInt&)v).Value(); break;
1874 case eDB_TinyInt : *this = ((const CDB_TinyInt &)v).Value(); break;
1875 default:
1876 DATABASE_DRIVER_ERROR(string("wrong type of CDB_Object: ")
1877 + GetTypeName(v.GetType(), false),
1878 2);
1879 }
1880 }
1881
1882 /////////////////////////////////////////////////////////////////////////////
1883 // CDB_Double::
1884 //
1885
1886
CDB_Double()1887 CDB_Double::CDB_Double() :
1888 CDB_Object(true),
1889 m_Val(0.0)
1890 {
1891 return;
1892 }
1893
CDB_Double(double i)1894 CDB_Double::CDB_Double(double i) :
1895 CDB_Object(false),
1896 m_Val(i)
1897 {
1898 return;
1899 }
1900
~CDB_Double(void)1901 CDB_Double::~CDB_Double(void)
1902 {
1903 }
1904
operator =(const double & i)1905 CDB_Double& CDB_Double::operator= (const double& i)
1906 {
1907 SetNULL(false);
1908 m_Val = i;
1909 return *this;
1910 }
1911
GetType() const1912 EDB_Type CDB_Double::GetType() const
1913 {
1914 return eDB_Double;
1915 }
1916
Clone() const1917 CDB_Object* CDB_Double::Clone() const
1918 {
1919 return IsNULL() ? new CDB_Double : new CDB_Double(m_Val);
1920 }
1921
AssignValue(const CDB_Object & v)1922 void CDB_Double::AssignValue(const CDB_Object& v)
1923 {
1924 switch( v.GetType() ) {
1925 case eDB_Double : *this = (const CDB_Double&)v; break;
1926 case eDB_Float : *this = ((const CDB_Float &)v).Value(); break;
1927 case eDB_Int : *this = ((const CDB_Int &)v).Value(); break;
1928 case eDB_SmallInt: *this = ((const CDB_SmallInt&)v).Value(); break;
1929 case eDB_TinyInt : *this = ((const CDB_TinyInt &)v).Value(); break;
1930 default:
1931 DATABASE_DRIVER_ERROR(string("wrong type of CDB_Object: ")
1932 + GetTypeName(v.GetType(), false),
1933 2);
1934 }
1935 }
1936
1937 /////////////////////////////////////////////////////////////////////////////
1938 // CDB_Stream::
1939 //
1940
CDB_Stream()1941 CDB_Stream::CDB_Stream()
1942 : CDB_Object(true), m_Encoding(eBulkEnc_RawBytes)
1943
1944 {
1945 m_Store = new CMemStore;
1946 m_Store->AddReference();
1947 }
1948
CDB_Stream(const CDB_Stream & s,bool share_data)1949 CDB_Stream::CDB_Stream(const CDB_Stream& s, bool share_data)
1950 : CDB_Object(s), m_Encoding(s.m_Encoding), m_Store(s.m_Store)
1951 {
1952 if (share_data) {
1953 m_Store->AddReference();
1954 } else {
1955 m_Store = new CMemStore;
1956 m_Store->AddReference();
1957 Assign(s);
1958 }
1959 }
1960
Assign(const CDB_Stream & v)1961 CDB_Stream& CDB_Stream::Assign(const CDB_Stream& v)
1962 {
1963 SetNULL(v.IsNULL());
1964 m_Store->Truncate();
1965 m_Encoding = v.m_Encoding;
1966 if ( !IsNULL() ) {
1967 char buff[1024];
1968 CMemStore* s = const_cast<CMemStore*>(&*v.m_Store);
1969 size_t pos = s->Tell();
1970 s->Seek(0L, C_RA_Storage::eHead);
1971 for (size_t n = s->Read((void*) buff, sizeof(buff));
1972 n > 0;
1973 n = s->Read((void*) buff, sizeof(buff))) {
1974 Append((void*) buff, n);
1975 }
1976 s->Seek((long) pos, C_RA_Storage::eHead);
1977 }
1978 return *this;
1979 }
1980
AssignNULL()1981 void CDB_Stream::AssignNULL()
1982 {
1983 CDB_Object::AssignNULL();
1984 Truncate();
1985 }
1986
Read(void * buff,size_t nof_bytes)1987 size_t CDB_Stream::Read(void* buff, size_t nof_bytes)
1988 {
1989 return m_Store->Read(buff, nof_bytes);
1990 }
1991
Peek(void * buff,size_t nof_bytes) const1992 size_t CDB_Stream::Peek(void* buff, size_t nof_bytes) const
1993 {
1994 return m_Store->Peek(buff, nof_bytes);
1995 }
1996
PeekAt(void * buff,size_t start,size_t nof_bytes) const1997 size_t CDB_Stream::PeekAt(void* buff, size_t start, size_t nof_bytes) const
1998 {
1999 return m_Store->PeekAt(buff, start, nof_bytes);
2000 }
2001
Append(const void * buff,size_t nof_bytes)2002 size_t CDB_Stream::Append(const void* buff, size_t nof_bytes)
2003 {
2004 /* if (buff && (nof_bytes > 0)) */ SetNULL(false);
2005 return m_Store->Append(buff, nof_bytes);
2006 }
2007
MoveTo(size_t byte_number)2008 bool CDB_Stream::MoveTo(size_t byte_number)
2009 {
2010 return m_Store->Seek((long) byte_number, C_RA_Storage::eHead)
2011 == (long) byte_number;
2012 }
2013
Size() const2014 size_t CDB_Stream::Size() const
2015 {
2016 return m_Store->GetDataSize();
2017 }
2018
Truncate(size_t nof_bytes)2019 void CDB_Stream::Truncate(size_t nof_bytes)
2020 {
2021 m_Store->Truncate(nof_bytes);
2022 SetNULL(m_Store->GetDataSize() <= 0);
2023 }
2024
AssignValue(const CDB_Object & v)2025 void CDB_Stream::AssignValue(const CDB_Object& v)
2026 {
2027 CHECK_DRIVER_ERROR( !IsBlobType(v.GetType()),
2028 string("wrong type of CDB_Object: ") + GetTypeName(v.GetType(), false),
2029 2
2030 );
2031 Assign(static_cast<const CDB_Stream&>(v));
2032 }
2033
~CDB_Stream()2034 CDB_Stream::~CDB_Stream()
2035 {
2036 try {
2037 m_Store->RemoveReference();
2038 }
2039 NCBI_CATCH_ALL_X( 7, NCBI_CURRENT_FUNCTION )
2040 }
2041
x_SetEncoding(EBulkEnc e)2042 void CDB_Stream::x_SetEncoding(EBulkEnc e)
2043 {
2044 if (e == eBulkEnc_UCS2FromChar) {
2045 e = eBulkEnc_RawUCS2;
2046 }
2047 if (e != m_Encoding && Size() > 0) {
2048 // Alternatively, arrange to recode existing text?
2049 ERR_POST_X(8, string("Creating a mixed-encoding C")
2050 + GetTypeName(GetType()) + " object.");
2051 }
2052 m_Encoding = e;
2053 }
2054
x_Append(const void * buff,size_t nof_bytes)2055 size_t CDB_Stream::x_Append(const void* buff, size_t nof_bytes)
2056 {
2057 if (buff == NULL) {
2058 // return 0;
2059 buff = kEmptyCStr;
2060 }
2061 // Warn if nof_bytes == 0?
2062 return CDB_Stream::Append
2063 (buff, nof_bytes ? nof_bytes : strlen((const char*) buff));
2064 }
2065
x_Append(const CTempString & s,EEncoding enc)2066 size_t CDB_Stream::x_Append(const CTempString& s, EEncoding enc)
2067 {
2068 switch (m_Encoding) {
2069 case eBulkEnc_RawBytes:
2070 return Append(s.data(), s.size());
2071 case eBulkEnc_RawUCS2:
2072 {
2073 TStringUCS2 s2 = CUtf8::AsBasicString<TCharUCS2>
2074 (CUtf8::AsUTF8(s, enc));
2075 s_MakeLittleEndian(s2);
2076 return Append(s2.data(), s2.size() * sizeof(TCharUCS2));
2077 }
2078 default:
2079 _TROUBLE;
2080 return 0;
2081 }
2082 }
2083
x_Append(const TStringUCS2 & s,size_t l)2084 size_t CDB_Stream::x_Append(const TStringUCS2& s, size_t l)
2085 {
2086 x_SetEncoding(eBulkEnc_RawUCS2);
2087 #ifdef WORDS_BIGENDIAN
2088 if (l == TStringUCS2::npos) {
2089 l = s.size();
2090 }
2091 TStringUCS2 s2(s, l);
2092 s_MakeLittleEndian(s2);
2093 return Append(s2.data(), s2.size() * sizeof(TCharUCS2));
2094 #else
2095 return Append(s.data(), s.size() * sizeof(TCharUCS2));
2096 #endif
2097 }
2098
2099 /////////////////////////////////////////////////////////////////////////////
2100 // CDB_Image::
2101 //
2102
CDB_Image(void)2103 CDB_Image::CDB_Image(void)
2104 {
2105 }
2106
CDB_Image(const CDB_Image & image,bool share_data)2107 CDB_Image::CDB_Image(const CDB_Image& image, bool share_data)
2108 : CDB_Stream(image, share_data)
2109 {
2110 }
2111
~CDB_Image(void)2112 CDB_Image::~CDB_Image(void)
2113 {
2114 }
2115
operator =(const CDB_Image & image)2116 CDB_Image& CDB_Image::operator= (const CDB_Image& image)
2117 {
2118 return dynamic_cast<CDB_Image&> (Assign(image));
2119 }
2120
GetType() const2121 EDB_Type CDB_Image::GetType() const
2122 {
2123 return eDB_Image;
2124 }
2125
Clone() const2126 CDB_Object* CDB_Image::Clone() const
2127 {
2128 return new CDB_Image(*this);
2129 }
2130
ShallowClone() const2131 CDB_Object* CDB_Image::ShallowClone() const
2132 {
2133 return new CDB_Image(*this, true);
2134 }
2135
2136
2137 /////////////////////////////////////////////////////////////////////////////
2138 // CDB_VarBinaryMax::
2139 //
2140
CDB_VarBinaryMax(void)2141 CDB_VarBinaryMax::CDB_VarBinaryMax(void)
2142 {
2143 }
2144
CDB_VarBinaryMax(const CDB_VarBinaryMax & v,bool share_data)2145 CDB_VarBinaryMax::CDB_VarBinaryMax(const CDB_VarBinaryMax& v, bool share_data)
2146 : CDB_Stream(v, share_data)
2147 {
2148 }
2149
CDB_VarBinaryMax(const void * v,size_t l)2150 CDB_VarBinaryMax::CDB_VarBinaryMax(const void* v, size_t l)
2151 {
2152 Append(v, l);
2153 }
2154
~CDB_VarBinaryMax(void)2155 CDB_VarBinaryMax::~CDB_VarBinaryMax(void)
2156 {
2157 }
2158
operator =(const CDB_VarBinaryMax & v)2159 CDB_VarBinaryMax& CDB_VarBinaryMax::operator= (const CDB_VarBinaryMax& v)
2160 {
2161 return dynamic_cast<CDB_VarBinaryMax&>(Assign(v));
2162 }
2163
GetType() const2164 EDB_Type CDB_VarBinaryMax::GetType() const
2165 {
2166 return eDB_VarBinaryMax;
2167 }
2168
Clone() const2169 CDB_Object* CDB_VarBinaryMax::Clone() const
2170 {
2171 return new CDB_VarBinaryMax(*this);
2172 }
2173
ShallowClone() const2174 CDB_Object* CDB_VarBinaryMax::ShallowClone() const
2175 {
2176 return new CDB_VarBinaryMax(*this, true);
2177 }
2178
2179
2180 /////////////////////////////////////////////////////////////////////////////
2181 // CDB_Text::
2182 //
2183
CDB_Text(void)2184 CDB_Text::CDB_Text(void)
2185 {
2186 }
2187
CDB_Text(const CDB_Text & text,bool share_data)2188 CDB_Text::CDB_Text(const CDB_Text& text, bool share_data)
2189 : CDB_Stream(text, share_data)
2190 {
2191 }
2192
~CDB_Text(void)2193 CDB_Text::~CDB_Text(void)
2194 {
2195 }
2196
SetEncoding(EBulkEnc e)2197 void CDB_Text::SetEncoding(EBulkEnc e)
2198 {
2199 x_SetEncoding(e);
2200 }
2201
Append(const void * buff,size_t nof_bytes)2202 size_t CDB_Text::Append(const void* buff, size_t nof_bytes)
2203 {
2204 return x_Append(buff, nof_bytes);
2205 }
2206
Append(const CTempString & s,EEncoding enc)2207 size_t CDB_Text::Append(const CTempString& s, EEncoding enc)
2208 {
2209 return x_Append(s, enc);
2210 }
2211
2212
Append(const TStringUCS2 & s)2213 size_t CDB_Text::Append(const TStringUCS2& s)
2214 {
2215 return x_Append(s);
2216 }
2217
operator =(const CDB_Text & text)2218 CDB_Text& CDB_Text::operator= (const CDB_Text& text)
2219 {
2220 m_Encoding = text.m_Encoding;
2221 return dynamic_cast<CDB_Text&> (Assign(text));
2222 }
2223
GetType() const2224 EDB_Type CDB_Text::GetType() const
2225 {
2226 return eDB_Text;
2227 }
2228
Clone() const2229 CDB_Object* CDB_Text::Clone() const
2230 {
2231 return new CDB_Text(*this);
2232 }
2233
ShallowClone() const2234 CDB_Object* CDB_Text::ShallowClone() const
2235 {
2236 return new CDB_Text(*this, true);
2237 }
2238
2239
2240 /////////////////////////////////////////////////////////////////////////////
2241 // CDB_VarCharMax::
2242 //
2243
CDB_VarCharMax(void)2244 CDB_VarCharMax::CDB_VarCharMax(void)
2245 {
2246 }
2247
CDB_VarCharMax(const CDB_VarCharMax & v,bool share_data)2248 CDB_VarCharMax::CDB_VarCharMax(const CDB_VarCharMax& v, bool share_data)
2249 : CDB_Stream(v, share_data)
2250 {
2251 }
2252
CDB_VarCharMax(const string & s,EEncoding enc)2253 CDB_VarCharMax::CDB_VarCharMax(const string& s, EEncoding enc)
2254 {
2255 SetValue(s, enc);
2256 }
2257
CDB_VarCharMax(const char * s,EEncoding enc)2258 CDB_VarCharMax::CDB_VarCharMax(const char* s, EEncoding enc)
2259 {
2260 SetValue(s, enc);
2261 }
2262
CDB_VarCharMax(const char * s,size_t l,EEncoding enc)2263 CDB_VarCharMax::CDB_VarCharMax(const char* s, size_t l, EEncoding enc)
2264 {
2265 SetValue(s, l, enc);
2266 }
2267
CDB_VarCharMax(const TStringUCS2 & s,size_t l)2268 CDB_VarCharMax::CDB_VarCharMax(const TStringUCS2& s, size_t l)
2269 {
2270 SetValue(s);
2271 }
2272
~CDB_VarCharMax(void)2273 CDB_VarCharMax::~CDB_VarCharMax(void)
2274 {
2275 }
2276
SetEncoding(EBulkEnc e)2277 void CDB_VarCharMax::SetEncoding(EBulkEnc e)
2278 {
2279 x_SetEncoding(e);
2280 }
2281
Append(const void * buff,size_t nof_bytes)2282 size_t CDB_VarCharMax::Append(const void* buff, size_t nof_bytes)
2283 {
2284 return x_Append(buff, nof_bytes);
2285 }
2286
Append(const CTempString & s,EEncoding enc)2287 size_t CDB_VarCharMax::Append(const CTempString& s, EEncoding enc)
2288 {
2289 return x_Append(s, enc);
2290 }
2291
Append(const TStringUCS2 & s,size_t l)2292 size_t CDB_VarCharMax::Append(const TStringUCS2& s, size_t l)
2293 {
2294 return x_Append(s);
2295 }
2296
operator =(const CDB_VarCharMax & v)2297 CDB_VarCharMax& CDB_VarCharMax::operator= (const CDB_VarCharMax& v)
2298 {
2299 m_Encoding = v.m_Encoding;
2300 return dynamic_cast<CDB_VarCharMax&>(Assign(v));
2301 }
2302
GetType() const2303 EDB_Type CDB_VarCharMax::GetType() const
2304 {
2305 return eDB_VarCharMax;
2306 }
2307
Clone() const2308 CDB_Object* CDB_VarCharMax::Clone() const
2309 {
2310 return new CDB_VarCharMax(*this);
2311 }
2312
ShallowClone() const2313 CDB_Object* CDB_VarCharMax::ShallowClone() const
2314 {
2315 return new CDB_VarCharMax(*this, true);
2316 }
2317
2318
2319
2320 /////////////////////////////////////////////////////////////////////////////
2321 // CDB_SmallDateTime::
2322 //
2323
2324
CDB_SmallDateTime(CTime::EInitMode mode)2325 CDB_SmallDateTime::CDB_SmallDateTime(CTime::EInitMode mode)
2326 : m_NCBITime(mode)
2327 , m_Status( 0x1 )
2328 {
2329 m_DBTime.days = 0;
2330 m_DBTime.time = 0;
2331 SetNULL(mode == CTime::eEmpty);
2332 }
2333
2334
CDB_SmallDateTime(const CTime & t)2335 CDB_SmallDateTime::CDB_SmallDateTime(const CTime& t)
2336 : m_NCBITime( t )
2337 , m_Status( 0x1 )
2338 {
2339 m_DBTime.days = 0;
2340 m_DBTime.time = 0;
2341 SetNULL(t.IsEmpty());
2342 }
2343
2344
CDB_SmallDateTime(Uint2 days,Uint2 minutes)2345 CDB_SmallDateTime::CDB_SmallDateTime(Uint2 days, Uint2 minutes)
2346 : m_Status( 0x2 )
2347 {
2348 m_DBTime.days = days;
2349 m_DBTime.time = minutes;
2350 SetNULL(false);
2351 }
2352
2353
~CDB_SmallDateTime(void)2354 CDB_SmallDateTime::~CDB_SmallDateTime(void)
2355 {
2356 }
2357
Assign(Uint2 days,Uint2 minutes)2358 CDB_SmallDateTime& CDB_SmallDateTime::Assign(Uint2 days, Uint2 minutes)
2359 {
2360 m_DBTime.days = days;
2361 m_DBTime.time = minutes;
2362 m_Status = 0x2;
2363 SetNULL(false);
2364
2365 return *this;
2366 }
2367
2368
operator =(const CTime & t)2369 CDB_SmallDateTime& CDB_SmallDateTime::operator= (const CTime& t)
2370 {
2371 m_NCBITime = t;
2372 m_DBTime.days = 0;
2373 m_DBTime.time = 0;
2374 m_Status = 0x1;
2375 SetNULL(t.IsEmpty());
2376
2377 return *this;
2378 }
2379
2380
Value(void) const2381 const CTime& CDB_SmallDateTime::Value(void) const
2382 {
2383 if((m_Status & 0x1) == 0) {
2384 m_NCBITime.SetTimeDBU(m_DBTime);
2385 m_Status |= 0x1;
2386 }
2387 return m_NCBITime;
2388 }
2389
2390
GetDays(void) const2391 Uint2 CDB_SmallDateTime::GetDays(void) const
2392 {
2393 if((m_Status & 0x2) == 0) {
2394 m_DBTime = m_NCBITime.GetTimeDBU();
2395 m_Status |= 0x2;
2396 }
2397 return m_DBTime.days;
2398 }
2399
2400
GetMinutes(void) const2401 Uint2 CDB_SmallDateTime::GetMinutes(void) const
2402 {
2403 if((m_Status & 0x2) == 0) {
2404 m_DBTime = m_NCBITime.GetTimeDBU();
2405 m_Status |= 0x2;
2406 }
2407 return m_DBTime.time;
2408 }
2409
2410
GetType() const2411 EDB_Type CDB_SmallDateTime::GetType() const
2412 {
2413 return eDB_SmallDateTime;
2414 }
2415
Clone() const2416 CDB_Object* CDB_SmallDateTime::Clone() const
2417 {
2418 return IsNULL() ? new CDB_SmallDateTime : new CDB_SmallDateTime(Value());
2419 }
2420
AssignValue(const CDB_Object & v)2421 void CDB_SmallDateTime::AssignValue(const CDB_Object& v)
2422 {
2423 CHECK_DRIVER_ERROR(
2424 v.GetType() != eDB_SmallDateTime,
2425 string("wrong type of CDB_Object: ") + GetTypeName(v.GetType(), false),
2426 2 );
2427 *this= (const CDB_SmallDateTime&)v;
2428 }
2429
2430
2431 /////////////////////////////////////////////////////////////////////////////
2432 // CDB_DateTime::
2433 //
2434
2435
CDB_DateTime(CTime::EInitMode mode)2436 CDB_DateTime::CDB_DateTime(CTime::EInitMode mode)
2437 : m_NCBITime(mode)
2438 , m_Status(0x1)
2439 {
2440 m_DBTime.days = 0;
2441 m_DBTime.time = 0;
2442 SetNULL(mode == CTime::eEmpty);
2443 }
2444
2445
CDB_DateTime(const CTime & t)2446 CDB_DateTime::CDB_DateTime(const CTime& t)
2447 : m_NCBITime( t )
2448 , m_Status( 0x1 )
2449 {
2450 m_DBTime.days = 0;
2451 m_DBTime.time = 0;
2452 SetNULL(t.IsEmpty());
2453 }
2454
2455
CDB_DateTime(Int4 d,Int4 s300)2456 CDB_DateTime::CDB_DateTime(Int4 d, Int4 s300)
2457 : m_Status( 0x2 )
2458 {
2459 m_DBTime.days = d;
2460 m_DBTime.time = s300;
2461 SetNULL(false);
2462 }
2463
2464
~CDB_DateTime(void)2465 CDB_DateTime::~CDB_DateTime(void)
2466 {
2467 }
2468
2469
operator =(const CTime & t)2470 CDB_DateTime& CDB_DateTime::operator= (const CTime& t)
2471 {
2472 m_NCBITime = t;
2473 m_DBTime.days = 0;
2474 m_DBTime.time = 0;
2475 m_Status = 0x1;
2476 SetNULL(t.IsEmpty());
2477 return *this;
2478 }
2479
2480
Assign(Int4 d,Int4 s300)2481 CDB_DateTime& CDB_DateTime::Assign(Int4 d, Int4 s300)
2482 {
2483 m_DBTime.days = d;
2484 m_DBTime.time = s300;
2485 m_Status = 0x2;
2486 SetNULL(false);
2487 return *this;
2488 }
2489
2490
Value(void) const2491 const CTime& CDB_DateTime::Value(void) const
2492 {
2493 if((m_Status & 0x1) == 0) {
2494 m_NCBITime.SetTimeDBI(m_DBTime);
2495 m_Status |= 0x1;
2496 }
2497 return m_NCBITime;
2498 }
2499
2500
GetDays(void) const2501 Int4 CDB_DateTime::GetDays(void) const
2502 {
2503 if((m_Status & 0x2) == 0) {
2504 m_DBTime = m_NCBITime.GetTimeDBI();
2505 m_Status |= 0x2;
2506 }
2507 return m_DBTime.days;
2508 }
2509
2510
Get300Secs(void) const2511 Int4 CDB_DateTime::Get300Secs(void) const
2512 {
2513 if((m_Status & 0x2) == 0) {
2514 m_DBTime = m_NCBITime.GetTimeDBI();
2515 m_Status |= 0x2;
2516 }
2517 return m_DBTime.time;
2518 }
2519
2520
GetType() const2521 EDB_Type CDB_DateTime::GetType() const
2522 {
2523 return eDB_DateTime;
2524 }
2525
Clone() const2526 CDB_Object* CDB_DateTime::Clone() const
2527 {
2528 return IsNULL() ? new CDB_DateTime : new CDB_DateTime(Value());
2529 }
2530
AssignValue(const CDB_Object & v)2531 void CDB_DateTime::AssignValue(const CDB_Object& v)
2532 {
2533 CHECK_DRIVER_ERROR(
2534 v.GetType() != eDB_DateTime,
2535 string("wrong type of CDB_Object: ") + GetTypeName(v.GetType(), false),
2536 2 );
2537 *this= (const CDB_DateTime&)v;
2538 }
2539
2540
2541 /////////////////////////////////////////////////////////////////////////////
2542 // CDB_BigDateTime::
2543 //
2544
2545
CDB_BigDateTime(CTime::EInitMode mode,ESQLType sql_type)2546 CDB_BigDateTime::CDB_BigDateTime(CTime::EInitMode mode, ESQLType sql_type)
2547 : m_Time(mode), m_SQLType(sql_type)
2548 {
2549 SetNULL(mode == CTime::eEmpty);
2550 }
2551
2552
CDB_BigDateTime(const CTime & t,ESQLType sql_type)2553 CDB_BigDateTime::CDB_BigDateTime(const CTime& t, ESQLType sql_type)
2554 : m_Time(t), m_SQLType(sql_type)
2555 {
2556 SetNULL(t.IsEmpty());
2557 }
2558
2559
Assign(const CTime & t,ESQLType sql_type)2560 CDB_BigDateTime& CDB_BigDateTime::Assign(const CTime& t, ESQLType sql_type)
2561 {
2562 m_Time = t;
2563 m_SQLType = sql_type;
2564 SetNULL(t.IsEmpty());
2565 return *this;
2566 }
2567
GetSQLTypeName(ESyntax syntax)2568 const char * CDB_BigDateTime::GetSQLTypeName(ESyntax syntax)
2569 {
2570 switch (syntax) {
2571 case eSyntax_Unknown:
2572 break;
2573 case eSyntax_Microsoft:
2574 switch (m_SQLType) {
2575 case eDate: return "DATE";
2576 case eTime: return "TIME";
2577 case eDateTime: return "DATETIME2";
2578 case eDateTimeOffset: return "DATETIMEOFFSET";
2579 }
2580 case eSyntax_Sybase:
2581 switch (m_SQLType) {
2582 case eDate: return "BIGDATE";
2583 case eTime: return "BIGTIME";
2584 case eDateTime: return "BIGDATETIME";
2585 case eDateTimeOffset: break;
2586 }
2587 }
2588 return kEmptyCStr;
2589 }
2590
GetType() const2591 EDB_Type CDB_BigDateTime::GetType() const
2592 {
2593 return eDB_BigDateTime;
2594 }
2595
Clone() const2596 CDB_Object* CDB_BigDateTime::Clone() const
2597 {
2598 return IsNULL() ? new CDB_BigDateTime : new CDB_BigDateTime(*this);
2599 }
2600
AssignValue(const CDB_Object & v)2601 void CDB_BigDateTime::AssignValue(const CDB_Object& v)
2602 {
2603 switch (v.GetType()) {
2604 case eDB_BigDateTime: *this = (const CDB_BigDateTime&) v; break;
2605 case eDB_DateTime : *this = ((const CDB_DateTime&)v).Value(); break;
2606 case eDB_VarChar :
2607 {
2608 const string& s = (const CDB_VarChar&) v;
2609 pair<ESyntax, ESQLType> id = Identify(s);
2610 Assign(CTime(s, GetTimeFormat(id.first, id.second)), id.second);
2611 break;
2612 }
2613 default:
2614 DATABASE_DRIVER_ERROR(string("wrong type of CDB_Object: ")
2615 + GetTypeName(v.GetType(), false), 2);
2616 }
2617 }
2618
GetTimeFormat(ESyntax syntax,ESQLType sql_type)2619 CTimeFormat CDB_BigDateTime::GetTimeFormat(ESyntax syntax, ESQLType sql_type)
2620 {
2621 const char* s = kEmptyCStr;
2622 switch (syntax) {
2623 case eSyntax_Unknown: // go with ISO
2624 switch (sql_type) {
2625 case eDate: s = "Y-M-D" ; break;
2626 case eTime: s = "h:m:G" ; break;
2627 case eDateTime: s = "Y-M-DTh:m:G" ; break;
2628 case eDateTimeOffset: s = "Y-M-DTh:m:Go"; break;
2629 }
2630 break;
2631 case eSyntax_Microsoft:
2632 switch (sql_type) {
2633 case eDate: s = "Y-M-D" ; break;
2634 case eTime: s = "h:m:G" ; break;
2635 case eDateTime: s = "Y-M-D h:m:G" ; break;
2636 case eDateTimeOffset: s = "Y-M-D h:m:Go"; break;
2637 }
2638 break;
2639 case eSyntax_Sybase: // cap time precision to avoid syntax errors(!)
2640 switch (sql_type) {
2641 case eDate: s = "b D Y" ; break;
2642 case eTime: s = "H:m:s.rP" ; break;
2643 case eDateTime: s = "b D Y H:m:s.rP" ; break;
2644 case eDateTimeOffset: s = "b D Y H:m:s.rPo"; break;
2645 }
2646 break;
2647 }
2648 return CTimeFormat(s);
2649 }
2650
2651 pair<CDB_BigDateTime::ESyntax, CDB_BigDateTime::ESQLType>
Identify(const CTempString & s)2652 CDB_BigDateTime::Identify(const CTempString& s)
2653 {
2654 ESyntax syntax = eSyntax_Unknown;
2655 ESQLType sql_type = eDateTime;
2656
2657 if (s.size() >= 8) {
2658 if (s[s.size() - 1] == 'M' || isalpha((unsigned char) s[0])) {
2659 syntax = eSyntax_Sybase;
2660 if (s.find(" ") == NPOS) {
2661 sql_type = (s[2] == ':') ? eTime : eDate;
2662 }
2663 } else {
2664 SIZE_TYPE pos = s.find_first_of(" T");
2665 if (pos == NPOS) {
2666 sql_type = (s[2] == ':') ? eTime : eDate;
2667 } else {
2668 if (s[pos] == ' ') {
2669 syntax = eSyntax_Microsoft;
2670 }
2671 char c = s[s.size() - 6];
2672 if (c == '+' || c == '-') {
2673 sql_type = eDateTimeOffset;
2674 }
2675 }
2676 }
2677 }
2678
2679 return make_pair(syntax, sql_type);
2680 }
2681
2682 /////////////////////////////////////////////////////////////////////////////
2683 // CDB_Bit::
2684 //
2685
2686
CDB_Bit()2687 CDB_Bit::CDB_Bit() :
2688 CDB_Object(true),
2689 m_Val(0)
2690 {
2691 return;
2692 }
2693
CDB_Bit(int i)2694 CDB_Bit::CDB_Bit(int i) :
2695 CDB_Object(false)
2696 {
2697 m_Val = i ? 1 : 0;
2698 }
2699
CDB_Bit(bool i)2700 CDB_Bit::CDB_Bit(bool i) :
2701 CDB_Object(false)
2702 {
2703 m_Val = i ? 1 : 0;
2704 }
2705
~CDB_Bit(void)2706 CDB_Bit::~CDB_Bit(void)
2707 {
2708 }
2709
operator =(const int & i)2710 CDB_Bit& CDB_Bit::operator= (const int& i)
2711 {
2712 SetNULL(false);
2713 m_Val = i ? 1 : 0;
2714 return *this;
2715 }
2716
2717
operator =(const bool & i)2718 CDB_Bit& CDB_Bit::operator= (const bool& i)
2719 {
2720 SetNULL(false);
2721 m_Val = i ? 1 : 0;
2722 return *this;
2723 }
2724
2725
GetType() const2726 EDB_Type CDB_Bit::GetType() const
2727 {
2728 return eDB_Bit;
2729 }
2730
Clone() const2731 CDB_Object* CDB_Bit::Clone() const
2732 {
2733 return IsNULL() ? new CDB_Bit : new CDB_Bit(m_Val ? 1 : 0);
2734 }
2735
AssignValue(const CDB_Object & v)2736 void CDB_Bit::AssignValue(const CDB_Object& v)
2737 {
2738 CHECK_DRIVER_ERROR(
2739 v.GetType() != eDB_Bit,
2740 string("wrong type of CDB_Object: ") + GetTypeName(v.GetType(), false),
2741 2 );
2742 *this= (const CDB_Bit&)v;
2743 }
2744
2745
2746 /////////////////////////////////////////////////////////////////////////////
2747 //
2748 // CDB_Numeric::
2749 //
2750
2751
CDB_Numeric()2752 CDB_Numeric::CDB_Numeric() :
2753 CDB_Object(true),
2754 m_Precision(0),
2755 m_Scale(0)
2756 {
2757 memset(m_Body, 0, sizeof(m_Body));
2758 }
2759
2760
CDB_Numeric(unsigned int precision,unsigned int scale)2761 CDB_Numeric::CDB_Numeric(unsigned int precision, unsigned int scale)
2762 : CDB_Object(false),
2763 m_Precision(precision),
2764 m_Scale(scale)
2765 {
2766 memset(m_Body, 0, sizeof(m_Body));
2767 }
2768
2769
CDB_Numeric(unsigned int precision,unsigned int scale,const unsigned char * arr)2770 CDB_Numeric::CDB_Numeric(unsigned int precision,
2771 unsigned int scale,
2772 const unsigned char* arr) :
2773 CDB_Object(false),
2774 m_Precision(precision),
2775 m_Scale(scale)
2776 {
2777 memcpy(m_Body, arr, sizeof(m_Body));
2778 }
2779
2780
CDB_Numeric(unsigned int precision,unsigned int scale,bool is_negative,const unsigned char * arr)2781 CDB_Numeric::CDB_Numeric(unsigned int precision,
2782 unsigned int scale,
2783 bool is_negative,
2784 const unsigned char* arr) :
2785 CDB_Object(false),
2786 m_Precision(precision),
2787 m_Scale(scale)
2788 {
2789 m_Body[0]= is_negative? 1 : 0;
2790 memcpy(m_Body+1, arr, sizeof(m_Body)-1);
2791 }
2792
2793
CDB_Numeric(unsigned int precision,unsigned int scale,const char * val)2794 CDB_Numeric::CDB_Numeric(unsigned int precision, unsigned int scale, const char* val)
2795 : m_Precision(0),
2796 m_Scale(0)
2797 {
2798 x_MakeFromString(precision, scale, val);
2799 }
2800
2801
CDB_Numeric(unsigned int precision,unsigned int scale,const string & val)2802 CDB_Numeric::CDB_Numeric(unsigned int precision, unsigned int scale, const string& val)
2803 : m_Precision(0),
2804 m_Scale(0)
2805 {
2806 x_MakeFromString(precision, scale, val);
2807 }
2808
2809
~CDB_Numeric(void)2810 CDB_Numeric::~CDB_Numeric(void)
2811 {
2812 }
2813
2814
Assign(unsigned int precision,unsigned int scale,const unsigned char * arr)2815 CDB_Numeric& CDB_Numeric::Assign(unsigned int precision,
2816 unsigned int scale,
2817 const unsigned char* arr)
2818 {
2819 m_Precision = precision;
2820 m_Scale = scale;
2821 SetNULL(false);
2822 memcpy(m_Body, arr, sizeof(m_Body));
2823 return *this;
2824 }
2825
2826
Assign(unsigned int precision,unsigned int scale,bool is_negative,const unsigned char * arr)2827 CDB_Numeric& CDB_Numeric::Assign(unsigned int precision,
2828 unsigned int scale,
2829 bool is_negative,
2830 const unsigned char* arr)
2831 {
2832 m_Precision = precision;
2833 m_Scale = scale;
2834 SetNULL(false);
2835 m_Body[0] = is_negative? 1 : 0;
2836 memcpy(m_Body + 1, arr, sizeof(m_Body) - 1);
2837 return *this;
2838 }
2839
2840
operator =(const char * val)2841 CDB_Numeric& CDB_Numeric::operator= (const char* val)
2842 {
2843 x_MakeFromString(m_Precision, m_Scale, val);
2844 return *this;
2845 }
2846
2847
operator =(const string & val)2848 CDB_Numeric& CDB_Numeric::operator= (const string& val)
2849 {
2850 x_MakeFromString(m_Precision, m_Scale, val);
2851 return *this;
2852 }
2853
2854
GetType() const2855 EDB_Type CDB_Numeric::GetType() const
2856 {
2857 return eDB_Numeric;
2858 }
2859
2860
Clone() const2861 CDB_Object* CDB_Numeric::Clone() const
2862 {
2863 return new CDB_Numeric((unsigned int) m_Precision,
2864 (unsigned int) m_Scale, m_Body);
2865 }
2866
2867
2868 static int s_NumericBytesPerPrec[] =
2869 {
2870 2, 2, 3, 3, 4, 4, 4, 5, 5, 6, 6, 6, 7, 7, 8, 8, 9, 9, 9,
2871 10, 10, 11, 11, 11, 12, 12, 13, 13, 14, 14, 14, 15, 15,
2872 16, 16, 16, 17, 17, 18, 18, 19, 19, 19, 20, 20, 21, 21, 21,
2873 22, 22, 23, 23, 24, 24, 24, 25, 25, 26, 26, 26
2874 };
2875
2876
2877 static const unsigned int kMaxPrecision = 50;
2878
2879
s_DoCarry(unsigned char * product)2880 static void s_DoCarry(unsigned char* product)
2881 {
2882 for (unsigned int j = 0; j < kMaxPrecision; j++) {
2883 if (product[j] > 9) {
2884 product[j + 1] += product[j] / 10;
2885 product[j] %= 10;
2886 }
2887 }
2888 }
2889
2890
s_MultiplyByte(unsigned char * product,int num,const unsigned char * multiplier)2891 static void s_MultiplyByte(unsigned char* product, int num,
2892 const unsigned char* multiplier)
2893 {
2894 unsigned char number[3];
2895 number[0] = num % 10;
2896 number[1] = (num / 10) % 10;
2897 number[2] = (num / 100) % 10;
2898
2899 int top;
2900 for (top = kMaxPrecision - 1; top >= 0 && !multiplier[top]; top--)
2901 continue;
2902
2903 int start = 0;
2904 for (int i = 0; i <= top; i++) {
2905 for (int j =0; j < 3; j++) {
2906 product[j + start] += multiplier[i] * number[j];
2907 }
2908 s_DoCarry(product);
2909 start++;
2910 }
2911 }
2912
2913
s_ArrayToString(const unsigned char * array,int scale,char * s)2914 static char* s_ArrayToString(const unsigned char* array, int scale, char* s)
2915 {
2916 int top;
2917
2918 for (top = kMaxPrecision - 1; top >= 0 && top > scale && !array[top];
2919 top--)
2920 continue;
2921
2922 if (top == -1) {
2923 s[0] = '0';
2924 s[1] = '\0';
2925 return s;
2926 }
2927
2928 int j = 0;
2929 for (int i = top; i >= 0; i--) {
2930 if (top + 1 - j == scale)
2931 s[j++] = '.';
2932 s[j++] = array[i] + '0';
2933 }
2934 s[j] = '\0';
2935
2936 return s;
2937 }
2938
2939
Value() const2940 string CDB_Numeric::Value() const
2941 {
2942 unsigned char multiplier[kMaxPrecision];
2943 unsigned char temp[kMaxPrecision];
2944 unsigned char product[kMaxPrecision];
2945 char result[kMaxPrecision + 1];
2946 char* s = result;
2947 int num_bytes = 0;
2948
2949 memset(multiplier, 0, kMaxPrecision);
2950 memset(product, 0, kMaxPrecision);
2951 multiplier[0] = 1;
2952 if (m_Precision != 0) {
2953 num_bytes = s_NumericBytesPerPrec[m_Precision-1];
2954 }
2955
2956 if (m_Body[0] == 1) {
2957 *s++ = '-';
2958 }
2959
2960 for (int pos = num_bytes - 1; pos > 0; pos--) {
2961 s_MultiplyByte(product, m_Body[pos], multiplier);
2962
2963 memcpy(temp, multiplier, kMaxPrecision);
2964 memset(multiplier, 0, kMaxPrecision);
2965 s_MultiplyByte(multiplier, 256, temp);
2966 }
2967
2968 s_ArrayToString(product, m_Scale, s);
2969 return result;
2970 }
2971
2972
2973
s_Div256(const char * value,char * product,int base)2974 static int s_Div256(const char* value, char* product, int base)
2975 {
2976 int res = 0;
2977 char* const initial = product;
2978
2979 while (*value < base) {
2980 res = res % 256 * base + (int)*value;
2981 ++value;
2982 while (product == initial && *value < base && res < 256) {
2983 res = res * base + (int)*value;
2984 ++value;
2985 }
2986 *product = (char) (res / 256);
2987 ++product;
2988 }
2989 *product = base;
2990 return res % 256;
2991 }
2992
2993
x_MakeFromString(unsigned int precision,unsigned int scale,const CTempString & s)2994 void CDB_Numeric::x_MakeFromString(unsigned int precision, unsigned int scale,
2995 const CTempString& s)
2996 {
2997
2998 if (m_Precision == 0 && precision == 0 && !s.empty()) {
2999 precision = (unsigned int) s.size();
3000 if (scale == 0) {
3001 SIZE_TYPE dot_pos = s.find('.');
3002 scale = (dot_pos == NPOS) ? 0 : precision - (unsigned int) dot_pos;
3003 if (scale > 1)
3004 --scale;
3005 }
3006 }
3007
3008 CHECK_DRIVER_ERROR(
3009 !precision || precision > kMaxPrecision,
3010 "illegal precision " + NStr::NumericToString(precision),
3011 100 );
3012 CHECK_DRIVER_ERROR(
3013 scale > precision,
3014 "scale (" + NStr::NumericToString(scale)
3015 + ") cannot be more than precision ("
3016 + NStr::NumericToString(precision) + ')',
3017 101 );
3018
3019 bool is_negative= false;
3020 CTempString::const_iterator val = s.begin();
3021 if (val != s.end() && *val == '-') {
3022 is_negative= true;
3023 ++val;
3024 }
3025
3026 while (val != s.end() && *val == '0') {
3027 ++val;
3028 }
3029
3030 char buff1[kMaxPrecision + 1];
3031 unsigned int n = 0;
3032 while (val != s.end() && n < precision) {
3033 if (*val >= '0' && *val <= '9') {
3034 buff1[n++] = *val - '0';
3035 } else if (*val == '.') {
3036 break;
3037 } else {
3038 DATABASE_DRIVER_ERROR("string cannot be converted: " + string(s),
3039 102 );
3040 }
3041 ++val;
3042 }
3043
3044 CHECK_DRIVER_ERROR(
3045 precision - n < scale,
3046 "string cannot be converted because of overflow: " + string(s),
3047 103 );
3048
3049 unsigned int dec = 0;
3050 if (val != s.end() && *val == '.') {
3051 ++val;
3052 while (val != s.end() && dec < scale) {
3053 if (*val >= '0' && *val <= '9') {
3054 buff1[n++] = *val - '0';
3055 } else {
3056 DATABASE_DRIVER_ERROR
3057 ("string cannot be converted: " + string(s), 102);
3058 }
3059 ++dec;
3060 ++val;
3061 }
3062 }
3063
3064 while (dec++ < scale) {
3065 buff1[n++] = 0;
3066 }
3067 if (n == 0) {
3068 buff1[n++] = 0;
3069 }
3070 buff1[n] = 10;
3071
3072 char buff2[kMaxPrecision + 1];
3073 char* p[2];
3074 p[0] = buff1;
3075 p[1] = buff2;
3076
3077 // Setup everything now
3078 memset(m_Body, 0, sizeof(m_Body));
3079 if (is_negative) {
3080 m_Body[0] = 1/*sign*/;
3081 }
3082 unsigned char* num = m_Body + s_NumericBytesPerPrec[precision - 1] - 1;
3083 for (int i = 0; *p[i] || p[i][1] != 10; i = 1 - i) {
3084 _ASSERT(num > m_Body);
3085 *num = s_Div256(p[i], p[1-i], 10);
3086 --num;
3087 }
3088
3089 m_Precision = precision;
3090 m_Scale = scale;
3091 SetNULL(false);
3092 }
3093
AssignValue(const CDB_Object & v)3094 void CDB_Numeric::AssignValue(const CDB_Object& v)
3095 {
3096 CHECK_DRIVER_ERROR(
3097 v.GetType() != eDB_Numeric,
3098 string("wrong type of CDB_Object: ") + GetTypeName(v.GetType(), false),
3099 2 );
3100 *this = (const CDB_Numeric&)v;
3101 }
3102
3103 END_NCBI_SCOPE
3104
3105
3106