diff options
Diffstat (limited to 'odb-tests/mssql/types')
-rw-r--r-- | odb-tests/mssql/types/driver.cxx | 381 | ||||
-rw-r--r-- | odb-tests/mssql/types/test.hxx | 517 | ||||
-rw-r--r-- | odb-tests/mssql/types/traits.hxx | 223 |
3 files changed, 1121 insertions, 0 deletions
diff --git a/odb-tests/mssql/types/driver.cxx b/odb-tests/mssql/types/driver.cxx new file mode 100644 index 0000000..d900a95 --- /dev/null +++ b/odb-tests/mssql/types/driver.cxx @@ -0,0 +1,381 @@ +// file : mssql/types/driver.cxx +// license : GNU GPL v2; see accompanying LICENSE file + +// Test SQL Server type conversion. +// + +#include <memory> // std::auto_ptr +#include <cassert> +#include <iostream> + +#include <odb/exceptions.hxx> +#include <odb/mssql/database.hxx> +#include <odb/mssql/transaction.hxx> + +#include <common/common.hxx> + +#include "test.hxx" +#include "test-odb.hxx" + +using namespace std; +namespace mssql = odb::mssql; +using namespace mssql; + +int +main (int argc, char* argv[]) +{ + try + { + auto_ptr<database> db (create_specific_database<database> (argc, argv)); + + { + object o (1); + + o.bit_ = 1; + o.utint_ = 222; + o.stint_ = -123; + o.usint_ = 65000; + o.ssint_ = -12345; + o.uint_ = 4294967290U; + o.sint_ = -1234567890; + o.ubint_ = 18446744073709551610ULL; + o.sbint_ = -1234567890123456789LL; + + o.fsm_ = -214748.3648F; + o.dsm_ = 214748.3647; + o.ism_ = -2147483647 -1; + + o.dm1_ = -922337203685477.5808; + o.dm2_ = 922337203685476.3520; // 922337203685477.5807 + o.im_ = 9223372036854775807LL; + + o.f4_ = 123.123F; + o.f8_ = 123.1234567; + + o.schar_ = "short data char "; + o.svchar_ = "short data varchar"; + + o.lchar_.assign (1025, 'a'); + o.lvchar_ = "long data varchar"; // Test the short string optimization. + o.mvchar_.assign (70000, 'm'); + o.text_.assign (70000, 't'); + + o.snchar_ = L"short data nchar\x1FFF\xD7FF "; + o.snvchar_ = L"short data nvarchar \x1FFF\xD7FF"; + + o.lnchar_.assign (513, L'\x1234'); + o.lnvchar_ = L""; // Test empty string. + o.mnvchar_.assign (70000, L'\x2345'); + o.ntext_.assign (70000, L'\x4356'); + + const char sdata[] = "abc""\x00\x01""def"; + memcpy (o.sbin_, sdata, sizeof (sdata)); + o.svbin_.assign (sdata, sdata + sizeof (sdata)); + + string ldata (256 * 1024, '\x01'); + memset (o.lbin_, 2, sizeof (o.lbin_)); + o.lvbin_.assign (50, '\x03'); + o.mvbin_.assign (ldata.begin (), ldata.end ()); + o.image_.assign (ldata.begin (), ldata.end ()); + +#if !defined(MSSQL_SERVER_VERSION) || MSSQL_SERVER_VERSION >= 1000 + o.date_ = date_time (2011, 12, 20, 0, 0, 0, 0, 0, 0); + o.time7_ = date_time (0, 0, 0, 13, 34, 39, 123456789, 0, 0); + o.time4_ = date_time (0, 0, 0, 13, 34, 39, 123456700, 0, 0); +#endif + o.sdt_ = date_time (2011, 12, 20, 15, 44, 29, 123456700, 0, 0); + o.dt_ = date_time (2011, 12, 20, 15, 44, 29, 123456700, 0, 0); +#if !defined(MSSQL_SERVER_VERSION) || MSSQL_SERVER_VERSION >= 1000 + o.dt2_ = date_time (2011, 12, 20, 15, 44, 29, 123456700, 0, 0); + o.dto7_ = date_time (2011, 12, 20, 15, 44, 29, 123456700, 2, 0); + o.dto0_ = date_time (2011, 12, 20, 15, 44, 29, 123456700, 2, 0); +#endif + +#ifdef _WIN32 + // 6F846D41-C89A-4E4D-B22F-56443CFA543F + o.guid_.Data1 = 0x6F846D41; + o.guid_.Data2 = 0xC89A; + o.guid_.Data3 = 0x4E4D; + memcpy (&o.guid_.Data4, "\xB2\x2F\x56\x44\x3C\xFA\x54\x3F", 8); +#endif + memcpy (o.uuid_, "\x6F\x84\x6D\x41\xC8\x9A\x4E\x4D\xB2\x2F" + "\x56\x44\x3C\xFA\x54\x3F", 16); + + // Persist. + // + { + transaction t (db->begin ()); + db->persist (o); + t.commit (); + } + +#if !defined(MSSQL_SERVER_VERSION) || MSSQL_SERVER_VERSION >= 1000 + o.time7_ = date_time (0, 0, 0, 13, 34, 39, 123456700, 0, 0); + o.time4_ = date_time (0, 0, 0, 13, 34, 39, 123400000, 0, 0); +#endif + o.sdt_ = date_time (2011, 12, 20, 15, 44, 0, 0, 0, 0); + o.dt_ = date_time (2011, 12, 20, 15, 44, 29, 123000000, 0, 0); +#if !defined(MSSQL_SERVER_VERSION) || MSSQL_SERVER_VERSION >= 1000 + o.dto0_ = date_time (2011, 12, 20, 15, 44, 29, 0, 2, 0); +#endif + + // Load. + // + { + transaction t (db->begin ()); + auto_ptr<object> o1 (db->load<object> (1)); + t.commit (); + + assert (o == *o1); + } + + typedef mssql::query<object> query; + typedef odb::result<object> result; + + // Test UUID in queries. + // + { + char uuid[16]; + memcpy (uuid, o.uuid_, 16); + + transaction t (db->begin ()); + + { + result r (db->query<object> (query::uuid == uuid)); + assert (size (r) == 1); + } + + { + result r (db->query<object> (query::uuid == query::_val (uuid))); + assert (size (r) == 1); + } + + { + result r (db->query<object> (query::uuid == query::_ref (uuid))); + assert (size (r) == 1); + } + + { + const char* d (uuid); + result r (db->query<object> (query::uuid == d)); + assert (size (r) == 1); + } + + t.commit (); + } + + // Test short/long data in queries. + // + { + transaction t (db->begin ()); + + { + result r (db->query<object> (query::svchar == o.svchar_)); + assert (size (r) == 1); + } + + { + result r (db->query<object> (query::snvchar == o.snvchar_)); + assert (size (r) == 1); + } + + { + result r (db->query<object> (query::mvchar == o.mvchar_)); + assert (size (r) == 1); + } + + { + result r (db->query<object> (query::mnvchar == o.mnvchar_)); + assert (size (r) == 1); + } + + t.commit (); + } + } + + // Test long NULL data. + // + { + long_null o1 (1); + long_null o2 (2); + o2.str_.reset (new string); + o2.str_->assign (70000, 'x'); + + // Persist. + // + { + transaction t (db->begin ()); + db->persist (o1); + db->persist (o2); + t.commit (); + } + + // Load. + // + { + transaction t (db->begin ()); + auto_ptr<long_null> p1 (db->load<long_null> (1)); + auto_ptr<long_null> p2 (db->load<long_null> (2)); + t.commit (); + + assert (o1 == *p1); + assert (o2 == *p2); + } + } + + // Test long data in containers. + // + { + long_cont o (1); + o.v.push_back (long_comp ("aaa", 123)); + o.v.push_back (long_comp (string (500, 'b'), 234)); + o.v.push_back (long_comp (string (70000, 'c'), 345)); + + // Persist. + // + { + transaction t (db->begin ()); + db->persist (o); + t.commit (); + } + + // Load. + // + { + transaction t (db->begin ()); + auto_ptr<long_cont> p (db->load<long_cont> (1)); + t.commit (); + + assert (o == *p); + } + } + + // Test char/wchar_t arrays. + // + { + char_array o1 (1, "", L""); + char_array o2 (2, "1234567890", L"12345678\x1FFF\xD7FF"); + char_array o3 (3, "1234567890123456", L"12345678901234\x1FFF\xD7FF"); + + { + transaction t (db->begin ()); + db->persist (o1); + db->persist (o2); + db->persist (o3); + t.commit (); + } + + // SQL Server returns padded values for CHAR(N)/NCHAR(N). + // + memcpy (o1.s2, " ", 16); + o1.s3[0] = o1.c1 = ' '; + memcpy (o2.s2, "1234567890 ", 16); + + memset (o1.ls2, ' ', 1025); + memset (o2.ls2 + 10, ' ', 1025 - 10); + + memcpy (o1.ws2, L" ", 16 * sizeof (wchar_t)); + o1.ws3[0] = o1.wc1 = L' '; + memcpy (o2.ws2, L"12345678\x1FFF\xD7FF ", 16 * sizeof (wchar_t)); + + for (size_t i (0); i < 257; ++i) + o1.lws2[i] = L' '; + + for (size_t i (10); i < 257; ++i) + o2.lws2[i] = L' '; + + { + transaction t (db->begin ()); + auto_ptr<char_array> p1 (db->load<char_array> (1)); + auto_ptr<char_array> p2 (db->load<char_array> (2)); + auto_ptr<char_array> p3 (db->load<char_array> (3)); + t.commit (); + + assert (o1 == *p1); + assert (o2 == *p2); + assert (o3 == *p3); + } + } + + // Test optimistic concurrency using ROWVERSION. + // + { + rowversion o (123); + o.str = "abc"; + + { + transaction t (db->begin ()); + db->persist (o); + assert (o.ver != 0); + t.commit (); + } + + { + transaction t (db->begin ()); + auto_ptr<rowversion> p (db->load<rowversion> (o.id_)); + assert (p->ver == o.ver); + p->str += 'd'; + db->update (*p); + assert (p->ver > o.ver); + + // Double-check object version was updated. + // + { + auto_ptr<rowversion> p1 (db->load<rowversion> (o.id_)); + assert (p->ver == p1->ver); + } + + o.str += 'D'; + try + { + db->update (o); + assert (false); + } + catch (const odb::object_changed&) {} + db->reload (o); + assert (o.ver == p->ver); + o.str += 'D'; + db->update (o); + t.commit (); + } + } + + { + rowversion_auto o; + o.str = "abc"; + + { + transaction t (db->begin ()); + db->persist (o); + assert (o.ver != 0); + t.commit (); + } + + { + transaction t (db->begin ()); + auto_ptr<rowversion_auto> p (db->load<rowversion_auto> (o.id_)); + assert (p->ver == o.ver); + p->str += 'd'; + db->update (*p); + assert (p->ver > o.ver); + o.str += 'D'; + try + { + db->update (o); + assert (false); + } + catch (const odb::object_changed&) {} + db->reload (o); + assert (o.ver == p->ver); + o.str += 'D'; + db->update (o); + t.commit (); + } + } + } + catch (const odb::exception& e) + { + cerr << e.what () << endl; + return 1; + } +} diff --git a/odb-tests/mssql/types/test.hxx b/odb-tests/mssql/types/test.hxx new file mode 100644 index 0000000..5d651a8 --- /dev/null +++ b/odb-tests/mssql/types/test.hxx @@ -0,0 +1,517 @@ +// file : mssql/types/test.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef TEST_HXX +#define TEST_HXX + +#ifdef _WIN32 +# ifndef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +# endif +# include <windows.h> // GUID +#elif defined(HOST_WIN32) +typedef struct _GUID +{ + unsigned int Data1; + unsigned short Data2; + unsigned short Data3; + unsigned char Data4[8]; +} GUID; +#endif + +#include <common/config.hxx> // HAVE_CXX11 + +#include <string> +#include <vector> +#include <memory> // std::auto_ptr +#include <cstring> // std::memcmp, std::memcpy, std::str[n]cmp, std::strlen +#include <cwchar> // std::wcslen, std::wcs[n]cmp + +#include <odb/core.hxx> + +struct date_time +{ + date_time () + { + } + + date_time (short y, + unsigned short m, + unsigned short d, + unsigned short h, + unsigned short min, + unsigned short sec, + unsigned int f, + short tzh, + short tzm) + : year (y), + month (m), + day (d), + hour (h), + minute (min), + second (sec), + fraction (f), + timezone_hour (tzh), + timezone_minute (tzm) + { + } + + bool + operator== (const date_time& y) const + { + return + year == y.year && + month == y.month && + day == y.day && + hour == y.hour && + minute == y.minute && + second == y.second && + fraction == y.fraction && + timezone_hour == y.timezone_hour && + timezone_minute == y.timezone_minute; + } + + short year; + unsigned short month; + unsigned short day; + unsigned short hour; + unsigned short minute; + unsigned short second; + unsigned int fraction; + short timezone_hour; + short timezone_minute; +}; + +#pragma db object +struct object +{ + object () {} + object (unsigned int id): id_ (id) {} + + #pragma db id + unsigned int id_; + + // Integer types. + // + #pragma db type ("BIT") + unsigned char bit_; + + #pragma db type ("TINYINT") + unsigned char utint_; + + #pragma db type ("TINYINT") + unsigned char stint_; + + #pragma db type ("SMALLINT") + unsigned short usint_; + + #pragma db type ("SMALLINT") + short ssint_; + + #pragma db type ("INT") + unsigned int uint_; + + #pragma db type ("INTEGER") + int sint_; + + #pragma db type ("BIGINT") + unsigned long long ubint_; + + #pragma db type ("BIGINT") + long long sbint_; + + // Floating/fixed point types. + // + #pragma db type ("SMALLMONEY") + float fsm_; + + #pragma db type ("SMALLMONEY") + double dsm_; + + #pragma db type ("SMALLMONEY") + int ism_; + + #pragma db type ("MONEY") + double dm1_; + + #pragma db type ("MONEY") + double dm2_; + + #pragma db type ("MONEY") + long long im_; + + #pragma db type ("REAL") + float f4_; + + #pragma db type ("FLOAT") + double f8_; + + // Strings. + // + #pragma db type ("CHAR(20)") + std::string schar_; + + #pragma db type ("VARCHAR(128)") + std::string svchar_; + + #pragma db type ("CHAR(1025)") + std::string lchar_; + + #pragma db type ("CHARACTER VARYING(8000)") + std::string lvchar_; + + #pragma db type ("VARCHAR(max)") + std::string mvchar_; + + #pragma db type ("TEXT") + std::string text_; + + // National strings. + // + #pragma db type ("NCHAR(20)") + std::wstring snchar_; + + #pragma db type ("NVARCHAR(128)") + std::wstring snvchar_; + + #pragma db type ("NCHAR(513)") + std::wstring lnchar_; + + #pragma db type ("NATIONAL CHARACTER VARYING(4000)") + std::wstring lnvchar_; + + #pragma db type ("NVARCHAR(max)") + std::wstring mnvchar_; + + #pragma db type ("NTEXT") + std::wstring ntext_; + + // Binary. + // + #pragma db type ("BINARY(9)") + unsigned char sbin_[9]; + + #pragma db type ("VARBINARY(256)") + std::vector<char> svbin_; + + #pragma db type ("BINARY(1025)") + char lbin_[1025]; + + #pragma db type ("BINARY VARYING(8000)") + std::vector<char> lvbin_; + + #pragma db type ("VARBINARY(max)") + std::vector<unsigned char> mvbin_; + + #pragma db type ("IMAGE") + std::vector<char> image_; + + // Date-time. SQL Server 2005 (9.0) only has DATETIME and SMALLDATETIME. + // +#if !defined(MSSQL_SERVER_VERSION) || MSSQL_SERVER_VERSION >= 1000 + #pragma db type ("DATE") + date_time date_; + + #pragma db type ("TIME") + date_time time7_; + + #pragma db type ("TIME(4)") + date_time time4_; +#endif + + #pragma db type ("SMALLDATETIME") + date_time sdt_; + + #pragma db type ("DATETIME") + date_time dt_; + +#if !defined(MSSQL_SERVER_VERSION) || MSSQL_SERVER_VERSION >= 1000 + #pragma db type ("DATETIME2") + date_time dt2_; + + #pragma db type ("DATETIMEOFFSET") + date_time dto7_; + + #pragma db type ("DATETIMEOFFSET(0)") + date_time dto0_; +#endif + + // Other types. + // +#if defined(_WIN32) || defined(HOST_WIN32) + //#pragma db type ("UNIQUEIDENTIFIER") + GUID guid_; +#endif + + #pragma db type ("UNIQUEIDENTIFIER") + char uuid_[16]; + + bool + operator== (const object& y) const + { + return + id_ == y.id_ && + bit_ == y.bit_ && + utint_ == y.utint_ && + stint_ == y.stint_ && + usint_ == y.usint_ && + ssint_ == y.ssint_ && + uint_ == y.uint_ && + sint_ == y.sint_ && + ubint_ == y.ubint_ && + sbint_ == y.sbint_ && + fsm_ == y.fsm_ && + dsm_ == y.dsm_ && + ism_ == y.ism_ && + dm1_ == y.dm1_ && + dm2_ == y.dm2_ && + im_ == y.im_ && + f4_ == y.f4_ && + f8_ == y.f8_ && + + schar_ == y.schar_ && + svchar_ == y.svchar_ && + lchar_ == y.lchar_ && + lvchar_ == y.lvchar_ && + mvchar_ == y.mvchar_ && + text_ == y.text_ && + + snchar_ == y.snchar_ && + snvchar_ == y.snvchar_ && + lnchar_ == y.lnchar_ && + lnvchar_ == y.lnvchar_ && + mnvchar_ == y.mnvchar_ && + ntext_ == y.ntext_ && + + std::memcmp (sbin_, y.sbin_, sizeof (sbin_)) == 0 && + svbin_ == y.svbin_ && + std::memcmp (lbin_, y.lbin_, sizeof (lbin_)) == 0 && + lvbin_ == y.lvbin_ && + mvbin_ == y.mvbin_ && + image_ == y.image_ + +#if !defined(MSSQL_SERVER_VERSION) || MSSQL_SERVER_VERSION >= 1000 + && date_ == y.date_ + && time7_ == y.time7_ + && time4_ == y.time4_ +#endif + && sdt_ == y.sdt_ + && dt_ == y.dt_ +#if !defined(MSSQL_SERVER_VERSION) || MSSQL_SERVER_VERSION >= 1000 + && dt2_ == y.dt2_ + && dto7_ == y.dto7_ + && dto0_ == y.dto0_ +#endif + +#ifdef _WIN32 + && std::memcmp (&guid_, &y.guid_, sizeof (guid_)) == 0 +#endif + && std::memcmp (uuid_, y.uuid_, sizeof (uuid_)) == 0; + } +}; + +// Test long NULL data. +// +#pragma db object +struct long_null +{ + long_null () {} + long_null (unsigned int id): id_ (id) {} + + #pragma db id + unsigned int id_; + + #pragma db type ("VARCHAR(max)") null +#ifdef HAVE_CXX11 + std::unique_ptr<std::string> str_; +#else + std::auto_ptr<std::string> str_; +#endif + + bool + operator== (const long_null& y) const + { + return + id_ == y.id_ && + ((str_.get () == 0 && y.str_.get () == 0) || *str_ == *y.str_); + } +}; + +// Test long data in containers, in particular column re-arrangement. +// +#pragma db value +struct long_comp +{ + long_comp () {} + long_comp (std::string s, unsigned int n): str (s), num (n) {} + + #pragma db type ("VARCHAR(max)") + std::string str; + + unsigned int num; + + bool + operator== (const long_comp& y) const + { + return str == y.str && num == y.num; + } +}; + +#pragma db object +struct long_cont +{ + long_cont () {} + long_cont (unsigned int id): id_ (id) {} + + #pragma db id + unsigned int id_; + + std::vector<long_comp> v; + + bool + operator== (const long_cont& y) const + { + return id_ == y.id_ && v == y.v; + } +}; + +// Test char/wchar_t arrays. +// +#pragma db object +struct char_array +{ + char_array () {} + char_array (unsigned long id, const char* s, const wchar_t* ws) + : id_ (id) + { + std::memcpy (s1, s, std::strlen (s) + 1); // VC++ strncpy deprecation. + std::memcpy (s2, s, std::strlen (s) + 1); + s3[0] = c1 = *s; + + std::memcpy (ws1, ws, (std::wcslen (ws) + 1) * sizeof (wchar_t)); + std::memcpy (ws2, ws, (std::wcslen (ws) + 1) * sizeof (wchar_t)); + ws3[0] = wc1 = *ws; + + if (std::strlen (s) == sizeof (s2)) + { + std::memset (ls1, '1', 1025); + ls1[1025] = '\0'; + std::memset (ls2, '2', 1025); + + for (std::size_t i (0); i < 257; ++i) + { + lws1[i] = L'1'; + lws2[i] = L'2'; + } + lws1[257] = L'\0'; + } + else + { + std::memcpy (ls1, s, std::strlen (s) + 1); // VC++ strcpy deprecation. + std::memcpy (ls2, s, std::strlen (s) + 1); + + std::memcpy (lws1, ws, (std::wcslen (ws) + 1) * sizeof (wchar_t)); + std::memcpy (lws2, ws, (std::wcslen (ws) + 1) * sizeof (wchar_t)); + } + } + + #pragma db id + unsigned long id_; + + // + // + char s1[17]; + + #pragma db type("CHAR(16)") + char s2[16]; + + char s3[1]; + char c1; + + // Long data. + // + char ls1[1026]; + + #pragma db type("CHAR(1025)") + char ls2[1025]; + + // + // + wchar_t ws1[17]; + + #pragma db type("NCHAR(16)") + wchar_t ws2[16]; + + wchar_t ws3[1]; + wchar_t wc1; + + // Long data. + // + wchar_t lws1[258]; + + #pragma db type("NCHAR(257)") + wchar_t lws2[257]; + + bool + operator== (const char_array& y) const + { + return id_ == y.id_ && + + std::strcmp (s1, y.s1) == 0 && + std::strncmp (s2, y.s2, sizeof (s2)) == 0 && + s3[0] == y.s3[0] && + c1 == y.c1 && + + std::strcmp (ls1, y.ls1) == 0 && + std::strncmp (ls2, y.ls2, sizeof (ls2)) == 0 && + + std::wcscmp (ws1, y.ws1) == 0 && + std::wcsncmp (ws2, y.ws2, sizeof (ws2) / sizeof (wchar_t)) == 0 && + ws3[0] == y.ws3[0] && + wc1 == y.wc1 && + + std::wcscmp (lws1, y.lws1) == 0 && + std::wcsncmp (lws2, y.lws2, sizeof (lws2) / sizeof (wchar_t)) == 0; + } +}; + +// Test optimistic concurrency using ROWVERSION, both with auto and +// manually-assigned ids. +// +#pragma db object optimistic +struct rowversion +{ + rowversion (unsigned int id = 0): id_ (id), ver (0) {} + + #pragma db id + unsigned int id_; + + #pragma db version type("ROWVERSION") +#ifdef _WIN32 + unsigned __int64 ver; +#else + unsigned long long ver; +#endif + + std::string str; +}; + +#pragma db object optimistic +struct rowversion_auto +{ + rowversion_auto (): ver (0) {} + + #pragma db id auto + unsigned int id_; + + #pragma db version type("ROWVERSION") +#ifdef _WIN32 + unsigned __int64 ver; +#else + unsigned long long ver; +#endif + + std::string str; +}; + +#endif // TEST_HXX diff --git a/odb-tests/mssql/types/traits.hxx b/odb-tests/mssql/types/traits.hxx new file mode 100644 index 0000000..5881f50 --- /dev/null +++ b/odb-tests/mssql/types/traits.hxx @@ -0,0 +1,223 @@ +// file : mssql/types/traits.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef TRAITS_HXX +#define TRAITS_HXX + +#include <odb/mssql/mssql-fwd.hxx> // date, time, datetime, datetimeoffset +#include <odb/mssql/traits.hxx> + +#include "test.hxx" // date_time + +namespace odb +{ + namespace mssql + { + template <> + class value_traits<date_time, id_date> + { + public: + typedef date_time value_type; + typedef date_time query_type; + typedef date image_type; + + static void + set_value (date_time& v, const date& i, bool is_null) + { + if (!is_null) + { + v.year = i.year; + v.month = i.month; + v.day = i.day; + v.hour = 0; + v.minute = 0; + v.second = 0; + v.fraction = 0; + v.timezone_hour = 0; + v.timezone_minute = 0; + } + } + + static void + set_image (date& i, bool& is_null, const date_time& v) + { + is_null = false; + i.year = v.year; + i.month = v.month; + i.day = v.day; + } + }; + + template <> + class value_traits<date_time, id_time> + { + public: + typedef date_time value_type; + typedef date_time query_type; + typedef time image_type; + + static void + set_value (date_time& v, const time& i, bool is_null) + { + if (!is_null) + { + v.year = 0; + v.month = 0; + v.day = 0; + v.hour = i.hour; + v.minute = i.minute; + v.second = i.second; + v.fraction = i.fraction; + v.timezone_hour = 0; + v.timezone_minute = 0; + } + } + + static void + set_image (time& i, unsigned short s, bool& is_null, const date_time& v) + { + const unsigned int divider[8] = + { + 1000000000, + 100000000, + 10000000, + 1000000, + 100000, + 10000, + 1000, + 100 + }; + + is_null = false; + i.hour = v.hour; + i.minute = v.minute; + i.second = v.second; + i.fraction = v.fraction - v.fraction % divider[s]; + } + }; + + template <> + class value_traits<date_time, id_datetime> + { + public: + typedef date_time value_type; + typedef date_time query_type; + typedef datetime image_type; + + static void + set_value (date_time& v, const datetime& i, bool is_null) + { + if (!is_null) + { + v.year = i.year; + v.month = i.month; + v.day = i.day; + v.hour = i.hour; + v.minute = i.minute; + v.second = i.second; + v.fraction = i.fraction; + v.timezone_hour = 0; + v.timezone_minute = 0; + } + } + + static void + set_image (datetime& i, + unsigned short s, + bool& is_null, + const date_time& v) + { + const unsigned int divider[8] = + { + 1000000000, + 100000000, + 10000000, + 1000000, + 100000, + 10000, + 1000, + 100 + }; + + is_null = false; + i.year = v.year; + i.month = v.month; + i.day = v.day; + i.hour = v.hour; + i.minute = v.minute; + + // Scale value 8 indicates we are dealing with SMALLDATETIME + // which has the minutes precision. + // + if (s != 8) + { + i.second = v.second; + i.fraction = v.fraction - v.fraction % divider[s]; + } + else + { + i.second = 0; + i.fraction = 0; + } + } + }; + + template <> + class value_traits<date_time, id_datetimeoffset> + { + public: + typedef date_time value_type; + typedef date_time query_type; + typedef datetimeoffset image_type; + + static void + set_value (date_time& v, const datetimeoffset& i, bool is_null) + { + if (!is_null) + { + v.year = i.year; + v.month = i.month; + v.day = i.day; + v.hour = i.hour; + v.minute = i.minute; + v.second = i.second; + v.fraction = i.fraction; + v.timezone_hour = i.timezone_hour; + v.timezone_minute = i.timezone_minute; + } + } + + static void + set_image (datetimeoffset& i, + unsigned short s, + bool& is_null, + const date_time& v) + { + const unsigned int divider[8] = + { + 1000000000, + 100000000, + 10000000, + 1000000, + 100000, + 10000, + 1000, + 100 + }; + + is_null = false; + i.year = v.year; + i.month = v.month; + i.day = v.day; + i.hour = v.hour; + i.minute = v.minute; + i.second = v.second; + i.fraction = v.fraction - v.fraction % divider[s]; + i.timezone_hour = v.timezone_hour; + i.timezone_minute = v.timezone_minute; + } + }; + } +} + +#endif // TRAITS_HXX |