mirror of
https://github.com/SOCI/soci.git
synced 2026-05-06 20:00:03 -05:00
Merge branch 'firebird-errors'
Improve Firebird errors generation too. See #1242.
This commit is contained in:
@@ -30,27 +30,16 @@
|
||||
namespace soci
|
||||
{
|
||||
|
||||
std::size_t const stat_size = 20;
|
||||
|
||||
// size of buffer for error messages. All examples use this value.
|
||||
// Anyone knows, where it is stated that 512 bytes is enough ?
|
||||
std::size_t const SOCI_FIREBIRD_ERRMSG = 512;
|
||||
|
||||
class SOCI_FIREBIRD_DECL firebird_soci_error : public soci_error
|
||||
{
|
||||
public:
|
||||
firebird_soci_error(std::string const & msg,
|
||||
ISC_STATUS const * status = 0);
|
||||
|
||||
~firebird_soci_error() noexcept override {};
|
||||
error_category get_error_category() const override;
|
||||
|
||||
std::string get_backend_name() const override { return "firebird"; }
|
||||
int get_backend_error_code() const override
|
||||
{
|
||||
// We can't return the full vector using this generic interface, so
|
||||
// return just the first status.
|
||||
return status_.empty() ? 0 : status_[0];
|
||||
}
|
||||
int get_backend_error_code() const override;
|
||||
|
||||
std::vector<ISC_STATUS> status_;
|
||||
};
|
||||
|
||||
@@ -21,13 +21,87 @@ firebird_soci_error::firebird_soci_error(std::string const & msg, ISC_STATUS con
|
||||
if (status != 0)
|
||||
{
|
||||
std::size_t i = 0;
|
||||
while (i < stat_size && status[i] != 0)
|
||||
while (i < ISC_STATUS_LENGTH && status[i] != isc_arg_end)
|
||||
{
|
||||
status_.push_back(status[i++]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int firebird_soci_error::get_backend_error_code() const
|
||||
{
|
||||
// Search for the InterBase error code in the status vector, which consists
|
||||
// of clusters of 2 (mostly) or 3 (exceptionally, see below) elements.
|
||||
for (std::size_t i = 0; i < status_.size(); i += 2)
|
||||
{
|
||||
switch (status_[i])
|
||||
{
|
||||
case isc_arg_end:
|
||||
// This is never supposed to happen due to the way status_ is
|
||||
// filled in the ctor above.
|
||||
return 0;
|
||||
|
||||
case isc_arg_gds:
|
||||
// Cluster starting with this value contains the error code
|
||||
// we're looking for in the next element.
|
||||
if (i + 1 < status_.size())
|
||||
{
|
||||
return static_cast<int>(status_[i + 1]);
|
||||
}
|
||||
break;
|
||||
|
||||
case isc_arg_cstring:
|
||||
// This is the only cluster consisting of 3 elements, so skip
|
||||
// an extra one.
|
||||
++i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
soci_error::error_category firebird_soci_error::get_error_category() const
|
||||
{
|
||||
switch (get_backend_error_code())
|
||||
{
|
||||
case isc_bad_db_format:
|
||||
case isc_unavailable:
|
||||
case isc_wrong_ods:
|
||||
case isc_badodsver:
|
||||
case isc_connect_reject:
|
||||
case isc_login:
|
||||
case isc_network_error:
|
||||
case isc_net_connect_err:
|
||||
case isc_lost_db_connection:
|
||||
return connection_error;
|
||||
|
||||
case isc_syntaxerr:
|
||||
case isc_dsql_error:
|
||||
case isc_command_end_err:
|
||||
return invalid_statement;
|
||||
|
||||
case isc_no_priv:
|
||||
return no_privilege;
|
||||
|
||||
case isc_not_valid:
|
||||
case isc_no_dup:
|
||||
case isc_foreign_key:
|
||||
case isc_primary_key_ref:
|
||||
case isc_primary_key_notnull:
|
||||
return constraint_violation;
|
||||
|
||||
case isc_tra_state:
|
||||
return unknown_transaction_state;
|
||||
|
||||
case isc_io_error:
|
||||
case isc_virmemexh:
|
||||
return system_error;
|
||||
}
|
||||
|
||||
return unknown;
|
||||
}
|
||||
|
||||
namespace details
|
||||
{
|
||||
|
||||
@@ -36,6 +110,9 @@ namespace firebird
|
||||
|
||||
void get_iscerror_details(ISC_STATUS * status_vector, std::string &msg)
|
||||
{
|
||||
// Size of buffer for error messages: 4K should be enough for everybody.
|
||||
constexpr std::size_t const SOCI_FIREBIRD_ERRMSG = 4096;
|
||||
|
||||
char msg_buffer[SOCI_FIREBIRD_ERRMSG];
|
||||
const ISC_STATUS *pvector = status_vector;
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ firebird_session_backend::firebird_session_backend(
|
||||
auto params = parameters;
|
||||
params.extract_options_from_space_separated_string();
|
||||
|
||||
ISC_STATUS stat[stat_size];
|
||||
ISC_STATUS stat[ISC_STATUS_LENGTH];
|
||||
std::string param;
|
||||
|
||||
// preparing connection options
|
||||
@@ -91,7 +91,7 @@ void firebird_session_backend::begin()
|
||||
{
|
||||
if (trhp_ == 0)
|
||||
{
|
||||
ISC_STATUS stat[stat_size];
|
||||
ISC_STATUS stat[ISC_STATUS_LENGTH];
|
||||
if (isc_start_transaction(stat, &trhp_, 1, &dbhp_, 0, NULL))
|
||||
{
|
||||
throw_iscerror(stat);
|
||||
@@ -106,7 +106,7 @@ firebird_session_backend::~firebird_session_backend()
|
||||
|
||||
bool firebird_session_backend::is_connected()
|
||||
{
|
||||
ISC_STATUS stat[stat_size];
|
||||
ISC_STATUS stat[ISC_STATUS_LENGTH];
|
||||
ISC_SCHAR req[] = { isc_info_ods_version, isc_info_end };
|
||||
ISC_SCHAR res[256];
|
||||
|
||||
@@ -115,7 +115,7 @@ bool firebird_session_backend::is_connected()
|
||||
|
||||
void firebird_session_backend::commit()
|
||||
{
|
||||
ISC_STATUS stat[stat_size];
|
||||
ISC_STATUS stat[ISC_STATUS_LENGTH];
|
||||
|
||||
if (trhp_ != 0)
|
||||
{
|
||||
@@ -130,7 +130,7 @@ void firebird_session_backend::commit()
|
||||
|
||||
void firebird_session_backend::rollback()
|
||||
{
|
||||
ISC_STATUS stat[stat_size];
|
||||
ISC_STATUS stat[ISC_STATUS_LENGTH];
|
||||
|
||||
if (trhp_ != 0)
|
||||
{
|
||||
@@ -153,7 +153,7 @@ isc_tr_handle* firebird_session_backend::current_transaction()
|
||||
|
||||
void firebird_session_backend::cleanUp()
|
||||
{
|
||||
ISC_STATUS stat[stat_size];
|
||||
ISC_STATUS stat[ISC_STATUS_LENGTH];
|
||||
|
||||
// at the end of session our transaction is finally commited.
|
||||
if (trhp_ != 0)
|
||||
|
||||
@@ -40,7 +40,7 @@ void firebird_statement_backend::prepareSQLDA(XSQLDA ** sqldap, short size)
|
||||
|
||||
void firebird_statement_backend::alloc()
|
||||
{
|
||||
ISC_STATUS stat[stat_size];
|
||||
ISC_STATUS stat[ISC_STATUS_LENGTH];
|
||||
|
||||
if (isc_dsql_allocate_statement(stat, &session_.dbhp_, &stmtp_))
|
||||
{
|
||||
@@ -52,7 +52,7 @@ void firebird_statement_backend::clean_up()
|
||||
{
|
||||
rowsAffectedBulk_ = -1LL;
|
||||
|
||||
ISC_STATUS stat[stat_size];
|
||||
ISC_STATUS stat[ISC_STATUS_LENGTH];
|
||||
|
||||
if (stmtp_ != 0)
|
||||
{
|
||||
@@ -155,7 +155,7 @@ namespace
|
||||
char type_item[] = {isc_info_sql_stmt_type};
|
||||
char res_buffer[8];
|
||||
|
||||
ISC_STATUS stat[stat_size];
|
||||
ISC_STATUS stat[ISC_STATUS_LENGTH];
|
||||
|
||||
if (isc_dsql_sql_info(stat, &stmt, sizeof(type_item),
|
||||
type_item, sizeof(res_buffer), res_buffer))
|
||||
@@ -217,7 +217,7 @@ void firebird_statement_backend::rewriteQuery(
|
||||
prepareSQLDA(&sqldap_);
|
||||
}
|
||||
|
||||
ISC_STATUS stat[stat_size];
|
||||
ISC_STATUS stat[ISC_STATUS_LENGTH];
|
||||
isc_stmt_handle tmpStmtp = 0;
|
||||
|
||||
// allocate temporary statement to determine its type
|
||||
@@ -300,7 +300,7 @@ void firebird_statement_backend::prepare(std::string const & query,
|
||||
// firebird's api
|
||||
rewriteQuery(query, queryBuffer);
|
||||
|
||||
ISC_STATUS stat[stat_size];
|
||||
ISC_STATUS stat[ISC_STATUS_LENGTH];
|
||||
|
||||
// prepare real statement
|
||||
if (isc_dsql_prepare(stat, session_.current_transaction(), &stmtp_, 0,
|
||||
@@ -374,7 +374,7 @@ namespace
|
||||
statement_backend::exec_fetch_result
|
||||
firebird_statement_backend::execute(int number)
|
||||
{
|
||||
ISC_STATUS stat[stat_size];
|
||||
ISC_STATUS stat[ISC_STATUS_LENGTH];
|
||||
XSQLDA *t = NULL;
|
||||
|
||||
std::size_t usize = uses_.size();
|
||||
@@ -481,7 +481,7 @@ firebird_statement_backend::fetch(int number)
|
||||
if (endOfRowSet_)
|
||||
return ef_no_data;
|
||||
|
||||
ISC_STATUS stat[stat_size];
|
||||
ISC_STATUS stat[ISC_STATUS_LENGTH];
|
||||
|
||||
for (size_t i = 0; i<static_cast<unsigned int>(sqldap_->sqld); ++i)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user