aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--odb/oracle/oracle-types.cxx197
-rw-r--r--odb/oracle/oracle-types.hxx146
-rw-r--r--odb/oracle/query.hxx124
-rw-r--r--odb/oracle/statement.cxx445
-rw-r--r--odb/oracle/statement.hxx9
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