aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorConstantin Michael <constantin@codesynthesis.com>2011-11-15 16:23:39 +0200
committerConstantin Michael <constantin@codesynthesis.com>2011-11-16 12:48:18 +0200
commit65b89ab22d0d2fe3cff2f3c071b3628b786afeb5 (patch)
tree73266e783901646ec1bdc8e5fc68f4b48ebf293d
parentf8d8de4ef1ec010cb81c75b00d8229204e7b1788 (diff)
Refactor LOB descriptor, callback context, and temporary buffer handling
Due to image sharing amongst container statements, LOB binding placeholders cannot be shared between parameter and result versions of a bind.
-rw-r--r--odb/oracle/oracle-types.cxx38
-rw-r--r--odb/oracle/oracle-types.hxx49
-rw-r--r--odb/oracle/statement.cxx134
3 files changed, 120 insertions, 101 deletions
diff --git a/odb/oracle/oracle-types.cxx b/odb/oracle/oracle-types.cxx
index 9de57cd..9f2ca3e 100644
--- a/odb/oracle/oracle-types.cxx
+++ b/odb/oracle/oracle-types.cxx
@@ -15,6 +15,44 @@ namespace odb
namespace oracle
{
//
+ // lob
+ //
+
+ lob::
+ ~lob ()
+ {
+ if (locator != 0)
+ OCIDescriptorFree (locator, OCI_DTYPE_LOB);
+ }
+
+ lob::
+ lob (lob& x)
+ : locator (x.locator),
+ buffer (x.buffer),
+ position_context (x.position_context)
+ {
+ x.locator = 0;
+ }
+
+ lob& lob::
+ operator= (lob& x)
+ {
+ if (this != &x)
+ {
+ if (locator != 0)
+ OCIDescriptorFree (locator, OCI_DTYPE_LOB);
+
+ locator = x.locator;
+ buffer = x.buffer;
+ position_context = x.position_context;
+
+ x.locator = 0;
+ }
+
+ return *this;
+ }
+
+ //
// datetime
//
diff --git a/odb/oracle/oracle-types.hxx b/odb/oracle/oracle-types.hxx
index 5e08a87..01e5956 100644
--- a/odb/oracle/oracle-types.hxx
+++ b/odb/oracle/oracle-types.hxx
@@ -8,6 +8,8 @@
#include <odb/pre.hxx>
+#include <odb/details/buffer.hxx>
+
#include <odb/oracle/version.hxx>
#include <odb/oracle/oracle-fwd.hxx>
#include <odb/oracle/auto-descriptor.hxx>
@@ -103,11 +105,9 @@ namespace odb
};
buffer_type type; // The type stored by buffer.
- void* buffer; // Data buffer pointer. When result callbacks are in
- // use, this is interpreted as a lob_auto_descriptor*.
- ub2* size; // The number of bytes in buffer. When parameter
- // callbacks are in use, this is interpreted as a ub4*
- // indicating the current position. For LOB result
+ void* buffer; // Data buffer pointer. For LOB type bindings, this is
+ // interpreted as an oracle::lob*.
+ ub2* size; // The number of bytes in buffer. For LOB result
// bindings, this is interpreted as the OCIDefine
// handle associated with the LOB result parameter.
ub4 capacity; // The maximum number of bytes that can be stored in
@@ -134,39 +134,22 @@ namespace odb
void* context;
};
+ // The lob structure wraps data required for both parameter and result
+ // LOB type bindings.
//
- // These specialized auto_descriptor classes allows for transparent
- // transferal of descriptors between auto_descriptor instances. This
- // simplifies the implementation of a private copy of the shared image
- // associated with queries.
- //
-
- class LIBODB_ORACLE_EXPORT lob_auto_descriptor:
- public auto_descriptor<OCILobLocator>
+ struct LIBODB_ORACLE_EXPORT lob
{
- typedef auto_descriptor <OCILobLocator> base;
-
- public:
- lob_auto_descriptor (OCILobLocator* l = 0)
- : base (l)
- {
- }
+ lob (): locator (0), buffer (0), position_context (0) {}
- lob_auto_descriptor (lob_auto_descriptor& x)
- : base (x.d_)
- {
- x.d_ = 0;
- }
+ lob (lob&);
+ lob& operator= (lob&);
- lob_auto_descriptor&
- operator= (lob_auto_descriptor& x)
- {
- OCILobLocator* l (x.d_);
- x.d_ = 0;
- reset (l);
+ ~lob ();
- return *this;
- }
+ public:
+ OCILobLocator* locator;
+ details::buffer* buffer;
+ ub4* position_context;
};
//
diff --git a/odb/oracle/statement.cxx b/odb/oracle/statement.cxx
index d056a76..33af160 100644
--- a/odb/oracle/statement.cxx
+++ b/odb/oracle/statement.cxx
@@ -80,9 +80,7 @@ namespace odb
void** indicator)
{
bind& b (*static_cast<bind*> (context));
-
- details::buffer* lob_buffer (
- reinterpret_cast<details::buffer*> (b.buffer));
+ lob* l (static_cast<lob*> (b.buffer));
// Only call the callback if the parameter is not NULL.
//
@@ -90,12 +88,12 @@ namespace odb
{
chunk_position pos;
if (!(*b.callback->param) (b.context->param,
- reinterpret_cast<ub4*> (b.size),
+ l->position_context,
const_cast<const void**> (buffer),
size,
&pos,
- lob_buffer->data (),
- lob_buffer->capacity ()))
+ l->buffer->data (),
+ l->buffer->capacity ()))
return OCI_ERROR;
switch (pos)
@@ -313,7 +311,9 @@ namespace odb
for (ub4 i (1); i < n; ++i, ++b)
{
- void* value (0);
+ void* value;
+ sb4 capacity;
+ ub2* size (0);
bool callback (b->callback != 0);
switch (b->type)
@@ -378,6 +378,8 @@ namespace odb
else
value = &dt->descriptor;
+ capacity = static_cast<sb4> (sizeof (OCIDateTime*));
+
break;
}
case bind::interval_ym:
@@ -433,6 +435,8 @@ namespace odb
else
value = &iym->descriptor;
+ capacity = static_cast<sb4> (sizeof (OCIInterval*));
+
break;
}
case bind::interval_ds:
@@ -491,23 +495,33 @@ namespace odb
else
value = &ids->descriptor;
+ capacity = static_cast<sb4> (sizeof (OCIInterval*));
+
break;
}
case bind::blob:
case bind::clob:
case bind::nclob:
{
- details::buffer& lob_buffer (conn_.lob_buffer ());
+ lob* l (static_cast<lob*> (b->buffer));
+
+ if (l->buffer == 0)
+ {
+ details::buffer& lob_buffer (conn_.lob_buffer ());
- if (lob_buffer.capacity () == 0)
- lob_buffer.capacity (4096);
+ if (lob_buffer.capacity () == 0)
+ lob_buffer.capacity (4096);
- // Generally, we should not modify the binding structure or
- // image since that would break the thread-safety guarantee
- // of the query expression. However, in Oracle, LOBs cannot
- // be used in queries so we can make an exception here.
- //
- b->buffer = &lob_buffer;
+ // Generally, we should not modify the image since that would
+ // break the thread-safety guarantee of the query expression.
+ // However, in Oracle, LOBs cannot be used in queries so we can
+ // make an exception here.
+ //
+ l->buffer = &lob_buffer;
+ }
+
+ assert (callback);
+ value = 0;
// When binding LOB parameters, the capacity must be greater than
// 4000 and less than the maximum LOB length in bytes. If it is
@@ -515,7 +529,7 @@ namespace odb
// to be irrelevant to OCI bind behaviour for LOB parameters when
// used with callbacks.
//
- b->capacity = 4096;
+ capacity = 4096;
break;
}
@@ -530,8 +544,9 @@ namespace odb
assert ((b->type != bind::integer &&
b->type != bind::uinteger) || b->capacity <= 4);
#endif
- if (!callback)
- value = b->buffer;
+ value = callback ? 0 : b->buffer;
+ capacity = static_cast<sb4> (b->capacity);
+ size = b->size;
break;
}
@@ -543,10 +558,10 @@ namespace odb
err,
i,
value,
- static_cast<sb4> (b->capacity),
+ capacity,
param_sqlt_lookup[b->type],
b->indicator,
- b->size,
+ size,
0,
0,
0,
@@ -593,7 +608,8 @@ namespace odb
for (size_t i (1); i <= c; ++i, ++b)
{
- void* value (0);
+ void* value;
+ sb4 capacity;
ub2* size (0);
switch (b->type)
@@ -608,11 +624,7 @@ namespace odb
(dt->flags & descriptor_free));
void* d (0);
- r = OCIDescriptorAlloc (env,
- &d,
- OCI_DTYPE_TIMESTAMP,
- 0,
- 0);
+ r = OCIDescriptorAlloc (env, &d, OCI_DTYPE_TIMESTAMP, 0, 0);
if (r != OCI_SUCCESS)
throw invalid_oci_handle ();
@@ -623,6 +635,8 @@ namespace odb
}
value = &dt->descriptor;
+ capacity = static_cast<sb4> (sizeof (OCIDateTime*));
+
break;
}
case bind::interval_ym:
@@ -635,11 +649,7 @@ namespace odb
(iym->flags & descriptor_free));
void* d (0);
- r = OCIDescriptorAlloc (env,
- &d,
- OCI_DTYPE_INTERVAL_YM,
- 0,
- 0);
+ r = OCIDescriptorAlloc (env, &d, OCI_DTYPE_INTERVAL_YM, 0, 0);
if (r != OCI_SUCCESS)
throw invalid_oci_handle ();
@@ -650,6 +660,8 @@ namespace odb
}
value = &iym->descriptor;
+ capacity = static_cast<sb4> (sizeof (OCIInterval*));
+
break;
}
case bind::interval_ds:
@@ -662,11 +674,7 @@ namespace odb
(ids->flags & descriptor_free));
void* d (0);
- r = OCIDescriptorAlloc (env,
- &d,
- OCI_DTYPE_INTERVAL_DS,
- 0,
- 0);
+ r = OCIDescriptorAlloc (env, &d, OCI_DTYPE_INTERVAL_DS, 0, 0);
if (r != OCI_SUCCESS)
throw invalid_oci_handle ();
@@ -677,16 +685,17 @@ namespace odb
}
value = &ids->descriptor;
+ capacity = static_cast<sb4> (sizeof (OCIInterval*));
+
break;
}
case bind::blob:
case bind::clob:
case bind::nclob:
{
- auto_descriptor<OCILobLocator>* lob (
- static_cast<auto_descriptor<OCILobLocator>*> (b->buffer));
+ lob* l (static_cast<lob*> (b->buffer));
- if (lob->get () == 0)
+ if (l->locator == 0)
{
void* d (0);
r = OCIDescriptorAlloc (env, &d, OCI_DTYPE_LOB, 0, 0);
@@ -694,10 +703,12 @@ namespace odb
if (r != OCI_SUCCESS)
throw invalid_oci_handle ();
- lob->reset (static_cast<OCILobLocator*> (d));
+ l->locator = static_cast<OCILobLocator*> (d);
}
- value = &lob->get ();
+ value = &l->locator;
+ capacity = static_cast<sb4> (sizeof (OCILobLocator*));
+
break;
}
default:
@@ -712,6 +723,7 @@ namespace odb
b->capacity <= 4);
#endif
value = b->buffer;
+ capacity = static_cast<sb4> (b->capacity);
size = b->size;
break;
@@ -724,7 +736,7 @@ namespace odb
err,
i,
value,
- static_cast<sb4> (b->capacity),
+ capacity,
result_sqlt_lookup[b->type],
b->indicator,
size,
@@ -794,7 +806,7 @@ namespace odb
for (size_t i (1); i <= c; ++i, ++b)
{
- void* value (0);
+ void* value;
switch (b->type)
{
@@ -805,11 +817,7 @@ namespace odb
if (dt->descriptor == 0)
{
void* d (0);
- r = OCIDescriptorAlloc (env,
- &d,
- OCI_DTYPE_TIMESTAMP,
- 0,
- 0);
+ r = OCIDescriptorAlloc (env, &d, OCI_DTYPE_TIMESTAMP, 0, 0);
if (r != OCI_SUCCESS)
throw invalid_oci_handle ();
@@ -827,11 +835,7 @@ namespace odb
if (iym->descriptor == 0)
{
void* d (0);
- r = OCIDescriptorAlloc (env,
- &d,
- OCI_DTYPE_INTERVAL_YM,
- 0,
- 0);
+ r = OCIDescriptorAlloc (env, &d, OCI_DTYPE_INTERVAL_YM, 0, 0);
if (r != OCI_SUCCESS)
throw invalid_oci_handle ();
@@ -849,11 +853,7 @@ namespace odb
if (ids->descriptor == 0)
{
void* d (0);
- r = OCIDescriptorAlloc (env,
- &d,
- OCI_DTYPE_INTERVAL_DS,
- 0,
- 0);
+ r = OCIDescriptorAlloc (env, &d, OCI_DTYPE_INTERVAL_DS, 0, 0);
if (r != OCI_SUCCESS)
throw invalid_oci_handle ();
@@ -868,10 +868,9 @@ namespace odb
case bind::clob:
case bind::nclob:
{
- auto_descriptor<OCILobLocator>* lob (
- reinterpret_cast<auto_descriptor<OCILobLocator>*> (b->buffer));
+ lob* l (static_cast<lob*> (b->buffer));
- if (lob->get () == 0)
+ if (l->locator == 0)
{
void* d (0);
r = OCIDescriptorAlloc (env, &d, OCI_DTYPE_LOB, 0, 0);
@@ -879,10 +878,10 @@ namespace odb
if (r != OCI_SUCCESS)
throw invalid_oci_handle ();
- lob->reset (static_cast <OCILobLocator*> (d));
+ l->locator = static_cast<OCILobLocator*> (d);
}
- value = &lob->get ();
+ value = &l->locator;
break;
}
default:
@@ -903,7 +902,7 @@ namespace odb
err,
i,
value,
- static_cast<sb4> (b->capacity),
+ static_cast<sb4> (sizeof (void*)),
result_sqlt_lookup[b->type],
b->indicator,
0,
@@ -961,8 +960,7 @@ namespace odb
(b->indicator == 0 || *b->indicator != -1) &&
b->callback->result != 0)
{
- auto_descriptor<OCILobLocator>& locator (
- *reinterpret_cast<auto_descriptor<OCILobLocator>*> (b->buffer));
+ lob* l (static_cast<lob*> (b->buffer));
ub4 position (0); // Position context.
ub1 piece (OCI_FIRST_PIECE);
@@ -987,7 +985,7 @@ namespace odb
{
r = OCILobRead2 (conn_.handle (),
err,
- locator,
+ l->locator,
&read,
0,
1,