Skip to content

Commit d4a1582

Browse files
committed
Add PDO_FETCH_NAMED; closes PECL #4641 by providing a way to access columns
by name, even when multiple columns have the same name: $sql = "SELECT 1 a, 2 a, 3 b, 4 c, 5 d, 6 c, 7 a"; echo "$sql\n"; print_r($db->query($sql)->fetchAll(PDO_FETCH_NAMED)); Array ( [0] => Array ( [a] => Array ( [0] => 1 [1] => 2 [2] => 7 ) [b] => 3 [c] => Array ( [0] => 4 [1] => 6 ) [d] => 5 ) ) Also added two new attributes for use at prepare time; PDO_ATTR_FETCH_TABLE_NAMES and PDO_ATTR_FETCH_CATALOG_NAMES instruct the driver that the names of the columns that they return to PDO should include the table and catalog names respectively. Both attributes may be used together or independently. The catalog, table and column name components should be separated by a . character.
1 parent 75cfa5c commit d4a1582

File tree

3 files changed

+45
-19
lines changed

3 files changed

+45
-19
lines changed

ext/pdo/pdo.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,7 @@ PHP_MINIT_FUNCTION(pdo)
318318
#if PHP_MAJOR_VERSION > 5 || PHP_MINOR_VERSION >= 1
319319
REGISTER_LONG_CONSTANT("PDO_FETCH_SERIALIZE",(long)PDO_FETCH_SERIALIZE, CONST_CS|CONST_PERSISTENT);
320320
#endif
321+
REGISTER_LONG_CONSTANT("PDO_FETCH_NAMED",(long)PDO_FETCH_NAMED, CONST_CS|CONST_PERSISTENT);
321322

322323
REGISTER_LONG_CONSTANT("PDO_ATTR_AUTOCOMMIT", (long)PDO_ATTR_AUTOCOMMIT, CONST_CS|CONST_PERSISTENT);
323324
REGISTER_LONG_CONSTANT("PDO_ATTR_PREFETCH", (long)PDO_ATTR_PREFETCH, CONST_CS|CONST_PERSISTENT);
@@ -333,6 +334,8 @@ PHP_MINIT_FUNCTION(pdo)
333334
REGISTER_LONG_CONSTANT("PDO_ATTR_ORACLE_NULLS", (long)PDO_ATTR_ORACLE_NULLS, CONST_CS|CONST_PERSISTENT);
334335
REGISTER_LONG_CONSTANT("PDO_ATTR_PERSISTENT", (long)PDO_ATTR_PERSISTENT, CONST_CS|CONST_PERSISTENT);
335336
REGISTER_LONG_CONSTANT("PDO_ATTR_STATEMENT_CLASS", (long)PDO_ATTR_STATEMENT_CLASS, CONST_CS|CONST_PERSISTENT);
337+
REGISTER_LONG_CONSTANT("PDO_ATTR_FETCH_TABLE_NAMES", (long)PDO_ATTR_FETCH_TABLE_NAMES, CONST_CS|CONST_PERSISTENT);
338+
REGISTER_LONG_CONSTANT("PDO_ATTR_FETCH_CATALOG_NAMES", (long)PDO_ATTR_FETCH_CATALOG_NAMES, CONST_CS|CONST_PERSISTENT);
336339

337340
REGISTER_LONG_CONSTANT("PDO_ERRMODE_SILENT", (long)PDO_ERRMODE_SILENT, CONST_CS|CONST_PERSISTENT);
338341
REGISTER_LONG_CONSTANT("PDO_ERRMODE_WARNING", (long)PDO_ERRMODE_WARNING, CONST_CS|CONST_PERSISTENT);

ext/pdo/pdo_stmt.c

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -735,6 +735,7 @@ static int do_fetch(pdo_stmt_t *stmt, int do_bind, zval *return_value,
735735
case PDO_FETCH_ASSOC:
736736
case PDO_FETCH_BOTH:
737737
case PDO_FETCH_NUM:
738+
case PDO_FETCH_NAMED:
738739
array_init(return_value);
739740
break;
740741

@@ -842,6 +843,43 @@ static int do_fetch(pdo_stmt_t *stmt, int do_bind, zval *return_value,
842843
add_next_index_zval(return_value, val);
843844
break;
844845

846+
case PDO_FETCH_NAMED:
847+
/* already have an item with this name? */
848+
{
849+
zval **curr_val = NULL;
850+
if (zend_hash_find(Z_ARRVAL_P(return_value), stmt->columns[i].name,
851+
strlen(stmt->columns[i].name)+1,
852+
(void**)&curr_val) == SUCCESS) {
853+
zval *arr;
854+
if (Z_TYPE_PP(curr_val) != IS_ARRAY) {
855+
/* a little bit of black magic here:
856+
* we're creating a new array and swapping it for the
857+
* zval that's already stored in the hash under the name
858+
* we want. We then add that zval to the array.
859+
* This is effectively the same thing as:
860+
* if (!is_array($hash[$name])) {
861+
* $hash[$name] = array($hash[$name]);
862+
* }
863+
* */
864+
zval *cur;
865+
866+
MAKE_STD_ZVAL(arr);
867+
array_init(arr);
868+
869+
cur = *curr_val;
870+
*curr_val = arr;
871+
872+
add_next_index_zval(arr, cur);
873+
} else {
874+
arr = *curr_val;
875+
}
876+
add_next_index_zval(arr, val);
877+
} else {
878+
add_assoc_zval(return_value, stmt->columns[i].name, val);
879+
}
880+
}
881+
break;
882+
845883
case PDO_FETCH_NUM:
846884
add_next_index_zval(return_value, val);
847885
break;

ext/pdo/php_pdo_driver.h

Lines changed: 4 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ PDO_API char *php_pdo_int64_to_str(pdo_int64_t i64 TSRMLS_DC);
4444
# define FALSE 0
4545
#endif
4646

47-
#define PDO_DRIVER_API 20050610
47+
#define PDO_DRIVER_API 20050702
4848

4949
enum pdo_param_type {
5050
PDO_PARAM_NULL,
@@ -89,6 +89,7 @@ enum pdo_fetch_type {
8989
PDO_FETCH_CLASS, /* create an instance of named class, call ctor and set properties */
9090
PDO_FETCH_INTO, /* fetch row into an existing object */
9191
PDO_FETCH_FUNC, /* fetch into function and return its result */
92+
PDO_FETCH_NAMED, /* like PDO_FETCH_ASSOC, but can handle duplicate names */
9293
PDO_FETCH__MAX /* must be last */
9394
};
9495

@@ -123,6 +124,8 @@ enum pdo_attribute_type {
123124
PDO_ATTR_ORACLE_NULLS, /* convert empty strings to NULL */
124125
PDO_ATTR_PERSISTENT, /* pconnect style connection */
125126
PDO_ATTR_STATEMENT_CLASS, /* array(classname, array(ctor_args)) to specify the class of the constructed statement */
127+
PDO_ATTR_FETCH_TABLE_NAMES, /* include table names in the column names, where available */
128+
PDO_ATTR_FETCH_CATALOG_NAMES, /* include the catalog/db name names in the column names, where available */
126129

127130
/* this defines the start of the range for driver specific options.
128131
* Drivers should define their own attribute constants beginning with this
@@ -156,24 +159,6 @@ typedef char pdo_error_type[6]; /* SQLSTATE */
156159

157160

158161
#define PDO_ERR_NONE "00000"
159-
#if 0
160-
/* generic error code values.
161-
* Don't want to go overboard with these.
162-
* */
163-
#define PDO_ERR_SYNTAX "42000"
164-
#define PDO_ERR_CONSTRAINT "23000"
165-
#define PDO_ERR_NOT_FOUND ""
166-
#define PDO_ERR_ALREADY_EXISTS,
167-
#define PDO_ERR_NOT_IMPLEMENTED,
168-
#define PDO_ERR_MISMATCH,
169-
#define PDO_ERR_TRUNCATED,
170-
#define PDO_ERR_DISCONNECTED,
171-
#define PDO_ERR_NO_PERM,
172-
173-
PDO_ERR_CANT_MAP /* no way to map native error to the generic
174-
* codes; consult the native error for more info */
175-
};
176-
#endif
177162

178163
enum pdo_error_mode {
179164
PDO_ERRMODE_SILENT, /* just set error codes */

0 commit comments

Comments
 (0)