From 65b89ab22d0d2fe3cff2f3c071b3628b786afeb5 Mon Sep 17 00:00:00 2001 From: Constantin Michael Date: Tue, 15 Nov 2011 16:23:39 +0200 Subject: 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. --- odb/oracle/oracle-types.cxx | 38 +++++++++++++ odb/oracle/oracle-types.hxx | 49 ++++++---------- odb/oracle/statement.cxx | 134 ++++++++++++++++++++++---------------------- 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 +#include + #include #include #include @@ -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 + struct LIBODB_ORACLE_EXPORT lob { - typedef auto_descriptor 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 (context)); - - details::buffer* lob_buffer ( - reinterpret_cast (b.buffer)); + lob* l (static_cast (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 (b.size), + l->position_context, const_cast (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 (sizeof (OCIDateTime*)); + break; } case bind::interval_ym: @@ -433,6 +435,8 @@ namespace odb else value = &iym->descriptor; + capacity = static_cast (sizeof (OCIInterval*)); + break; } case bind::interval_ds: @@ -491,23 +495,33 @@ namespace odb else value = &ids->descriptor; + capacity = static_cast (sizeof (OCIInterval*)); + break; } case bind::blob: case bind::clob: case bind::nclob: { - details::buffer& lob_buffer (conn_.lob_buffer ()); + lob* l (static_cast (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 (b->capacity); + size = b->size; break; } @@ -543,10 +558,10 @@ namespace odb err, i, value, - static_cast (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 (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 (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 (sizeof (OCIInterval*)); + break; } case bind::blob: case bind::clob: case bind::nclob: { - auto_descriptor* lob ( - static_cast*> (b->buffer)); + lob* l (static_cast (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 (d)); + l->locator = static_cast (d); } - value = &lob->get (); + value = &l->locator; + capacity = static_cast (sizeof (OCILobLocator*)); + break; } default: @@ -712,6 +723,7 @@ namespace odb b->capacity <= 4); #endif value = b->buffer; + capacity = static_cast (b->capacity); size = b->size; break; @@ -724,7 +736,7 @@ namespace odb err, i, value, - static_cast (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* lob ( - reinterpret_cast*> (b->buffer)); + lob* l (static_cast (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 (d)); + l->locator = static_cast (d); } - value = &lob->get (); + value = &l->locator; break; } default: @@ -903,7 +902,7 @@ namespace odb err, i, value, - static_cast (b->capacity), + static_cast (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& locator ( - *reinterpret_cast*> (b->buffer)); + lob* l (static_cast (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, -- cgit v1.1