aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorConstantin Michael <constantin@codesynthesis.com>2011-10-20 10:13:51 +0200
committerConstantin Michael <constantin@codesynthesis.com>2011-10-20 10:13:51 +0200
commita64b2d953da436bdca5cf35329d10fd95e1ae860 (patch)
tree41895467ab26cee1f2d8a685367b9329dd6d31ed
parent3f98883f49d8f0823e6d2d0fca1c5ac87a320f89 (diff)
Use SQLT_NUM instead of SQLT_VNU OCI type due to inconsistent buffer lengths
The size returned by OCI into the bound rlen parameter of a SQLT_VNU buffer does not include the additional length byte. This causes problems with images that are shared across multiple statements in ODB, such as the object_id image of containers.
-rw-r--r--odb/oracle/details/number.cxx72
-rw-r--r--odb/oracle/details/number.hxx4
-rw-r--r--odb/oracle/statement.cxx4
-rw-r--r--odb/oracle/traits.hxx72
4 files changed, 64 insertions, 88 deletions
diff --git a/odb/oracle/details/number.cxx b/odb/oracle/details/number.cxx
index e62894d..6c0a56c 100644
--- a/odb/oracle/details/number.cxx
+++ b/odb/oracle/details/number.cxx
@@ -16,38 +16,32 @@ namespace odb
{
namespace details
{
- // The VARNUM type's binary representation is made up of the following
+ // The NUMBER type's binary representation is made up of the following
// bit fields, ordered in increasing memory address.
//
- // 000 to 007: The size of the binary representation, including the
- // exponent bits and the mantissa bits, but excluding these
- // length bits.
- //
- // 008 to 015: The base-100 exponent bits. The most significant bit is
+ // 000 to 007: The base-100 exponent bits. The most significant bit is
// the sign bit of the number, which is set for positive
// numbers and cleared for negative numbers. For positive
// numbers, the exponent has a bias of 65 added to it.
//
- // 016 to 175: The mantissa bits. Each byte of this field represents a
+ // 008 to 167: The mantissa bits. Each byte of this field represents a
// single base-100 value.
//
//
long long
- number_to_int64 (const char* b)
+ number_to_int64 (const char* b, size_t n)
{
// All bytes in the buffer are interpreted as unsigned.
//
const unsigned char* ub (reinterpret_cast<const unsigned char*> (b));
- int n (ub[0]);
-
// Zero is represented by zero significant bits and an exponent
// set to 128.
//
if (n == 1)
{
- assert (ub[1] == 128);
+ assert (ub[0] == 128);
return 0;
}
@@ -55,21 +49,21 @@ namespace odb
// Test the sign bit of the exponent.
//
- if ((ub[1] & 0x80) != 0)
+ if ((ub[0] & 0x80) != 0)
{
// The unbiased exponent of a positive number may be calculated as
- // ub[1] - 128 - 65. For an integer, this is the order of magnitude
+ // ub[0 - 128 - 65. For an integer, this is the order of magnitude
// of the number. Calculate the maximum weight, 100 ^ o, where o is
// the order of magnitude of the number.
//
long long w (1);
- for (size_t i (0), o (ub[1] - 193); i < o; ++i)
+ for (size_t i (0), o (ub[0] - 193); i < o; ++i)
w *= 100;
// Accumlate the sum of the significant base-100 terms.
//
- for (const unsigned char* m (ub + 2), *e (ub + 1 + n); m < e; ++m)
+ for (const unsigned char* m (ub + 1), *e (ub + n); m < e; ++m)
{
v += (*m - 1) * w;
w /= 100;
@@ -78,20 +72,20 @@ namespace odb
else
{
// The unbiased exponent of a negative number is calculated as
- // (~ub[1] & 0x7F) - 193. For an integer, this is the order of
+ // (~ub[0] & 0x7F) - 193. For an integer, this is the order of
// magnitude of the number. Calculate the maximum weight, 100 ^ o,
// where o is the order of magnitude of the number.
//
long long w (1);
- for (size_t i (0), o ((~ub[1] & 0x7F) - 65); i < o; ++i)
+ for (size_t i (0), o ((~ub[0] & 0x7F) - 65); i < o; ++i)
w *= 100;
// Accumulate the sum of the significant base-100 terms. Note that
// negative values will have a terminator byte which is included
// in the length. This is ignored.
//
- for (const unsigned char* m (ub + 2), *e (ub + n); m < e; ++m)
+ for (const unsigned char* m (ub + 1), *e (ub + n - 1); m < e; ++m)
{
v -= (101 - *m) * w;
w /= 100;
@@ -104,7 +98,7 @@ namespace odb
void
int64_to_number (char* b, size_t& n, long long v)
{
- // We assume that b is long enough to contain a long long VARNUM
+ // We assume that b is long enough to contain a long long NUMBER
// representation, that being 12 bytes.
//
@@ -114,8 +108,8 @@ namespace odb
if (v == 0)
{
- ub[0] = 1;
- ub[1] = 128;
+ ub[0] = 128;
+ n = 1;
return;
}
@@ -145,7 +139,7 @@ namespace odb
// The exponent is one less than the number of base 100 digits. It is
// inverted for negative values.
//
- ub[1] = static_cast<unsigned char> (~(n + 192));
+ ub[0] = static_cast<unsigned char> (~(n + 192));
}
else
{
@@ -163,36 +157,33 @@ namespace odb
// Exponent is one less than the number of base 100 digits.
//
- ub[1] = static_cast<unsigned char> (n + 192);
+ ub[0] = static_cast<unsigned char> (n + 192);
}
// Set the length.
//
- ub[0] = static_cast<unsigned char> (m - t + 1);
- n = static_cast<size_t> (ub[0] + 1);
+ n = static_cast<unsigned char> (m - t + 1);
// Set the significant digits in big-endian byte order and the
// terminator, if any.
//
- for (size_t i (2); m > t; ++i)
+ for (size_t i (1); m > t; ++i)
ub[i] = *--m;
}
unsigned long long
- number_to_uint64 (const char* b)
+ number_to_uint64 (const char* b, size_t n)
{
// All bytes in the buffer are interpreted as unsigned.
//
const unsigned char* ub (reinterpret_cast<const unsigned char*> (b));
- int n (ub[0]);
-
// Zero is represented by zero significant bits and an exponent
// set to 128.
//
if (n == 1)
{
- assert (ub[1] == 128);
+ assert (ub[0] == 128);
return 0;
}
@@ -200,25 +191,25 @@ namespace odb
// Test the sign bit of the exponent.
//
- if ((ub[1] & 0x80) == 0)
+ if ((ub[0] & 0x80) == 0)
{
assert (false);
return 0;
}
// The unbiased exponent of a positive number may be calculated as
- // ub[1] - 128 - 65. For an integer, this is the order of magnitude
+ // ub[0] - 128 - 65. For an integer, this is the order of magnitude
// of the number. Calculate the maximum weight, 100 ^ o, where o is
// the order of magnitude of the number.
//
unsigned long long w (1);
- for (size_t i (0), o (ub[1] - 193); i < o; ++i)
+ for (size_t i (0), o (ub[0] - 193); i < o; ++i)
w *= 100;
// Accumlate the sum of the significant base-100 terms.
//
- for (const unsigned char* m (ub + 2), *e (ub + 1 + n); m < e; ++m)
+ for (const unsigned char* m (ub + 1), *e (ub + n); m < e; ++m)
{
v += (*m - 1) * w;
w /= 100;
@@ -231,7 +222,7 @@ namespace odb
uint64_to_number (char* b, size_t& n, unsigned long long v)
{
// We assume that b is long enough to contain an unsigned long long
- // VARNUM representation, that being 12 bytes.
+ // NUMBER representation, that being 12 bytes.
//
// All bytes in the buffer are interpreted as unsigned.
@@ -240,8 +231,8 @@ namespace odb
if (v == 0)
{
- ub[0] = 1;
- ub[1] = 128;
+ ub[0] = 128;
+ n = 1;
return;
}
@@ -264,16 +255,15 @@ namespace odb
// Exponent is one less than the number of base 100 digits.
//
- ub[1] = static_cast<unsigned char> (n + 192);
+ ub[0] = static_cast<unsigned char> (n + 192);
// Set the length.
//
- ub[0] = static_cast<unsigned char> (m - t + 1);
- n = static_cast<size_t> (ub[0] + 1);
+ n = static_cast<unsigned char> (m - t + 1);
// Set the significant digits in big-endian byte order.
//
- for (size_t i (2); m > t; ++i)
+ for (size_t i (1); m > t; ++i)
ub[i] = *--m;
}
}
diff --git a/odb/oracle/details/number.hxx b/odb/oracle/details/number.hxx
index 90fb038..3b10a3c 100644
--- a/odb/oracle/details/number.hxx
+++ b/odb/oracle/details/number.hxx
@@ -27,13 +27,13 @@ namespace odb
using namespace odb::details;
LIBODB_ORACLE_EXPORT long long
- number_to_int64 (const char* buffer);
+ number_to_int64 (const char* buffer, std::size_t n);
LIBODB_ORACLE_EXPORT void
int64_to_number (char* buffer, std::size_t& n, long long val);
LIBODB_ORACLE_EXPORT unsigned long long
- number_to_uint64 (const char* buffer);
+ number_to_uint64 (const char* buffer, std::size_t n);
LIBODB_ORACLE_EXPORT void
uint64_to_number (char* buffer, std::size_t& n, unsigned long long val);
diff --git a/odb/oracle/statement.cxx b/odb/oracle/statement.cxx
index 7233e05..d63e4a7 100644
--- a/odb/oracle/statement.cxx
+++ b/odb/oracle/statement.cxx
@@ -33,7 +33,7 @@ namespace odb
SQLT_UIN, // bind::uinteger
SQLT_BFLOAT, // bind::binary_float
SQLT_BDOUBLE, // bind::binary_double
- SQLT_VNU, // bind::number
+ SQLT_NUM, // bind::number
SQLT_DAT, // bind::date
SQLT_TIMESTAMP, // bind::timestamp
SQLT_CHR, // bind::string
@@ -53,7 +53,7 @@ namespace odb
SQLT_UIN, // bind::uinteger
SQLT_BFLOAT, // bind::binary_float
SQLT_BDOUBLE, // bind::binary_double
- SQLT_VNU, // bind::number
+ SQLT_NUM, // bind::number
SQLT_DAT, // bind::date
SQLT_TIMESTAMP, // bind::timestamp
SQLT_CHR, // bind::string
diff --git a/odb/oracle/traits.hxx b/odb/oracle/traits.hxx
index 6bcc1ac..0458aef 100644
--- a/odb/oracle/traits.hxx
+++ b/odb/oracle/traits.hxx
@@ -8,9 +8,6 @@
#include <odb/pre.hxx>
-// @@
-#include <iostream>
-
#include <string>
#include <vector>
#include <cstddef> // std::size_t
@@ -263,21 +260,7 @@ namespace odb
vtraits::set_image (i, is_null, wtraits::get_ref (v));
}
- // big_int, big_float.
- //
- static void
- set_value (W& v, const char* i, bool is_null)
- {
- vtraits::set_value (wtraits::set_ref (v), i, is_null);
- }
-
- static void
- set_image (char* i, std::size_t& n, bool& is_null, const W& v)
- {
- vtraits::set_image (i, n, is_null, wtraits::get_ref (v));
- }
-
- // timestamp, string, nstring, raw.
+ // big_int, big_float, timestamp, string, nstring, raw.
//
static void
set_value (W& v, const char* i, std::size_t n, bool is_null)
@@ -285,6 +268,8 @@ namespace odb
vtraits::set_value (wtraits::set_ref (v), i, n, is_null);
}
+ // timestamp, string, nstring, raw.
+ //
static void
set_image (char* i,
std::size_t c,
@@ -295,6 +280,14 @@ namespace odb
vtraits::set_image (i, c, n, is_null, wtraits::get_ref (v));
}
+ // big_int, big_float.
+ //
+ static void
+ set_image (char* i, std::size_t& n, bool& is_null, const W& v)
+ {
+ vtraits::set_image (i, n, is_null, wtraits::get_ref (v));
+ }
+
// blob, clob, nclob.
//
static void
@@ -343,27 +336,7 @@ namespace odb
vtraits::set_image (i, is_null, wtraits::get_ref (v));
}
- // big_int, big_float.
- //
- static void
- set_value (W& v, const char& i, bool is_null)
- {
- if (is_null)
- wtraits::set_null (v);
- else
- vtraits::set_value (wtraits::set_ref (v), i, is_null);
- }
-
- static void
- set_image (char* i, std::size_t& n, bool& is_null, const W& v)
- {
- is_null = wtraits::get_null (v);
-
- if (!is_null)
- vtraits::set_image (i, n, is_null, wtraits::get_ref (v));
- }
-
- // timestamp, string, nstring, raw.
+ // big_int, big_float, timestamp, string, nstring, raw.
//
static void
set_value (W& v, const char* i, std::size_t n, bool is_null)
@@ -374,6 +347,8 @@ namespace odb
vtraits::set_value (wtraits::set_ref (v), i, n, is_null);
}
+ // timestamp, string, nstring, raw.
+ //
static void
set_image (char* i,
std::size_t c,
@@ -387,6 +362,17 @@ namespace odb
vtraits::set_image (i, c, n, is_null, wtraits::get_ref (v));
}
+ // big_int, big_float
+ //
+ static void
+ set_image (char* i, std::size_t& n, bool& is_null, const W& v)
+ {
+ is_null = wtraits::get_null (v);
+
+ if (!is_null)
+ vtraits::set_image (i, n, is_null, wtraits::get_ref (v));
+ }
+
// blob, clob, nclob.
//
static void
@@ -444,10 +430,10 @@ namespace odb
struct big_int_value_traits<T, false>
{
static void
- set_value (T& v, const char* b, bool is_null)
+ set_value (T& v, const char* b, std::size_t n, bool is_null)
{
if (!is_null)
- v = static_cast<T> (details::number_to_int64 (b));
+ v = static_cast<T> (details::number_to_int64 (b, n));
else
v = 0;
}
@@ -464,10 +450,10 @@ namespace odb
struct big_int_value_traits<T, true>
{
static void
- set_value (T& v, const char* b, bool is_null)
+ set_value (T& v, const char* b, std::size_t n, bool is_null)
{
if (!is_null)
- v = static_cast<T> (details::number_to_uint64 (b));
+ v = static_cast<T> (details::number_to_uint64 (b, n));
else
v = 0;
}