aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2012-01-12 09:02:40 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2012-01-12 09:02:40 +0200
commitedb5c55e828ad333ce1059b60b6fe97eface5dc4 (patch)
treeadeaee9709478c0498d0cdd20511c095c95e070b
parent725d1a2f7952ea47ddaa8c9f056002879d470169 (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.txx15
-rw-r--r--odb/oracle/statement.cxx58
-rw-r--r--odb/oracle/statement.hxx18
-rw-r--r--odb/oracle/view-result.txx8
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);
}