From 72787ae83e1f74bcca93c9eeb167a9a50df595ff Mon Sep 17 00:00:00 2001 From: Sam Minnee Date: Wed, 10 Oct 2018 22:23:22 +1300 Subject: [PATCH 1/2] FIX: Return correct types in PostgreSQLQuery Fixes https://github.com/silverstripe/silverstripe-postgresql/issues/90 Helps fix https://github.com/silverstripe/silverstripe-framework/issues/7039 --- code/PostgreSQLQuery.php | 44 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 42 insertions(+), 2 deletions(-) diff --git a/code/PostgreSQLQuery.php b/code/PostgreSQLQuery.php index fc7748f..d372d3c 100644 --- a/code/PostgreSQLQuery.php +++ b/code/PostgreSQLQuery.php @@ -18,6 +18,23 @@ class PostgreSQLQuery extends Query */ private $handle; + private $columnNames = []; + + /** + * Mapping of postgresql types to PHP types + * Note that the bool => int mapping is by design, designed to mimic MySQL's behaviour + * @var array + */ + protected static $typeMapping = [ + 'bool' => 'int', + 'int2' => 'int', + 'int4' => 'int', + 'int8' => 'int', + 'float4' => 'float', + 'float8' => 'float', + 'numeric' => 'float', + ]; + /** * Hook the result-set given into a Query class, suitable for use by sapphire. * @param resource $handle the internal Postgres handle that is points to the resultset. @@ -25,6 +42,11 @@ class PostgreSQLQuery extends Query public function __construct($handle) { $this->handle = $handle; + + $numColumns = pg_num_fields($handle); + for ($i = 0; $i<$numColumns; $i++) { + $this->columnNames[$i] = pg_field_name($handle, $i); + } } public function __destruct() @@ -37,7 +59,7 @@ class PostgreSQLQuery extends Query public function seek($row) { pg_result_seek($this->handle, $row); - return pg_fetch_assoc($this->handle); + return $this->nextRecord(); } public function numRecords() @@ -47,6 +69,24 @@ class PostgreSQLQuery extends Query public function nextRecord() { - return pg_fetch_assoc($this->handle); + $row = pg_fetch_array($this->handle, null, PGSQL_NUM); + + // Correct non-string types + if ($row) { + $record = []; + + foreach ($row as $i => $v) { + $k = $this->columnNames[$i]; + $record[$k] = $v; + $type = pg_field_type($this->handle, $i); + if (isset(self::$typeMapping[$type])) { + settype($record[$k], self::$typeMapping[$type]); + } + } + + return $record; + } + + return false; } } From 8f70ac89ca00d6facee40205c26cda2d2c183230 Mon Sep 17 00:00:00 2001 From: Sam Minnee Date: Thu, 18 Oct 2018 20:26:42 +1300 Subject: [PATCH 2/2] FIX: Removed test that has been moved back to framework This test has been added for all database types in framework in https://github.com/silverstripe/silverstripe-framework/pull/8448 --- tests/PostgreSQLDatabaseTest.php | 57 -------------------------------- 1 file changed, 57 deletions(-) delete mode 100644 tests/PostgreSQLDatabaseTest.php diff --git a/tests/PostgreSQLDatabaseTest.php b/tests/PostgreSQLDatabaseTest.php deleted file mode 100644 index 2c9ebe3..0000000 --- a/tests/PostgreSQLDatabaseTest.php +++ /dev/null @@ -1,57 +0,0 @@ -supportsTransactions() == true - && DB::get_conn() instanceof PostgreSQLDatabase - ) { - $page = new Page(); - $page->Title = 'Read only success'; - $page->write(); - - DB::get_conn()->transactionStart('READ ONLY'); - - try { - $page = new Page(); - $page->Title = 'Read only page failed'; - $page->write(); - } catch (Exception $e) { - //could not write this record - //We need to do a rollback or a commit otherwise we'll get error messages - DB::get_conn()->transactionRollback(); - } - - DB::get_conn()->transactionEnd(); - - DataObject::flush_and_destroy_cache(); - - $success = DataObject::get('Page', "\"Title\"='Read only success'"); - $fail = DataObject::get('Page', "\"Title\"='Read only page failed'"); - - //This page should be in the system - $this->assertTrue(is_object($success) && $success->exists()); - - //This page should NOT exist, we had 'read only' permissions - $this->assertFalse(is_object($fail) && $fail->exists()); - } else { - $this->markTestSkipped('Current database is not PostgreSQL'); - } - } -}