Hello Hans-Peter, can you add tests so we get a better idea? cvs add <test> ; cvd di -N > patchfile.txt
marcus Monday, November 26, 2007, 5:43:33 PM, you wrote: > 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 26 Nov 2007 16:38:16 -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 26 Nov 2007 16:38:16 -0000 > @@ -886,6 +886,68 @@ > } > /* }}} */ > > +/* 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_ptr_dtor(&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 > ); > + zval_ptr_dtor(&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 ); > + if( i < stmt->column_count ) { > + fetch_value( stmt, index, i++, NULL TSRMLS_CC > ); > + } > + else { > + break; > + } > + } > + } > +} > + > /* 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 +956,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 +988,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 +1001,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 +1114,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); > @@ -1060,27 +1127,66 @@ > > for (idx = 0; i < stmt->column_count; i++, idx++) { > zval *val; > + 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 +1645,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 +1668,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 +1686,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 +2037,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 +2106,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 +2478,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.1 > diff -u -r1.66.2.11.2.6.2.1 php_pdo_driver.h > --- ext/pdo/php_pdo_driver.h 27 Sep 2007 18:00:42 -0000 > 1.66.2.11.2.6.2.1 > +++ ext/pdo/php_pdo_driver.h 26 Nov 2007 16:38:16 -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_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 26 Nov 2007 16:38:16 -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) { > 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 26 Nov 2007 16:38:17 -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; Best regards, Marcus -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php