Passed
Pull Request — master (#3833)
by Benjamin
08:37
created

Statement::execute()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
eloc 2
dl 0
loc 5
ccs 3
cts 3
cp 1
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
crap 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Doctrine\DBAL\Portability;
6
7
use Doctrine\DBAL\Driver\ResultStatement;
8
use Doctrine\DBAL\Driver\Statement as DriverStatement;
9
use Doctrine\DBAL\Driver\StatementIterator;
10
use Doctrine\DBAL\FetchMode;
11
use Doctrine\DBAL\ParameterType;
12
use IteratorAggregate;
13
use function array_change_key_case;
14
use function assert;
15
use function is_string;
16
use function rtrim;
17
18
/**
19
 * Portability wrapper for a Statement.
20
 */
21
final class Statement implements IteratorAggregate, DriverStatement
22
{
23
    /** @var int */
24
    private $portability;
25
26
    /** @var DriverStatement|ResultStatement */
27
    private $stmt;
28
29
    /** @var int|null */
30
    private $case;
31
32
    /** @var int */
33
    private $defaultFetchMode = FetchMode::MIXED;
34
35
    /**
36
     * Wraps <tt>Statement</tt> and applies portability measures.
37
     *
38
     * @param DriverStatement|ResultStatement $stmt
39
     */
40 351
    public function __construct($stmt, Connection $conn)
41
    {
42 351
        $this->stmt        = $stmt;
43 351
        $this->portability = $conn->getPortability();
44 351
        $this->case        = $conn->getFetchCase();
45 351
    }
46
47
    /**
48
     * {@inheritdoc}
49
     */
50 27
    public function bindParam($param, &$variable, int $type = ParameterType::STRING, ?int $length = null) : void
51
    {
52 27
        assert($this->stmt instanceof DriverStatement);
53
54 27
        $this->stmt->bindParam($param, $variable, $type, $length);
55 27
    }
56
57
    /**
58
     * {@inheritdoc}
59
     */
60 27
    public function bindValue($param, $value, int $type = ParameterType::STRING) : void
61
    {
62 27
        assert($this->stmt instanceof DriverStatement);
63
64 27
        $this->stmt->bindValue($param, $value, $type);
65 27
    }
66
67
    /**
68
     * {@inheritdoc}
69
     */
70 27
    public function closeCursor() : void
71
    {
72 27
        $this->stmt->closeCursor();
73 27
    }
74
75
    /**
76
     * {@inheritdoc}
77
     */
78 27
    public function columnCount() : int
79
    {
80 27
        return $this->stmt->columnCount();
81
    }
82
83
    /**
84
     * {@inheritdoc}
85
     */
86 81
    public function execute(?array $params = null) : void
87
    {
88 81
        assert($this->stmt instanceof DriverStatement);
89
90 81
        $this->stmt->execute($params);
91 81
    }
92
93
    /**
94
     * {@inheritdoc}
95
     */
96 162
    public function setFetchMode(int $fetchMode, ...$args) : void
97
    {
98 162
        $this->defaultFetchMode = $fetchMode;
99
100 162
        $this->stmt->setFetchMode($fetchMode, ...$args);
101 162
    }
102
103
    /**
104
     * {@inheritdoc}
105
     */
106 81
    public function getIterator()
107
    {
108 81
        return new StatementIterator($this);
109
    }
110
111
    /**
112
     * {@inheritdoc}
113
     */
114 81
    public function fetch(?int $fetchMode = null, ...$args)
115
    {
116 81
        $fetchMode = $fetchMode ?: $this->defaultFetchMode;
117
118 81
        $row = $this->stmt->fetch($fetchMode, ...$args);
119
120 81
        $iterateRow = ($this->portability & (Connection::PORTABILITY_EMPTY_TO_NULL|Connection::PORTABILITY_RTRIM)) !== 0;
121 81
        $fixCase    = $this->case !== null
122 81
            && ($fetchMode === FetchMode::ASSOCIATIVE || $fetchMode === FetchMode::MIXED)
123 81
            && ($this->portability & Connection::PORTABILITY_FIX_CASE);
124
125 81
        $row = $this->fixRow($row, $iterateRow, $fixCase);
126
127 81
        return $row;
128
    }
129
130
    /**
131
     * {@inheritdoc}
132
     */
133 135
    public function fetchAll(?int $fetchMode = null, ...$args) : array
134
    {
135 135
        $fetchMode = $fetchMode ?: $this->defaultFetchMode;
136
137 135
        $rows = $this->stmt->fetchAll($fetchMode, ...$args);
138
139 135
        $iterateRow = ($this->portability & (Connection::PORTABILITY_EMPTY_TO_NULL|Connection::PORTABILITY_RTRIM)) !== 0;
140 135
        $fixCase    = $this->case !== null
141 135
            && ($fetchMode === FetchMode::ASSOCIATIVE || $fetchMode === FetchMode::MIXED)
142 135
            && ($this->portability & Connection::PORTABILITY_FIX_CASE);
143
144 135
        if (! $iterateRow && ! $fixCase) {
145
            return $rows;
146
        }
147
148 135
        if ($fetchMode === FetchMode::COLUMN) {
149 81
            foreach ($rows as $num => $row) {
150 81
                $rows[$num] = [$row];
151
            }
152
        }
153
154 135
        foreach ($rows as $num => $row) {
155 135
            $rows[$num] = $this->fixRow($row, $iterateRow, $fixCase);
156
        }
157
158 135
        if ($fetchMode === FetchMode::COLUMN) {
159 81
            foreach ($rows as $num => $row) {
160 81
                $rows[$num] = $row[0];
161
            }
162
        }
163
164 135
        return $rows;
165
    }
166
167
    /**
168
     * {@inheritdoc}
169
     */
170
    public function fetchColumn(int $columnIndex = 0)
171
    {
172
        $value = $this->stmt->fetchColumn($columnIndex);
173
174
        if ($this->portability & (Connection::PORTABILITY_EMPTY_TO_NULL|Connection::PORTABILITY_RTRIM)) {
175
            if (($this->portability & Connection::PORTABILITY_EMPTY_TO_NULL) && $value === '') {
176
                $value = null;
177
            } elseif (($this->portability & Connection::PORTABILITY_RTRIM) && is_string($value)) {
178
                $value = rtrim($value);
179
            }
180
        }
181
182
        return $value;
183
    }
184
185
    /**
186
     * {@inheritdoc}
187
     */
188 27
    public function rowCount() : int
189
    {
190 27
        assert($this->stmt instanceof DriverStatement);
191
192 27
        return $this->stmt->rowCount();
193
    }
194
195
    /**
196
     * @param mixed $row
197
     *
198
     * @return mixed
199
     */
200 162
    private function fixRow($row, bool $iterateRow, bool $fixCase)
201
    {
202 162
        if (! $row) {
203 81
            return $row;
204
        }
205
206 162
        if ($fixCase) {
207 20
            assert($this->case !== null);
208 20
            $row = array_change_key_case($row, $this->case);
209
        }
210
211 162
        if ($iterateRow) {
212 135
            foreach ($row as $k => $v) {
213 135
                if (($this->portability & Connection::PORTABILITY_EMPTY_TO_NULL) && $v === '') {
214 75
                    $row[$k] = null;
215 135
                } elseif (($this->portability & Connection::PORTABILITY_RTRIM) && is_string($v)) {
216 34
                    $row[$k] = rtrim($v);
217
                }
218
            }
219
        }
220
221 162
        return $row;
222
    }
223
}
224