Passed
Push — master ( 545e22...b70257 )
by Robbie
11:19 queued 10s
created

PDOQuery::fetchAllPgsql()   A

Complexity

Conditions 5
Paths 2

Size

Total Lines 23
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 13
nc 2
nop 1
dl 0
loc 23
rs 9.5222
c 0
b 0
f 0
1
<?php
2
3
namespace SilverStripe\ORM\Connect;
4
5
use ArrayIterator;
6
use PDO;
7
use PDOStatement;
8
9
/**
10
 * A result-set from a PDO database.
11
 */
12
class PDOQuery extends Query
13
{
14
    /**
15
     * The internal MySQL handle that points to the result set.
16
     * @var PDOStatement
17
     */
18
    protected $statement = null;
19
20
    protected $results = null;
21
22
    /**
23
     * Hook the result-set given into a Query class, suitable for use by SilverStripe.
24
     * @param PDOStatement $statement The internal PDOStatement containing the results
25
     */
26
    public function __construct(PDOStatement $statement, PDOConnector $conn)
27
    {
28
        $this->statement = $statement;
29
        // Since no more than one PDOStatement for any one connection can be safely
30
        // traversed, each statement simply requests all rows at once for safety.
31
        // This could be re-engineered to call fetchAll on an as-needed basis
32
33
        // Special case for Postgres
34
        if ($conn->getDriver() == 'pgsql') {
35
            $this->results = $this->fetchAllPgsql($statement);
36
        } else {
37
            $this->results = $statement->fetchAll(PDO::FETCH_ASSOC);
38
        }
39
        $statement->closeCursor();
40
    }
41
42
    /**
43
     * Fetch a record form the statement with its type data corrected
44
     * Necessary to fix float data retrieved from PGSQL
45
     * Returns data as an array of maps
46
     * @return array
47
     */
48
    protected function fetchAllPgsql($statement)
49
    {
50
        $columnCount = $statement->columnCount();
51
        $columnMeta = [];
52
        for ($i = 0; $i<$columnCount; $i++) {
53
            $columnMeta[$i] = $statement->getColumnMeta($i);
54
        }
55
56
        // Re-map fetched data using columnMeta
57
        return array_map(
58
            function ($rowArray) use ($columnMeta) {
59
                $row = [];
60
                foreach ($columnMeta as $i => $meta) {
61
                    // Coerce floats from string to float
62
                    // PDO PostgreSQL fails to do this
63
                    if (isset($meta['native_type']) && strpos($meta['native_type'], 'float') === 0) {
64
                        $rowArray[$i] = (float)$rowArray[$i];
65
                    }
66
                    $row[$meta['name']] = $rowArray[$i];
67
                }
68
                return $row;
69
            },
70
            $statement->fetchAll(PDO::FETCH_NUM)
71
        );
72
    }
73
74
    public function getIterator()
75
    {
76
        return new ArrayIterator($this->results);
77
    }
78
79
    public function numRecords()
80
    {
81
        return count($this->results);
82
    }
83
}
84