From e76ab3a1ac2487e0dcb16ecdfe0c6e53c3f1e86c Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Fri, 29 Mar 2013 18:51:07 +0200 Subject: Add test for custom-mapping SQL Server SQL_VARIANT type --- mssql/custom/traits.cxx | 129 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 129 insertions(+) create mode 100644 mssql/custom/traits.cxx (limited to 'mssql/custom/traits.cxx') diff --git a/mssql/custom/traits.cxx b/mssql/custom/traits.cxx new file mode 100644 index 0000000..80fe42f --- /dev/null +++ b/mssql/custom/traits.cxx @@ -0,0 +1,129 @@ +// file : mssql/types/traits.cxx +// copyright : Copyright (c) 2009-2013 Code Synthesis Tools CC +// license : GNU GPL v2; see accompanying LICENSE file + +#include "traits.hxx" + +using namespace std; + +namespace odb +{ + namespace mssql + { + void value_traits:: + param_callback (const void* context, + size_t*, + const void** buffer, + size_t* size, + chunk_type* chunk, + void* tmp_buf, + size_t tmp_capacity) + { + const variant& v (*static_cast (context)); + string str; + + switch (v.val_type) + { + case variant::type_int: + { + ostringstream os; + os << v.int_val; + + str = "bigint "; + str += os.str (); + break; + } + case variant::type_str: + { + str = "varchar "; + str += v.str_val; + break; + } + } + + // Here we assume that the temoprary buffer is large enough to fit + // the whole string in one go. If that were not the case, then we + // would have had to chunk it. + // + assert (tmp_capacity >= str.size ()); + memcpy (tmp_buf, str.c_str (), str.size ()); + + *buffer = tmp_buf; + *size = str.size (); + *chunk = chunk_one; + } + + void value_traits:: + result_callback (void* context, + size_t*, + void** buffer, + size_t* size, + chunk_type chunk, + size_t, + void* tmp_buf, + size_t tmp_capacity) + { + variant& v (*static_cast (context)); + + switch (chunk) + { + case chunk_null: + case chunk_one: + { + assert (false); // The value cannot be NULL or empty. + break; + } + case chunk_first: + { + // Use the variant's string value as a temporary buffer. If this + // were not possible, we could have allocated one as part of + // context. + // + v.str_val.clear (); + + *buffer = tmp_buf; + *size = tmp_capacity; + break; + } + case chunk_next: + { + v.str_val.append (static_cast (tmp_buf), *size); + + *buffer = tmp_buf; + *size = tmp_capacity; + break; + } + case chunk_last: + { + v.str_val.append (static_cast (tmp_buf), *size); + + // Figure out what we've got. + // + string::size_type p (v.str_val.find (' ')); + assert (p != string::npos); // Must have type followed by value. + string type (v.str_val, 0, p); + string text (v.str_val, p + 1, string::npos); + + if (type == "tinyint" || + type == "smallint" || + type == "int" || + type == "bigint") + { + istringstream is (text); + is >> v.int_val; + v.val_type = variant::type_int; + } + else if (type == "char" || type == "varchar") + { + v.str_val = text; + v.val_type = variant::type_str; + } + else + assert (false); // Unknown type. + + break; + } + } + } + } +} -- cgit v1.1