aboutsummaryrefslogtreecommitdiff
path: root/odb/oracle/details
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 /odb/oracle/details
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.
Diffstat (limited to 'odb/oracle/details')
-rw-r--r--odb/oracle/details/number.cxx72
-rw-r--r--odb/oracle/details/number.hxx4
2 files changed, 33 insertions, 43 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);