]> granicus.if.org Git - php/commitdiff
Enable setting the different error modes via PDO::setAttribute()
authorWez Furlong <wez@php.net>
Thu, 20 May 2004 19:16:49 +0000 (19:16 +0000)
committerWez Furlong <wez@php.net>
Thu, 20 May 2004 19:16:49 +0000 (19:16 +0000)
ext/pdo/pdo.c
ext/pdo/pdo_dbh.c
ext/pdo/php_pdo_driver.h
ext/pdo/php_pdo_int.h

index 28512e75b5587b81d951a49ece34319b3038fedc..e0c2dbec53cdcf3c22806e4e90cacfb11a54ad67 100755 (executable)
@@ -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;
index 0433bae2d0191ec8c36ae6565ba97759589c898f..eabafc55ce5dce2ce545dec117ab2747be2d726c 100755 (executable)
@@ -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;
        }
index d32ddac526994dfe97fa0ccb5e3a9570938dcddb..cfe2511075c0683971513d94d1f96aa5e3531a47 100755 (executable)
@@ -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;
index 2915ee201737fdcdc397eab3f2bee002c77e8c5d..2c3b73de31ef55a51e9991e59f308cabb5191003 100755 (executable)
@@ -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); }
 
 
 /*