diff --git a/ext/pdo/pdo_stmt.c b/ext/pdo/pdo_stmt.c index 9ba82e822b676..2ae3b1dd9e8ca 100644 --- a/ext/pdo/pdo_stmt.c +++ b/ext/pdo/pdo_stmt.c @@ -1733,6 +1733,10 @@ bool pdo_stmt_setup_fetch_mode(pdo_stmt_t *stmt, zend_long mode, uint32_t mode_a flags = mode & PDO_FETCH_FLAGS; + if ((mode & ~PDO_FETCH_FLAGS) == PDO_FETCH_USE_DEFAULT) { + mode = stmt->dbh->default_fetch_type | flags; + } + if (!pdo_stmt_verify_mode(stmt, mode, mode_arg_num, false)) { return false; } diff --git a/ext/pdo/tests/gh20214.phpt b/ext/pdo/tests/gh20214.phpt new file mode 100644 index 0000000000000..8afd667558c4e --- /dev/null +++ b/ext/pdo/tests/gh20214.phpt @@ -0,0 +1,64 @@ +--TEST-- +GH-20214 (PDO::FETCH_DEFAULT unexpected behavior with PDOStatement::setFetchMode) +--EXTENSIONS-- +pdo +--SKIPIF-- + +--FILE-- +exec('CREATE TABLE gh20214 (c1 VARCHAR(10), c2 VARCHAR(10))'); +$db->exec("INSERT INTO gh20214 VALUES ('v1', 'v2')"); + +$db->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_OBJ); + +// setFetchMode with FETCH_DEFAULT should use connection default (FETCH_OBJ) +$stmt = $db->query('SELECT c1, c2 FROM gh20214'); +$stmt->setFetchMode(PDO::FETCH_DEFAULT); +$row = $stmt->fetch(); +var_dump($row instanceof stdClass); +var_dump($row->c1); + +// fetch with FETCH_DEFAULT should also use connection default +$stmt = $db->query('SELECT c1, c2 FROM gh20214'); +$row = $stmt->fetch(PDO::FETCH_DEFAULT); +var_dump($row instanceof stdClass); + +// fetchAll with FETCH_DEFAULT should also use connection default +$stmt = $db->query('SELECT c1, c2 FROM gh20214'); +$rows = $stmt->fetchAll(PDO::FETCH_DEFAULT); +var_dump($rows[0] instanceof stdClass); + +// setFetchMode then fetch without argument +$stmt = $db->query('SELECT c1, c2 FROM gh20214'); +$stmt->setFetchMode(PDO::FETCH_DEFAULT); +$row = $stmt->fetch(); +var_dump($row instanceof stdClass); + +// query() with FETCH_DEFAULT as second argument +$db->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_NUM); +$stmt = $db->query('SELECT c1, c2 FROM gh20214', PDO::FETCH_DEFAULT); +$row = $stmt->fetch(); +var_dump(is_array($row) && isset($row[0])); +?> +--CLEAN-- + +--EXPECT-- +bool(true) +string(2) "v1" +bool(true) +bool(true) +bool(true) +bool(true)