Passed
Push — int-types ( 274c73...c29a72 )
by Sam
05:04
created

PDOQuery::nextRecord()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

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

In the issue above, the returned value is violating the contract defined by the mentioned interface.

Let's take a look at an example:

interface HasName {
    /** @return string */
    public function getName();
}

class Name {
    public $name;
}

class User implements HasName {
    /** @return string|Name */
    public function getName() {
        return new Name('foo'); // This is a violation of the ``HasName`` interface
                                // which only allows a string value to be returned.
    }
}
Loading history...
90
        }
91
    }
92
}
93