1
0
mirror of https://github.com/php/php-src.git synced 2026-03-24 00:02:20 +01:00

ext/pdo: Rename and add tests for PDO::FETCH_CLASS fetch mode (#17526)

This commit is contained in:
Gina Peter Banyard
2025-01-19 20:33:13 +00:00
committed by GitHub
parent b60f9bf27a
commit 9283abc1a0
9 changed files with 429 additions and 0 deletions

View File

@@ -0,0 +1,81 @@
--TEST--
PDO Common: PDO::FETCH_CLASS with by-ref constructor and arg by value
--EXTENSIONS--
pdo
--SKIPIF--
<?php
$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='.__DIR__ . '/../../pdo/tests/');
require_once getenv('REDIR_TEST_DIR') . 'pdo_test.inc';
$db = PDOTest::factory();
$db->exec('CREATE TABLE pdo_fetch_class_by_ref_ctor(id int NOT NULL PRIMARY KEY, val VARCHAR(10), val2 VARCHAR(10))');
$db->exec("INSERT INTO pdo_fetch_class_by_ref_ctor VALUES(1, 'A', 'AA')");
$db->exec("INSERT INTO pdo_fetch_class_by_ref_ctor VALUES(2, 'B', 'BB')");
$db->exec("INSERT INTO pdo_fetch_class_by_ref_ctor VALUES(3, 'C', 'CC')");
$stmt = $db->prepare('SELECT id, val FROM pdo_fetch_class_by_ref_ctor');
class TestByRefCtor
{
public $id;
public $val;
private $str;
public function __construct(string &$str)
{
echo __METHOD__ . "($str, {$this->id})\n";
$str .= $this->val;
$this->str = $str;
}
}
$stmt->execute();
// Use of random_int(10,10) is to defeat SCCP
var_dump($stmt->fetchAll(PDO::FETCH_CLASS, 'TestByRefCtor', [str_repeat('a', random_int(10,10))]));
?>
--CLEAN--
<?php
require_once getenv('REDIR_TEST_DIR') . 'pdo_test.inc';
$db = PDOTest::factory();
PDOTest::dropTableIfExists($db, "pdo_fetch_class_by_ref_ctor");
?>
--EXPECTF--
TestByRefCtor::__construct(aaaaaaaaaa, 1)
TestByRefCtor::__construct(aaaaaaaaaaA, 2)
TestByRefCtor::__construct(aaaaaaaaaaAB, 3)
array(3) {
[0]=>
object(TestByRefCtor)#%d (3) {
["id"]=>
string(1) "1"
["val"]=>
string(1) "A"
["str":"TestByRefCtor":private]=>
string(11) "aaaaaaaaaaA"
}
[1]=>
object(TestByRefCtor)#%d (3) {
["id"]=>
string(1) "2"
["val"]=>
string(1) "B"
["str":"TestByRefCtor":private]=>
string(12) "aaaaaaaaaaAB"
}
[2]=>
object(TestByRefCtor)#%d (3) {
["id"]=>
string(1) "3"
["val"]=>
string(1) "C"
["str":"TestByRefCtor":private]=>
string(13) "aaaaaaaaaaABC"
}
}

View File

@@ -0,0 +1,81 @@
--TEST--
PDO Common: PDO::FETCH_CLASS using named arguments in constructor array
--EXTENSIONS--
pdo
--SKIPIF--
<?php
$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='.__DIR__ . '/../../pdo/tests/');
require_once getenv('REDIR_TEST_DIR') . 'pdo_test.inc';
$db = PDOTest::factory();
$db->exec('CREATE TABLE pdo_fetch_class_ctor_named(id int NOT NULL PRIMARY KEY, val VARCHAR(10), val2 VARCHAR(10))');
$db->exec("INSERT INTO pdo_fetch_class_ctor_named VALUES(1, 'A', 'AA')");
$db->exec("INSERT INTO pdo_fetch_class_ctor_named VALUES(2, 'B', 'BB')");
$db->exec("INSERT INTO pdo_fetch_class_ctor_named VALUES(3, 'C', 'CC')");
$stmt = $db->prepare('SELECT id, val, val2 from pdo_fetch_class_ctor_named');
class TestBase
{
public $id;
protected $val;
private $val2;
public function __construct(string $a, string $b) {
echo 'Value of $a: ', $a, PHP_EOL,
'Value of $b: ', $b, PHP_EOL;
}
}
$stmt->execute();
var_dump($stmt->fetchAll(PDO::FETCH_CLASS, 'TestBase', ['b' => 'My key is B', 'a' => 'My key is A']));
?>
--CLEAN--
<?php
require_once getenv('REDIR_TEST_DIR') . 'pdo_test.inc';
$db = PDOTest::factory();
PDOTest::dropTableIfExists($db, "pdo_fetch_class_ctor_named");
?>
--EXPECTF--
Value of $a: My key is B
Value of $b: My key is A
Value of $a: My key is B
Value of $b: My key is A
Value of $a: My key is B
Value of $b: My key is A
array(3) {
[0]=>
object(TestBase)#%d (3) {
["id"]=>
string(1) "1"
["val":protected]=>
string(1) "A"
["val2":"TestBase":private]=>
string(2) "AA"
}
[1]=>
object(TestBase)#%d (3) {
["id"]=>
string(1) "2"
["val":protected]=>
string(1) "B"
["val2":"TestBase":private]=>
string(2) "BB"
}
[2]=>
object(TestBase)#%d (3) {
["id"]=>
string(1) "3"
["val":protected]=>
string(1) "C"
["val2":"TestBase":private]=>
string(2) "CC"
}
}

View File

@@ -0,0 +1,86 @@
--TEST--
PDO Common: PDO::FETCH_CLASS using mixed string and int arguments in constructor array
--EXTENSIONS--
pdo
--SKIPIF--
<?php
$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='.__DIR__ . '/../../pdo/tests/');
require_once getenv('REDIR_TEST_DIR') . 'pdo_test.inc';
$db = PDOTest::factory();
$db->exec('CREATE TABLE pdo_fetch_class_ctor_named_and_positional(id int NOT NULL PRIMARY KEY, val VARCHAR(10), val2 VARCHAR(10))');
$db->exec("INSERT INTO pdo_fetch_class_ctor_named_and_positional VALUES(1, 'A', 'AA')");
$db->exec("INSERT INTO pdo_fetch_class_ctor_named_and_positional VALUES(2, 'B', 'BB')");
$db->exec("INSERT INTO pdo_fetch_class_ctor_named_and_positional VALUES(3, 'C', 'CC')");
$stmt = $db->prepare('SELECT id, val, val2 from pdo_fetch_class_ctor_named_and_positional');
class TestBase
{
public $id;
protected $val;
private $val2;
public function __construct(string $a, string $b) {
echo 'Value of $a: ', $a, PHP_EOL,
'Value of $b: ', $b, PHP_EOL;
}
}
$stmt->execute();
try {
var_dump($stmt->fetchAll(PDO::FETCH_CLASS, 'TestBase', ['b' => 'My key is B', 'No key']));
} catch (\Throwable $e) {
echo $e::class, ': ', $e->getMessage(), \PHP_EOL;
}
?>
--CLEAN--
<?php
require_once getenv('REDIR_TEST_DIR') . 'pdo_test.inc';
$db = PDOTest::factory();
PDOTest::dropTableIfExists($db, "pdo_fetch_class_ctor_named_and_positional");
?>
--EXPECTF--
Value of $a: My key is B
Value of $b: No key
Value of $a: My key is B
Value of $b: No key
Value of $a: My key is B
Value of $b: No key
array(3) {
[0]=>
object(TestBase)#%d (3) {
["id"]=>
string(1) "1"
["val":protected]=>
string(1) "A"
["val2":"TestBase":private]=>
string(2) "AA"
}
[1]=>
object(TestBase)#%d (3) {
["id"]=>
string(1) "2"
["val":protected]=>
string(1) "B"
["val2":"TestBase":private]=>
string(2) "BB"
}
[2]=>
object(TestBase)#%d (3) {
["id"]=>
string(1) "3"
["val":protected]=>
string(1) "C"
["val2":"TestBase":private]=>
string(2) "CC"
}
}

View File

@@ -0,0 +1,85 @@
--TEST--
PDO Common: PDO::FETCH_CLASS with private constructor and arg by value
--EXTENSIONS--
pdo
--SKIPIF--
<?php
$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='.__DIR__ . '/../../pdo/tests/');
require_once getenv('REDIR_TEST_DIR') . 'pdo_test.inc';
$db = PDOTest::factory();
$db->exec('CREATE TABLE pdo_fetch_class_private_ctor(id int NOT NULL PRIMARY KEY, val VARCHAR(10), val2 VARCHAR(10))');
$db->exec("INSERT INTO pdo_fetch_class_private_ctor VALUES(1, 'A', 'AA')");
$db->exec("INSERT INTO pdo_fetch_class_private_ctor VALUES(2, 'B', 'BB')");
$stmt = $db->prepare('SELECT id, val FROM pdo_fetch_class_private_ctor');
class TestPrivateCtor
{
public $id;
public $val;
private function __construct(string $str)
{
echo __METHOD__ . "($str, {$this->id})\n";
}
}
class TestDerivedPrivateCtor extends TestPrivateCtor {}
$stmt->execute();
var_dump($stmt->fetchAll(PDO::FETCH_CLASS, 'TestPrivateCtor', ['test']));
$stmt->execute();
var_dump($stmt->fetchAll(PDO::FETCH_CLASS, 'TestDerivedPrivateCtor', ['testFromDerived']));
?>
--CLEAN--
<?php
require_once getenv('REDIR_TEST_DIR') . 'pdo_test.inc';
$db = PDOTest::factory();
PDOTest::dropTableIfExists($db, "pdo_fetch_class_private_ctor");
?>
--EXPECTF--
TestPrivateCtor::__construct(test, 1)
TestPrivateCtor::__construct(test, 2)
array(2) {
[0]=>
object(TestPrivateCtor)#%d (2) {
["id"]=>
string(1) "1"
["val"]=>
string(1) "A"
}
[1]=>
object(TestPrivateCtor)#%d (2) {
["id"]=>
string(1) "2"
["val"]=>
string(1) "B"
}
}
TestPrivateCtor::__construct(testFromDerived, 1)
TestPrivateCtor::__construct(testFromDerived, 2)
array(2) {
[0]=>
object(TestDerivedPrivateCtor)#%d (2) {
["id"]=>
string(1) "1"
["val"]=>
string(1) "A"
}
[1]=>
object(TestDerivedPrivateCtor)#%d (2) {
["id"]=>
string(1) "2"
["val"]=>
string(1) "B"
}
}

View File

@@ -0,0 +1,51 @@
--TEST--
PDO Common: Setting PDO::FETCH_CLASS with ctor_args when class has no constructor
--EXTENSIONS--
pdo
--SKIPIF--
<?php
$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='.__DIR__ . '/../../pdo/tests/');
require_once getenv('REDIR_TEST_DIR') . 'pdo_test.inc';
$db = PDOTest::factory();
$db->exec('CREATE TABLE pdo_fetch_all_class_ctor_error(id int NOT NULL PRIMARY KEY, val VARCHAR(10), val2 VARCHAR(10))');
$db->exec("INSERT INTO pdo_fetch_all_class_ctor_error VALUES(1, 'A', 'AA')");
$stmt = $db->prepare('SELECT id, val, val2 from pdo_fetch_all_class_ctor_error');
class TestBase
{
public $id;
protected $val;
private $val2;
}
$stmt->execute();
try {
var_dump($stmt->fetchAll(PDO::FETCH_CLASS, 'TestBase', [0]));
} catch (\Throwable $e) {
echo $e::class, ': ', $e->getMessage(), \PHP_EOL;
}
try {
var_dump($stmt->setFetchMode(PDO::FETCH_CLASS, 'TestBase', [0]));
} catch (\Throwable $e) {
echo $e::class, ': ', $e->getMessage(), \PHP_EOL;
}
?>
--CLEAN--
<?php
require_once getenv('REDIR_TEST_DIR') . 'pdo_test.inc';
$db = PDOTest::factory();
PDOTest::dropTableIfExists($db, "pdo_fetch_all_class_ctor_error");
?>
--EXPECT--
Error: User-supplied statement does not accept constructor arguments
Error: User-supplied statement does not accept constructor arguments

View File

@@ -0,0 +1,45 @@
--TEST--
PDO Common: Setting PDO::FETCH_CLASS with an unknown class
--EXTENSIONS--
pdo
--SKIPIF--
<?php
$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='.__DIR__ . '/../../pdo/tests/');
require_once getenv('REDIR_TEST_DIR') . 'pdo_test.inc';
$db = PDOTest::factory();
$db->exec('CREATE TABLE pdo_fetch_all_class_error_unknown(id int NOT NULL PRIMARY KEY, val VARCHAR(10), val2 VARCHAR(10))');
$db->exec("INSERT INTO pdo_fetch_all_class_error_unknown VALUES(1, 'A', 'AA')");
$stmt = $db->prepare('SELECT id, val, val2 from pdo_fetch_all_class_error_unknown');
$stmt->execute();
try {
var_dump($stmt->setFetchMode(PDO::FETCH_CLASS, 'Unknown'));
} catch (\Throwable $e) {
echo $e::class, ': ', $e->getMessage(), \PHP_EOL;
}
try {
var_dump($stmt->fetchAll(PDO::FETCH_CLASS, 'Unknown'));
} catch (\Throwable $e) {
echo $e::class, ': ', $e->getMessage(), \PHP_EOL;
}
?>
--CLEAN--
<?php
require_once getenv('REDIR_TEST_DIR') . 'pdo_test.inc';
$db = PDOTest::factory();
PDOTest::dropTableIfExists($db, "pdo_fetch_all_class_error_unknown");
?>
--EXPECTF--
TypeError: PDOStatement::setFetchMode(): Argument #2 must be a valid class
Fatal error: Class "Unknown" not found in %s on line %d