1 | <?php |
||
2 | |||
3 | namespace SilverStripe\PostgreSQL; |
||
4 | |||
5 | use SilverStripe\ORM\Connect\Query; |
||
6 | |||
7 | /** |
||
8 | * A result-set from a PostgreSQL database. |
||
9 | * |
||
10 | * @package sapphire |
||
11 | * @subpackage model |
||
12 | */ |
||
13 | class PostgreSQLQuery extends Query |
||
14 | { |
||
15 | /** |
||
16 | * The internal Postgres handle that points to the result set. |
||
17 | * @var resource |
||
18 | */ |
||
19 | private $handle; |
||
20 | |||
21 | private $columnNames = []; |
||
22 | |||
23 | /** |
||
24 | * Mapping of postgresql types to PHP types |
||
25 | * Note that the bool => int mapping is by design, designed to mimic MySQL's behaviour |
||
26 | * @var array |
||
27 | */ |
||
28 | protected static $typeMapping = [ |
||
29 | 'bool' => 'int', |
||
30 | 'int2' => 'int', |
||
31 | 'int4' => 'int', |
||
32 | 'int8' => 'int', |
||
33 | 'float4' => 'float', |
||
34 | 'float8' => 'float', |
||
35 | 'numeric' => 'float', |
||
36 | ]; |
||
37 | |||
38 | /** |
||
39 | * Hook the result-set given into a Query class, suitable for use by sapphire. |
||
40 | * @param resource $handle the internal Postgres handle that is points to the resultset. |
||
41 | */ |
||
42 | public function __construct($handle) |
||
43 | { |
||
44 | $this->handle = $handle; |
||
45 | |||
46 | $numColumns = pg_num_fields($handle); |
||
47 | for ($i = 0; $i < $numColumns; $i++) { |
||
48 | $this->columnNames[$i] = pg_field_name($handle, $i); |
||
49 | } |
||
50 | } |
||
51 | |||
52 | public function __destruct() |
||
53 | { |
||
54 | if (is_resource($this->handle)) { |
||
55 | pg_free_result($this->handle); |
||
56 | } |
||
57 | } |
||
58 | |||
59 | public function getIterator() |
||
60 | { |
||
61 | pg_result_seek($this->handle, 0); |
||
62 | while ($data = $this->nextRecord()) { |
||
63 | yield $data; |
||
64 | } |
||
65 | } |
||
66 | |||
67 | public function numRecords() |
||
68 | { |
||
69 | return pg_num_rows($this->handle); |
||
70 | } |
||
71 | |||
72 | public function nextRecord() |
||
73 | { |
||
74 | $row = pg_fetch_array($this->handle, null, PGSQL_NUM); |
||
75 | |||
76 | // Correct non-string types |
||
77 | if ($row) { |
||
0 ignored issues
–
show
|
|||
78 | return $this->parseResult($row); |
||
79 | } |
||
80 | |||
81 | return false; |
||
82 | } |
||
83 | |||
84 | /** |
||
85 | * @param array $row |
||
86 | * @return array |
||
87 | */ |
||
88 | protected function parseResult(array $row) |
||
89 | { |
||
90 | $record = []; |
||
91 | |||
92 | foreach ($row as $i => $v) { |
||
93 | $k = $this->columnNames[$i]; |
||
94 | $record[$k] = $v; |
||
95 | $type = pg_field_type($this->handle, $i); |
||
96 | if (isset(self::$typeMapping[$type])) { |
||
97 | if ($type === 'bool' && $record[$k] === 't') { |
||
98 | $record[$k] = 1; |
||
99 | |||
100 | // Note that boolean 'f' will be converted to 0 by this |
||
101 | } else { |
||
102 | settype($record[$k], self::$typeMapping[$type]); |
||
103 | } |
||
104 | } |
||
105 | } |
||
106 | |||
107 | return $record; |
||
108 | } |
||
109 | } |
||
110 |
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.
Consider making the comparison explicit by using
empty(..)
or! empty(...)
instead.