Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:33468 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 27901 invoked by uid 1010); 27 Nov 2007 18:34:20 -0000 Delivered-To: ezmlm-scan-internals@lists.php.net Delivered-To: ezmlm-internals@lists.php.net Received: (qmail 27860 invoked from network); 27 Nov 2007 18:34:18 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 27 Nov 2007 18:34:18 -0000 X-Host-Fingerprint: 84.75.68.140 84-75-68-140.dclient.hispeed.ch Received: from [84.75.68.140] ([84.75.68.140:11064] helo=localhost.localdomain) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id DC/10-25304-F036C474 for ; Tue, 27 Nov 2007 13:33:58 -0500 To: internals@lists.php.net,Marcus Boerger Message-ID: <474C630B.1040309@oeri.ch> Date: Tue, 27 Nov 2007 19:33:47 +0100 User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.9) Gecko/20071031 Thunderbird/2.0.0.9 Mnenhy/0.7.5.0 MIME-Version: 1.0 References: <7D.72.55421.8B7FA474@pb1.pair.com> <1345545949.20071126182117@marcus-boerger.de> In-Reply-To: <1345545949.20071126182117@marcus-boerger.de> Content-Type: multipart/mixed; boundary="------------070404060906080007060000" X-Posted-By: 84.75.68.140 Subject: Re: [PHP-DEV] [PATCH] PDO::FETCH_KEYS From: hp@oeri.ch (Hans-Peter Oeri) --------------070404060906080007060000 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit Hoi! Marcus Boerger wrote: > can you add tests so we get a better idea? > cvs add ; cvd di -N > patchfile.txt I could... If I had a cvs account. As I don't, please find attached an updated patch (I hope I got the zval allocation right) as well as: - pdo_034.phpt (updated in patch) - pdo_035.phpt (addition, not in patch) Please be aware that pdo_035.phpt may only pass on firebird and mysql as it depends on an updated column information struct. HPO --------------070404060906080007060000 Content-Type: text/plain; name="pdo_tests.patch" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="pdo_tests.patch" Index: ext/pdo/pdo_dbh.c =================================================================== RCS file: /repository/php-src/ext/pdo/pdo_dbh.c,v retrieving revision 1.82.2.31.2.17.2.2 diff -u -r1.82.2.31.2.17.2.2 pdo_dbh.c --- ext/pdo/pdo_dbh.c 7 Oct 2007 05:22:05 -0000 1.82.2.31.2.17.2.2 +++ ext/pdo/pdo_dbh.c 27 Nov 2007 18:27:09 -0000 @@ -784,6 +784,15 @@ return SUCCESS; } + case PDO_ATTR_2D_NULLBASE: + if( dbh->nullbase ) { + efree( dbh->nullbase ); + } + + dbh->nullbase = (value ? estrdup( Z_STRVAL_P(value) ) : NULL ); + + return SUCCESS; + default: ; } @@ -872,6 +881,8 @@ case PDO_ATTR_DEFAULT_FETCH_MODE: RETURN_LONG(dbh->default_fetch_type); + case PDO_ATTR_2D_NULLBASE: + RETURN_STRING(dbh->nullbase, 1); } if (!dbh->methods->get_attribute) { @@ -1331,10 +1342,11 @@ REGISTER_PDO_CLASS_CONST_LONG("PARAM_EVT_FETCH_POST", (long)PDO_PARAM_EVT_FETCH_POST); REGISTER_PDO_CLASS_CONST_LONG("PARAM_EVT_NORMALIZE", (long)PDO_PARAM_EVT_NORMALIZE); - REGISTER_PDO_CLASS_CONST_LONG("FETCH_LAZY", (long)PDO_FETCH_LAZY); REGISTER_PDO_CLASS_CONST_LONG("FETCH_ASSOC",(long)PDO_FETCH_ASSOC); REGISTER_PDO_CLASS_CONST_LONG("FETCH_NUM", (long)PDO_FETCH_NUM); REGISTER_PDO_CLASS_CONST_LONG("FETCH_BOTH", (long)PDO_FETCH_BOTH); + REGISTER_PDO_CLASS_CONST_LONG("FETCH_2D", (long)PDO_FETCH_2D); + REGISTER_PDO_CLASS_CONST_LONG("FETCH_LAZY", (long)PDO_FETCH_LAZY); REGISTER_PDO_CLASS_CONST_LONG("FETCH_OBJ", (long)PDO_FETCH_OBJ); REGISTER_PDO_CLASS_CONST_LONG("FETCH_BOUND",(long)PDO_FETCH_BOUND); REGISTER_PDO_CLASS_CONST_LONG("FETCH_COLUMN",(long)PDO_FETCH_COLUMN); @@ -1343,7 +1355,8 @@ REGISTER_PDO_CLASS_CONST_LONG("FETCH_FUNC", (long)PDO_FETCH_FUNC); REGISTER_PDO_CLASS_CONST_LONG("FETCH_GROUP",(long)PDO_FETCH_GROUP); REGISTER_PDO_CLASS_CONST_LONG("FETCH_UNIQUE",(long)PDO_FETCH_UNIQUE); - REGISTER_PDO_CLASS_CONST_LONG("FETCH_KEY_PAIR",(long)PDO_FETCH_KEY_PAIR); + REGISTER_PDO_CLASS_CONST_LONG("FETCH_KEY_PAIR",(long)PDO_FETCH_KEYS); + REGISTER_PDO_CLASS_CONST_LONG("FETCH_KEYS",(long)PDO_FETCH_KEYS); REGISTER_PDO_CLASS_CONST_LONG("FETCH_CLASSTYPE",(long)PDO_FETCH_CLASSTYPE); #if PHP_MAJOR_VERSION > 5 || PHP_MINOR_VERSION >= 1 REGISTER_PDO_CLASS_CONST_LONG("FETCH_SERIALIZE",(long)PDO_FETCH_SERIALIZE); @@ -1372,7 +1385,7 @@ 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("ATTR_2D_NULLBASE", (long)PDO_ATTR_2D_NULLBASE); REGISTER_PDO_CLASS_CONST_LONG("ERRMODE_SILENT", (long)PDO_ERRMODE_SILENT); REGISTER_PDO_CLASS_CONST_LONG("ERRMODE_WARNING", (long)PDO_ERRMODE_WARNING); REGISTER_PDO_CLASS_CONST_LONG("ERRMODE_EXCEPTION", (long)PDO_ERRMODE_EXCEPTION); @@ -1472,13 +1485,17 @@ dbh->methods->rollback(dbh TSRMLS_CC); dbh->in_txn = 0; } - + if (dbh->properties) { zend_hash_destroy(dbh->properties); efree(dbh->properties); dbh->properties = NULL; } + if( dbh->nullbase ) { + efree( dbh->nullbase ); + } + if (!dbh->is_persistent) { dbh_free(dbh TSRMLS_CC); } else if (dbh->methods && dbh->methods->persistent_shutdown) { @@ -1496,6 +1513,7 @@ memset(dbh, 0, sizeof(*dbh)); dbh->ce = ce; dbh->refcount = 1; + dbh->nullbase = estrdup( "" ); ALLOC_HASHTABLE(dbh->properties); zend_hash_init(dbh->properties, 0, NULL, ZVAL_PTR_DTOR, 0); zend_hash_copy(dbh->properties, &ce->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *)); Index: ext/pdo/pdo_stmt.c =================================================================== RCS file: /repository/php-src/ext/pdo/pdo_stmt.c,v retrieving revision 1.118.2.38.2.24.2.7 diff -u -r1.118.2.38.2.24.2.7 pdo_stmt.c --- ext/pdo/pdo_stmt.c 20 Nov 2007 23:12:17 -0000 1.118.2.38.2.24.2.7 +++ ext/pdo/pdo_stmt.c 27 Nov 2007 18:27:09 -0000 @@ -886,6 +886,74 @@ } /* }}} */ +/* iteratively create array out of a column */ +static void do_fetch_keys_iterative( pdo_stmt_t *stmt, zval *base, zval *index ) { + zval *val; + zval **valp; + int isfound; + int i=1; + + while( + (i < stmt->fetch.num_keys) + || (i <= stmt->fetch.num_keys && stmt->column_count-stmt->fetch.num_keys > 1) + ){ + isfound = (( (Z_TYPE_P(index) == IS_LONG) + ? zend_hash_index_find(Z_ARRVAL_P(base), Z_LVAL_P(index), (void**)&valp) + : zend_hash_find(Z_ARRVAL_P(base), Z_STRVAL_P(index), Z_STRLEN_P(index)+1, (void**)&valp) + ) == SUCCESS); + if( !isfound ) { + MAKE_STD_ZVAL(val); + array_init(val); + + if( Z_TYPE_P(index) == IS_LONG ) { + add_index_zval( base, Z_LVAL_P(index), val ); + } else { + add_assoc_zval( base, Z_STRVAL_P(index), val ); + } + } + + base = (isfound ? (*valp) : val); + zval_dtor(index); + FREE_ZVAL(index); + MAKE_STD_ZVAL(index); + fetch_value( stmt, index, i++, NULL TSRMLS_CC); + } + + if( stmt->column_count-stmt->fetch.num_keys > 1 ) { + do { + add_assoc_zval( base, stmt->columns[i-1].name, index ); + MAKE_STD_ZVAL(index); + if( i < stmt->column_count ) { + fetch_value( stmt, index, i, NULL TSRMLS_CC); + } + } while( i++ < stmt->column_count ); + } + else if( stmt->fetch.num_keys > 0 ) { + MAKE_STD_ZVAL(val); + fetch_value( stmt, val, i, NULL TSRMLS_CC ); + if( Z_TYPE_P(index) == IS_LONG ) { + add_index_zval( base, Z_LVAL_P(index), val ); + } else { + add_assoc_zval( base, Z_STRVAL_P(index), val ); + } + } + else { + while( TRUE ) { + add_next_index_zval( base, index ); + MAKE_STD_ZVAL(index); /* -- add_next_index seems to copy zvals */ + if( i < stmt->column_count ) { + fetch_value( stmt, index, i++, NULL TSRMLS_CC ); + } + else { + break; + } + } + } + + zval_dtor(index); + FREE_ZVAL(index); +} + /* perform a fetch. If do_bind is true, update any bound columns. * If return_value is not null, store values into it according to HOW. */ static int do_fetch(pdo_stmt_t *stmt, int do_bind, zval *return_value, @@ -894,7 +962,8 @@ int flags = how & PDO_FETCH_FLAGS, idx, old_arg_count = 0; zend_class_entry *ce = NULL, *old_ce = NULL; zval grp_val, *grp, **pgrp, *retval, *old_ctor_args = NULL; - + zval *nullbase = NULL; + if (how == PDO_FETCH_USE_DEFAULT) { how = stmt->default_fetch_type; } @@ -925,6 +994,10 @@ case PDO_FETCH_BOTH: case PDO_FETCH_NUM: case PDO_FETCH_NAMED: + case PDO_FETCH_2D: + case PDO_FETCH_2D_NUM: + case PDO_FETCH_2D_ASSOC: + case PDO_FETCH_2D_BOTH: if (!return_all) { ALLOC_HASHTABLE(return_value->value.ht); zend_hash_init(return_value->value.ht, stmt->column_count, NULL, ZVAL_PTR_DTOR, 0); @@ -934,9 +1007,9 @@ } break; - case PDO_FETCH_KEY_PAIR: - if (stmt->column_count != 2) { - pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "PDO::FETCH_KEY_PAIR fetch mode requires the result set to contain extactly 2 columns." TSRMLS_CC); + case PDO_FETCH_KEYS: + if (stmt->column_count <= stmt->fetch.num_keys) { + pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "PDO::FETCH_KEYS needs at least one value column." TSRMLS_CC); return 0; } if (!return_all) { @@ -1047,7 +1120,7 @@ return 0; } - if (return_all && how != PDO_FETCH_KEY_PAIR) { + if (return_all && how != PDO_FETCH_KEYS) { INIT_PZVAL(&grp_val); fetch_value(stmt, &grp_val, i, NULL TSRMLS_CC); convert_to_string(&grp_val); @@ -1059,28 +1132,68 @@ } for (idx = 0; i < stmt->column_count; i++, idx++) { - zval *val; - MAKE_STD_ZVAL(val); + zval *val = NULL; + zval *base2d; + + MAKE_STD_ZVAL(val); fetch_value(stmt, val, i, NULL TSRMLS_CC); switch (how) { + case PDO_FETCH_2D: + case PDO_FETCH_2D_NUM: + case PDO_FETCH_2D_ASSOC: + case PDO_FETCH_2D_BOTH: + if( !nullbase && ((how & PDO_FETCH_BOTH) || !stmt->columns[i].relname) ) { + if( stmt->dbh->nullbase ) { + MAKE_STD_ZVAL(nullbase); + array_init(nullbase); + add_assoc_zval(return_value, stmt->dbh->nullbase, nullbase); + } + else { + nullbase = return_value; + } + } + + if( stmt->columns[i].relname ) { + zval **curr_val = NULL; + if (zend_hash_find(Z_ARRVAL_P(return_value), stmt->columns[i].relname, + stmt->columns[i].relnamelen+1, + (void**)&curr_val) == SUCCESS) { + if( Z_TYPE_PP(curr_val) != IS_ARRAY ) { + /* TODO: ERROR OUT OR NOT? */ + return 0; + } + base2d = *curr_val; + } + else { + MAKE_STD_ZVAL(base2d); + array_init(base2d); + add_assoc_zval(return_value, stmt->columns[i].relname, base2d); + } + } + else { + base2d = nullbase; + } + + add_assoc_zval(base2d, stmt->columns[i].name, val); + + if( how & PDO_FETCH_ASSOC ) { + Z_ADDREF_P(val); + add_assoc_zval(nullbase, stmt->columns[i].name, val); + } + if( how & PDO_FETCH_NUM ) { + Z_ADDREF_P(val); + add_next_index_zval(nullbase, val); + } + break; + case PDO_FETCH_ASSOC: add_assoc_zval(return_value, stmt->columns[i].name, val); break; - case PDO_FETCH_KEY_PAIR: + case PDO_FETCH_KEYS: { - zval *tmp; - MAKE_STD_ZVAL(tmp); - fetch_value(stmt, tmp, ++i, NULL TSRMLS_CC); - - if (Z_TYPE_P(val) == IS_LONG) { - zend_hash_index_update((return_all ? Z_ARRVAL_P(return_all) : Z_ARRVAL_P(return_value)), Z_LVAL_P(val), &tmp, sizeof(zval *), NULL); - } else { - convert_to_string(val); - zend_symtable_update((return_all ? Z_ARRVAL_P(return_all) : Z_ARRVAL_P(return_value)), Z_STRVAL_P(val), Z_STRLEN_P(val) + 1, &tmp, sizeof(zval *), NULL); - } - zval_ptr_dtor(&val); + do_fetch_keys_iterative( stmt, (return_all ? return_all : return_value), val ); return 1; } break; @@ -1539,6 +1652,15 @@ } break; + case PDO_FETCH_KEYS: + if( ZEND_NUM_ARGS() == 2 ) { + stmt->fetch.num_keys = Z_LVAL_P(arg2); + } + else { + stmt->fetch.num_keys = 1; + } + break; + default: if (ZEND_NUM_ARGS() > 1) { pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "Extraneous additional parameters" TSRMLS_CC); @@ -1553,8 +1675,8 @@ if (!error) { PDO_STMT_CLEAR_ERR(); MAKE_STD_ZVAL(data); - if ( (how & PDO_FETCH_GROUP) || how == PDO_FETCH_KEY_PAIR || - (how == PDO_FETCH_USE_DEFAULT && stmt->default_fetch_type == PDO_FETCH_KEY_PAIR) + if ( (how & PDO_FETCH_GROUP) || how == PDO_FETCH_KEYS || + (how == PDO_FETCH_USE_DEFAULT && stmt->default_fetch_type == PDO_FETCH_KEYS) ) { array_init(return_value); return_all = return_value; @@ -1571,7 +1693,7 @@ do { MAKE_STD_ZVAL(data); } while (do_fetch(stmt, TRUE, data, how, PDO_FETCH_ORI_NEXT, 0, return_all TSRMLS_CC)); - } else if (how == PDO_FETCH_KEY_PAIR || (how == PDO_FETCH_USE_DEFAULT && stmt->default_fetch_type == PDO_FETCH_KEY_PAIR)) { + } else if (how == PDO_FETCH_KEYS || (how == PDO_FETCH_USE_DEFAULT && stmt->default_fetch_type == PDO_FETCH_KEYS)) { while (do_fetch(stmt, TRUE, data, how, PDO_FETCH_ORI_NEXT, 0, return_all TSRMLS_CC)); } else { array_init(return_value); @@ -1922,7 +2044,10 @@ case PDO_FETCH_OBJ: case PDO_FETCH_BOUND: case PDO_FETCH_NAMED: - case PDO_FETCH_KEY_PAIR: + case PDO_FETCH_2D: + case PDO_FETCH_2D_NUM: + case PDO_FETCH_2D_ASSOC: + case PDO_FETCH_2D_BOTH: break; case PDO_FETCH_COLUMN: @@ -1988,6 +2113,18 @@ zend_objects_store_add_ref(stmt->fetch.into TSRMLS_CC); break; + case PDO_FETCH_KEYS: + if( argc != 2 ) { + stmt->fetch.num_keys = 1; + } + else if( Z_TYPE_PP(args[skip+1]) == IS_LONG ) { + stmt->fetch.num_keys = Z_LVAL_PP(args[skip+1]); + } + else { + pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "num_keys must be integer" TSRMLS_CC); + } + break; + default: pdo_raise_impl_error(stmt->dbh, stmt, "22003", "Invalid fetch mode specified" TSRMLS_CC); goto fail_out; @@ -2348,6 +2485,10 @@ efree(cols[i].name); cols[i].name = NULL; } + if (cols[i].relname) { + efree(cols[i].relname); + cols[i].relname = NULL; + } } efree(stmt->columns); stmt->columns = NULL; Index: ext/pdo/php_pdo_driver.h =================================================================== RCS file: /repository/php-src/ext/pdo/php_pdo_driver.h,v retrieving revision 1.66.2.11.2.6.2.2 diff -u -r1.66.2.11.2.6.2.2 php_pdo_driver.h --- ext/pdo/php_pdo_driver.h 26 Nov 2007 10:59:04 -0000 1.66.2.11.2.6.2.2 +++ ext/pdo/php_pdo_driver.h 27 Nov 2007 18:27:09 -0000 @@ -79,10 +79,14 @@ enum pdo_fetch_type { PDO_FETCH_USE_DEFAULT, + PDO_FETCH_ASSOC, /* BEGIN */ + PDO_FETCH_NUM, /* All values from BEGIN to END are specially */ + PDO_FETCH_BOTH, /* arranged to be bitwise combineable. */ + PDO_FETCH_2D, /* e.g. ASSOC | NUM = BOTH */ + PDO_FETCH_2D_ASSOC, /* e.g. 2D | ASSOC = 2D_ASSOC */ + PDO_FETCH_2D_NUM, + PDO_FETCH_2D_BOTH, /* END */ PDO_FETCH_LAZY, - PDO_FETCH_ASSOC, - PDO_FETCH_NUM, - PDO_FETCH_BOTH, PDO_FETCH_OBJ, PDO_FETCH_BOUND, /* return true/false only; rely on bound columns */ PDO_FETCH_COLUMN, /* fetch a numbered column only */ @@ -90,7 +94,7 @@ PDO_FETCH_INTO, /* fetch row into an existing object */ PDO_FETCH_FUNC, /* fetch into function and return its result */ PDO_FETCH_NAMED, /* like PDO_FETCH_ASSOC, but can handle duplicate names */ - PDO_FETCH_KEY_PAIR, /* fetch into an array where the 1st column is a key and all subsequent columns are values */ + PDO_FETCH_KEYS, /* fetch into an array where the first column(s) are keys and all subsequent columns are values */ PDO_FETCH__MAX /* must be last */ }; @@ -124,6 +128,7 @@ PDO_ATTR_CURSOR_NAME, /* name a cursor for use in "WHERE CURRENT OF " */ PDO_ATTR_CURSOR, /* cursor type */ PDO_ATTR_ORACLE_NULLS, /* convert empty strings to NULL */ + PDO_ATTR_CONNECTION_LAZY, /* only connect to database upon use */ PDO_ATTR_PERSISTENT, /* pconnect style connection */ PDO_ATTR_STATEMENT_CLASS, /* array(classname, array(ctor_args)) to specify the class of the constructed statement */ PDO_ATTR_FETCH_TABLE_NAMES, /* include table names in the column names, where available */ @@ -133,6 +138,7 @@ PDO_ATTR_MAX_COLUMN_LEN, /* make database calculate maximum length of data found in a column */ PDO_ATTR_DEFAULT_FETCH_MODE, /* Set the default fetch mode */ PDO_ATTR_EMULATE_PREPARES, /* use query emulation rather than native */ + PDO_ATTR_2D_NULLBASE, /* array name for not further qualified columns */ /* this defines the start of the range for driver specific options. * Drivers should define their own attribute constants beginning with this @@ -470,6 +476,9 @@ * equal 32 */ unsigned _reserved_flags:21; + /* 2d nullbase */ + char *nullbase; + /* data source string used to open this handle */ const char *data_source; unsigned long data_source_len; @@ -508,6 +517,8 @@ /* describes a column */ struct pdo_column_data { + char *relname; + int relnamelen; char *name; int namelen; unsigned long maxlen; @@ -620,6 +631,7 @@ zend_fcall_info_cache fcc; zval **values; /* freed */ } func; + int num_keys; zval *into; } fetch; Index: ext/pdo/tests/pdo_034.phpt =================================================================== RCS file: /repository/php-src/ext/pdo/tests/Attic/pdo_034.phpt,v retrieving revision 1.1.2.6 diff -u -r1.1.2.6 pdo_034.phpt --- ext/pdo/tests/pdo_034.phpt 23 Jul 2007 22:46:03 -0000 1.1.2.6 +++ ext/pdo/tests/pdo_034.phpt 27 Nov 2007 18:27:09 -0000 @@ -1,5 +1,5 @@ --TEST-- -PDO Common: PDO::FETCH_KEY_PAIR fetch mode test +PDO Common: PDO::FETCH_KEYS fetch mode test --SKIPIF-- exec("CREATE TABLE test (a varchar(100), b varchar(100), c varchar(100))"); +$db->exec("CREATE TABLE test (a varchar(100), b varchar(100), c int)"); -for ($i = 0; $i < 5; $i++) { - $db->exec("INSERT INTO test (a,b,c) VALUES('test".$i."','".$i."','".$i."')"); +$stmt = $db->prepare('INSERT INTO test (a,b,c) VALUES(?,?,?)'); + +for ($i = 1; $i <= 3; $i++) { + for ($j = 1; $j <= 3; $j++) { + $stmt->execute( array( "Cat $i", "Subcat ".($i*10+$j), $i*100 + $j*10) ); + } } -var_dump($db->query("SELECT a,b FROM test")->fetch(PDO::FETCH_KEY_PAIR)); -var_dump($db->query("SELECT a,b FROM test")->fetchAll(PDO::FETCH_KEY_PAIR)); -var_dump($db->query("SELECT * FROM test")->fetch(PDO::FETCH_KEY_PAIR)); -var_dump($db->query("SELECT a,a FROM test")->fetchAll(PDO::FETCH_KEY_PAIR)); +echo "-- Classical PDO::FETCH_KEY_PAIR --\n"; +var_dump( $db->query("SELECT a,b FROM test")->fetchAll(PDO::FETCH_KEYS) ); +echo "\n-- FETCH_KEYS with ZERO key columns and ONE data column --\n"; +var_dump( $db->query("SELECT DISTINCT a FROM test")->fetchAll(PDO::FETCH_KEYS, 0) ); +echo "\n-- FETCH_KEYS with ONE key column and TWO data columns --\n"; +var_dump( $db->query("SELECT a,b,c FROM test")->fetchAll(PDO::FETCH_KEYS, 1) ); +echo "\n-- FETCH_KEYS with TWO key columns and ONE data column --\n"; +var_dump( $db->query("SELECT a,b,c FROM test")->fetchAll(PDO::FETCH_KEYS, 2) ); ?> --EXPECTF-- -array(1) { - ["test0"]=> - string(1) "0" +-- Classical PDO::FETCH_KEY_PAIR -- +array(3) { + ["Cat 1"]=> + string(9) "Subcat 13" + ["Cat 2"]=> + string(9) "Subcat 23" + ["Cat 3"]=> + string(9) "Subcat 33" } -array(5) { - ["test0"]=> - string(1) "0" - ["test1"]=> - string(1) "1" - ["test2"]=> - string(1) "2" - ["test3"]=> - string(1) "3" - ["test4"]=> - string(1) "4" + +-- FETCH_KEYS with ZERO key columns and ONE data column -- +array(3) { + [0]=> + string(5) "Cat 1" + [1]=> + string(5) "Cat 2" + [2]=> + string(5) "Cat 3" } -Warning: PDOStatement::fetch(): SQLSTATE[HY000]: General error: PDO::FETCH_KEY_PAIR fetch mode requires the result set to contain extactly 2 columns. in %s/pdo_034.php on line %d +-- FETCH_KEYS with ONE key column and TWO data columns -- +array(3) { + ["Cat 1"]=> + array(2) { + ["b"]=> + string(9) "Subcat 13" + ["c"]=> + string(3) "130" + } + ["Cat 2"]=> + array(2) { + ["b"]=> + string(9) "Subcat 23" + ["c"]=> + string(3) "230" + } + ["Cat 3"]=> + array(2) { + ["b"]=> + string(9) "Subcat 33" + ["c"]=> + string(3) "330" + } +} -Warning: PDOStatement::fetch(): SQLSTATE[HY000]: General error%s/pdo_034.php on line %d -bool(false) -array(5) { - ["test0"]=> - string(5) "test0" - ["test1"]=> - string(5) "test1" - ["test2"]=> - string(5) "test2" - ["test3"]=> - string(5) "test3" - ["test4"]=> - string(5) "test4" +-- FETCH_KEYS with TWO key columns and ONE data column -- +array(3) { + ["Cat 1"]=> + array(3) { + ["Subcat 11"]=> + string(3) "110" + ["Subcat 12"]=> + string(3) "120" + ["Subcat 13"]=> + string(3) "130" + } + ["Cat 2"]=> + array(3) { + ["Subcat 21"]=> + string(3) "210" + ["Subcat 22"]=> + string(3) "220" + ["Subcat 23"]=> + string(3) "230" + } + ["Cat 3"]=> + array(3) { + ["Subcat 31"]=> + string(3) "310" + ["Subcat 32"]=> + string(3) "320" + ["Subcat 33"]=> + string(3) "330" + } } Index: ext/pdo_firebird/firebird_statement.c =================================================================== RCS file: /repository/php-src/ext/pdo_firebird/firebird_statement.c,v retrieving revision 1.18.2.1.2.5.2.8 diff -u -r1.18.2.1.2.5.2.8 firebird_statement.c --- ext/pdo_firebird/firebird_statement.c 19 Nov 2007 21:55:30 -0000 1.18.2.1.2.5.2.8 +++ ext/pdo_firebird/firebird_statement.c 27 Nov 2007 18:27:10 -0000 @@ -164,8 +164,10 @@ colname_len = (S->H->fetch_table_names && var->relname_length) ? (var->aliasname_length + var->relname_length + 1) : (var->aliasname_length); - col->precision = -var->sqlscale; + col->precision = -var->sqlscale; col->maxlen = var->sqllen; + col->relname = (var->relname_length ? estrndup(var->relname, var->relname_length) : NULL); + col->relnamelen = var->relname_length; col->namelen = colname_len; col->name = cp = emalloc(colname_len + 1); if (colname_len > var->aliasname_length) { @@ -470,6 +472,9 @@ case PDO_PARAM_EVT_ALLOC: if (param->is_param) { /* allocate the parameter */ + if( var->sqlind ) { + efree( var->sqlind ); + } var->sqlind = (void*)emalloc(var->sqllen + 2*sizeof(short)); var->sqldata = &((char*)var->sqlind)[sizeof(short)]; } Index: ext/pdo_mysql/mysql_statement.c =================================================================== RCS file: /repository/php-src/ext/pdo_mysql/mysql_statement.c,v retrieving revision 1.48.2.14.2.6 diff -u -r1.48.2.14.2.6 mysql_statement.c --- ext/pdo_mysql/mysql_statement.c 17 May 2007 15:12:23 -0000 1.48.2.14.2.6 +++ ext/pdo_mysql/mysql_statement.c 27 Nov 2007 18:27:10 -0000 @@ -454,6 +454,8 @@ cols[i].maxlen = S->fields[i].length; cols[i].namelen = namelen; cols[i].name = estrndup(S->fields[i].name, namelen); + cols[i].relnamelen = strlen(S->fields[i].table); /* TODO: WHERE are names efree'd? */ + cols[i].relname = (cols[i].relnamelen ? estrndup(S->fields[i].table, cols[i].relnamelen) : NULL); cols[i].param_type = PDO_PARAM_STR; } return 1; --------------070404060906080007060000 Content-Type: text/plain; name="pdo_035.phpt" Content-Transfer-Encoding: base64 Content-Disposition: inline; filename="pdo_035.phpt" LS1URVNULS0KUERPIENvbW1vbjogUERPOjpGRVRDSF8yRCBmZXRjaCBtb2RlIHRlc3QKLS1T S0lQSUYtLQo8P3BocCAjIHZpbTpmdD1waHAKaWYgKCFleHRlbnNpb25fbG9hZGVkKCdwZG8n KSkgZGllKCdza2lwJyk7CiRkaXIgPSBnZXRlbnYoJ1JFRElSX1RFU1RfRElSJyk7CmlmIChm YWxzZSA9PSAkZGlyKSBkaWUoJ3NraXAgbm8gZHJpdmVyJyk7CnJlcXVpcmVfb25jZSAkZGly IC4gJ3Bkb190ZXN0LmluYyc7ClBET1Rlc3Q6OnNraXAoKTsKPz4KLS1GSUxFLS0KPD9waHAK aWYgKGdldGVudignUkVESVJfVEVTVF9ESVInKSA9PT0gZmFsc2UpIHB1dGVudignUkVESVJf VEVTVF9ESVI9Jy5kaXJuYW1lKF9fRklMRV9fKSAuICcvLi4vLi4vcGRvL3Rlc3RzLycpOwpy ZXF1aXJlX29uY2UgZ2V0ZW52KCdSRURJUl9URVNUX0RJUicpIC4gJ3Bkb190ZXN0LmluYyc7 CiRkYiA9IFBET1Rlc3Q6OmZhY3RvcnkoKTsKCiRkYi0+ZXhlYygiQ1JFQVRFIFRBQkxFIHRl c3QgKGEgdmFyY2hhcigxMDApLCBiIHZhcmNoYXIoMTAwKSwgYyBpbnQpIik7CiRkYi0+ZXhl YygiQ1JFQVRFIFRBQkxFIHRlc3QyIChkIGludCwgZSB2YXJjaGFyKDEwMCkpIik7Cgokc3Rt dCA9ICRkYi0+cHJlcGFyZSgnSU5TRVJUIElOVE8gdGVzdCAoYSxiLGMpIFZBTFVFUyg/LD8s PyknKTsKJHN0bXQtPmV4ZWN1dGUoIGFycmF5KCAnQ2F0IDEnLCAnU3ViY2F0IDEnLCAxICkg KTsKJHN0bXQtPmV4ZWN1dGUoIGFycmF5KCAnQ2F0IDInLCAnU3ViY2F0IDInLCAyICkgKTsK CiRzdG10ID0gJGRiLT5wcmVwYXJlKCdJTlNFUlQgSU5UTyB0ZXN0MiAoZCxlKSBWQUxVRVMo Pyw/KScpOwokc3RtdC0+ZXhlY3V0ZSggYXJyYXkoIDEsICdEYXRhIDFhJyApICk7CiRzdG10 LT5leGVjdXRlKCBhcnJheSggMiwgJ0RhdGEgMmEnICkgKTsKJHN0bXQtPmV4ZWN1dGUoIGFy cmF5KCAyLCAnRGF0YSAyYicgKSApOwoKJHN0bXQgPSAkZGItPnByZXBhcmUoICdTRUxFQ1Qg dGVzdC4qLCB0ZXN0Mi4qLCBUUklNKGUpIEFTIGNvbXB1dGVkdmFsIEZST00gdGVzdCx0ZXN0 MiBXSEVSRSBjPWQnICk7CgplY2hvICItLSBQRE86OkZFVENIXzJEIHdpdGggZGVmYXVsdCBu dWxsYmFzZSAtLVxuIjsKJHN0bXQtPmV4ZWN1dGUoKTsKdmFyX2R1bXAoICRzdG10LT5mZXRj aChQRE86OkZFVENIXzJEKSApOwplY2hvICJcbi0tIFBET19GRVRDSF8yRCB3aXRoIE5VTEwg bnVsbGJhc2UgLS1cbiI7CiRkYi0+c2V0QXR0cmlidXRlKCBQRE86OkFUVFJfMkRfTlVMTEJB U0UsIE5VTEwgKTsKJHN0bXQtPmV4ZWN1dGUoKTsKdmFyX2R1bXAoICRzdG10LT5mZXRjaChQ RE86OkZFVENIXzJEKSApOwplY2hvICJcbi0tIFBET19GRVRDSF8yRCB3aXRoIG51bGxiYXNl IC0tXG4iOwokZGItPnNldEF0dHJpYnV0ZSggUERPOjpBVFRSXzJEX05VTExCQVNFLCAnbnVs bGJhc2UnICk7CiRzdG10LT5leGVjdXRlKCk7CnZhcl9kdW1wKCAkc3RtdC0+ZmV0Y2goUERP OjpGRVRDSF8yRCkgKTsKZWNobyAiXG4tLSBQRE9fRkVUQ0hfMkQgfCBQRE9fRkVUQ0hfQVNT T0MgLS1cbiI7CiRzdG10LT5leGVjdXRlKCk7CnZhcl9kdW1wKCAkc3RtdC0+ZmV0Y2hBbGwo UERPOjpGRVRDSF8yRHxQRE86OkZFVENIX0FTU09DKSApOwplY2hvICJcbi0tIFBET19GRVRD SF8yRCB8IFBET19GRVRDSF9OVU0gLS1cbiI7CiRzdG10LT5leGVjdXRlKCk7CnZhcl9kdW1w KCAkc3RtdC0+ZmV0Y2hBbGwoUERPOjpGRVRDSF8yRHxQRE86OkZFVENIX05VTSkgKTsKCj8+ Ci0tRVhQRUNURi0tCi0tIFBETzo6RkVUQ0hfMkQgd2l0aCBkZWZhdWx0IG51bGxiYXNlIC0t CmFycmF5KDMpIHsKICBbIlRFU1QiXT0+CiAgYXJyYXkoMykgewogICAgWyJhIl09PgogICAg c3RyaW5nKDUpICJDYXQgMSIKICAgIFsiYiJdPT4KICAgIHN0cmluZyg4KSAiU3ViY2F0IDEi CiAgICBbImMiXT0+CiAgICBzdHJpbmcoMSkgIjEiCiAgfQogIFsiVEVTVDIiXT0+CiAgYXJy YXkoMikgewogICAgWyJkIl09PgogICAgc3RyaW5nKDEpICIxIgogICAgWyJlIl09PgogICAg c3RyaW5nKDcpICJEYXRhIDFhIgogIH0KICBbIiJdPT4KICBhcnJheSgxKSB7CiAgICBbImNv bXB1dGVkdmFsIl09PgogICAgc3RyaW5nKDcpICJEYXRhIDFhIgogIH0KfQoKLS0gUERPX0ZF VENIXzJEIHdpdGggTlVMTCBudWxsYmFzZSAtLQphcnJheSgzKSB7CiAgWyJURVNUIl09Pgog IGFycmF5KDMpIHsKICAgIFsiYSJdPT4KICAgIHN0cmluZyg1KSAiQ2F0IDEiCiAgICBbImIi XT0+CiAgICBzdHJpbmcoOCkgIlN1YmNhdCAxIgogICAgWyJjIl09PgogICAgc3RyaW5nKDEp ICIxIgogIH0KICBbIlRFU1QyIl09PgogIGFycmF5KDIpIHsKICAgIFsiZCJdPT4KICAgIHN0 cmluZygxKSAiMSIKICAgIFsiZSJdPT4KICAgIHN0cmluZyg3KSAiRGF0YSAxYSIKICB9CiAg WyJjb21wdXRlZHZhbCJdPT4KICBzdHJpbmcoNykgIkRhdGEgMWEiCn0KCi0tIFBET19GRVRD SF8yRCB3aXRoIG51bGxiYXNlIC0tCmFycmF5KDMpIHsKICBbIlRFU1QiXT0+CiAgYXJyYXko MykgewogICAgWyJhIl09PgogICAgc3RyaW5nKDUpICJDYXQgMSIKICAgIFsiYiJdPT4KICAg IHN0cmluZyg4KSAiU3ViY2F0IDEiCiAgICBbImMiXT0+CiAgICBzdHJpbmcoMSkgIjEiCiAg fQogIFsiVEVTVDIiXT0+CiAgYXJyYXkoMikgewogICAgWyJkIl09PgogICAgc3RyaW5nKDEp ICIxIgogICAgWyJlIl09PgogICAgc3RyaW5nKDcpICJEYXRhIDFhIgogIH0KICBbIm51bGxi YXNlIl09PgogIGFycmF5KDEpIHsKICAgIFsiY29tcHV0ZWR2YWwiXT0+CiAgICBzdHJpbmco NykgIkRhdGEgMWEiCiAgfQp9CgotLSBQRE9fRkVUQ0hfMkQgfCBQRE9fRkVUQ0hfQVNTT0Mg LS0KYXJyYXkoMykgewogIFswXT0+CiAgYXJyYXkoMykgewogICAgWyJudWxsYmFzZSJdPT4K ICAgIGFycmF5KDYpIHsKICAgICAgWyJhIl09PgogICAgICBzdHJpbmcoNSkgIkNhdCAxIgog ICAgICBbImIiXT0+CiAgICAgIHN0cmluZyg4KSAiU3ViY2F0IDEiCiAgICAgIFsiYyJdPT4K ICAgICAgc3RyaW5nKDEpICIxIgogICAgICBbImQiXT0+CiAgICAgIHN0cmluZygxKSAiMSIK ICAgICAgWyJlIl09PgogICAgICBzdHJpbmcoNykgIkRhdGEgMWEiCiAgICAgIFsiY29tcHV0 ZWR2YWwiXT0+CiAgICAgIHN0cmluZyg3KSAiRGF0YSAxYSIKICAgIH0KICAgIFsiVEVTVCJd PT4KICAgIGFycmF5KDMpIHsKICAgICAgWyJhIl09PgogICAgICBzdHJpbmcoNSkgIkNhdCAx IgogICAgICBbImIiXT0+CiAgICAgIHN0cmluZyg4KSAiU3ViY2F0IDEiCiAgICAgIFsiYyJd PT4KICAgICAgc3RyaW5nKDEpICIxIgogICAgfQogICAgWyJURVNUMiJdPT4KICAgIGFycmF5 KDIpIHsKICAgICAgWyJkIl09PgogICAgICBzdHJpbmcoMSkgIjEiCiAgICAgIFsiZSJdPT4K ICAgICAgc3RyaW5nKDcpICJEYXRhIDFhIgogICAgfQogIH0KICBbMV09PgogIGFycmF5KDMp IHsKICAgIFsibnVsbGJhc2UiXT0+CiAgICBhcnJheSg2KSB7CiAgICAgIFsiYSJdPT4KICAg ICAgc3RyaW5nKDUpICJDYXQgMiIKICAgICAgWyJiIl09PgogICAgICBzdHJpbmcoOCkgIlN1 YmNhdCAyIgogICAgICBbImMiXT0+CiAgICAgIHN0cmluZygxKSAiMiIKICAgICAgWyJkIl09 PgogICAgICBzdHJpbmcoMSkgIjIiCiAgICAgIFsiZSJdPT4KICAgICAgc3RyaW5nKDcpICJE YXRhIDJhIgogICAgICBbImNvbXB1dGVkdmFsIl09PgogICAgICBzdHJpbmcoNykgIkRhdGEg MmEiCiAgICB9CiAgICBbIlRFU1QiXT0+CiAgICBhcnJheSgzKSB7CiAgICAgIFsiYSJdPT4K ICAgICAgc3RyaW5nKDUpICJDYXQgMiIKICAgICAgWyJiIl09PgogICAgICBzdHJpbmcoOCkg IlN1YmNhdCAyIgogICAgICBbImMiXT0+CiAgICAgIHN0cmluZygxKSAiMiIKICAgIH0KICAg IFsiVEVTVDIiXT0+CiAgICBhcnJheSgyKSB7CiAgICAgIFsiZCJdPT4KICAgICAgc3RyaW5n KDEpICIyIgogICAgICBbImUiXT0+CiAgICAgIHN0cmluZyg3KSAiRGF0YSAyYSIKICAgIH0K ICB9CiAgWzJdPT4KICBhcnJheSgzKSB7CiAgICBbIm51bGxiYXNlIl09PgogICAgYXJyYXko NikgewogICAgICBbImEiXT0+CiAgICAgIHN0cmluZyg1KSAiQ2F0IDIiCiAgICAgIFsiYiJd PT4KICAgICAgc3RyaW5nKDgpICJTdWJjYXQgMiIKICAgICAgWyJjIl09PgogICAgICBzdHJp bmcoMSkgIjIiCiAgICAgIFsiZCJdPT4KICAgICAgc3RyaW5nKDEpICIyIgogICAgICBbImUi XT0+CiAgICAgIHN0cmluZyg3KSAiRGF0YSAyYiIKICAgICAgWyJjb21wdXRlZHZhbCJdPT4K ICAgICAgc3RyaW5nKDcpICJEYXRhIDJiIgogICAgfQogICAgWyJURVNUIl09PgogICAgYXJy YXkoMykgewogICAgICBbImEiXT0+CiAgICAgIHN0cmluZyg1KSAiQ2F0IDIiCiAgICAgIFsi YiJdPT4KICAgICAgc3RyaW5nKDgpICJTdWJjYXQgMiIKICAgICAgWyJjIl09PgogICAgICBz dHJpbmcoMSkgIjIiCiAgICB9CiAgICBbIlRFU1QyIl09PgogICAgYXJyYXkoMikgewogICAg ICBbImQiXT0+CiAgICAgIHN0cmluZygxKSAiMiIKICAgICAgWyJlIl09PgogICAgICBzdHJp bmcoNykgIkRhdGEgMmIiCiAgICB9CiAgfQp9CgotLSBQRE9fRkVUQ0hfMkQgfCBQRE9fRkVU Q0hfTlVNIC0tCmFycmF5KDMpIHsKICBbMF09PgogIGFycmF5KDMpIHsKICAgIFsibnVsbGJh c2UiXT0+CiAgICBhcnJheSg3KSB7CiAgICAgIFswXT0+CiAgICAgIHN0cmluZyg1KSAiQ2F0 IDEiCiAgICAgIFsxXT0+CiAgICAgIHN0cmluZyg4KSAiU3ViY2F0IDEiCiAgICAgIFsyXT0+ CiAgICAgIHN0cmluZygxKSAiMSIKICAgICAgWzNdPT4KICAgICAgc3RyaW5nKDEpICIxIgog ICAgICBbNF09PgogICAgICBzdHJpbmcoNykgIkRhdGEgMWEiCiAgICAgIFsiY29tcHV0ZWR2 YWwiXT0+CiAgICAgIHN0cmluZyg3KSAiRGF0YSAxYSIKICAgICAgWzVdPT4KICAgICAgc3Ry aW5nKDcpICJEYXRhIDFhIgogICAgfQogICAgWyJURVNUIl09PgogICAgYXJyYXkoMykgewog ICAgICBbImEiXT0+CiAgICAgIHN0cmluZyg1KSAiQ2F0IDEiCiAgICAgIFsiYiJdPT4KICAg ICAgc3RyaW5nKDgpICJTdWJjYXQgMSIKICAgICAgWyJjIl09PgogICAgICBzdHJpbmcoMSkg IjEiCiAgICB9CiAgICBbIlRFU1QyIl09PgogICAgYXJyYXkoMikgewogICAgICBbImQiXT0+ CiAgICAgIHN0cmluZygxKSAiMSIKICAgICAgWyJlIl09PgogICAgICBzdHJpbmcoNykgIkRh dGEgMWEiCiAgICB9CiAgfQogIFsxXT0+CiAgYXJyYXkoMykgewogICAgWyJudWxsYmFzZSJd PT4KICAgIGFycmF5KDcpIHsKICAgICAgWzBdPT4KICAgICAgc3RyaW5nKDUpICJDYXQgMiIK ICAgICAgWzFdPT4KICAgICAgc3RyaW5nKDgpICJTdWJjYXQgMiIKICAgICAgWzJdPT4KICAg ICAgc3RyaW5nKDEpICIyIgogICAgICBbM109PgogICAgICBzdHJpbmcoMSkgIjIiCiAgICAg IFs0XT0+CiAgICAgIHN0cmluZyg3KSAiRGF0YSAyYSIKICAgICAgWyJjb21wdXRlZHZhbCJd PT4KICAgICAgc3RyaW5nKDcpICJEYXRhIDJhIgogICAgICBbNV09PgogICAgICBzdHJpbmco NykgIkRhdGEgMmEiCiAgICB9CiAgICBbIlRFU1QiXT0+CiAgICBhcnJheSgzKSB7CiAgICAg IFsiYSJdPT4KICAgICAgc3RyaW5nKDUpICJDYXQgMiIKICAgICAgWyJiIl09PgogICAgICBz dHJpbmcoOCkgIlN1YmNhdCAyIgogICAgICBbImMiXT0+CiAgICAgIHN0cmluZygxKSAiMiIK ICAgIH0KICAgIFsiVEVTVDIiXT0+CiAgICBhcnJheSgyKSB7CiAgICAgIFsiZCJdPT4KICAg ICAgc3RyaW5nKDEpICIyIgogICAgICBbImUiXT0+CiAgICAgIHN0cmluZyg3KSAiRGF0YSAy YSIKICAgIH0KICB9CiAgWzJdPT4KICBhcnJheSgzKSB7CiAgICBbIm51bGxiYXNlIl09Pgog ICAgYXJyYXkoNykgewogICAgICBbMF09PgogICAgICBzdHJpbmcoNSkgIkNhdCAyIgogICAg ICBbMV09PgogICAgICBzdHJpbmcoOCkgIlN1YmNhdCAyIgogICAgICBbMl09PgogICAgICBz dHJpbmcoMSkgIjIiCiAgICAgIFszXT0+CiAgICAgIHN0cmluZygxKSAiMiIKICAgICAgWzRd PT4KICAgICAgc3RyaW5nKDcpICJEYXRhIDJiIgogICAgICBbImNvbXB1dGVkdmFsIl09Pgog ICAgICBzdHJpbmcoNykgIkRhdGEgMmIiCiAgICAgIFs1XT0+CiAgICAgIHN0cmluZyg3KSAi RGF0YSAyYiIKICAgIH0KICAgIFsiVEVTVCJdPT4KICAgIGFycmF5KDMpIHsKICAgICAgWyJh Il09PgogICAgICBzdHJpbmcoNSkgIkNhdCAyIgogICAgICBbImIiXT0+CiAgICAgIHN0cmlu Zyg4KSAiU3ViY2F0IDIiCiAgICAgIFsiYyJdPT4KICAgICAgc3RyaW5nKDEpICIyIgogICAg fQogICAgWyJURVNUMiJdPT4KICAgIGFycmF5KDIpIHsKICAgICAgWyJkIl09PgogICAgICBz dHJpbmcoMSkgIjIiCiAgICAgIFsiZSJdPT4KICAgICAgc3RyaW5nKDcpICJEYXRhIDJiIgog ICAgfQogIH0KfQ== --------------070404060906080007060000--