diff --git a/ext/pdo/pdo_stmt.c b/ext/pdo/pdo_stmt.c index 73d4530e8f657..8ea8bac02447f 100644 --- a/ext/pdo/pdo_stmt.c +++ b/ext/pdo/pdo_stmt.c @@ -1628,6 +1628,10 @@ bool pdo_stmt_setup_fetch_mode(pdo_stmt_t *stmt, zend_long mode, uint32_t mode_a stmt->default_fetch_type = PDO_FETCH_BOTH; + if ((mode & ~PDO_FETCH_FLAGS) == PDO_FETCH_USE_DEFAULT) { + mode = stmt->dbh->default_fetch_type; + } + flags = mode & PDO_FETCH_FLAGS; if (!pdo_verify_fetch_mode(stmt->default_fetch_type, mode, mode_arg_num, false)) { diff --git a/ext/pdo_sqlite/tests/gh20214.phpt b/ext/pdo_sqlite/tests/gh20214.phpt new file mode 100644 index 0000000000000..29adc50b0b747 --- /dev/null +++ b/ext/pdo_sqlite/tests/gh20214.phpt @@ -0,0 +1,38 @@ +--TEST-- +GH-20214 (PDO::FETCH_DEFAULT unexpected behavior with PDOStatement::setFetchMode) +--EXTENSIONS-- +pdo_sqlite +--FILE-- +setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_OBJ); + +// setFetchMode with FETCH_DEFAULT should use connection default (FETCH_OBJ) +$stmt = $db->query("SELECT 'v1' AS c1, 'v2' AS c2"); +$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 'v1' AS c1, 'v2' AS c2"); +$row = $stmt->fetch(PDO::FETCH_DEFAULT); +var_dump($row instanceof stdClass); + +// fetchAll with FETCH_DEFAULT should also use connection default +$stmt = $db->query("SELECT 'v1' AS c1, 'v2' AS c2"); +$rows = $stmt->fetchAll(PDO::FETCH_DEFAULT); +var_dump($rows[0] instanceof stdClass); + +// setFetchMode then fetch without argument +$stmt = $db->query("SELECT 'v1' AS c1, 'v2' AS c2"); +$stmt->setFetchMode(PDO::FETCH_DEFAULT); +$row = $stmt->fetch(); +var_dump($row instanceof stdClass); +?> +--EXPECT-- +bool(true) +string(2) "v1" +bool(true) +bool(true) +bool(true)