Hoi!
Marcus Boerger wrote:
> can you add tests so we get a better idea?
> cvs add <test> ; 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
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 <name>" */
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--
<?php # vim:ft=php
if (!extension_loaded('pdo')) die('skip');
@@ -14,49 +14,99 @@
require_once getenv('REDIR_TEST_DIR') . 'pdo_test.inc';
$db = PDOTest::factory();
-$db->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;
--TEST--
PDO Common: PDO::FETCH_2D fetch mode test
--SKIPIF--
<?php # vim:ft=php
if (!extension_loaded('pdo')) die('skip');
$dir = getenv('REDIR_TEST_DIR');
if (false == $dir) die('skip no driver');
require_once $dir . 'pdo_test.inc';
PDOTest::skip();
?>
--FILE--
<?php
if (getenv('REDIR_TEST_DIR') === false)
putenv('REDIR_TEST_DIR='.dirname(__FILE__) . '/../../pdo/tests/');
require_once getenv('REDIR_TEST_DIR') . 'pdo_test.inc';
$db = PDOTest::factory();
$db->exec("CREATE TABLE test (a varchar(100), b varchar(100), c int)");
$db->exec("CREATE TABLE test2 (d int, e varchar(100))");
$stmt = $db->prepare('INSERT INTO test (a,b,c) VALUES(?,?,?)');
$stmt->execute( array( 'Cat 1', 'Subcat 1', 1 ) );
$stmt->execute( array( 'Cat 2', 'Subcat 2', 2 ) );
$stmt = $db->prepare('INSERT INTO test2 (d,e) VALUES(?,?)');
$stmt->execute( array( 1, 'Data 1a' ) );
$stmt->execute( array( 2, 'Data 2a' ) );
$stmt->execute( array( 2, 'Data 2b' ) );
$stmt = $db->prepare( 'SELECT test.*, test2.*, TRIM(e) AS computedval FROM
test,test2 WHERE c=d' );
echo "-- PDO::FETCH_2D with default nullbase --\n";
$stmt->execute();
var_dump( $stmt->fetch(PDO::FETCH_2D) );
echo "\n-- PDO_FETCH_2D with NULL nullbase --\n";
$db->setAttribute( PDO::ATTR_2D_NULLBASE, NULL );
$stmt->execute();
var_dump( $stmt->fetch(PDO::FETCH_2D) );
echo "\n-- PDO_FETCH_2D with nullbase --\n";
$db->setAttribute( PDO::ATTR_2D_NULLBASE, 'nullbase' );
$stmt->execute();
var_dump( $stmt->fetch(PDO::FETCH_2D) );
echo "\n-- PDO_FETCH_2D | PDO_FETCH_ASSOC --\n";
$stmt->execute();
var_dump( $stmt->fetchAll(PDO::FETCH_2D|PDO::FETCH_ASSOC) );
echo "\n-- PDO_FETCH_2D | PDO_FETCH_NUM --\n";
$stmt->execute();
var_dump( $stmt->fetchAll(PDO::FETCH_2D|PDO::FETCH_NUM) );
?>
--EXPECTF--
-- PDO::FETCH_2D with default nullbase --
array(3) {
["TEST"]=>
array(3) {
["a"]=>
string(5) "Cat 1"
["b"]=>
string(8) "Subcat 1"
["c"]=>
string(1) "1"
}
["TEST2"]=>
array(2) {
["d"]=>
string(1) "1"
["e"]=>
string(7) "Data 1a"
}
[""]=>
array(1) {
["computedval"]=>
string(7) "Data 1a"
}
}
-- PDO_FETCH_2D with NULL nullbase --
array(3) {
["TEST"]=>
array(3) {
["a"]=>
string(5) "Cat 1"
["b"]=>
string(8) "Subcat 1"
["c"]=>
string(1) "1"
}
["TEST2"]=>
array(2) {
["d"]=>
string(1) "1"
["e"]=>
string(7) "Data 1a"
}
["computedval"]=>
string(7) "Data 1a"
}
-- PDO_FETCH_2D with nullbase --
array(3) {
["TEST"]=>
array(3) {
["a"]=>
string(5) "Cat 1"
["b"]=>
string(8) "Subcat 1"
["c"]=>
string(1) "1"
}
["TEST2"]=>
array(2) {
["d"]=>
string(1) "1"
["e"]=>
string(7) "Data 1a"
}
["nullbase"]=>
array(1) {
["computedval"]=>
string(7) "Data 1a"
}
}
-- PDO_FETCH_2D | PDO_FETCH_ASSOC --
array(3) {
[0]=>
array(3) {
["nullbase"]=>
array(6) {
["a"]=>
string(5) "Cat 1"
["b"]=>
string(8) "Subcat 1"
["c"]=>
string(1) "1"
["d"]=>
string(1) "1"
["e"]=>
string(7) "Data 1a"
["computedval"]=>
string(7) "Data 1a"
}
["TEST"]=>
array(3) {
["a"]=>
string(5) "Cat 1"
["b"]=>
string(8) "Subcat 1"
["c"]=>
string(1) "1"
}
["TEST2"]=>
array(2) {
["d"]=>
string(1) "1"
["e"]=>
string(7) "Data 1a"
}
}
[1]=>
array(3) {
["nullbase"]=>
array(6) {
["a"]=>
string(5) "Cat 2"
["b"]=>
string(8) "Subcat 2"
["c"]=>
string(1) "2"
["d"]=>
string(1) "2"
["e"]=>
string(7) "Data 2a"
["computedval"]=>
string(7) "Data 2a"
}
["TEST"]=>
array(3) {
["a"]=>
string(5) "Cat 2"
["b"]=>
string(8) "Subcat 2"
["c"]=>
string(1) "2"
}
["TEST2"]=>
array(2) {
["d"]=>
string(1) "2"
["e"]=>
string(7) "Data 2a"
}
}
[2]=>
array(3) {
["nullbase"]=>
array(6) {
["a"]=>
string(5) "Cat 2"
["b"]=>
string(8) "Subcat 2"
["c"]=>
string(1) "2"
["d"]=>
string(1) "2"
["e"]=>
string(7) "Data 2b"
["computedval"]=>
string(7) "Data 2b"
}
["TEST"]=>
array(3) {
["a"]=>
string(5) "Cat 2"
["b"]=>
string(8) "Subcat 2"
["c"]=>
string(1) "2"
}
["TEST2"]=>
array(2) {
["d"]=>
string(1) "2"
["e"]=>
string(7) "Data 2b"
}
}
}
-- PDO_FETCH_2D | PDO_FETCH_NUM --
array(3) {
[0]=>
array(3) {
["nullbase"]=>
array(7) {
[0]=>
string(5) "Cat 1"
[1]=>
string(8) "Subcat 1"
[2]=>
string(1) "1"
[3]=>
string(1) "1"
[4]=>
string(7) "Data 1a"
["computedval"]=>
string(7) "Data 1a"
[5]=>
string(7) "Data 1a"
}
["TEST"]=>
array(3) {
["a"]=>
string(5) "Cat 1"
["b"]=>
string(8) "Subcat 1"
["c"]=>
string(1) "1"
}
["TEST2"]=>
array(2) {
["d"]=>
string(1) "1"
["e"]=>
string(7) "Data 1a"
}
}
[1]=>
array(3) {
["nullbase"]=>
array(7) {
[0]=>
string(5) "Cat 2"
[1]=>
string(8) "Subcat 2"
[2]=>
string(1) "2"
[3]=>
string(1) "2"
[4]=>
string(7) "Data 2a"
["computedval"]=>
string(7) "Data 2a"
[5]=>
string(7) "Data 2a"
}
["TEST"]=>
array(3) {
["a"]=>
string(5) "Cat 2"
["b"]=>
string(8) "Subcat 2"
["c"]=>
string(1) "2"
}
["TEST2"]=>
array(2) {
["d"]=>
string(1) "2"
["e"]=>
string(7) "Data 2a"
}
}
[2]=>
array(3) {
["nullbase"]=>
array(7) {
[0]=>
string(5) "Cat 2"
[1]=>
string(8) "Subcat 2"
[2]=>
string(1) "2"
[3]=>
string(1) "2"
[4]=>
string(7) "Data 2b"
["computedval"]=>
string(7) "Data 2b"
[5]=>
string(7) "Data 2b"
}
["TEST"]=>
array(3) {
["a"]=>
string(5) "Cat 2"
["b"]=>
string(8) "Subcat 2"
["c"]=>
string(1) "2"
}
["TEST2"]=>
array(2) {
["d"]=>
string(1) "2"
["e"]=>
string(7) "Data 2b"
}
}
}
--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php