diff options
author | Boris Kolpackov <boris@codesynthesis.com> | 2012-01-12 09:02:40 +0200 |
---|---|---|
committer | Boris Kolpackov <boris@codesynthesis.com> | 2012-01-12 09:02:40 +0200 |
commit | edb5c55e828ad333ce1059b60b6fe97eface5dc4 (patch) | |
tree | adeaee9709478c0498d0cdd20511c095c95e070b | |
parent | 725d1a2f7952ea47ddaa8c9f056002879d470169 (diff) |
Implement callback data re-basing support for LOB result streaming
This is used by the query machinery when a copy of the image has
to be made. In this case stream_result() needs to use data from
the copy of the image, and not from the image that was bound to
the bind array.
-rw-r--r-- | odb/oracle/object-result.txx | 15 | ||||
-rw-r--r-- | odb/oracle/statement.cxx | 58 | ||||
-rw-r--r-- | odb/oracle/statement.hxx | 18 | ||||
-rw-r--r-- | odb/oracle/view-result.txx | 8 |
4 files changed, 82 insertions, 17 deletions
diff --git a/odb/oracle/object-result.txx b/odb/oracle/object-result.txx index 3cf4e3e..6b68fac 100644 --- a/odb/oracle/object-result.txx +++ b/odb/oracle/object-result.txx @@ -62,7 +62,13 @@ namespace odb use_copy_ ? *image_copy_ : statements_.image ()); object_traits::init (obj, i, db); - statement_->stream_result (); + + // If we are using a copy, make sure the callback information for + // LOB data also comes from the copy. + // + statement_->stream_result ( + use_copy_ ? &statements_.image () : 0, + use_copy_ ? image_copy_ : 0); // Initialize the id image and binding and load the rest of the object // (containers, etc). @@ -208,7 +214,12 @@ namespace odb use_copy_ ? *image_copy_ : statements_.image (), db); - statement_->stream_result (); + // If we are using a copy, make sure the callback information for + // LOB data also comes from the copy. + // + statement_->stream_result ( + use_copy_ ? &statements_.image () : 0, + use_copy_ ? image_copy_ : 0); object_traits::callback (db, obj, callback_event::post_load); } diff --git a/odb/oracle/statement.cxx b/odb/oracle/statement.cxx index bc31d1c..709d07a 100644 --- a/odb/oracle/statement.cxx +++ b/odb/oracle/statement.cxx @@ -971,22 +971,58 @@ namespace odb } void statement:: - stream_result (bind* b, size_t c) + stream_result (bind* b, size_t c, void* obase, void* nbase) { OCIError* err (conn_.error_handle ()); for (size_t i (0); i < c; ++i, ++b) { - // Only stream if the bind specifies a LOB type, and the LOB value is - // not NULL, and a result callback has been provided. + // Only stream if the bind specifies a LOB type. // - if ((b->type == bind::blob || - b->type == bind::clob || - b->type == bind::nclob) && - (b->indicator == 0 || *b->indicator != -1) && - b->callback->callback.result != 0) + if (b->type == bind::blob || + b->type == bind::clob || + b->type == bind::nclob) { - lob* l (static_cast<lob*> (b->buffer)); + lob* l; + sb2* ind; + lob_callback* cb; + + if (obase == 0) + { + l = static_cast<lob*> (b->buffer); + ind = b->indicator; + cb = b->callback; + } + else + { + // Re-base the pointers. + // + char* ob (static_cast<char*> (obase)); + char* nb (static_cast<char*> (nbase)); + + char* p (static_cast<char*> (b->buffer)); + assert (ob <= p); + l = reinterpret_cast<lob*> (nb + (p - ob)); + + if (b->indicator == 0) + ind = 0; + else + { + p = reinterpret_cast<char*> (b->indicator); + assert (ob <= p); + ind = reinterpret_cast<sb2*> (nb + (p - ob)); + } + + p = reinterpret_cast<char*> (b->callback); + assert (ob <= p); + cb = reinterpret_cast<lob_callback*> (nb + (p - ob)); + } + + // Nothing to do if the LOB value is NULL or the result callback + // hasn't been provided. + // + if ((ind != 0 && *ind == -1) || cb->callback.result == 0) + continue; ub4 position (0); // Position context. ub1 piece (OCI_FIRST_PIECE); @@ -1040,8 +1076,8 @@ namespace odb // OCI generates and ORA-24343 error when an error code is // returned from a user callback. We simulate this. // - if (!(*b->callback->callback.result) ( - b->callback->context.result, + if (!(*cb->callback.result) ( + cb->context.result, &position, lob_buffer.data (), static_cast<ub4> (read), diff --git a/odb/oracle/statement.hxx b/odb/oracle/statement.hxx index fa2e879..6aa16e9 100644 --- a/odb/oracle/statement.hxx +++ b/odb/oracle/statement.hxx @@ -84,9 +84,18 @@ namespace odb std::size_t lob_prefetch_size = 0); // Stream the result LOBs, calling user callbacks where necessary. + // The old_base and new_base arguments can be used to "re-base" the + // lob_callback struct pointer (stored in bind::callback), the lob + // struct pointer (stored in bind::buffer), and the indicator value + // pointer (stored in bind::indicator). This is used by the query + // machinery to cause stream_result() to use the callback information + // from a copy of the image instead of the bound image. // void - stream_result (bind*, std::size_t count); + stream_result (bind*, + std::size_t count, + void* old_base = 0, + void* new_base = 0); protected: connection& conn_; @@ -162,9 +171,12 @@ namespace odb fetch (); void - stream_result () + stream_result (void* old_base = 0, void* new_base = 0) { - statement::stream_result (result_.bind, result_.count); + statement::stream_result (result_.bind, + result_.count, + old_base, + new_base); } void diff --git a/odb/oracle/view-result.txx b/odb/oracle/view-result.txx index 9488e2b..ed9b411 100644 --- a/odb/oracle/view-result.txx +++ b/odb/oracle/view-result.txx @@ -52,7 +52,13 @@ namespace odb use_copy_ ? *image_copy_ : statements_.image (), db); - statement_->stream_result (); + // If we are using a copy, make sure the callback information for + // LOB data also comes from the copy. + // + statement_->stream_result ( + use_copy_ ? &statements_.image () : 0, + use_copy_ ? image_copy_ : 0); + view_traits::callback (db, view, callback_event::post_load); } |