]> granicus.if.org Git - php/commitdiff
- Revert signature of PDO:prepare()
authorMarcus Boerger <helly@php.net>
Tue, 22 Feb 2005 20:25:56 +0000 (20:25 +0000)
committerMarcus Boerger <helly@php.net>
Tue, 22 Feb 2005 20:25:56 +0000 (20:25 +0000)
  old: proto object PDO::prepare(string statment [, array driver_options [, string classname ]])
  now: proto object PDO::prepare(string statment [, array options])
  param 'classname' and and 'ctor_args' are now set through options
  using index PDO_ATTR_STATEMENT_CLASS
- Change all deriver_options parameters to 'options' to reflect the fact
  that they may contain statement as well as driver specific flags

ext/pdo/pdo.c
ext/pdo/pdo_dbh.c
ext/pdo/php_pdo_driver.h
ext/pdo/tests/pdo_011.inc [new file with mode: 0755]

index a99edac3688e227e704340470a8788ecd8dd9f1d..74b7fbd93ebc2d6250865b180f7bec19a44869c7 100755 (executable)
@@ -255,6 +255,7 @@ PHP_MINIT_FUNCTION(pdo)
        REGISTER_LONG_CONSTANT("PDO_ATTR_CURSOR",               (long)PDO_ATTR_CURSOR,          CONST_CS|CONST_PERSISTENT);
        REGISTER_LONG_CONSTANT("PDO_ATTR_ORACLE_NULLS", (long)PDO_ATTR_ORACLE_NULLS,    CONST_CS|CONST_PERSISTENT);
        REGISTER_LONG_CONSTANT("PDO_ATTR_PERSISTENT",   (long)PDO_ATTR_PERSISTENT,              CONST_CS|CONST_PERSISTENT);
+       REGISTER_LONG_CONSTANT("PDO_ATTR_STATEMENT_CLASS",              (long)PDO_ATTR_STATEMENT_CLASS,                 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);
index 98280d430465c6b8a5647619168fc3cf2b6e21ed..22dee929b8a299875cf59c7fb2b8f1e0921a8329 100755 (executable)
@@ -201,7 +201,7 @@ static char *dsn_from_uri(char *uri, char *buf, size_t buflen TSRMLS_DC)
        return dsn;
 }
 
-/* {{{ proto object PDO::__construct(string dsn, string username, string passwd [, array driver_opts])
+/* {{{ proto object PDO::__construct(string dsn, string username, string passwd [, array options])
    */
 static PHP_FUNCTION(dbh_constructor)
 {
@@ -214,11 +214,11 @@ static PHP_FUNCTION(dbh_constructor)
        char *username=NULL, *password=NULL;
        int usernamelen, passwordlen;
        pdo_driver_t *driver = NULL;
-       zval *driver_options = NULL;
+       zval *options = NULL;
        char alt_dsn[512];
 
        if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|ssa!", &data_source, &data_source_len,
-                               &username, &usernamelen, &password, &passwordlen, &driver_options)) {
+                               &username, &usernamelen, &password, &passwordlen, &options)) {
                ZVAL_NULL(object);
                return;
        }
@@ -276,14 +276,14 @@ static PHP_FUNCTION(dbh_constructor)
        dbh = (pdo_dbh_t *) zend_object_store_get_object(object TSRMLS_CC);
 
        /* is this supposed to be a persistent connection ? */
-       if (driver_options) {
+       if (options) {
                zval **v;
                int plen;
                char *hashkey = NULL;
                list_entry *le;
                pdo_dbh_t *pdbh = NULL;
 
-               if (SUCCESS == zend_hash_index_find(Z_ARRVAL_P(driver_options), PDO_ATTR_PERSISTENT, (void**)&v)) {
+               if (SUCCESS == zend_hash_index_find(Z_ARRVAL_P(options), PDO_ATTR_PERSISTENT, (void**)&v)) {
                        if (Z_TYPE_PP(v) == IS_STRING) {
                                /* user specified key */
                                plen = spprintf(&hashkey, 0, "PDO:DBH:DSN=%s:%s:%s:%s", data_source,
@@ -351,13 +351,13 @@ static PHP_FUNCTION(dbh_constructor)
        dbh->username = username ? pestrdup(username, is_persistent) : NULL;
        dbh->password = password ? pestrdup(password, is_persistent) : NULL;
 
-       dbh->auto_commit = pdo_attr_lval(driver_options, PDO_ATTR_AUTOCOMMIT, 1 TSRMLS_CC);
+       dbh->auto_commit = pdo_attr_lval(options, PDO_ATTR_AUTOCOMMIT, 1 TSRMLS_CC);
 
        if (!dbh->data_source || (username && !dbh->username) || (password && !dbh->password)) {
                php_error_docref(NULL TSRMLS_CC, E_ERROR, "out of memory");
        }
        
-       if (driver->db_handle_factory(dbh, driver_options TSRMLS_CC)) {
+       if (driver->db_handle_factory(dbh, options TSRMLS_CC)) {
                /* all set */
 
                if (is_persistent) {
@@ -453,48 +453,53 @@ static zval * pdo_instanciate_stmt(zval *object, zend_class_entry *dbstmt_ce, zv
 }
 /* }}} */
 
-/* {{{ proto object PDO::prepare(string statment [, array driver_options [, string classname ]])
+/* {{{ proto object PDO::prepare(string statment [, array options])
    Prepares a statement for execution and returns a statement object */
 static PHP_METHOD(PDO, prepare)
 {
        pdo_dbh_t *dbh = zend_object_store_get_object(getThis() TSRMLS_CC);
        pdo_stmt_t *stmt;
-       char *statement, *class_name = NULL;
-       int statement_len, class_name_len;
-       zval *driver_options = NULL, *ctor_args = NULL;
+       char *statement;
+       int statement_len;
+       zval *options = NULL, **opt, **item, *ctor_args;
        zend_class_entry *dbstmt_ce, **pce;
 
-       if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|asz", &statement,
-                       &statement_len, &driver_options, &class_name, &class_name_len, &ctor_args)) {
+       if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|a", &statement,
+                       &statement_len, &options)) {
                RETURN_FALSE;
        }
        
        PDO_DBH_CLEAR_ERR();
 
-       switch(ZEND_NUM_ARGS()) {
-       case 4:
-       case 3:
-               if (zend_lookup_class(class_name, class_name_len, &pce TSRMLS_CC) == FAILURE) {
+       if (ZEND_NUM_ARGS() > 1 && SUCCESS == zend_hash_index_find(Z_ARRVAL_P(options), PDO_ATTR_STATEMENT_CLASS, (void**)&opt)) {
+               if (zend_hash_index_find(Z_ARRVAL_PP(opt), 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
+               ) {
+                       zend_throw_exception_ex(php_pdo_get_exception(), 0 TSRMLS_CC, "PDO_ATTR_STATEMENT_CLASS requires format array(classname, ctor_args) and classname must be a string specifying an existing class");
                        RETURN_FALSE;
                }
-               if (!instanceof_function(*pce, pdo_dbstmt_ce TSRMLS_CC)) {
+               dbstmt_ce = *pce;
+               if (!instanceof_function(dbstmt_ce, pdo_dbstmt_ce TSRMLS_CC)) {
                        zend_throw_exception_ex(php_pdo_get_exception(), 0 TSRMLS_CC, "The provided statement class must be derived from %s", pdo_dbstmt_ce->name);
                        RETURN_FALSE;
                }
-               dbstmt_ce = *pce;
                if (dbstmt_ce->constructor && !(dbstmt_ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) {
                        zend_throw_exception_ex(php_pdo_get_exception(), 0 TSRMLS_CC, "The provided statement class %s must not have a protected or public constructor", dbstmt_ce->name);
                        RETURN_FALSE;
                }
-               break;
-
-       case 2:
-       case 1:
-       case 0:
+               if (zend_hash_index_find(Z_ARRVAL_PP(opt), 1, (void**)&item) == SUCCESS) {
+                       if (Z_TYPE_PP(item) != IS_ARRAY) {
+                               zend_throw_exception_ex(php_pdo_get_exception(), 0 TSRMLS_CC, "PDO_ATTR_STATEMENT_CLASS requires format array(classname, ctor_args) and ctor args must be an array");
+                               RETURN_FALSE;
+                       }
+                       ctor_args = *item;
+               }
+       } else {
                dbstmt_ce = pdo_dbstmt_ce;
-               break;
+               ctor_args = NULL;
        }
-       
+
        if (!pdo_instanciate_stmt(return_value, dbstmt_ce, ctor_args TSRMLS_CC)) {
                zend_throw_exception_ex(php_pdo_get_exception(), 0 TSRMLS_CC, "Failed to instanciate statement class %s", dbstmt_ce->name);
                return;
@@ -512,7 +517,7 @@ static PHP_METHOD(PDO, prepare)
        /* we haven't created a lazy object yet */
        ZVAL_NULL(&stmt->lazy_object_ref);
 
-       if (dbh->methods->preparer(dbh, statement, statement_len, stmt, driver_options TSRMLS_CC)) {
+       if (dbh->methods->preparer(dbh, statement, statement_len, stmt, options TSRMLS_CC)) {
 
                return;
        }
@@ -803,7 +808,6 @@ static PHP_METHOD(PDO, query)
        pdo_stmt_t *stmt;
        char *statement;
        int statement_len;
-       zval *driver_options = NULL;
 
        if (FAILURE == zend_parse_parameters(1 TSRMLS_CC, "s", &statement,
                        &statement_len)) {
@@ -831,7 +835,7 @@ static PHP_METHOD(PDO, query)
        /* we haven't created a lazy object yet */
        ZVAL_NULL(&stmt->lazy_object_ref);
 
-       if (dbh->methods->preparer(dbh, statement, statement_len, stmt, driver_options TSRMLS_CC)) {
+       if (dbh->methods->preparer(dbh, statement, statement_len, stmt, NULL TSRMLS_CC)) {
                if (1) {//ZEND_NUM_ARGS() > 1 || SUCCESS == pdo_stmt_setup_fetch_mode(INTERNAL_FUNCTION_PARAM_PASSTHRU, stmt, 1)) {
                        PDO_STMT_CLEAR_ERR();
 
index f4e70a939af584d0010374ea819c19c7b1351432..b0937a3e3f84ae9a63244ba6009487ba801bcaa3 100755 (executable)
@@ -111,6 +111,7 @@ enum pdo_attribute_type {
        PDO_ATTR_CURSOR,                        /* cursor type */
        PDO_ATTR_ORACLE_NULLS,          /* convert empty strings to NULL */
        PDO_ATTR_PERSISTENT,            /* pconnect style connection */
+       PDO_ATTR_STATEMENT_CLASS,       /* array(classname, array(ctor_args)) to specify the class of the constructed statement */
 
        /* this defines the start of the range for driver specific options.
         * Drivers should define their own attribute constants beginning with this
diff --git a/ext/pdo/tests/pdo_011.inc b/ext/pdo/tests/pdo_011.inc
new file mode 100755 (executable)
index 0000000..494732f
--- /dev/null
@@ -0,0 +1,67 @@
+<?php # vim:ft=php
+
+require_once('pdo.inc');
+       
+set_sql('create', 'CREATE TABLE test(id int PRIMARY KEY, val VARCHAR(10), grp VARCHAR(10))');
+set_sql('insert1', 'INSERT INTO test VALUES(1, \'A\', \'Group1\')'); 
+set_sql('insert2', 'INSERT INTO test VALUES(2, \'B\', \'Group1\')'); 
+set_sql('insert3', 'INSERT INTO test VALUES(3, \'C\', \'Group2\')'); 
+set_sql('insert4', 'INSERT INTO test VALUES(4, \'D\', \'Group2\')'); 
+set_sql('select1',  'SELECT grp, id FROM test');
+set_sql('select2',  'SELECT id, val FROM test');
+
+$DB->exec($SQL['create']);
+$DB->exec($SQL['insert1']);
+$DB->exec($SQL['insert2']);
+$DB->exec($SQL['insert3']);
+$DB->exec($SQL['insert4']);
+
+class Test1
+{
+       public function __construct($id, $val)
+       {
+               echo __METHOD__ . "($id,$val)\n";
+               $this->id = $id;
+               $this->val = $val;
+       }
+       
+       static public function factory($id, $val)
+       {
+               echo __METHOD__ . "($id,$val)\n";
+               return new self($id, $val);
+       }
+}
+
+function test($id,$val='N/A')
+{
+       echo __METHOD__ . "($id,$val)\n";
+       return array($id=>$val);
+}
+
+$f = new Test1(0,0);
+
+var_dump($DB->query($SQL['select1'])->fetchAll(PDO_FETCH_FUNC|PDO_FETCH_GROUP, 'test'));
+var_dump($DB->query($SQL['select2'])->fetchAll(PDO_FETCH_FUNC, 'test'));
+var_dump($DB->query($SQL['select2'])->fetchAll(PDO_FETCH_FUNC, array('Test1','factory')));
+var_dump($DB->query($SQL['select2'])->fetchAll(PDO_FETCH_FUNC, array($f, 'factory')));
+
+class DerivedStatement extends PDOStatement
+{
+       private function __construct($name, $db)
+       {
+               $this->name = $name;
+               echo __METHOD__ . "($name)\n";
+       }
+       
+       function retrieve($id, $val) {
+               echo __METHOD__ . "($id,$val)\n";
+               return array($id=>$val);
+       }
+}
+
+$stmt = $DB->prepare($SQL['select2'], array(PDO_ATTR_STATEMENT_CLASS=>array('DerivedStatement', array('Overloaded', $DB))));
+var_dump(get_class($stmt));
+$stmt->execute();
+var_dump($stmt->fetchAll(PDO_FETCH_FUNC, array($stmt, 'retrieve')));
+
+?>