Browse Source

Enable setting the different error modes via PDO::setAttribute()

PHP-5.0
Wez Furlong 22 years ago
parent
commit
5023a7c61c
  1. 6
      ext/pdo/pdo.c
  2. 69
      ext/pdo/pdo_dbh.c
  3. 9
      ext/pdo/php_pdo_driver.h
  4. 4
      ext/pdo/php_pdo_int.h

6
ext/pdo/pdo.c

@ -220,11 +220,16 @@ PHP_MINIT_FUNCTION(pdo)
REGISTER_LONG_CONSTANT("PDO_ATTR_SCROLL", (long)PDO_ATTR_SCROLL, CONST_CS|CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("PDO_ATTR_PREFETCH", (long)PDO_ATTR_PREFETCH, CONST_CS|CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("PDO_ATTR_TIMEOUT", (long)PDO_ATTR_TIMEOUT, CONST_CS|CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("PDO_ATTR_ERRMODE", (long)PDO_ATTR_ERRMODE, CONST_CS|CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("PDO_ATTR_SERVER_VERSION", (long)PDO_ATTR_SERVER_VERSION, CONST_CS|CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("PDO_ATTR_CLIENT_VERSION", (long)PDO_ATTR_CLIENT_VERSION, CONST_CS|CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("PDO_ATTR_SERVER_INFO", (long)PDO_ATTR_SERVER_INFO, CONST_CS|CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("PDO_ATTR_CONNECTION_STATUS", (long)PDO_ATTR_CONNECTION_STATUS, CONST_CS|CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("PDO_ERRMODE_SILENT", (long)PDO_ERRMODE_SILENT, CONST_CS|CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("PDO_ERRMODE_WARNING", (long)PDO_ERRMODE_WARNING, CONST_CS|CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("PDO_ERRMODE_EXCEPTION", (long)PDO_ERRMODE_EXCEPTION, CONST_CS|CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("PDO_ERR_NONE", (long)PDO_ERR_NONE, CONST_CS|CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("PDO_ERR_CANT_MAP", (long)PDO_ERR_CANT_MAP, CONST_CS|CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("PDO_ERR_SYNTAX", (long)PDO_ERR_SYNTAX, CONST_CS|CONST_PERSISTENT);
@ -238,6 +243,7 @@ PHP_MINIT_FUNCTION(pdo)
INIT_CLASS_ENTRY(ce, "PDOException", NULL);
pdo_exception_ce = zend_register_internal_class_ex(&ce, zend_exception_get_default(), NULL TSRMLS_CC);
zend_declare_property_null(pdo_exception_ce, "errorInfo", sizeof("errorInfo")-1, ZEND_ACC_PUBLIC TSRMLS_CC);
INIT_CLASS_ENTRY(ce, "PDO", pdo_dbh_functions);
ce.create_object = pdo_dbh_new;

69
ext/pdo/pdo_dbh.c

@ -40,8 +40,12 @@ void pdo_handle_error(pdo_dbh_t *dbh, pdo_stmt_t *stmt TSRMLS_DC)
const char *msg = "<<Unknown>>";
char *supp = NULL;
long native_code = 0;
char *message = NULL;
zval *info = NULL;
/* TODO: if the dbh->error_mode is set to "silent" mode, just return */
if (dbh->error_mode == PDO_ERRMODE_SILENT) {
return;
}
if (stmt) {
pdo_err = &stmt->error_code;
@ -62,35 +66,58 @@ void pdo_handle_error(pdo_dbh_t *dbh, pdo_stmt_t *stmt TSRMLS_DC)
}
if (dbh->methods->fetch_err) {
zval *info;
MAKE_STD_ZVAL(info);
array_init(info);
add_next_index_long(info, *pdo_err);
if (dbh->methods->fetch_err(dbh, stmt, info TSRMLS_CC)) {
zval **item;
if (SUCCESS == zend_hash_index_find(Z_ARRVAL_P(info), 0, (void**)&item)) {
if (SUCCESS == zend_hash_index_find(Z_ARRVAL_P(info), 1, (void**)&item)) {
native_code = Z_LVAL_PP(item);
}
if (SUCCESS == zend_hash_index_find(Z_ARRVAL_P(info), 1, (void**)&item)) {
if (SUCCESS == zend_hash_index_find(Z_ARRVAL_P(info), 2, (void**)&item)) {
supp = estrndup(Z_STRVAL_PP(item), Z_STRLEN_PP(item));
}
}
FREE_ZVAL(info);
}
/* TODO: if the dbh->error_mode is set to exception mode, set up an
* exception instead */
if (supp && *pdo_err == PDO_ERR_CANT_MAP) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "%ld %s", native_code, supp);
spprintf(&message, 0, "%ld %s", native_code, supp);
} else if (supp) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s: %ld %s", msg, native_code, supp);
spprintf(&message, 0, "%s: %ld %s", msg, native_code, supp);
} else {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", msg);
spprintf(&message, 0, "%s", msg);
}
if (dbh->error_mode == PDO_ERRMODE_WARNING) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, message);
if (info) {
FREE_ZVAL(info);
}
} else {
zval *ex;
zend_class_entry *def_ex = zend_exception_get_default(), *pdo_ex = php_pdo_get_exception();
MAKE_STD_ZVAL(ex);
object_init_ex(ex, pdo_ex);
zend_update_property_string(def_ex, ex, "message", sizeof("message")-1, message TSRMLS_CC);
zend_update_property_long(def_ex, ex, "code", sizeof("code")-1, *pdo_err TSRMLS_CC);
if (info) {
zend_update_property(pdo_ex, ex, "errorInfo", sizeof("errorInfo")-1, info TSRMLS_CC);
}
zend_throw_exception_object(ex TSRMLS_CC);
}
if (message) {
efree(message);
}
if (supp) {
@ -304,6 +331,24 @@ static PHP_METHOD(PDO, setAttribute)
RETURN_FALSE;
}
switch (attr) {
case PDO_ATTR_ERRMODE:
convert_to_long(value);
switch (Z_LVAL_P(value)) {
case PDO_ERRMODE_SILENT:
case PDO_ERRMODE_WARNING:
case PDO_ERRMODE_EXCEPTION:
dbh->error_mode = Z_LVAL_P(value);
RETURN_TRUE;
default:
zend_throw_exception_ex(php_pdo_get_exception(), PDO_ERR_SYNTAX TSRMLS_CC, "Error mode %d is invalid", Z_LVAL_P(value));
}
RETURN_FALSE;
default:
;
}
if (!dbh->methods->set_attribute) {
goto fail;
}

9
ext/pdo/php_pdo_driver.h

@ -59,6 +59,7 @@ enum pdo_attribute_type {
PDO_ATTR_SCROLL, /* ask for a scrollable cursor (when you prepare()) */
PDO_ATTR_PREFETCH, /* configure the prefetch size for drivers that support it */
PDO_ATTR_TIMEOUT, /* connection timeout in seconds */
PDO_ATTR_ERRMODE, /* control how errors are handled */
PDO_ATTR_SERVER_VERSION, /* database server version */
PDO_ATTR_CLIENT_VERSION, /* client library version */
PDO_ATTR_SERVER_INFO, /* server information */
@ -81,6 +82,12 @@ enum pdo_error_type {
PDO_ERR_DISCONNECTED,
};
enum pdo_error_mode {
PDO_ERRMODE_SILENT, /* just set error codes */
PDO_ERRMODE_WARNING, /* raise E_WARNING */
PDO_ERRMODE_EXCEPTION, /* throw exceptions */
};
/* {{{ utils for reading attributes set as driver_options */
static inline long pdo_attr_lval(zval *options, enum pdo_fetch_type option_name, long defval TSRMLS_DC)
{
@ -257,6 +264,8 @@ struct _pdo_dbh_t {
/* the global error code. */
enum pdo_error_type error_code;
enum pdo_error_mode error_mode;
#if 0
/* persistent hash key associated with this handle */
const char *persistent_id;

4
ext/pdo/php_pdo_int.h

@ -40,8 +40,8 @@ extern void pdo_handle_error(pdo_dbh_t *dbh, pdo_stmt_t *stmt TSRMLS_DC);
#define PDO_DBH_CLEAR_ERR() dbh->error_code = PDO_ERR_NONE
#define PDO_STMT_CLEAR_ERR() stmt->error_code = PDO_ERR_NONE
#define PDO_HANDLE_DBH_ERR() pdo_handle_error(dbh, NULL TSRMLS_CC)
#define PDO_HANDLE_STMT_ERR() pdo_handle_error(stmt->dbh, stmt TSRMLS_CC)
#define PDO_HANDLE_DBH_ERR() if (dbh->error_code) { pdo_handle_error(dbh, NULL TSRMLS_CC); }
#define PDO_HANDLE_STMT_ERR() if (stmt->error_code) { pdo_handle_error(stmt->dbh, stmt TSRMLS_CC); }
/*

Loading…
Cancel
Save