diff --git a/tests/WP_PDO_MySQL_On_SQLite_PDO_API_Tests.php b/tests/WP_PDO_MySQL_On_SQLite_PDO_API_Tests.php index d9b474fb..9ac8a301 100644 --- a/tests/WP_PDO_MySQL_On_SQLite_PDO_API_Tests.php +++ b/tests/WP_PDO_MySQL_On_SQLite_PDO_API_Tests.php @@ -2,6 +2,20 @@ use PHPUnit\Framework\TestCase; +// phpcs:disable Generic.Files.OneObjectStructurePerFile.MultipleFound +class FetchObjectTestClass { + public $col1; + public $col2; + public $col3; + public $arg1; + public $arg2; + + public function __construct( $arg1 = null, $arg2 = null ) { + $this->arg1 = $arg1; + $this->arg2 = $arg2; + } +} + class WP_PDO_MySQL_On_SQLite_PDO_API_Tests extends TestCase { /** @var WP_PDO_MySQL_On_SQLite */ private $driver; @@ -324,6 +338,106 @@ public function test_fetch( $query, $mode, $expected ): void { } } + public function test_fetch_column(): void { + $query = " + SELECT 1, 'abc', true + UNION ALL + SELECT 2, 'xyz', false + UNION ALL + SELECT 3, null, null + "; + + // Fetch first column (default). + $stmt = $this->driver->query( $query ); + $this->assertSame( '1', $stmt->fetchColumn() ); + $this->assertSame( '2', $stmt->fetchColumn() ); + $this->assertSame( '3', $stmt->fetchColumn() ); + $this->assertFalse( $stmt->fetchColumn() ); + + // Fetch second column. + $stmt = $this->driver->query( $query ); + $this->assertSame( 'abc', $stmt->fetchColumn( 1 ) ); + $this->assertSame( 'xyz', $stmt->fetchColumn( 1 ) ); + $this->assertNull( $stmt->fetchColumn( 1 ) ); + $this->assertFalse( $stmt->fetchColumn( 1 ) ); + + // Fetch third column. + $stmt = $this->driver->query( $query ); + $this->assertSame( '1', $stmt->fetchColumn( 2 ) ); + $this->assertSame( '0', $stmt->fetchColumn( 2 ) ); + $this->assertNull( $stmt->fetchColumn( 2 ) ); + $this->assertFalse( $stmt->fetchColumn( 2 ) ); + + // Fetch different columns across rows. + $stmt = $this->driver->query( $query ); + $this->assertSame( '1', $stmt->fetchColumn( 0 ) ); + $this->assertSame( 'xyz', $stmt->fetchColumn( 1 ) ); + $this->assertNull( $stmt->fetchColumn( 2 ) ); + $this->assertFalse( $stmt->fetchColumn() ); + } + + public function test_fetch_column_invalid_index(): void { + $stmt = $this->driver->query( "SELECT 1, 'abc', true" ); + + if ( PHP_VERSION_ID < 80000 ) { + $this->expectException( PDOException::class ); + $this->expectExceptionMessage( 'Invalid column index' ); + } else { + $this->expectException( ValueError::class ); + $this->expectExceptionMessage( 'Invalid column index' ); + } + $stmt->fetchColumn( 3 ); + } + + public function test_fetch_column_negative_index(): void { + $stmt = $this->driver->query( "SELECT 1, 'abc', true" ); + + if ( PHP_VERSION_ID < 80000 ) { + $this->expectException( PDOException::class ); + $this->expectExceptionMessage( 'Invalid column index' ); + } else { + $this->expectException( ValueError::class ); + $this->expectExceptionMessage( 'Column index must be greater than or equal to 0' ); + } + $stmt->fetchColumn( -1 ); + } + + public function test_fetch_obj(): void { + // No arguments (stdClass). + $stmt = $this->driver->query( "SELECT 1, 'abc', true" ); + $this->assertEquals( + (object) array( + 1 => '1', + 'abc' => 'abc', + 'true' => true, + ), + $stmt->fetchObject() + ); + $this->assertFalse( $stmt->fetchObject() ); + + // Custom class. + $stmt = $this->driver->query( "SELECT 1 AS col1, 'abc' AS col2, true AS col3" ); + $result = $stmt->fetchObject( FetchObjectTestClass::class ); + $this->assertInstanceOf( FetchObjectTestClass::class, $result ); + $this->assertSame( '1', $result->col1 ); + $this->assertSame( 'abc', $result->col2 ); + $this->assertSame( '1', $result->col3 ); + $this->assertNull( $result->arg1 ); + $this->assertNull( $result->arg2 ); + $this->assertFalse( $stmt->fetchObject( FetchObjectTestClass::class ) ); + + // Custom class with constructor arguments. + $stmt = $this->driver->query( "SELECT 1 AS col1, 'abc' AS col2, true AS col3" ); + $result = $stmt->fetchObject( FetchObjectTestClass::class, array( 'val1', 'val2' ) ); + $this->assertInstanceOf( FetchObjectTestClass::class, $result ); + $this->assertSame( '1', $result->col1 ); + $this->assertSame( 'abc', $result->col2 ); + $this->assertSame( '1', $result->col3 ); + $this->assertSame( 'val1', $result->arg1 ); + $this->assertSame( 'val2', $result->arg2 ); + $this->assertFalse( $stmt->fetchObject( FetchObjectTestClass::class, array( 'val1', 'val2' ) ) ); + } + public function test_attr_default_fetch_mode(): void { $this->driver->setAttribute( PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_NUM ); $result = $this->driver->query( "SELECT 'a', 'b', 'c'" ); diff --git a/wp-includes/sqlite-ast/class-wp-pdo-proxy-statement.php b/wp-includes/sqlite-ast/class-wp-pdo-proxy-statement.php index c5efd2b4..f56340d7 100644 --- a/wp-includes/sqlite-ast/class-wp-pdo-proxy-statement.php +++ b/wp-includes/sqlite-ast/class-wp-pdo-proxy-statement.php @@ -196,7 +196,7 @@ public function fetch( */ #[ReturnTypeWillChange] public function fetchColumn( $column = 0 ) { - throw new RuntimeException( 'Not implemented' ); + return $this->statement->fetchColumn( $column ); } /** @@ -208,7 +208,7 @@ public function fetchColumn( $column = 0 ) { */ #[ReturnTypeWillChange] public function fetchObject( $class = 'stdClass', $constructorArgs = array() ) { - throw new RuntimeException( 'Not implemented' ); + return $this->statement->fetchObject( $class, $constructorArgs ); } /**