summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWez Furlong <wez@php.net>2005-02-06 21:05:59 +0000
committerWez Furlong <wez@php.net>2005-02-06 21:05:59 +0000
commite3ba31e899b5b1e6cf639086e71b033c5bbb3725 (patch)
tree414e5528a41014c12d6566403bcf8f3a7ff292d2
parentec98e744bebe36d81cb62349435771c30dccd1ae (diff)
downloadphp-git-e3ba31e899b5b1e6cf639086e71b033c5bbb3725.tar.gz
better handling of pdo-level errors
-rwxr-xr-xext/pdo/TODO8
-rwxr-xr-xext/pdo/config.m44
-rwxr-xr-xext/pdo/pdo_dbh.c81
-rwxr-xr-xext/pdo/pdo_stmt.c23
-rwxr-xr-xext/pdo/php_pdo_int.h1
5 files changed, 91 insertions, 26 deletions
diff --git a/ext/pdo/TODO b/ext/pdo/TODO
index 5f00d244eb..ff3b6ed505 100755
--- a/ext/pdo/TODO
+++ b/ext/pdo/TODO
@@ -2,14 +2,14 @@ $Id$
In no particular order:
+Probable Bugs:
+- persistent connections with bound parameters might segv on subsequent
+ requests
+
Low-level:
- $dbh->quote()
-- Scrollable cursors
-- meta data from driver, such as server version and supported features
-- field meta data from statement handles
- LOB support via Streams API
-- iterator support
- make errors generated at the pdo level (as opposed to driver level) use the
selected error mode.
diff --git a/ext/pdo/config.m4 b/ext/pdo/config.m4
index 41bf1bf4ad..a5abc65683 100755
--- a/ext/pdo/config.m4
+++ b/ext/pdo/config.m4
@@ -1,8 +1,8 @@
dnl $Id$
dnl config.m4 for extension pdo
-PHP_ARG_ENABLE(pdo, whether to enable PDO support,
-[ --enable-pdo Enable PHP Data Objects support])
+PHP_ARG_ENABLE(pdo, whether to disable PDO support,
+[ --disable-pdo Disable PHP Data Objects support], yes)
if test "$PHP_PDO" != "no"; then
PHP_NEW_EXTENSION(pdo, pdo.c pdo_dbh.c pdo_stmt.c pdo_sql_parser.c pdo_sqlstate.c, $ext_shared)
diff --git a/ext/pdo/pdo_dbh.c b/ext/pdo/pdo_dbh.c
index f31a20f1ef..a8f0ec9e4f 100755
--- a/ext/pdo/pdo_dbh.c
+++ b/ext/pdo/pdo_dbh.c
@@ -36,6 +36,74 @@
#include "zend_object_handlers.h"
#include "zend_hash.h"
+void pdo_raise_impl_error(pdo_dbh_t *dbh, pdo_stmt_t *stmt, const char *sqlstate, const char *supp TSRMLS_DC)
+{
+ pdo_error_type *pdo_err = &dbh->error_code;
+ char *message = NULL;
+ const char *msg;
+ zval *info = NULL;
+
+ if (dbh->error_mode == PDO_ERRMODE_SILENT) {
+#if 0
+ /* BUG: if user is running in silent mode and hits an error at the driver level
+ * when they use the PDO methods to call up the error information, they may
+ * get bogus information */
+ return;
+#endif
+ }
+
+ if (stmt) {
+ pdo_err = &stmt->error_code;
+ }
+
+ strcpy(*pdo_err, sqlstate);
+
+ /* hash sqlstate to error messages */
+ msg = pdo_sqlstate_state_to_description(*pdo_err);
+ if (!msg) {
+ msg = "<<Unknown error>>";
+ }
+
+ MAKE_STD_ZVAL(info);
+ array_init(info);
+
+ add_next_index_string(info, *pdo_err, 1);
+ add_next_index_long(info, 0);
+
+ if (supp) {
+ spprintf(&message, 0, "SQLSTATE[%s]: %s: 0 %s", *pdo_err, msg, supp);
+ } else {
+ spprintf(&message, 0, "SQLSTATE[%s]: %s", *pdo_err, msg);
+ }
+
+ if (dbh->error_mode != PDO_ERRMODE_EXCEPTION) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", message);
+
+ if (info) {
+ zval_ptr_dtor(&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_string(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);
+ }
+}
+
void pdo_handle_error(pdo_dbh_t *dbh, pdo_stmt_t *stmt TSRMLS_DC)
{
pdo_error_type *pdo_err = &dbh->error_code;
@@ -495,8 +563,7 @@ fail:
if (attr == PDO_ATTR_AUTOCOMMIT) {
zend_throw_exception_ex(php_pdo_get_exception(), 0 TSRMLS_CC, "The auto-commit mode cannot be changed for this driver");
} else if (!dbh->methods->set_attribute) {
- /* XXX: do something better here */
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "This driver doesn't support setting attributes");
+ pdo_raise_impl_error(dbh, NULL, "IM001", "driver does not support setting attributes" TSRMLS_CC);
} else {
PDO_HANDLE_DBH_ERR();
}
@@ -534,7 +601,7 @@ static PHP_METHOD(PDO, getAttribute)
}
if (!dbh->methods->get_attribute) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "This driver doesn't support fetching attributes");
+ pdo_raise_impl_error(dbh, NULL, "IM001", "driver does not support getting attributes" TSRMLS_CC);
RETURN_FALSE;
}
@@ -544,9 +611,8 @@ static PHP_METHOD(PDO, getAttribute)
RETURN_FALSE;
case 0:
- /* XXX: should do something better here */
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "This driver doesn't support fetching %ld attribute", attr);
- break;
+ pdo_raise_impl_error(dbh, NULL, "IM001", "driver does not support that attribute" TSRMLS_CC);
+ RETURN_FALSE;
default:
return;
@@ -594,7 +660,8 @@ static PHP_METHOD(PDO, lastInsertId)
PDO_DBH_CLEAR_ERR();
if (!dbh->methods->last_id) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "This driver does not support last inserted id retrieval.");
+ pdo_raise_impl_error(dbh, NULL, "IM001", "driver does not support lastInsertId()" TSRMLS_CC);
+ RETURN_FALSE;
} else {
RETURN_LONG(dbh->methods->last_id(dbh TSRMLS_CC));
}
diff --git a/ext/pdo/pdo_stmt.c b/ext/pdo/pdo_stmt.c
index a3614180d1..83bbec7e96 100755
--- a/ext/pdo/pdo_stmt.c
+++ b/ext/pdo/pdo_stmt.c
@@ -293,7 +293,7 @@ static PHP_METHOD(PDOStatement, execute)
} else {
/* we're okay to be zero based here */
if (num_index < 0) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid parameter index");
+ pdo_raise_impl_error(stmt->dbh, stmt, "HY093", NULL TSRMLS_CC);
RETURN_FALSE;
}
param.paramno = num_index;
@@ -646,7 +646,7 @@ static int register_bound_param(INTERNAL_FUNCTION_PARAMETERS, pdo_stmt_t *stmt,
if (param.paramno > 0) {
--param.paramno; /* make it zero-based internally */
} else if (!param.name) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid parameter number: columns are 1-based");
+ pdo_raise_impl_error(stmt->dbh, stmt, "HY093", "Columns/Parameters are 1-based" TSRMLS_CC);
return 0;
}
@@ -737,8 +737,7 @@ static PHP_METHOD(PDOStatement, setAttribute)
fail:
if (!stmt->methods->set_attribute) {
- /* XXX: do something better here */
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "This driver doesn't support setting attributes");
+ pdo_raise_impl_error(stmt->dbh, stmt, "IM001", "This driver doesn't support setting attributes" TSRMLS_CC);
} else {
PDO_HANDLE_STMT_ERR();
}
@@ -758,7 +757,7 @@ static PHP_METHOD(PDOStatement, getAttribute)
}
if (!stmt->methods->get_attribute) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "This driver doesn't support fetching attributes");
+ pdo_raise_impl_error(stmt->dbh, stmt, "IM001", "This driver doesn't support getting attributes" TSRMLS_CC);
RETURN_FALSE;
}
@@ -770,8 +769,8 @@ static PHP_METHOD(PDOStatement, getAttribute)
case 0:
/* XXX: should do something better here */
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "This driver doesn't support fetching %ld attribute", attr);
- break;
+ pdo_raise_impl_error(stmt->dbh, stmt, "IM001", "driver doesn't support getting that attribute" TSRMLS_CC);
+ RETURN_FALSE;
default:
return;
@@ -804,7 +803,7 @@ static PHP_METHOD(PDOStatement, getColumnMeta)
}
if (!stmt->methods->get_column_meta) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "This driver does not support meta data");
+ pdo_raise_impl_error(stmt->dbh, stmt, "IM001", "driver doesn't support meta data" TSRMLS_CC);
RETURN_FALSE;
}
@@ -824,7 +823,7 @@ static PHP_METHOD(PDOStatement, getColumnMeta)
/* }}} */
/* {{{ proto bool PDOStatement::setFetchMode(int mode [)
- Returns meta data for a numbered column */
+ changes the default fetch mode for subsequent fetches */
int pdo_stmt_setup_fetch_mode(INTERNAL_FUNCTION_PARAMETERS, pdo_stmt_t *stmt, int skip)
{
@@ -833,7 +832,6 @@ int pdo_stmt_setup_fetch_mode(INTERNAL_FUNCTION_PARAMETERS, pdo_stmt_t *stmt, in
zval ***args;
zend_class_entry **cep;
- /* TODO: clear up class stuff here */
switch (stmt->default_fetch_type) {
case PDO_FETCH_CLASS:
if (stmt->fetch.cls.ctor_args) {
@@ -935,7 +933,7 @@ fail_out:
break;
default:
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "mode is out of range");
+ pdo_raise_impl_error(stmt->dbh, stmt, "22003", "mode is out of range" TSRMLS_CC);
return FAILURE;
}
@@ -965,8 +963,7 @@ static PHP_METHOD(PDOStatement, nextRowset)
struct pdo_column_data *col;
if (!stmt->methods->next_rowset) {
- /* TODO: need a better pdo-level error function */
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "This driver does not support multiple rowsets");
+ pdo_raise_impl_error(stmt->dbh, stmt, "IM001", "driver does not support multiple rowsets" TSRMLS_CC);
RETURN_FALSE;
}
diff --git a/ext/pdo/php_pdo_int.h b/ext/pdo/php_pdo_int.h
index 48e0df1850..fed5c861f4 100755
--- a/ext/pdo/php_pdo_int.h
+++ b/ext/pdo/php_pdo_int.h
@@ -50,6 +50,7 @@ zend_object_iterator *php_pdo_dbstmt_iter_get(zend_class_entry *ce, zval *object
extern pdo_driver_t *pdo_find_driver(const char *name, int namelen);
extern void pdo_handle_error(pdo_dbh_t *dbh, pdo_stmt_t *stmt TSRMLS_DC);
+extern void pdo_raise_impl_error(pdo_dbh_t *dbh, pdo_stmt_t *stmt, const char *sqlstate, const char *supp TSRMLS_DC);
#define PDO_DBH_CLEAR_ERR() strcpy(dbh->error_code, PDO_ERR_NONE)
#define PDO_STMT_CLEAR_ERR() strcpy(stmt->error_code, PDO_ERR_NONE)