mirror of
https://github.com/php/php-src.git
synced 2026-03-24 08:12:21 +01:00
ext/pdo_firebird: Output correct error messages
This commit is contained in:
@@ -460,16 +460,67 @@ int preprocess(const zend_string* sql, char* sql_out, HashTable* named_params)
|
||||
}
|
||||
|
||||
/* map driver specific error message to PDO error */
|
||||
void _firebird_error(pdo_dbh_t *dbh, pdo_stmt_t *stmt, char const *file, zend_long line) /* {{{ */
|
||||
void _firebird_error(pdo_dbh_t *dbh, pdo_stmt_t *stmt, const char *state, const size_t state_len,
|
||||
const char *msg, const size_t msg_len) /* {{{ */
|
||||
{
|
||||
pdo_error_type *const error_code = stmt ? &stmt->error_code : &dbh->error_code;
|
||||
pdo_firebird_db_handle *H = (pdo_firebird_db_handle *)dbh->driver_data;
|
||||
pdo_firebird_error_info *einfo = &H->einfo;
|
||||
int sqlcode = -999;
|
||||
|
||||
strcpy(*error_code, "HY000");
|
||||
if (einfo->errmsg) {
|
||||
pefree(einfo->errmsg, dbh->is_persistent);
|
||||
einfo->errmsg = NULL;
|
||||
einfo->errmsg_length = 0;
|
||||
}
|
||||
|
||||
if (H->isc_status && (H->isc_status[0] == 1 && H->isc_status[1] > 0)) {
|
||||
char buf[512];
|
||||
size_t buf_size = sizeof(buf), read_len = 0;
|
||||
ssize_t tmp_len;
|
||||
const ISC_STATUS *s = H->isc_status;
|
||||
sqlcode = isc_sqlcode(s);
|
||||
|
||||
while ((buf_size > (read_len + 1)) && (tmp_len = fb_interpret(&buf[read_len], (buf_size - read_len - 1), &s)) && tmp_len > 0) {
|
||||
read_len += tmp_len;
|
||||
buf[read_len++] = ' ';
|
||||
}
|
||||
|
||||
/* remove last space */
|
||||
if (read_len) {
|
||||
buf[read_len--] = '\0';
|
||||
}
|
||||
|
||||
einfo->errmsg_length = read_len;
|
||||
einfo->errmsg = pestrndup(buf, read_len, dbh->is_persistent);
|
||||
|
||||
#if FB_API_VER >= 25
|
||||
char sqlstate[sizeof(pdo_error_type)];
|
||||
fb_sqlstate(sqlstate, H->isc_status);
|
||||
if (sqlstate != NULL && strlen(sqlstate) < sizeof(pdo_error_type)) {
|
||||
strcpy(*error_code, sqlstate);
|
||||
goto end;
|
||||
}
|
||||
#endif
|
||||
} else if (msg && msg_len) {
|
||||
einfo->errmsg_length = msg_len;
|
||||
einfo->errmsg = pestrndup(msg, einfo->errmsg_length, dbh->is_persistent);
|
||||
}
|
||||
|
||||
if (state && state_len && state_len < sizeof(pdo_error_type)) {
|
||||
memcpy(*error_code, state, state_len + 1);
|
||||
} else {
|
||||
memcpy(*error_code, "HY000", sizeof("HY000"));
|
||||
}
|
||||
|
||||
end:
|
||||
einfo->sqlcode = sqlcode;
|
||||
if (!dbh->methods) {
|
||||
pdo_throw_exception(0, einfo->errmsg, error_code);
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
#define RECORD_ERROR(dbh) _firebird_error(dbh, NULL, __FILE__, __LINE__)
|
||||
|
||||
/* called by PDO to close a db handle */
|
||||
static void firebird_handle_closer(pdo_dbh_t *dbh) /* {{{ */
|
||||
{
|
||||
@@ -478,17 +529,17 @@ static void firebird_handle_closer(pdo_dbh_t *dbh) /* {{{ */
|
||||
if (dbh->in_txn) {
|
||||
if (dbh->auto_commit) {
|
||||
if (isc_commit_transaction(H->isc_status, &H->tr)) {
|
||||
RECORD_ERROR(dbh);
|
||||
firebird_error(dbh);
|
||||
}
|
||||
} else {
|
||||
if (isc_rollback_transaction(H->isc_status, &H->tr)) {
|
||||
RECORD_ERROR(dbh);
|
||||
firebird_error(dbh);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isc_detach_database(H->isc_status, &H->db)) {
|
||||
RECORD_ERROR(dbh);
|
||||
firebird_error(dbh);
|
||||
}
|
||||
|
||||
if (H->date_format) {
|
||||
@@ -501,6 +552,11 @@ static void firebird_handle_closer(pdo_dbh_t *dbh) /* {{{ */
|
||||
efree(H->timestamp_format);
|
||||
}
|
||||
|
||||
if (H->einfo.errmsg) {
|
||||
pefree(H->einfo.errmsg, dbh->is_persistent);
|
||||
H->einfo.errmsg = NULL;
|
||||
}
|
||||
|
||||
pefree(H, dbh->is_persistent);
|
||||
}
|
||||
/* }}} */
|
||||
@@ -547,7 +603,7 @@ static bool firebird_handle_preparer(pdo_dbh_t *dbh, zend_string *sql, /* {{{ */
|
||||
|
||||
/* fill the output sqlda with information about the prepared query */
|
||||
if (isc_dsql_describe(H->isc_status, &s, PDO_FB_SQLDA_VERSION, &S->out_sqlda)) {
|
||||
RECORD_ERROR(dbh);
|
||||
firebird_error(dbh);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -574,7 +630,7 @@ static bool firebird_handle_preparer(pdo_dbh_t *dbh, zend_string *sql, /* {{{ */
|
||||
|
||||
} while (0);
|
||||
|
||||
RECORD_ERROR(dbh);
|
||||
firebird_error(dbh);
|
||||
|
||||
zend_hash_destroy(np);
|
||||
FREE_HASHTABLE(np);
|
||||
@@ -612,7 +668,7 @@ static zend_long firebird_handle_doer(pdo_dbh_t *dbh, const zend_string *sql) /*
|
||||
|
||||
/* execute the statement */
|
||||
if (isc_dsql_execute2(H->isc_status, &H->tr, &stmt, PDO_FB_SQLDA_VERSION, &in_sqlda, &out_sqlda)) {
|
||||
RECORD_ERROR(dbh);
|
||||
firebird_error(dbh);
|
||||
ret = -1;
|
||||
goto free_statement;
|
||||
}
|
||||
@@ -620,7 +676,7 @@ static zend_long firebird_handle_doer(pdo_dbh_t *dbh, const zend_string *sql) /*
|
||||
/* find out how many rows were affected */
|
||||
if (isc_dsql_sql_info(H->isc_status, &stmt, sizeof(info_count), const_cast(info_count),
|
||||
sizeof(result), result)) {
|
||||
RECORD_ERROR(dbh);
|
||||
firebird_error(dbh);
|
||||
ret = -1;
|
||||
goto free_statement;
|
||||
}
|
||||
@@ -648,13 +704,13 @@ static zend_long firebird_handle_doer(pdo_dbh_t *dbh, const zend_string *sql) /*
|
||||
|
||||
/* commit if we're in auto_commit mode */
|
||||
if (dbh->auto_commit && isc_commit_retaining(H->isc_status, &H->tr)) {
|
||||
RECORD_ERROR(dbh);
|
||||
firebird_error(dbh);
|
||||
}
|
||||
|
||||
free_statement:
|
||||
|
||||
if (isc_dsql_free_statement(H->isc_status, &stmt, DSQL_drop)) {
|
||||
RECORD_ERROR(dbh);
|
||||
firebird_error(dbh);
|
||||
}
|
||||
|
||||
return ret;
|
||||
@@ -746,7 +802,7 @@ static bool firebird_handle_begin(pdo_dbh_t *dbh) /* {{{ */
|
||||
}
|
||||
#endif
|
||||
if (isc_start_transaction(H->isc_status, &H->tr, 1, &H->db, (unsigned short)(ptpb-tpb), tpb)) {
|
||||
RECORD_ERROR(dbh);
|
||||
firebird_error(dbh);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@@ -759,7 +815,7 @@ static bool firebird_handle_commit(pdo_dbh_t *dbh) /* {{{ */
|
||||
pdo_firebird_db_handle *H = (pdo_firebird_db_handle *)dbh->driver_data;
|
||||
|
||||
if (isc_commit_transaction(H->isc_status, &H->tr)) {
|
||||
RECORD_ERROR(dbh);
|
||||
firebird_error(dbh);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@@ -772,7 +828,7 @@ static bool firebird_handle_rollback(pdo_dbh_t *dbh) /* {{{ */
|
||||
pdo_firebird_db_handle *H = (pdo_firebird_db_handle *)dbh->driver_data;
|
||||
|
||||
if (isc_rollback_transaction(H->isc_status, &H->tr)) {
|
||||
RECORD_ERROR(dbh);
|
||||
firebird_error(dbh);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@@ -804,7 +860,7 @@ static int firebird_alloc_prepare_stmt(pdo_dbh_t *dbh, const zend_string *sql,
|
||||
|
||||
/* allocate the statement */
|
||||
if (isc_dsql_allocate_statement(H->isc_status, &H->db, s)) {
|
||||
RECORD_ERROR(dbh);
|
||||
firebird_error(dbh);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -820,7 +876,7 @@ static int firebird_alloc_prepare_stmt(pdo_dbh_t *dbh, const zend_string *sql,
|
||||
|
||||
/* prepare the statement */
|
||||
if (isc_dsql_prepare(H->isc_status, &H->tr, s, 0, new_sql, H->sql_dialect, out_sqlda)) {
|
||||
RECORD_ERROR(dbh);
|
||||
firebird_error(dbh);
|
||||
efree(new_sql);
|
||||
return 0;
|
||||
}
|
||||
@@ -848,7 +904,8 @@ static bool firebird_handle_set_attribute(pdo_dbh_t *dbh, zend_long attr, zval *
|
||||
if (bval) {
|
||||
/* turning on auto_commit with an open transaction is illegal, because
|
||||
we won't know what to do with it */
|
||||
H->last_app_error = "Cannot enable auto-commit while a transaction is already open";
|
||||
const char *msg = "Cannot enable auto-commit while a transaction is already open";
|
||||
firebird_error_with_info(dbh, "HY000", strlen("HY000"), msg, strlen(msg));
|
||||
return false;
|
||||
} else {
|
||||
/* close the transaction */
|
||||
@@ -992,21 +1049,11 @@ static int firebird_handle_get_attribute(pdo_dbh_t *dbh, zend_long attr, zval *v
|
||||
static void pdo_firebird_fetch_error_func(pdo_dbh_t *dbh, pdo_stmt_t *stmt, zval *info) /* {{{ */
|
||||
{
|
||||
pdo_firebird_db_handle *H = (pdo_firebird_db_handle *)dbh->driver_data;
|
||||
const ISC_STATUS *s = H->isc_status;
|
||||
char buf[400];
|
||||
zend_long i = 0, l, sqlcode = isc_sqlcode(s);
|
||||
|
||||
if (sqlcode) {
|
||||
add_next_index_long(info, sqlcode);
|
||||
|
||||
while ((sizeof(buf)>(i+2))&&(l = fb_interpret(&buf[i],(sizeof(buf)-i-2),&s))) {
|
||||
i += l;
|
||||
strcpy(&buf[i++], " ");
|
||||
}
|
||||
add_next_index_string(info, buf);
|
||||
} else if (H->last_app_error) {
|
||||
add_next_index_long(info, -999);
|
||||
add_next_index_string(info, const_cast(H->last_app_error));
|
||||
if (H->einfo.sqlcode != IS_NULL) {
|
||||
add_next_index_long(info, H->einfo.sqlcode);
|
||||
}
|
||||
if (H->einfo.errmsg && H->einfo.errmsg_length) {
|
||||
add_next_index_stringl(info, H->einfo.errmsg, H->einfo.errmsg_length);
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
@@ -28,8 +28,6 @@
|
||||
|
||||
#include <time.h>
|
||||
|
||||
#define RECORD_ERROR(stmt) _firebird_error(NULL, stmt, __FILE__, __LINE__)
|
||||
|
||||
#define READ_AND_RETURN_USING_MEMCPY(type, sqldata) do { \
|
||||
type ret; \
|
||||
memcpy(&ret, sqldata, sizeof(ret)); \
|
||||
@@ -89,7 +87,7 @@ static int firebird_stmt_dtor(pdo_stmt_t *stmt) /* {{{ */
|
||||
|
||||
/* release the statement */
|
||||
if (isc_dsql_free_statement(S->H->isc_status, &S->stmt, DSQL_drop)) {
|
||||
RECORD_ERROR(stmt);
|
||||
firebird_error_stmt(stmt);
|
||||
result = 0;
|
||||
}
|
||||
|
||||
@@ -195,7 +193,7 @@ static int firebird_stmt_execute(pdo_stmt_t *stmt) /* {{{ */
|
||||
} while (0);
|
||||
|
||||
error:
|
||||
RECORD_ERROR(stmt);
|
||||
firebird_error_stmt(stmt);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -209,8 +207,8 @@ static int firebird_stmt_fetch(pdo_stmt_t *stmt, /* {{{ */
|
||||
pdo_firebird_db_handle *H = S->H;
|
||||
|
||||
if (!stmt->executed) {
|
||||
strcpy(stmt->error_code, "HY000");
|
||||
H->last_app_error = "Cannot fetch from a closed cursor";
|
||||
const char *msg = "Cannot fetch from a closed cursor";
|
||||
firebird_error_stmt_with_info(stmt, "HY000", strlen("HY000"), msg, strlen(msg));
|
||||
} else if (!S->exhausted) {
|
||||
if (S->statement_type == isc_info_sql_stmt_exec_procedure) {
|
||||
stmt->row_count = 1;
|
||||
@@ -219,7 +217,7 @@ static int firebird_stmt_fetch(pdo_stmt_t *stmt, /* {{{ */
|
||||
}
|
||||
if (isc_dsql_fetch(H->isc_status, &S->stmt, PDO_FB_SQLDA_VERSION, &S->out_sqlda)) {
|
||||
if (H->isc_status[0] && H->isc_status[1]) {
|
||||
RECORD_ERROR(stmt);
|
||||
firebird_error_stmt(stmt);
|
||||
}
|
||||
S->exhausted = 1;
|
||||
return 0;
|
||||
@@ -308,13 +306,13 @@ static int firebird_fetch_blob(pdo_stmt_t *stmt, int colno, zval *result, ISC_QU
|
||||
size_t len = 0;
|
||||
|
||||
if (isc_open_blob(H->isc_status, &H->db, &H->tr, &blobh, blob_id)) {
|
||||
RECORD_ERROR(stmt);
|
||||
firebird_error_stmt(stmt);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (isc_blob_info(H->isc_status, &blobh, 1, const_cast(&bl_item),
|
||||
sizeof(bl_info), bl_info)) {
|
||||
RECORD_ERROR(stmt);
|
||||
firebird_error_stmt(stmt);
|
||||
goto fetch_blob_end;
|
||||
}
|
||||
|
||||
@@ -325,7 +323,8 @@ static int firebird_fetch_blob(pdo_stmt_t *stmt, int colno, zval *result, ISC_QU
|
||||
|
||||
if (item == isc_info_end || item == isc_info_truncated || item == isc_info_error
|
||||
|| i >= sizeof(bl_info)) {
|
||||
H->last_app_error = "Couldn't determine BLOB size";
|
||||
const char *msg = "Couldn't determine BLOB size";
|
||||
firebird_error_stmt_with_info(stmt, "HY000", strlen("HY000"), msg, strlen(msg));
|
||||
goto fetch_blob_end;
|
||||
}
|
||||
|
||||
@@ -366,7 +365,8 @@ static int firebird_fetch_blob(pdo_stmt_t *stmt, int colno, zval *result, ISC_QU
|
||||
ZVAL_STR(result, str);
|
||||
|
||||
if (H->isc_status[0] == 1 && (stat != 0 && stat != isc_segstr_eof && stat != isc_segment)) {
|
||||
H->last_app_error = "Error reading from BLOB";
|
||||
const char *msg = "Error reading from BLOB";
|
||||
firebird_error_stmt_with_info(stmt, "HY000", strlen("HY000"), msg, strlen(msg));
|
||||
goto fetch_blob_end;
|
||||
}
|
||||
}
|
||||
@@ -374,7 +374,7 @@ static int firebird_fetch_blob(pdo_stmt_t *stmt, int colno, zval *result, ISC_QU
|
||||
|
||||
fetch_blob_end:
|
||||
if (isc_close_blob(H->isc_status, &blobh)) {
|
||||
RECORD_ERROR(stmt);
|
||||
firebird_error_stmt(stmt);
|
||||
return 0;
|
||||
}
|
||||
return retval;
|
||||
@@ -516,7 +516,7 @@ static int firebird_bind_blob(pdo_stmt_t *stmt, ISC_QUAD *blob_id, zval *param)
|
||||
int result = 1;
|
||||
|
||||
if (isc_create_blob(H->isc_status, &H->db, &H->tr, &h, blob_id)) {
|
||||
RECORD_ERROR(stmt);
|
||||
firebird_error_stmt(stmt);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -529,7 +529,7 @@ static int firebird_bind_blob(pdo_stmt_t *stmt, ISC_QUAD *blob_id, zval *param)
|
||||
for (rem_cnt = Z_STRLEN(data); rem_cnt > 0; rem_cnt -= chunk_size) {
|
||||
chunk_size = rem_cnt > USHRT_MAX ? USHRT_MAX : (unsigned short)rem_cnt;
|
||||
if (isc_put_segment(H->isc_status, &h, chunk_size, &Z_STRVAL(data)[put_cnt])) {
|
||||
RECORD_ERROR(stmt);
|
||||
firebird_error_stmt(stmt);
|
||||
result = 0;
|
||||
break;
|
||||
}
|
||||
@@ -541,7 +541,7 @@ static int firebird_bind_blob(pdo_stmt_t *stmt, ISC_QUAD *blob_id, zval *param)
|
||||
}
|
||||
|
||||
if (isc_close_blob(H->isc_status, &h)) {
|
||||
RECORD_ERROR(stmt);
|
||||
firebird_error_stmt(stmt);
|
||||
return 0;
|
||||
}
|
||||
return result;
|
||||
@@ -559,8 +559,8 @@ static int firebird_stmt_param_hook(pdo_stmt_t *stmt, struct pdo_bound_param_dat
|
||||
}
|
||||
|
||||
if (!sqlda || param->paramno >= sqlda->sqld) {
|
||||
strcpy(stmt->error_code, "HY093");
|
||||
S->H->last_app_error = "Invalid parameter index";
|
||||
const char *msg = "Invalid parameter index";
|
||||
firebird_error_stmt_with_info(stmt, "HY093", strlen("HY093"), msg, strlen(msg));
|
||||
return 0;
|
||||
}
|
||||
if (param->is_param && param->paramno == -1) {
|
||||
@@ -585,8 +585,8 @@ static int firebird_stmt_param_hook(pdo_stmt_t *stmt, struct pdo_bound_param_dat
|
||||
}
|
||||
}
|
||||
if (i >= sqlda->sqld) {
|
||||
strcpy(stmt->error_code, "HY093");
|
||||
S->H->last_app_error = "Invalid parameter name";
|
||||
const char *msg = "Invalid parameter name";
|
||||
firebird_error_stmt_with_info(stmt, "HY093", strlen("HY093"), msg, strlen(msg));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -636,16 +636,18 @@ static int firebird_stmt_param_hook(pdo_stmt_t *stmt, struct pdo_bound_param_dat
|
||||
|
||||
switch (var->sqltype & ~1) {
|
||||
case SQL_ARRAY:
|
||||
strcpy(stmt->error_code, "HY000");
|
||||
S->H->last_app_error = "Cannot bind to array field";
|
||||
{
|
||||
const char *msg = "Cannot bind to array field";
|
||||
firebird_error_stmt_with_info(stmt, "HY000", strlen("HY000"), msg, strlen(msg));
|
||||
}
|
||||
return 0;
|
||||
|
||||
case SQL_BLOB: {
|
||||
if (Z_TYPE_P(parameter) == IS_NULL) {
|
||||
/* Check if field allow NULL values */
|
||||
if (~var->sqltype & 1) {
|
||||
strcpy(stmt->error_code, "HY105");
|
||||
S->H->last_app_error = "Parameter requires non-null value";
|
||||
const char *msg = "Parameter requires non-null value";
|
||||
firebird_error_stmt_with_info(stmt, "HY105", strlen("HY105"), msg, strlen(msg));
|
||||
return 0;
|
||||
}
|
||||
*var->sqlind = -1;
|
||||
@@ -693,8 +695,8 @@ static int firebird_stmt_param_hook(pdo_stmt_t *stmt, struct pdo_bound_param_dat
|
||||
} else if (!zend_binary_strncasecmp(Z_STRVAL_P(parameter), Z_STRLEN_P(parameter), "false", 5, 5)) {
|
||||
*(FB_BOOLEAN*)var->sqldata = FB_FALSE;
|
||||
} else {
|
||||
strcpy(stmt->error_code, "HY105");
|
||||
S->H->last_app_error = "Cannot convert string to boolean";
|
||||
const char *msg = "Cannot convert string to boolean";
|
||||
firebird_error_stmt_with_info(stmt, "HY105", strlen("HY105"), msg, strlen(msg));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -705,8 +707,10 @@ static int firebird_stmt_param_hook(pdo_stmt_t *stmt, struct pdo_bound_param_dat
|
||||
*var->sqlind = -1;
|
||||
break;
|
||||
default:
|
||||
strcpy(stmt->error_code, "HY105");
|
||||
S->H->last_app_error = "Binding arrays/objects is not supported";
|
||||
{
|
||||
const char *msg = "Binding arrays/objects is not supported";
|
||||
firebird_error_stmt_with_info(stmt, "HY105", strlen("HY105"), msg, strlen(msg));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
@@ -756,15 +760,17 @@ static int firebird_stmt_param_hook(pdo_stmt_t *stmt, struct pdo_bound_param_dat
|
||||
case IS_NULL:
|
||||
/* complain if this field doesn't allow NULL values */
|
||||
if (~var->sqltype & 1) {
|
||||
strcpy(stmt->error_code, "HY105");
|
||||
S->H->last_app_error = "Parameter requires non-null value";
|
||||
const char *msg = "Parameter requires non-null value";
|
||||
firebird_error_stmt_with_info(stmt, "HY105", strlen("HY105"), msg, strlen(msg));
|
||||
return 0;
|
||||
}
|
||||
*var->sqlind = -1;
|
||||
break;
|
||||
default:
|
||||
strcpy(stmt->error_code, "HY105");
|
||||
S->H->last_app_error = "Binding arrays/objects is not supported";
|
||||
{
|
||||
const char *msg = "Binding arrays/objects is not supported";
|
||||
firebird_error_stmt_with_info(stmt, "HY105", strlen("HY105"), msg, strlen(msg));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
@@ -804,7 +810,7 @@ static int firebird_stmt_set_attribute(pdo_stmt_t *stmt, zend_long attr, zval *v
|
||||
}
|
||||
|
||||
if (isc_dsql_set_cursor_name(S->H->isc_status, &S->stmt, Z_STRVAL_P(val),0)) {
|
||||
RECORD_ERROR(stmt);
|
||||
firebird_error_stmt(stmt);
|
||||
return 0;
|
||||
}
|
||||
strlcpy(S->name, Z_STRVAL_P(val), sizeof(S->name));
|
||||
@@ -839,7 +845,7 @@ static int firebird_stmt_cursor_closer(pdo_stmt_t *stmt) /* {{{ */
|
||||
|
||||
/* close the statement handle */
|
||||
if ((*S->name || S->cursor_open) && isc_dsql_free_statement(S->H->isc_status, &S->stmt, DSQL_close)) {
|
||||
RECORD_ERROR(stmt);
|
||||
firebird_error_stmt(stmt);
|
||||
return 0;
|
||||
}
|
||||
*S->name = 0;
|
||||
|
||||
@@ -59,6 +59,12 @@ typedef void (*info_func_t)(char*);
|
||||
# define PDO_FIREBIRD_HANDLE_INITIALIZER NULL
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
int sqlcode;
|
||||
char *errmsg;
|
||||
size_t errmsg_length;
|
||||
} pdo_firebird_error_info;
|
||||
|
||||
typedef struct {
|
||||
|
||||
/* the result of the last API call */
|
||||
@@ -70,9 +76,6 @@ typedef struct {
|
||||
/* the transaction handle */
|
||||
isc_tr_handle tr;
|
||||
|
||||
/* the last error that didn't come from the API */
|
||||
char const *last_app_error;
|
||||
|
||||
/* date and time format strings, can be set by the set_attribute method */
|
||||
char *date_format;
|
||||
char *time_format;
|
||||
@@ -85,6 +88,7 @@ typedef struct {
|
||||
|
||||
unsigned _reserved:29;
|
||||
|
||||
pdo_firebird_error_info einfo;
|
||||
} pdo_firebird_db_handle;
|
||||
|
||||
|
||||
@@ -125,7 +129,12 @@ extern const pdo_driver_t pdo_firebird_driver;
|
||||
|
||||
extern const struct pdo_stmt_methods firebird_stmt_methods;
|
||||
|
||||
void _firebird_error(pdo_dbh_t *dbh, pdo_stmt_t *stmt, char const *file, zend_long line);
|
||||
extern void _firebird_error(pdo_dbh_t *dbh, pdo_stmt_t *stmt, const char *state, const size_t state_len,
|
||||
const char *msg, const size_t msg_len);
|
||||
#define firebird_error(d) _firebird_error(d, NULL, NULL, 0, NULL, 0)
|
||||
#define firebird_error_stmt(s) _firebird_error(s->dbh, s, NULL, 0, NULL, 0)
|
||||
#define firebird_error_with_info(d,e,el,m,ml) _firebird_error(d, NULL, e, el, m, ml)
|
||||
#define firebird_error_stmt_with_info(s,e,el,m,ml) _firebird_error(s->dbh, s, e, el, m, ml)
|
||||
|
||||
enum {
|
||||
PDO_FB_ATTR_DATE_FORMAT = PDO_ATTR_DRIVER_SPECIFIC,
|
||||
|
||||
41
ext/pdo_firebird/tests/error_handle.phpt
Normal file
41
ext/pdo_firebird/tests/error_handle.phpt
Normal file
@@ -0,0 +1,41 @@
|
||||
--TEST--
|
||||
PDO_Firebird: error handle
|
||||
--EXTENSIONS--
|
||||
pdo_firebird
|
||||
--SKIPIF--
|
||||
<?php require('skipif.inc'); ?>
|
||||
--XLEAK--
|
||||
A bug in firebird causes a memory leak when calling `isc_attach_database()`.
|
||||
See https://github.com/FirebirdSQL/firebird/issues/7849
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
require("testdb.inc");
|
||||
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
|
||||
|
||||
$table = 'error_handle';
|
||||
$dbh->query("CREATE TABLE {$table} (val int)");
|
||||
|
||||
echo "dbh error";
|
||||
$dbh->query("INSERT INTO {$table} VALUES ('str')");
|
||||
|
||||
echo "\n";
|
||||
|
||||
echo "stmt error";
|
||||
$stmt = $dbh->prepare("INSERT INTO {$table} VALUES ('str')");
|
||||
$stmt->execute();
|
||||
|
||||
unset($dbh);
|
||||
?>
|
||||
--CLEAN--
|
||||
<?php
|
||||
require 'testdb.inc';
|
||||
@$dbh->exec('DROP TABLE error_handle');
|
||||
unset($dbh);
|
||||
?>
|
||||
--EXPECTF--
|
||||
dbh error
|
||||
Warning: PDO::query(): SQLSTATE[22018]: Invalid character value for cast specification: -413 conversion error from string "str" in %s on line 10
|
||||
|
||||
stmt error
|
||||
Warning: PDOStatement::execute(): SQLSTATE[22018]: Invalid character value for cast specification: -413 conversion error from string "str" in %s on line 16
|
||||
Reference in New Issue
Block a user