Index: ext/pdo/pdo_dbh.c =================================================================== RCS file: /repository/php-src/ext/pdo/pdo_dbh.c,v retrieving revision 1.82.2.27 diff -u -p -d -r1.82.2.27 pdo_dbh.c --- ext/pdo/pdo_dbh.c 31 Jan 2006 17:20:32 -0000 1.82.2.27 +++ ext/pdo/pdo_dbh.c 10 Feb 2006 22:59:28 -0000 @@ -36,7 +36,7 @@ #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) +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; @@ -98,8 +98,9 @@ void pdo_raise_impl_error(pdo_dbh_t *dbh efree(message); } } +/* }}} */ -void pdo_handle_error(pdo_dbh_t *dbh, pdo_stmt_t *stmt TSRMLS_DC) +void pdo_handle_error(pdo_dbh_t *dbh, pdo_stmt_t *stmt TSRMLS_DC) /* {{{ */ { pdo_error_type *pdo_err = &dbh->error_code; const char *msg = "<>"; @@ -178,8 +179,9 @@ void pdo_handle_error(pdo_dbh_t *dbh, pd efree(supp); } } +/* }}} */ -static char *dsn_from_uri(char *uri, char *buf, size_t buflen TSRMLS_DC) +static char *dsn_from_uri(char *uri, char *buf, size_t buflen TSRMLS_DC) /* {{{ */ { php_stream *stream; char *dsn = NULL; @@ -191,6 +193,131 @@ static char *dsn_from_uri(char *uri, cha } return dsn; } +/* }}} */ + +static int pdo_dbh_attribute_set(pdo_dbh_t *dbh, long attr, zval *value TSRMLS_DC) /* {{{ */ +{ + 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 SUCCESS; + default: + pdo_raise_impl_error(dbh, NULL, "HY000", "invalid error mode" TSRMLS_CC); + PDO_HANDLE_DBH_ERR(); + return FAILURE; + } + return FAILURE; + + case PDO_ATTR_CASE: + convert_to_long(value); + switch (Z_LVAL_P(value)) { + case PDO_CASE_NATURAL: + case PDO_CASE_UPPER: + case PDO_CASE_LOWER: + dbh->desired_case = Z_LVAL_P(value); + return SUCCESS; + default: + pdo_raise_impl_error(dbh, NULL, "HY000", "invalid case folding mode" TSRMLS_CC); + PDO_HANDLE_DBH_ERR(); + return FAILURE; + } + return FAILURE; + + case PDO_ATTR_ORACLE_NULLS: + convert_to_long(value); + dbh->oracle_nulls = Z_LVAL_P(value); + return SUCCESS; + + case PDO_ATTR_STRINGIFY_FETCHES: + convert_to_long(value); + dbh->stringify = Z_LVAL_P(value) ? 1 : 0; + return SUCCESS; + + case PDO_ATTR_STATEMENT_CLASS: { + /* array(string classname, array(mixed ctor_args)) */ + zend_class_entry **pce; + zval **item; + + if (dbh->is_persistent) { + pdo_raise_impl_error(dbh, NULL, "HY000", + "PDO::ATTR_STATEMENT_CLASS cannot be used with persistent PDO instances" + TSRMLS_CC); + PDO_HANDLE_DBH_ERR(); + return FAILURE; + } + if (Z_TYPE_P(value) != IS_ARRAY + || zend_hash_index_find(Z_ARRVAL_P(value), 0, (void**)&item) == FAILURE + || Z_TYPE_PP(item) != IS_STRING + || zend_lookup_class(Z_STRVAL_PP(item), Z_STRLEN_PP(item), &pce TSRMLS_CC) == FAILURE + ) { + pdo_raise_impl_error(dbh, NULL, "HY000", + "PDO::ATTR_STATEMENT_CLASS requires format array(classname, array(ctor_args)); " + "the classname must be a string specifying an existing class" + TSRMLS_CC); + PDO_HANDLE_DBH_ERR(); + return FAILURE; + } + if (!instanceof_function(*pce, pdo_dbstmt_ce TSRMLS_CC)) { + pdo_raise_impl_error(dbh, NULL, "HY000", + "user-supplied statement class must be derived from PDOStatement" TSRMLS_CC); + PDO_HANDLE_DBH_ERR(); + return FAILURE; + } + if ((*pce)->constructor && !((*pce)->constructor->common.fn_flags & (ZEND_ACC_PRIVATE|ZEND_ACC_PROTECTED))) { + pdo_raise_impl_error(dbh, NULL, "HY000", + "user-supplied statement class cannot have a public constructor" TSRMLS_CC); + PDO_HANDLE_DBH_ERR(); + return FAILURE; + } + dbh->def_stmt_ce = *pce; + if (dbh->def_stmt_ctor_args) { + zval_ptr_dtor(&dbh->def_stmt_ctor_args); + dbh->def_stmt_ctor_args = NULL; + } + if (zend_hash_index_find(Z_ARRVAL_P(value), 1, (void**)&item) == SUCCESS) { + if (Z_TYPE_PP(item) != IS_ARRAY) { + pdo_raise_impl_error(dbh, NULL, "HY000", + "PDO::ATTR_STATEMENT_CLASS requires format array(classname, array(ctor_args)); " + "ctor_args must be an array" + TSRMLS_CC); + PDO_HANDLE_DBH_ERR(); + return FAILURE; + } + (*item)->refcount++; + dbh->def_stmt_ctor_args = *item; + } + return SUCCESS; + } + + default: + ; + } + + if (!dbh->methods->set_attribute) { + goto fail; + } + + PDO_DBH_CLEAR_ERR(); + if (dbh->methods->set_attribute(dbh, attr, value TSRMLS_CC)) { + return SUCCESS; + } + +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) { + pdo_raise_impl_error(dbh, NULL, "IM001", "driver does not support setting attributes" TSRMLS_CC); + } else { + PDO_HANDLE_DBH_ERR(); + } + return FAILURE; +} +/* }}} */ /* {{{ proto object PDO::__construct(string dsn, string username, string passwd [, array options]) */ @@ -383,6 +510,20 @@ static PHP_METHOD(PDO, dbh_constructor) } dbh->driver = driver; + + if (options) { + zval **attr_value; + char *str_key; + long long_key; + + zend_hash_internal_pointer_reset(Z_ARRVAL_P(options)); + while (SUCCESS == zend_hash_get_current_data(Z_ARRVAL_P(options), (void**)&attr_value) + && HASH_KEY_IS_LONG == zend_hash_get_current_key(Z_ARRVAL_P(options), &str_key, &long_key, 0)) { + + pdo_dbh_attribute_set(dbh, long_key, *attr_value TSRMLS_CC); + zend_hash_move_forward(Z_ARRVAL_P(options)); + } + } return; } @@ -658,124 +799,9 @@ static PHP_METHOD(PDO, setAttribute) PDO_CONSTRUCT_CHECK; - 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: - pdo_raise_impl_error(dbh, NULL, "HY000", "invalid error mode" TSRMLS_CC); - PDO_HANDLE_DBH_ERR(); - RETURN_FALSE; - } - RETURN_FALSE; - - case PDO_ATTR_CASE: - convert_to_long(value); - switch (Z_LVAL_P(value)) { - case PDO_CASE_NATURAL: - case PDO_CASE_UPPER: - case PDO_CASE_LOWER: - dbh->desired_case = Z_LVAL_P(value); - RETURN_TRUE; - default: - pdo_raise_impl_error(dbh, NULL, "HY000", "invalid case folding mode" TSRMLS_CC); - PDO_HANDLE_DBH_ERR(); - RETURN_FALSE; - } - RETURN_FALSE; - - case PDO_ATTR_ORACLE_NULLS: - convert_to_long(value); - dbh->oracle_nulls = Z_LVAL_P(value); - RETURN_TRUE; - - case PDO_ATTR_STRINGIFY_FETCHES: - convert_to_long(value); - dbh->stringify = Z_LVAL_P(value) ? 1 : 0; - RETURN_TRUE; - - case PDO_ATTR_STATEMENT_CLASS: { - /* array(string classname, array(mixed ctor_args)) */ - zend_class_entry **pce; - zval **item; - - if (dbh->is_persistent) { - pdo_raise_impl_error(dbh, NULL, "HY000", - "PDO::ATTR_STATEMENT_CLASS cannot be used with persistent PDO instances" - TSRMLS_CC); - PDO_HANDLE_DBH_ERR(); - RETURN_FALSE; - } - if (Z_TYPE_P(value) != IS_ARRAY - || zend_hash_index_find(Z_ARRVAL_P(value), 0, (void**)&item) == FAILURE - || Z_TYPE_PP(item) != IS_STRING - || zend_lookup_class(Z_STRVAL_PP(item), Z_STRLEN_PP(item), &pce TSRMLS_CC) == FAILURE - ) { - pdo_raise_impl_error(dbh, NULL, "HY000", - "PDO::ATTR_STATEMENT_CLASS requires format array(classname, array(ctor_args)); " - "the classname must be a string specifying an existing class" - TSRMLS_CC); - PDO_HANDLE_DBH_ERR(); - RETURN_FALSE; - } - if (!instanceof_function(*pce, pdo_dbstmt_ce TSRMLS_CC)) { - pdo_raise_impl_error(dbh, NULL, "HY000", - "user-supplied statement class must be derived from PDOStatement" TSRMLS_CC); - PDO_HANDLE_DBH_ERR(); - RETURN_FALSE; - } - if ((*pce)->constructor && !((*pce)->constructor->common.fn_flags & (ZEND_ACC_PRIVATE|ZEND_ACC_PROTECTED))) { - pdo_raise_impl_error(dbh, NULL, "HY000", - "user-supplied statement class cannot have a public constructor" TSRMLS_CC); - PDO_HANDLE_DBH_ERR(); - RETURN_FALSE; - } - dbh->def_stmt_ce = *pce; - if (dbh->def_stmt_ctor_args) { - zval_ptr_dtor(&dbh->def_stmt_ctor_args); - dbh->def_stmt_ctor_args = NULL; - } - if (zend_hash_index_find(Z_ARRVAL_P(value), 1, (void**)&item) == SUCCESS) { - if (Z_TYPE_PP(item) != IS_ARRAY) { - pdo_raise_impl_error(dbh, NULL, "HY000", - "PDO::ATTR_STATEMENT_CLASS requires format array(classname, array(ctor_args)); " - "ctor_args must be an array" - TSRMLS_CC); - PDO_HANDLE_DBH_ERR(); - RETURN_FALSE; - } - (*item)->refcount++; - dbh->def_stmt_ctor_args = *item; - } - RETURN_TRUE; - } - - default: - ; - } - - if (!dbh->methods->set_attribute) { - goto fail; - } - - PDO_DBH_CLEAR_ERR(); - if (dbh->methods->set_attribute(dbh, attr, value TSRMLS_CC)) { + if (pdo_dbh_attribute_set(dbh, attr, value TSRMLS_CC)) { RETURN_TRUE; } - -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) { - pdo_raise_impl_error(dbh, NULL, "IM001", "driver does not support setting attributes" TSRMLS_CC); - } else { - PDO_HANDLE_DBH_ERR(); - } RETURN_FALSE; } /* }}} */