diff options
-rw-r--r-- | odb/oracle/oracle-types.cxx | 197 | ||||
-rw-r--r-- | odb/oracle/oracle-types.hxx | 146 | ||||
-rw-r--r-- | odb/oracle/query.hxx | 124 | ||||
-rw-r--r-- | odb/oracle/statement.cxx | 445 | ||||
-rw-r--r-- | odb/oracle/statement.hxx | 9 |
5 files changed, 636 insertions, 285 deletions
diff --git a/odb/oracle/oracle-types.cxx b/odb/oracle/oracle-types.cxx index fad085f..9de57cd 100644 --- a/odb/oracle/oracle-types.cxx +++ b/odb/oracle/oracle-types.cxx @@ -14,10 +14,64 @@ namespace odb { namespace oracle { + // + // datetime + // + + datetime:: + ~datetime () + { + if (descriptor != 0 && (flags & descriptor_free)) + OCIDescriptorFree (descriptor, OCI_DTYPE_TIMESTAMP); + } + + datetime:: + datetime (datetime& x) + : environment (x.environment), + error (x.error), + descriptor (x.descriptor), + flags (x.flags), + year_ (x.year_), + month_ (x.month_), + day_ (x.day_), + hour_ (x.hour_), + minute_ (x.minute_), + second_ (x.second_), + nanosecond_ (x.nanosecond_) + { + x.descriptor = 0; + } + + datetime& datetime:: + operator= (datetime& x) + { + if (this != &x) + { + if (descriptor != 0 && (flags & descriptor_free)) + OCIDescriptorFree (descriptor, OCI_DTYPE_TIMESTAMP); + + environment = x.environment; + error = x.error; + descriptor = x.descriptor; + flags = x.flags; + year_ = x.year_; + month_ = x.month_; + day_ = x.day_; + hour_ = x.hour_; + minute_ = x.minute_; + second_ = x.second_; + nanosecond_ = x.nanosecond_; + + x.descriptor = 0; + } + + return *this; + } + void datetime:: get (sb2& y, ub1& m, ub1& d, ub1& h, ub1& minute, ub1& s, ub4& ns) const { - assert (descriptor.get () != 0); + assert (descriptor != 0); sword r (OCIDateTimeGetDate (environment, error, @@ -44,7 +98,7 @@ namespace odb void datetime:: set (sb2 y, ub1 m, ub1 d, ub1 h, ub1 minute, ub1 s, ub4 ns) { - if (descriptor.get () != 0) + if (descriptor != 0) { sword r (OCIDateTimeConstruct (environment, error, @@ -74,32 +128,54 @@ namespace odb } } - void datetime:: - set () + // + // interval_ym + // + + interval_ym:: + ~interval_ym () { - assert (descriptor.get () != 0); - - sword r (OCIDateTimeConstruct (environment, - error, - descriptor, - year_, - month_, - day_, - hour_, - minute_, - second_, - nanosecond_, - 0, - 0)); + if (descriptor != 0 && (flags & descriptor_free)) + OCIDescriptorFree (descriptor, OCI_DTYPE_INTERVAL_YM); + } - if (r != OCI_SUCCESS) - translate_error (error, r); + interval_ym:: + interval_ym (interval_ym& x) + : environment (x.environment), + error (x.error), + descriptor (x.descriptor), + flags (x.flags), + year_ (x.year_), + month_ (x.month_) + { + x.descriptor = 0; + } + + interval_ym& interval_ym:: + operator= (interval_ym& x) + { + if (this != &x) + { + if (descriptor != 0 && (flags & descriptor_free)) + OCIDescriptorFree (descriptor, OCI_DTYPE_INTERVAL_YM); + + environment = x.environment; + error = x.error; + descriptor = x.descriptor; + flags = x.flags; + year_ = x.year_; + month_ = x.month_; + + x.descriptor = 0; + } + + return *this; } void interval_ym:: get (sb4& y, sb4& m) const { - assert (descriptor.get () != 0); + assert (descriptor != 0); sword r (OCIIntervalGetYearMonth (environment, error, @@ -114,7 +190,7 @@ namespace odb void interval_ym:: set (sb4 y, sb4 m) { - if (descriptor.get () != 0) + if (descriptor != 0) { sword r (OCIIntervalSetYearMonth (environment, error, @@ -132,25 +208,60 @@ namespace odb } } - void interval_ym:: - set () + // + // interval_ds + // + + interval_ds:: + ~interval_ds () { - assert (descriptor.get () != 0); + if (descriptor != 0 && (flags & descriptor_free)) + OCIDescriptorFree (descriptor, OCI_DTYPE_INTERVAL_DS); + } - sword r (OCIIntervalSetYearMonth (environment, - error, - year_, - month_, - descriptor)); + interval_ds:: + interval_ds (interval_ds& x) + : environment (x.environment), + error (x.error), + descriptor (x.descriptor), + flags (x.flags), + day_ (x.day_), + hour_ (x.hour_), + minute_ (x.minute_), + second_ (x.second_), + nanosecond_ (x.nanosecond_) + { + x.descriptor = 0; + } - if (r != OCI_SUCCESS) - translate_error (error, r); + interval_ds& interval_ds:: + operator= (interval_ds& x) + { + if (this != &x) + { + if (descriptor != 0 && (flags & descriptor_free)) + OCIDescriptorFree (descriptor, OCI_DTYPE_INTERVAL_DS); + + environment = x.environment; + error = x.error; + descriptor = x.descriptor; + flags = x.flags; + day_ = x.day_; + hour_ = x.hour_; + minute_ = x.minute_; + second_ = x.second_; + nanosecond_ = x.nanosecond_; + + x.descriptor = 0; + } + + return *this; } void interval_ds:: get (sb4& d, sb4& h, sb4& m, sb4& s, sb4& ns) const { - assert (descriptor.get () != 0); + assert (descriptor != 0); sword r (OCIIntervalGetDaySecond (environment, error, @@ -168,7 +279,7 @@ namespace odb void interval_ds:: set (sb4 d, sb4 h, sb4 m, sb4 s, sb4 ns) { - if (descriptor.get () != 0) + if (descriptor != 0) { sword r (OCIIntervalSetDaySecond (environment, error, @@ -191,23 +302,5 @@ namespace odb nanosecond_ = ns; } } - - void interval_ds:: - set () - { - assert (descriptor.get () != 0); - - sword r (OCIIntervalSetDaySecond (environment, - error, - day_, - hour_, - minute_, - second_, - nanosecond_, - descriptor)); - - if (r != OCI_SUCCESS) - translate_error (error, r); - } } } diff --git a/odb/oracle/oracle-types.hxx b/odb/oracle/oracle-types.hxx index a4500d3..5e08a87 100644 --- a/odb/oracle/oracle-types.hxx +++ b/odb/oracle/oracle-types.hxx @@ -169,90 +169,6 @@ namespace odb } }; - class LIBODB_ORACLE_EXPORT datetime_auto_descriptor: - public auto_descriptor<OCIDateTime, dt_timestamp> - { - typedef auto_descriptor<OCIDateTime, dt_timestamp> base; - - public: - datetime_auto_descriptor (OCIDateTime* d = 0): - base (d) - { - } - - datetime_auto_descriptor (datetime_auto_descriptor& x): - base (x.d_) - { - x.d_ = 0; - } - - datetime_auto_descriptor& - operator= (datetime_auto_descriptor& x) - { - OCIDateTime* l (x.d_); - x.d_ = 0; - reset (l); - - return *this; - } - }; - - class LIBODB_ORACLE_EXPORT interval_ym_auto_descriptor: - public auto_descriptor<OCIInterval, dt_interval_ym> - { - typedef auto_descriptor<OCIInterval, dt_interval_ym> base; - - public: - interval_ym_auto_descriptor (OCIInterval* d = 0): - base (d) - { - } - - interval_ym_auto_descriptor (interval_ym_auto_descriptor& x): - base (x.d_) - { - x.d_ = 0; - } - - interval_ym_auto_descriptor& - operator= (interval_ym_auto_descriptor& x) - { - OCIInterval* l (x.d_); - x.d_ = 0; - reset (l); - - return *this; - } - }; - - class LIBODB_ORACLE_EXPORT interval_ds_auto_descriptor: - public auto_descriptor<OCIInterval, dt_interval_ds> - { - typedef auto_descriptor<OCIInterval, dt_interval_ds> base; - - public: - interval_ds_auto_descriptor (OCIInterval* d = 0): - base (d) - { - } - - interval_ds_auto_descriptor (interval_ds_auto_descriptor& x): - base (x.d_) - { - x.d_ = 0; - } - - interval_ds_auto_descriptor& - operator= (interval_ds_auto_descriptor& x) - { - OCIInterval* l (x.d_); - x.d_ = 0; - reset (l); - - return *this; - } - }; - // // The OCIDateTime and OCIInterval APIs require that an environment and // error handle be passed to any function that manipulates an OCIDateTime @@ -265,6 +181,11 @@ namespace odb // consistency. // + // Descriptor management flags. + // + const unsigned short descriptor_cache = 0x01; + const unsigned short descriptor_free = 0x02; + struct LIBODB_ORACLE_EXPORT datetime { void @@ -285,16 +206,25 @@ namespace odb ub1 second, ub4 nanosecond); - void - set (); - public: OCIEnv* environment; OCIError* error; + OCIDateTime* descriptor; + + unsigned short flags; + + public: + datetime (unsigned short f = descriptor_cache | descriptor_free) + : descriptor (0), flags (f) + { + } - datetime_auto_descriptor descriptor; + datetime (datetime&); + datetime& operator= (datetime&); - private: + ~datetime (); + + public: sb2 year_; ub1 month_; ub1 day_; @@ -312,16 +242,25 @@ namespace odb void set (sb4 year, sb4 month); - void - set (); - public: OCIEnv* environment; OCIError* error; + OCIInterval* descriptor; + + unsigned short flags; + + public: + interval_ym (unsigned short f = descriptor_cache | descriptor_free) + : descriptor (0), flags (f) + { + } + + interval_ym (interval_ym&); + interval_ym& operator= (interval_ym&); - interval_ym_auto_descriptor descriptor; + ~interval_ym (); - private: + public: sb4 year_; sb4 month_; }; @@ -342,16 +281,25 @@ namespace odb sb4 second, sb4 nanosecond); - void - set (); - public: OCIEnv* environment; OCIError* error; + OCIInterval* descriptor; + + unsigned short flags; + + public: + interval_ds (unsigned short f = descriptor_cache | descriptor_free) + : descriptor (0), flags (f) + { + } - interval_ds_auto_descriptor descriptor; + interval_ds (interval_ds&); + interval_ds& operator= (interval_ds&); - private: + ~interval_ds (); + + public: sb4 day_; sb4 hour_; sb4 minute_; diff --git a/odb/oracle/query.hxx b/odb/oracle/query.hxx index a7bacbe..d92296c 100644 --- a/odb/oracle/query.hxx +++ b/odb/oracle/query.hxx @@ -1436,8 +1436,19 @@ namespace odb template <typename T> struct query_param_impl<T, id_timestamp>: query_param { - query_param_impl (ref_bind<T> r) : query_param (&r.ref) {} - query_param_impl (val_bind<T> v) : query_param (0) {init (v.val);} + query_param_impl (ref_bind<T> r) + : query_param (&r.ref), + image_ (descriptor_cache) // Cache, don't free. + { + } + + query_param_impl (val_bind<T> v) + : query_param (0), + image_ (0) // Don't cache, don't free. + + { + init (v.val); + } virtual bool init () @@ -1451,8 +1462,8 @@ namespace odb { b->type = bind_type::timestamp; b->buffer = &image_; - b->capacity = sizeof (image_); - b->size = &size_; + b->capacity = sizeof (OCIDateTime*); + b->size = 0; } private: @@ -1460,18 +1471,105 @@ namespace odb init (const T& v) { bool dummy; - std::size_t size (0); - value_traits<T, id_timestamp>::set_image (image_, - size, - sizeof (image_), - dummy, - v); - size_ = static_cast<ub2> (size); + value_traits<T, id_timestamp>::set_image (image_, dummy, v); } private: - char image_[11]; - ub2 size_; + datetime image_; + }; + + // id_interval_ym + // + template <typename T> + struct query_param_impl<T, id_interval_ym>: query_param + { + query_param_impl (ref_bind<T> r) + : query_param (&r.ref), + image_ (descriptor_cache) // Cache, don't free. + { + } + + query_param_impl (val_bind<T> v) + : query_param (0), + image_ (0) // Don't cache, don't free. + + { + init (v.val); + } + + virtual bool + init () + { + init (*static_cast<const T*> (value_)); + return false; + } + + virtual void + bind (bind_type* b) + { + b->type = bind_type::interval_ym; + b->buffer = &image_; + b->capacity = sizeof (OCIInterval*); + b->size = 0; + } + + private: + void + init (const T& v) + { + bool dummy; + value_traits<T, id_interval_ym>::set_image (image_, dummy, v); + } + + private: + interval_ym image_; + }; + + // id_interval_ds + // + template <typename T> + struct query_param_impl<T, id_interval_ds>: query_param + { + query_param_impl (ref_bind<T> r) + : query_param (&r.ref), + image_ (descriptor_cache) // Cache, don't free. + { + } + + query_param_impl (val_bind<T> v) + : query_param (0), + image_ (0) // Don't cache, don't free. + + { + init (v.val); + } + + virtual bool + init () + { + init (*static_cast<const T*> (value_)); + return false; + } + + virtual void + bind (bind_type* b) + { + b->type = bind_type::interval_ds; + b->buffer = &image_; + b->capacity = sizeof (OCIInterval*); + b->size = 0; + } + + private: + void + init (const T& v) + { + bool dummy; + value_traits<T, id_interval_ds>::set_image (image_, dummy, v); + } + + private: + interval_ds image_; }; // id_string. diff --git a/odb/oracle/statement.cxx b/odb/oracle/statement.cxx index d1ab4be..67cec5e 100644 --- a/odb/oracle/statement.cxx +++ b/odb/oracle/statement.cxx @@ -144,18 +144,69 @@ namespace odb (t = conn_.database ().tracer ())) t->deallocate (conn_, *this); } + + // Unbind (free) parameter descriptors. + // + for (size_t i (0); i < usize_; ++i) + { + ub4 t; + bind& b (*udata_[i].bind); + + switch (b.type) + { + case bind::timestamp: + { + datetime* dt (static_cast<datetime*> (b.buffer)); + + if (dt->flags & descriptor_cache) + dt->descriptor = 0; + + t = OCI_DTYPE_TIMESTAMP; + break; + } + case bind::interval_ym: + { + interval_ym* iym (static_cast<interval_ym*> (b.buffer)); + + if (iym->flags & descriptor_cache) + iym->descriptor = 0; + + t = OCI_DTYPE_INTERVAL_YM; + break; + } + case bind::interval_ds: + { + interval_ds* ids (static_cast<interval_ds*> (b.buffer)); + + if (ids->flags & descriptor_cache) + ids->descriptor = 0; + + t = OCI_DTYPE_INTERVAL_DS; + break; + } + default: + { + assert (false); + return; + } + } + + OCIDescriptorFree (udata_[i].value, t); + } + + delete[] udata_; } statement:: statement (connection& conn, const string& text) - : conn_ (conn) + : conn_ (conn), udata_ (0), usize_ (0) { init (text.c_str (), text.size ()); } statement:: statement (connection& conn, const char* text) - : conn_ (conn) + : conn_ (conn), udata_ (0), usize_ (0) { init (text, strlen (text)); } @@ -212,6 +263,46 @@ namespace odb void statement:: bind_param (bind* b, size_t n) { + // Figure out how many unbind elements we will need and allocate them. + // + { + size_t un (0); + + for (size_t i (0); i < n; ++i) + { + switch (b[i].type) + { + case bind::timestamp: + { + datetime* dt (static_cast<datetime*> (b[i].buffer)); + if (dt->descriptor == 0 && (dt->flags & descriptor_free) == 0) + un++; + break; + } + case bind::interval_ym: + { + interval_ym* iym (static_cast<interval_ym*> (b[i].buffer)); + if (iym->descriptor == 0 && (iym->flags & descriptor_free) == 0) + un++; + break; + } + case bind::interval_ds: + { + interval_ds* ids (static_cast<interval_ds*> (b[i].buffer)); + if (ids->descriptor == 0 && (ids->flags & descriptor_free) == 0) + un++; + break; + } + default: + break; + } + } + + if (un != 0) + udata_ = new unbind[un]; + } + + sword r; OCIError* err (conn_.error_handle ()); OCIEnv* env (conn_.database ().environment ()); @@ -231,75 +322,172 @@ namespace odb { datetime* dt (static_cast<datetime*> (b->buffer)); - if (dt->descriptor.get () == 0) + if (dt->descriptor == 0) { void* d (0); - sword 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 (); - dt->descriptor.reset (static_cast<OCIDateTime*> (d)); - dt->environment = env; - dt->error = err; - dt->set (); + if (dt->flags & descriptor_cache) + { + dt->descriptor = static_cast<OCIDateTime*> (d); + dt->environment = env; + dt->error = err; + } + + // If the datetime instance is not responsible for the + // descriptor, then we have to arrange to have it freed + // using the unbind machinery. + // + if ((dt->flags & descriptor_free) == 0) + { + unbind& u (udata_[usize_++]); + + u.bind = b; + u.value = d; + value = &u.value; + } + else + value = &dt->descriptor; + + // Initialize the descriptor from the cached data. + // + r = OCIDateTimeConstruct (env, + err, + static_cast<OCIDateTime*> (d), + dt->year_, + dt->month_, + dt->day_, + dt->hour_, + dt->minute_, + dt->second_, + dt->nanosecond_, + 0, + 0); + + if (r != OCI_SUCCESS) + translate_error (err, r); } + else + value = &dt->descriptor; - value = &dt->descriptor.get (); break; } case bind::interval_ym: { interval_ym* iym (static_cast<interval_ym*> (b->buffer)); - if (iym->descriptor.get () == 0) + if (iym->descriptor == 0) { void* d (0); - sword 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 (); - iym->descriptor.reset (static_cast<OCIInterval*> (d)); - iym->environment = env; - iym->error = err; - iym->set (); + if (iym->flags & descriptor_cache) + { + iym->descriptor = static_cast<OCIInterval*> (d); + iym->environment = env; + iym->error = err; + } + + // If the interval_ym instance is not responsible for the + // descriptor, then we have to arrange to have it freed + // using the unbind machinery. + // + if ((iym->flags & descriptor_free) == 0) + { + unbind& u (udata_[usize_++]); + + u.bind = b; + u.value = d; + value = &u.value; + } + else + value = &iym->descriptor; + + // Initialize the descriptor from the cached data. + // + r = OCIIntervalSetYearMonth (env, + err, + iym->year_, + iym->month_, + static_cast<OCIInterval*> (d)); + + if (r != OCI_SUCCESS) + translate_error (err, r); } + else + value = &iym->descriptor; - value = &iym->descriptor.get (); break; } case bind::interval_ds: { interval_ds* ids (static_cast<interval_ds*> (b->buffer)); - if (ids->descriptor.get () == 0) + if (ids->descriptor == 0) { void* d (0); - sword 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 (); - ids->descriptor.reset (static_cast<OCIInterval*> (d)); - ids->environment = env; - ids->error = err; - ids->set (); + if (ids->flags & descriptor_cache) + { + ids->descriptor = static_cast<OCIInterval*> (d); + ids->environment = env; + ids->error = err; + } + + // If the interval_ds instance is not responsible for the + // descriptor, then we have to arrange to have it freed + // using the unbind machinery. + // + if ((ids->flags & descriptor_free) == 0) + { + unbind& u (udata_[usize_++]); + + u.bind = b; + u.value = d; + value = &u.value; + } + else + value = &ids->descriptor; + + // Initialize the descriptor from the cached data. + // + r = OCIIntervalSetDaySecond (env, + err, + ids->day_, + ids->hour_, + ids->minute_, + ids->second_, + ids->nanosecond_, + static_cast<OCIInterval*> (d)); + + if (r != OCI_SUCCESS) + translate_error (err, r); } + else + value = &ids->descriptor; - value = &ids->descriptor.get (); break; } case bind::blob: @@ -311,6 +499,11 @@ namespace odb 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; // When binding LOB parameters, the capacity must be greater than @@ -342,20 +535,19 @@ namespace odb } OCIBind* h (0); - - sword r (OCIBindByPos (stmt_, - &h, - err, - i, - value, - static_cast<sb4> (b->capacity), - param_sqlt_lookup[b->type], - b->indicator, - b->size, - 0, - 0, - 0, - callback ? OCI_DATA_AT_EXEC : OCI_DEFAULT)); + r = OCIBindByPos (stmt_, + &h, + err, + i, + value, + static_cast<sb4> (b->capacity), + param_sqlt_lookup[b->type], + b->indicator, + b->size, + 0, + 0, + 0, + callback ? OCI_DATA_AT_EXEC : OCI_DEFAULT); if (r == OCI_ERROR || r == OCI_INVALID_HANDLE) translate_error (err, r); @@ -392,6 +584,7 @@ namespace odb { ODB_POTENTIALLY_UNUSED (p); + sword r; OCIError* err (conn_.error_handle ()); OCIEnv* env (conn_.database ().environment ()); @@ -406,72 +599,81 @@ namespace odb { datetime* dt (static_cast<datetime*> (b->buffer)); - if (dt->descriptor.get () == 0) + if (dt->descriptor == 0) { + assert ((dt->flags & descriptor_cache) && + (dt->flags & descriptor_free)); + void* d (0); - sword 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 (); - dt->descriptor.reset (static_cast<OCIDateTime*> (d)); + dt->descriptor = static_cast<OCIDateTime*> (d); dt->environment = env; dt->error = err; } - value = &dt->descriptor.get (); + value = &dt->descriptor; break; } case bind::interval_ym: { interval_ym* iym (static_cast<interval_ym*> (b->buffer)); - if (iym->descriptor.get () == 0) + if (iym->descriptor == 0) { + assert ((iym->flags & descriptor_cache) && + (iym->flags & descriptor_free)); + void* d (0); - sword 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 (); - iym->descriptor.reset (static_cast<OCIInterval*> (d)); + iym->descriptor = static_cast<OCIInterval*> (d); iym->environment = env; iym->error = err; } - value = &iym->descriptor.get (); + value = &iym->descriptor; break; } case bind::interval_ds: { interval_ds* ids (static_cast<interval_ds*> (b->buffer)); - if (ids->descriptor.get () == 0) + if (ids->descriptor == 0) { + assert ((ids->flags & descriptor_cache) && + (ids->flags & descriptor_free)); + void* d (0); - sword 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 (); - ids->descriptor.reset (static_cast<OCIInterval*> (d)); + ids->descriptor = static_cast<OCIInterval*> (d); ids->environment = env; ids->error = err; } - value = &ids->descriptor.get (); + value = &ids->descriptor; break; } case bind::blob: @@ -484,7 +686,7 @@ namespace odb if (lob->get () == 0) { void* d (0); - sword r (OCIDescriptorAlloc (env, &d, OCI_DTYPE_LOB, 0, 0)); + r = OCIDescriptorAlloc (env, &d, OCI_DTYPE_LOB, 0, 0); if (r != OCI_SUCCESS) throw invalid_oci_handle (); @@ -514,17 +716,17 @@ namespace odb } OCIDefine* h (0); - sword r (OCIDefineByPos (stmt_, - &h, - err, - i, - value, - static_cast<sb4> (b->capacity), - result_sqlt_lookup[b->type], - b->indicator, - size, - 0, - OCI_DEFAULT)); + r = OCIDefineByPos (stmt_, + &h, + err, + i, + value, + static_cast<sb4> (b->capacity), + result_sqlt_lookup[b->type], + b->indicator, + size, + 0, + OCI_DEFAULT); if (r == OCI_ERROR || r == OCI_INVALID_HANDLE) translate_error (err, r); @@ -584,6 +786,7 @@ namespace odb { ODB_POTENTIALLY_UNUSED (p); + sword r; OCIEnv* env (conn_.database ().environment ()); for (size_t i (1); i <= c; ++i, ++b) @@ -596,66 +799,66 @@ namespace odb { datetime* dt (static_cast<datetime*> (b->buffer)); - if (dt->descriptor.get () == 0) + if (dt->descriptor == 0) { void* d (0); - sword 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 (); - dt->descriptor.reset (static_cast<OCIDateTime*> (d)); + dt->descriptor = static_cast<OCIDateTime*> (d); } - value = &dt->descriptor.get (); + value = &dt->descriptor; break; } case bind::interval_ym: { interval_ym* iym (static_cast<interval_ym*> (b->buffer)); - if (iym->descriptor.get () == 0) + if (iym->descriptor == 0) { void* d (0); - sword 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 (); - iym->descriptor.reset (static_cast<OCIInterval*> (d)); + iym->descriptor = static_cast<OCIInterval*> (d); } - value = &iym->descriptor.get (); + value = &iym->descriptor; break; } case bind::interval_ds: { interval_ds* ids (static_cast<interval_ds*> (b->buffer)); - if (ids->descriptor.get () == 0) + if (ids->descriptor == 0) { void* d (0); - sword 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 (); - ids->descriptor.reset (static_cast<OCIInterval*> (d)); + ids->descriptor = static_cast<OCIInterval*> (d); } - value = &ids->descriptor.get (); + value = &ids->descriptor; break; } case bind::blob: @@ -668,7 +871,7 @@ namespace odb if (lob->get () == 0) { void* d (0); - sword r (OCIDescriptorAlloc (env, &d, OCI_DTYPE_LOB, 0, 0)); + r = OCIDescriptorAlloc (env, &d, OCI_DTYPE_LOB, 0, 0); if (r != OCI_SUCCESS) throw invalid_oci_handle (); @@ -692,17 +895,17 @@ namespace odb OCIDefine* h (reinterpret_cast<OCIDefine*> (b->size)); OCIError* err (conn_.error_handle ()); - sword r (OCIDefineByPos (stmt_, - &h, - err, - i, - value, - static_cast<sb4> (b->capacity), - result_sqlt_lookup[b->type], - b->indicator, - 0, - 0, - OCI_DEFAULT)); + r = OCIDefineByPos (stmt_, + &h, + err, + i, + value, + static_cast<sb4> (b->capacity), + result_sqlt_lookup[b->type], + b->indicator, + 0, + 0, + OCI_DEFAULT); if (r == OCI_ERROR || r == OCI_INVALID_HANDLE) translate_error (err, r); diff --git a/odb/oracle/statement.hxx b/odb/oracle/statement.hxx index 8d97ab4..3687728 100644 --- a/odb/oracle/statement.hxx +++ b/odb/oracle/statement.hxx @@ -50,6 +50,12 @@ namespace odb init (const char* text, std::size_t text_size); protected: + struct unbind + { + oracle::bind* bind; // Corresponding bind entry. + void* value; // Actual value passed to OCIBindByPos. + }; + // Bind parameters for this statement. This function must only // be called once. Multiple calls to it will result in memory // leaks due to lost OCIBind resources. @@ -85,6 +91,9 @@ namespace odb protected: connection& conn_; auto_handle<OCIStmt> stmt_; + + unbind* udata_; + std::size_t usize_; }; class LIBODB_ORACLE_EXPORT generic_statement: public statement |