aboutsummaryrefslogtreecommitdiff
path: root/odb/oracle/statement.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'odb/oracle/statement.cxx')
-rw-r--r--odb/oracle/statement.cxx360
1 files changed, 224 insertions, 136 deletions
diff --git a/odb/oracle/statement.cxx b/odb/oracle/statement.cxx
index 10fa3a6..e932dab 100644
--- a/odb/oracle/statement.cxx
+++ b/odb/oracle/statement.cxx
@@ -334,7 +334,7 @@ namespace odb
}
ub4 statement::
- bind_param (bind* b, size_t n, size_t batch, size_t skip)
+ bind_param (bind* b, size_t n, size_t batch, size_t skip)
{
// Figure out how many unbind elements we will need and allocate them.
//
@@ -712,7 +712,7 @@ namespace odb
// Set array information if we have a batch.
//
- if (skip != 0)
+ if (batch != 1)
{
ub4 s (static_cast<ub4> (skip));
@@ -1215,6 +1215,143 @@ namespace odb
}
//
+ // bulk_statement
+ //
+
+ bulk_statement::
+ ~bulk_statement () {}
+
+ sword bulk_statement::
+ execute (size_t n, multiple_exceptions* mex)
+ {
+ {
+ odb::tracer* t;
+ if ((t = conn_.transaction_tracer ()) ||
+ (t = conn_.tracer ()) ||
+ (t = conn_.database ().tracer ()))
+ t->execute (conn_, *this);
+ }
+
+ mex_ = mex;
+
+ OCIError* err (conn_.error_handle ());
+ sword r (OCIStmtExecute (conn_.handle (),
+ stmt_,
+ err,
+ static_cast<ub4> (n),
+ 0,
+ 0,
+ 0,
+ n == 1 ? OCI_DEFAULT : OCI_BATCH_ERRORS));
+
+ // If the statement failed as a whole, assume only the first row
+ // was attempted (and failed). Otherwise, in the batch errors mode,
+ // all the rows are always attempted (let's hope this is true).
+ //
+ i_ = 0;
+ n_ = (r == OCI_ERROR || r == OCI_INVALID_HANDLE ? 1 : n);
+
+ if (mex_ != 0)
+ {
+ mex_->current (i_);
+ mex_->attempted (n_);
+ }
+
+ if (r == OCI_ERROR || r == OCI_INVALID_HANDLE)
+ {
+ if (mex_ != 0)
+ mex_->fatal (true); // An incomplete batch is always fatal.
+
+ return r;
+ }
+
+ // Initialize the batch status array.
+ //
+ if (n_ != 1)
+ {
+ sword r; // Our own return code.
+
+ // Clear the status array.
+ //
+ for (size_t i (0); i != n_; ++i)
+ status_[i].reset ();
+
+ // @@ TODO allocate per batch stmt (maybe lazily here if NULL).
+ //
+ auto_handle<OCIError> err1;
+ {
+ OCIError* e (0);
+ r = OCIHandleAlloc (conn_.database ().environment (),
+ reinterpret_cast<void**> (&e),
+ OCI_HTYPE_ERROR,
+ 0,
+ 0);
+
+ if (r != OCI_SUCCESS)
+ throw invalid_oci_handle ();
+
+ err1.reset (e);
+ }
+
+ ub4 en;
+ r = OCIAttrGet (stmt_,
+ OCI_HTYPE_STMT,
+ &en,
+ 0,
+ OCI_ATTR_NUM_DML_ERRORS,
+ err1);
+
+ if (r == OCI_ERROR || r == OCI_INVALID_HANDLE)
+ translate_error (err1, r);
+
+ cerr << "_NUM_DML_ERRORS: " << en << endl;
+
+ for (ub4 i (0); i != en; ++i)
+ {
+ auto_handle<OCIError> err2;
+
+ {
+ OCIError* e (0);
+ r = OCIHandleAlloc (conn_.database ().environment (),
+ reinterpret_cast<void**> (&e),
+ OCI_HTYPE_ERROR,
+ 0,
+ 0);
+
+ if (r != OCI_SUCCESS)
+ throw invalid_oci_handle ();
+
+ err2.reset (e);
+ }
+
+ OCIError* tmp (err2);
+ r = OCIParamGet (err, // from
+ OCI_HTYPE_ERROR,
+ err1, // diagnostics
+ reinterpret_cast<void**> (&tmp), // to
+ i);
+
+ if (r == OCI_ERROR || r == OCI_INVALID_HANDLE)
+ translate_error (err1, r);
+
+ ub4 row;
+ r = OCIAttrGet (err2,
+ OCI_HTYPE_ERROR,
+ &row,
+ 0,
+ OCI_ATTR_DML_ROW_OFFSET,
+ err1);
+
+ status_[row].reset (err2.release ());
+
+ cerr << "[" << row << "]" << endl;
+ }
+ }
+
+ return r;
+ }
+
+ //
// generic_statement
//
@@ -1697,10 +1834,11 @@ namespace odb
bool process,
binding& param,
binding* returning)
- : statement (conn,
- text, statement_insert,
- (process ? &param : 0), false),
- ret_ (returning), status_ (param.status)
+ : bulk_statement (conn,
+ text, statement_insert,
+ (process ? &param : 0), false,
+ param.batch, param.status),
+ ret_ (returning)
{
init (param);
}
@@ -1711,10 +1849,11 @@ namespace odb
bool process,
binding& param,
binding* returning)
- : statement (conn,
- text, statement_insert,
- (process ? &param : 0), false),
- ret_ (returning), status_ (param.status)
+ : bulk_statement (conn,
+ text, statement_insert,
+ (process ? &param : 0), false,
+ param.batch, param.status),
+ ret_ (returning)
{
init (param);
}
@@ -1772,129 +1911,14 @@ namespace odb
size_t insert_statement::
execute (size_t n, multiple_exceptions* mex)
{
- {
- odb::tracer* t;
- if ((t = conn_.transaction_tracer ()) ||
- (t = conn_.tracer ()) ||
- (t = conn_.database ().tracer ()))
- t->execute (conn_, *this);
- }
-
- mex_ = mex;
- OCIError* err (conn_.error_handle ());
-
- sword r (OCIStmtExecute (conn_.handle (),
- stmt_,
- err,
- static_cast<ub4> (n),
- 0,
- 0,
- 0,
- n == 1 ? OCI_DEFAULT : OCI_BATCH_ERRORS));
-
- // If the statement failed as a whole, assume only the first row
- // was attempted (and failed). Otherwise, in the batch errors mode,
- // all the rows are always attempted (let's hope this is true).
- //
- i_ = 0;
- n_ = (r == OCI_ERROR || r == OCI_INVALID_HANDLE ? 1 : n);
-
- if (mex_ != 0)
- {
- mex_->current (i_);
- mex_->attempted (n_);
- }
+ sword r (bulk_statement::execute (n, mex));
if (r == OCI_ERROR || r == OCI_INVALID_HANDLE)
{
- if (mex_ != 0)
- mex_->fatal (true); // An incomplete batch is always fatal.
-
- fetch (r, err);
+ fetch (r, conn_.error_handle ());
return n_;
}
- // Initialize the batch status array.
- //
- if (n_ != 1)
- {
- // Clear the status array.
- //
- for (size_t i (0); i != n_; ++i)
- status_[i].reset ();
-
- // @@ TODO allocate per batch stmt (maybe lazily here if NULL).
- //
- auto_handle<OCIError> err1;
- {
- OCIError* e (0);
- r = OCIHandleAlloc (conn_.database ().environment (),
- reinterpret_cast<void**> (&e),
- OCI_HTYPE_ERROR,
- 0,
- 0);
-
- if (r != OCI_SUCCESS)
- throw invalid_oci_handle ();
-
- err1.reset (e);
- }
-
- ub4 en;
- r = OCIAttrGet (stmt_,
- OCI_HTYPE_STMT,
- &en,
- 0,
- OCI_ATTR_NUM_DML_ERRORS,
- err1);
-
- if (r == OCI_ERROR || r == OCI_INVALID_HANDLE)
- translate_error (err1, r);
-
- cerr << "_NUM_DML_ERRORS: " << en << endl;
-
- for (ub4 i (0); i != en; ++i)
- {
- auto_handle<OCIError> err2;
-
- {
- OCIError* e (0);
- r = OCIHandleAlloc (conn_.database ().environment (),
- reinterpret_cast<void**> (&e),
- OCI_HTYPE_ERROR,
- 0,
- 0);
-
- if (r != OCI_SUCCESS)
- throw invalid_oci_handle ();
-
- err2.reset (e);
- }
-
- OCIError* tmp (err2);
- r = OCIParamGet (err, // from
- OCI_HTYPE_ERROR,
- err1, // diagnostics
- reinterpret_cast<void**> (&tmp), // to
- i);
-
- if (r == OCI_ERROR || r == OCI_INVALID_HANDLE)
- translate_error (err1, r);
-
- ub4 row;
- r = OCIAttrGet (err2,
- OCI_HTYPE_ERROR,
- &row,
- 0,
- OCI_ATTR_DML_ROW_OFFSET,
- err1);
-
- status_[row].reset (err2.release ());
-
- cerr << "[" << row << "]" << endl;
- }
- }
-
// Store the last returned id size (see odb_oracle_returning_out()
// for details).
//
@@ -1916,7 +1940,7 @@ namespace odb
}
}
- if (n_ == 1)
+ if (n == 1) // n and n_ are really the same here.
fetch (OCI_SUCCESS, 0);
else
fetch (status_[i_] == 0 ? OCI_SUCCESS : OCI_ERROR, status_[i_]);
@@ -2059,24 +2083,87 @@ namespace odb
delete_statement (connection_type& conn,
const string& text,
binding& param)
- : statement (conn,
- text, statement_delete,
- 0, false)
+ : bulk_statement (conn,
+ text, statement_delete,
+ 0, false,
+ param.batch, param.status)
{
- bind_param (param.bind, param.count);
+ bind_param (param.bind, param.count, param.batch, param.skip);
}
delete_statement::
delete_statement (connection_type& conn,
const char* text,
binding& param)
- : statement (conn,
- text, statement_delete,
- 0, false)
+ : bulk_statement (conn,
+ text, statement_delete,
+ 0, false,
+ param.batch, param.status)
+ {
+ bind_param (param.bind, param.count, param.batch, param.skip);
+ }
+
+ size_t delete_statement::
+ execute (size_t n, multiple_exceptions* mex)
+ {
+ sword r (bulk_statement::execute (n, mex));
+
+ if (r == OCI_ERROR || r == OCI_INVALID_HANDLE)
+ {
+ fetch (r, conn_.error_handle ());
+ return n_;
+ }
+
+ if (n == 1) // n and n_ are really the same here.
+ fetch (OCI_SUCCESS, 0);
+ else
+ fetch (status_[i_] == 0 ? OCI_SUCCESS : OCI_ERROR, status_[i_]);
+
+ return n_;
+ }
+
+ void delete_statement::
+ fetch (sword r, OCIError* err1)
{
- bind_param (param.bind, param.count);
+ if (r == OCI_ERROR || r == OCI_INVALID_HANDLE)
+ translate_error (err1, r, &conn_, i_, mex_); // Can return.
+ else
+ {
+ ub4 rows (0);
+ OCIError* err (conn_.error_handle ());
+ r = OCIAttrGet (stmt_,
+ OCI_HTYPE_STMT,
+ &rows,
+ 0,
+ OCI_ATTR_ROW_COUNT,
+ err);
+
+ if (r == OCI_ERROR || r == OCI_INVALID_HANDLE)
+ translate_error (err, r);
+
+ cerr << "fetch: " << rows << endl;
+
+ result_ = static_cast<unsigned long long> (rows);
+ }
+ }
+
+ unsigned long long delete_statement::
+ result (std::size_t i)
+ {
+ assert ((i_ == i || i_ + 1 == i) && i < n_);
+
+ // Get to the next row if necessary.
+ //
+ if (i != i_)
+ {
+ mex_->current (++i_); // It cannot be NULL since this is a batch.
+ fetch (status_[i_] == 0 ? OCI_SUCCESS : OCI_ERROR, status_[i_]);
+ }
+
+ return result_;
}
+ /*
unsigned long long delete_statement::
execute ()
{
@@ -2115,5 +2202,6 @@ namespace odb
return static_cast<unsigned long long> (row_count);
}
+ */
}
}