#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)
+static int pdo_dbh_attribute_set(pdo_dbh_t *dbh, long attr, zval *value 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;
const char *msg;
-
if (dbh->error_mode == PDO_ERRMODE_SILENT) {
#if 0
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 = "<<Unknown>>";
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;
}
return dsn;
}
+/* }}} */
/* {{{ proto void PDO::__construct(string dsn, string username, string passwd [, array options])
*/
dbh->data_source = (const char*)pestrdup(colon + 1, is_persistent);
dbh->username = username ? pestrdup(username, is_persistent) : NULL;
dbh->password = password ? pestrdup(password, is_persistent) : NULL;
+ dbh->default_fetch_type = PDO_FETCH_BOTH;
dbh->auto_commit = pdo_attr_lval(options, PDO_ATTR_AUTOCOMMIT, 1 TSRMLS_CC);
}
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;
}
|| 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, ctor_args); "
+ "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();
/* unconditionally keep this for later reference */
stmt->query_string = estrndup(statement, statement_len);
stmt->query_stringlen = statement_len;
- stmt->default_fetch_type = PDO_FETCH_BOTH;
+ stmt->default_fetch_type = dbh->default_fetch_type;
stmt->dbh = dbh;
/* give it a reference to me */
zend_objects_store_add_ref(getThis() TSRMLS_CC);
}
/* }}} */
-/* {{{ proto bool PDO::setAttribute(long attribute, mixed value)
- Set an attribute */
-static PHP_METHOD(PDO, setAttribute)
+static int pdo_dbh_attribute_set(pdo_dbh_t *dbh, long attr, zval *value TSRMLS_DC) /* {{{ */
{
- pdo_dbh_t *dbh = zend_object_store_get_object(getThis() TSRMLS_CC);
- long attr;
- zval *value = NULL;
-
- if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lz!", &attr, &value)) {
- RETURN_FALSE;
- }
-
- PDO_CONSTRUCT_CHECK;
-
switch (attr) {
case PDO_ATTR_ERRMODE:
convert_to_long(value);
case PDO_ERRMODE_WARNING:
case PDO_ERRMODE_EXCEPTION:
dbh->error_mode = Z_LVAL_P(value);
- RETURN_TRUE;
+ return SUCCESS;
default:
pdo_raise_impl_error(dbh, NULL, "HY000", "invalid error mode" TSRMLS_CC);
PDO_HANDLE_DBH_ERR();
- RETURN_FALSE;
+ return FAILURE;
}
- RETURN_FALSE;
+ return FAILURE;
case PDO_ATTR_CASE:
convert_to_long(value);
case PDO_CASE_UPPER:
case PDO_CASE_LOWER:
dbh->desired_case = Z_LVAL_P(value);
- RETURN_TRUE;
+ return SUCCESS;
default:
pdo_raise_impl_error(dbh, NULL, "HY000", "invalid case folding mode" TSRMLS_CC);
PDO_HANDLE_DBH_ERR();
- RETURN_FALSE;
+ return FAILURE;
}
- RETURN_FALSE;
+ return FAILURE;
case PDO_ATTR_ORACLE_NULLS:
convert_to_long(value);
dbh->oracle_nulls = Z_LVAL_P(value);
- RETURN_TRUE;
+ return SUCCESS;
+
+ case PDO_ATTR_DEFAULT_FETCH_MODE:
+ convert_to_long(value);
+ if (Z_LVAL_P(value) == PDO_FETCH_USE_DEFAULT) {
+ pdo_raise_impl_error(dbh, NULL, "HY000", "invalid fetch mode type" TSRMLS_CC);
+ return FAILURE;
+ }
+ dbh->default_fetch_type = Z_LVAL_P(value);
+ return SUCCESS;
case PDO_ATTR_STRINGIFY_FETCHES:
convert_to_long(value);
dbh->stringify = Z_LVAL_P(value) ? 1 : 0;
- RETURN_TRUE;
+ return SUCCESS;
case PDO_ATTR_STATEMENT_CLASS: {
/* array(string classname, array(mixed ctor_args)) */
"PDO::ATTR_STATEMENT_CLASS cannot be used with persistent PDO instances"
TSRMLS_CC);
PDO_HANDLE_DBH_ERR();
- RETURN_FALSE;
+ return FAILURE;
}
if (Z_TYPE_P(value) != IS_ARRAY
|| zend_hash_index_find(Z_ARRVAL_P(value), 0, (void**)&item) == FAILURE
"the classname must be a string specifying an existing class"
TSRMLS_CC);
PDO_HANDLE_DBH_ERR();
- RETURN_FALSE;
+ 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_FALSE;
+ 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_FALSE;
+ return FAILURE;
}
dbh->def_stmt_ce = *pce;
if (dbh->def_stmt_ctor_args) {
"ctor_args must be an array"
TSRMLS_CC);
PDO_HANDLE_DBH_ERR();
- RETURN_FALSE;
+ return FAILURE;
}
(*item)->refcount++;
dbh->def_stmt_ctor_args = *item;
}
- RETURN_TRUE;
+ return SUCCESS;
}
default:
PDO_DBH_CLEAR_ERR();
if (dbh->methods->set_attribute(dbh, attr, value TSRMLS_CC)) {
- RETURN_TRUE;
+ return SUCCESS;
}
fail:
} else {
PDO_HANDLE_DBH_ERR();
}
- RETURN_FALSE;
+ return FAILURE;
+}
+/* }}} */
+
+/* {{{ proto bool PDO::setAttribute(long attribute, mixed value)
+ Set an attribute */
+static PHP_METHOD(PDO, setAttribute)
+{
+ pdo_dbh_t *dbh = zend_object_store_get_object(getThis() TSRMLS_CC);
+ long attr;
+ zval *value = NULL;
+
+ if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lz!", &attr, &value)) {
+ RETURN_FALSE;
+ }
+
+ PDO_CONSTRUCT_CHECK;
+
+ if (pdo_dbh_attribute_set(dbh, attr, value TSRMLS_CC)) {
+ RETURN_TRUE;
+ }
+ RETURN_FALSE;
}
/* }}} */
add_next_index_zval(return_value, dbh->def_stmt_ctor_args);
}
return;
+ case PDO_ATTR_DEFAULT_FETCH_MODE:
+ RETURN_LONG(dbh->default_fetch_type);
+
}
if (!dbh->methods->get_attribute) {
/* unconditionally keep this for later reference */
stmt->query_string = estrndup(statement, statement_len);
stmt->query_stringlen = statement_len;
- stmt->default_fetch_type = PDO_FETCH_BOTH;
+
+ stmt->default_fetch_type = dbh->default_fetch_type;
stmt->active_query_string = stmt->query_string;
stmt->active_query_stringlen = statement_len;
stmt->dbh = dbh;
if (dbh->methods->preparer(dbh, statement, statement_len, stmt, NULL TSRMLS_CC)) {
if (ZEND_NUM_ARGS() == 1 || SUCCESS == pdo_stmt_setup_fetch_mode(INTERNAL_FUNCTION_PARAM_PASSTHRU, stmt, 1)) {
+ PDO_STMT_CLEAR_ERR();
+
/* now execute the statement */
PDO_STMT_CLEAR_ERR();
if (stmt->methods->executer(stmt TSRMLS_CC)) {
zval_dtor(return_value);
}
+ PDO_HANDLE_STMT_ERR();
+
+ /* kill the object handle for the stmt here */
+ zval_dtor(return_value);
+
RETURN_FALSE;
}
/* }}} */
zend_function_entry pdo_dbh_functions[] = {
ZEND_MALIAS(PDO, __construct, dbh_constructor, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(PDO, prepare, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(PDO, beginTransaction,NULL, ZEND_ACC_PUBLIC)
+ PHP_ME(PDO, prepare, NULL, ZEND_ACC_PUBLIC)
+ PHP_ME(PDO, beginTransaction, NULL, ZEND_ACC_PUBLIC)
PHP_ME(PDO, commit, NULL, ZEND_ACC_PUBLIC)
PHP_ME(PDO, rollBack, NULL, ZEND_ACC_PUBLIC)
PHP_ME(PDO, setAttribute, NULL, ZEND_ACC_PUBLIC)
static zend_object_handlers pdo_dbh_object_handlers;
-PDO_API void php_pdo_declare_stringl_constant(const char *const_name,
- size_t name_len, const char *value, size_t value_len TSRMLS_DC)
-{
-#if PHP_MAJOR_VERSION > 5 || PHP_MINOR_VERSION >= 1
- zend_declare_class_constant_stringl(pdo_dbh_ce, (char*)const_name, name_len, (char*)value, value_len TSRMLS_CC);
-#else
- zval *constant = malloc(sizeof(*constant));
- ZVAL_STRINGL(constant, zend_strndup(value, value_len), value_len, 0);
- INIT_PZVAL(constant);
- zend_hash_update(&pdo_dbh_ce->constants_table, (char*)const_name, name_len+1, &constant, sizeof(zval*), NULL);
-#endif
-}
-
-PDO_API void php_pdo_declare_long_constant(const char *const_name,
- size_t name_len, long value TSRMLS_DC)
-{
-#if PHP_MAJOR_VERSION > 5 || PHP_MINOR_VERSION >= 1
- zend_declare_class_constant_long(pdo_dbh_ce, (char*)const_name, name_len, value TSRMLS_CC);
-#else
- zval *constant = malloc(sizeof(*constant));
- ZVAL_LONG(constant, value);
- INIT_PZVAL(constant);
- zend_hash_update(&pdo_dbh_ce->constants_table, (char*)const_name, name_len+1, &constant, sizeof(zval*), NULL);
-#endif
-}
-
void pdo_dbh_init(TSRMLS_D)
{
zend_class_entry ce;
#if PHP_MAJOR_VERSION > 5 || PHP_MINOR_VERSION >= 1
REGISTER_PDO_CLASS_CONST_LONG("FETCH_SERIALIZE",(long)PDO_FETCH_SERIALIZE);
#endif
+ REGISTER_PDO_CLASS_CONST_LONG("FETCH_PROPS_LATE",(long)PDO_FETCH_PROPS_LATE);
REGISTER_PDO_CLASS_CONST_LONG("FETCH_NAMED",(long)PDO_FETCH_NAMED);
REGISTER_PDO_CLASS_CONST_LONG("ATTR_AUTOCOMMIT", (long)PDO_ATTR_AUTOCOMMIT);
REGISTER_PDO_CLASS_CONST_LONG("ATTR_STRINGIFY_FETCHES",(long)PDO_ATTR_STRINGIFY_FETCHES);
REGISTER_PDO_CLASS_CONST_LONG("ATTR_MAX_COLUMN_LEN",(long)PDO_ATTR_MAX_COLUMN_LEN);
REGISTER_PDO_CLASS_CONST_LONG("ATTR_EMULATE_PREPARES",(long)PDO_ATTR_EMULATE_PREPARES);
+ REGISTER_PDO_CLASS_CONST_LONG("ATTR_DEFAULT_FETCH_MODE",(long)PDO_ATTR_DEFAULT_FETCH_MODE);
REGISTER_PDO_CLASS_CONST_LONG("ERRMODE_SILENT", (long)PDO_ERRMODE_SILENT);
REGISTER_PDO_CLASS_CONST_LONG("ERRMODE_WARNING", (long)PDO_ERRMODE_WARNING);
static void dbh_free(pdo_dbh_t *dbh TSRMLS_DC)
{
int i;
-
+
if (--dbh->refcount)
return;
if (dbh->password) {
pefree(dbh->password, dbh->is_persistent);
}
-
+
if (dbh->def_stmt_ctor_args) {
zval_ptr_dtor(&dbh->def_stmt_ctor_args);
}
method = (zval**)Z_ARRVAL_P(callable)->pListHead->pListNext->pData;
if (Z_TYPE_PP(object) == IS_STRING) { /* static call */
+ if (zend_lookup_class(Z_STRVAL_PP(object), Z_STRLEN_PP(object), &pce TSRMLS_CC) == FAILURE) {
+ pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "user-supplied class does not exist" TSRMLS_CC);
+ return 0;
+ } else {
+ ce = *pce;
+ }
object = NULL;
} else if (Z_TYPE_PP(object) == IS_OBJECT) { /* object call */
ce = Z_OBJCE_PP(object);
pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "user-supplied function must be a valid callback; bogus method name" TSRMLS_CC);
return 0;
}
+ } else if (Z_TYPE_P(callable) == IS_STRING) {
+ method = &callable;
}
if (!zend_is_callable(callable, 0, &fname)) {
RETVAL_FALSE;
switch (how) {
+ case PDO_FETCH_USE_DEFAULT:
case PDO_FETCH_ASSOC:
case PDO_FETCH_BOTH:
case PDO_FETCH_NUM:
case PDO_FETCH_NAMED:
if (!return_all) {
ALLOC_HASHTABLE(return_value->value.ht);
- zend_hash_init(return_value->value.ht, stmt->column_count, NULL, ZVAL_PTR_DTOR, 0);
+ zend_hash_init(return_value->value.ht, stmt->column_count, NULL, ZVAL_PTR_DTOR, 0);
Z_TYPE_P(return_value) = IS_ARRAY;
} else {
array_init(return_value);
return 0;
}
}
+ if (ce->constructor && (flags & PDO_FETCH_PROPS_LATE)) {
+ stmt->fetch.cls.fci.object_pp = &return_value;
+ stmt->fetch.cls.fcc.object_pp = &return_value;
+ if (zend_call_function(&stmt->fetch.cls.fci, &stmt->fetch.cls.fcc TSRMLS_CC) == FAILURE) {
+ pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "could not call class constructor" TSRMLS_CC);
+ return 0;
+ } else {
+ if (stmt->fetch.cls.retval_ptr) {
+ zval_ptr_dtor(&stmt->fetch.cls.retval_ptr);
+ }
+ }
+ }
}
break;
add_assoc_zval(return_value, stmt->columns[i].name, val);
break;
+ case PDO_FETCH_USE_DEFAULT:
case PDO_FETCH_BOTH:
add_assoc_zval(return_value, stmt->columns[i].name, val);
ZVAL_ADDREF(val);
switch (how) {
case PDO_FETCH_CLASS:
- if (ce->constructor) {
+ if (ce->constructor && !(flags & PDO_FETCH_PROPS_LATE)) {
stmt->fetch.cls.fci.object_pp = &return_value;
stmt->fetch.cls.fcc.object_pp = &return_value;
if (zend_call_function(&stmt->fetch.cls.fci, &stmt->fetch.cls.fcc TSRMLS_CC) == FAILURE) {
param.paramno = -1;
param.param_type = PDO_PARAM_STR;
-
+
if (FAILURE == zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC,
"lz/|l", ¶m.paramno, ¶m.parameter, ¶m.param_type)) {
if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz/|l", ¶m.name,
NULL
};
-zend_object_iterator *pdo_stmt_iter_get(zend_class_entry *ce, zval *object TSRMLS_DC)
+zend_object_iterator *pdo_stmt_iter_get(zend_class_entry *ce, zval *object, int by_ref TSRMLS_DC)
{
pdo_stmt_t *stmt = (pdo_stmt_t*)zend_object_store_get_object(object TSRMLS_CC);
struct php_pdo_iterator *I;
+ if (by_ref) {
+ zend_error(E_ERROR, "An iterator cannot be used with foreach by reference");
+ }
+
I = ecalloc(1, sizeof(*I));
I->iter.funcs = &pdo_stmt_iter_funcs;
I->iter.data = I;