From 5023a7c61c7584ec7f976550f45e661c27ee3f7e Mon Sep 17 00:00:00 2001 From: Wez Furlong Date: Thu, 20 May 2004 19:16:49 +0000 Subject: [PATCH] Enable setting the different error modes via PDO::setAttribute() --- ext/pdo/pdo.c | 6 ++++ ext/pdo/pdo_dbh.c | 69 +++++++++++++++++++++++++++++++++------- ext/pdo/php_pdo_driver.h | 9 ++++++ ext/pdo/php_pdo_int.h | 4 +-- 4 files changed, 74 insertions(+), 14 deletions(-) diff --git a/ext/pdo/pdo.c b/ext/pdo/pdo.c index 28512e75b5..e0c2dbec53 100755 --- a/ext/pdo/pdo.c +++ b/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; diff --git a/ext/pdo/pdo_dbh.c b/ext/pdo/pdo_dbh.c index 0433bae2d0..eabafc55ce 100755 --- a/ext/pdo/pdo_dbh.c +++ b/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 = "<>"; 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; } diff --git a/ext/pdo/php_pdo_driver.h b/ext/pdo/php_pdo_driver.h index d32ddac526..cfe2511075 100755 --- a/ext/pdo/php_pdo_driver.h +++ b/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; diff --git a/ext/pdo/php_pdo_int.h b/ext/pdo/php_pdo_int.h index 2915ee2017..2c3b73de31 100755 --- a/ext/pdo/php_pdo_int.h +++ b/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); } /* -- 2.50.1