Passed
Push — main ( 9d67f9...af7fe2 )
by Thierry
02:49
created

Query::execute()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 4
c 0
b 0
f 0
nc 4
nop 1
dl 0
loc 7
rs 10
1
<?php
2
3
namespace Lagdo\DbAdmin\Driver\Db;
4
5
use Lagdo\DbAdmin\Driver\Entity\TableFieldEntity;
6
use Lagdo\DbAdmin\Driver\Entity\TableEntity;
7
8
use Lagdo\DbAdmin\Driver\DriverInterface;
9
use Lagdo\DbAdmin\Driver\UtilInterface;
10
use Lagdo\DbAdmin\Driver\TranslatorInterface;
11
use Lagdo\DbAdmin\Driver\Db\ConnectionInterface;
12
13
abstract class Query implements QueryInterface
14
{
15
    /**
16
     * @var DriverInterface
17
     */
18
    protected $driver;
19
20
    /**
21
     * @var UtilInterface
22
     */
23
    protected $util;
24
25
    /**
26
     * @var TranslatorInterface
27
     */
28
    protected $trans;
29
30
    /**
31
     * @var ConnectionInterface
32
     */
33
    protected $connection;
34
35
    /**
36
     * The last error code
37
     *
38
     * @var int
39
     */
40
    protected $errno = 0;
41
42
    /**
43
     * The last error message
44
     *
45
     * @var string
46
     */
47
    protected $error = '';
48
49
    /**
50
     * The number of rows affected by the last query
51
     *
52
     * @var int
53
     */
54
    protected $affectedRows;
55
56
    /**
57
     * Executed queries
58
     *
59
     * @var array
60
     */
61
    protected $queries = [];
62
63
    /**
64
     * Query start timestamp
65
     *
66
     * @var int
67
     */
68
    protected $start = 0;
69
70
    /**
71
     * The constructor
72
     *
73
     * @param DriverInterface $driver
74
     * @param UtilInterface $util
75
     * @param TranslatorInterface $trans
76
     * @param ConnectionInterface $connection
77
     */
78
    public function __construct(DriverInterface $driver, UtilInterface $util,
79
        TranslatorInterface $trans, ConnectionInterface $connection)
80
    {
81
        $this->driver = $driver;
82
        $this->util = $util;
83
        $this->trans = $trans;
84
        $this->connection = $connection;
85
    }
86
87
    /**
88
     * @inheritDoc
89
     */
90
    public function schema()
91
    {
92
        return "";
93
    }
94
95
    /**
96
     * @inheritDoc
97
     */
98
    public function select(string $table, array $select, array $where,
99
        array $group, array $order = [], int $limit = 1, int $page = 0)
100
    {
101
        $query = $this->driver->buildSelectQuery($table, $select, $where, $group, $order, $limit, $page);
102
        // $start = microtime(true);
103
        return $this->connection->query($query);
104
    }
105
106
    /**
107
     * @inheritDoc
108
     */
109
    public function insert(string $table, array $values)
110
    {
111
        $table = $this->driver->table($table);
112
        if (!empty($values)) {
113
            return $this->execute("INSERT INTO $table DEFAULT VALUES");
114
        }
115
        return $this->execute("INSERT INTO $table (" .
116
            implode(", ", array_keys($values)) . ") VALUES (" . implode(", ", $values) . ")");
117
    }
118
119
    /**
120
     * @inheritDoc
121
     */
122
    public function update(string $table, array $values, string $queryWhere, int $limit = 0, string $separator = "\n")
123
    {
124
        $assignments = [];
125
        foreach ($values as $name => $value) {
126
            $assignments[] = "$name = $value";
127
        }
128
        $query = $this->driver->table($table) . " SET$separator" . implode(",$separator", $assignments);
129
        if (!$limit) {
130
            return $this->execute('UPDATE ' . $query . $queryWhere);
131
        }
132
        return $this->execute('UPDATE' . $this->driver->limitToOne($table, $query, $queryWhere, $separator));
133
    }
134
135
    /**
136
     * @inheritDoc
137
     */
138
    public function delete(string $table, string $queryWhere, int $limit = 0)
139
    {
140
        $query = 'FROM ' . $this->driver->table($table);
141
        if (!$limit) {
142
            return $this->execute("DELETE $query $queryWhere");
143
        }
144
        return $this->execute('DELETE' . $this->driver->limitToOne($table, $query, $queryWhere));
145
    }
146
147
    /**
148
     * @inheritDoc
149
     */
150
    public function explain(ConnectionInterface $connection, string $query)
151
    {
152
        return null;
153
    }
154
155
    /**
156
     * @inheritDoc
157
     */
158
    public function slowQuery(string $query, int $timeout)
159
    {
160
    }
161
162
    /**
163
     * @inheritDoc
164
     */
165
    public function setError(string $error = '')
166
    {
167
        $this->error = $error;
168
    }
169
170
    /**
171
     * @inheritDoc
172
     */
173
    public function error()
174
    {
175
        return $this->error;
176
    }
177
178
    /**
179
     * @inheritDoc
180
     */
181
    public function hasError()
182
    {
183
        return $this->error !== '';
184
    }
185
186
    /**
187
     * @inheritDoc
188
     */
189
    public function setErrno($errno)
190
    {
191
        $this->errno = $errno;
192
    }
193
194
    /**
195
     * @inheritDoc
196
     */
197
    public function errno()
198
    {
199
        return $this->errno;
200
    }
201
202
    /**
203
     * @inheritDoc
204
     */
205
    public function hasErrno()
206
    {
207
        return $this->errno !== 0;
208
    }
209
210
    /**
211
     * @inheritDoc
212
     */
213
    public function setAffectedRows($affectedRows)
214
    {
215
        $this->affectedRows = $affectedRows;
216
    }
217
218
    /**
219
     * @inheritDoc
220
     */
221
    public function affectedRows()
222
    {
223
        return $this->affectedRows;
224
    }
225
226
    /**
227
     * @inheritDoc
228
     */
229
    public function execute(string $query)
230
    {
231
        if (!$this->start) {
232
            $this->start = microtime(true);
0 ignored issues
show
Documentation Bug introduced by
It seems like microtime(true) can also be of type string. However, the property $start is declared as type integer. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
233
        }
234
        $this->queries[] = (preg_match('~;$~', $query) ? "DELIMITER ;;\n$query;\nDELIMITER " : $query) . ";";
235
        return $this->connection->query($query);
236
    }
237
238
    /**
239
     * @inheritDoc
240
     */
241
    public function queries()
242
    {
243
        return [implode("\n", $this->queries), $this->trans->formatTime($this->start)];
244
    }
245
246
    /**
247
     * @inheritDoc
248
     */
249
    public function applyQueries(string $query, array $tables, $escape = null)
250
    {
251
        if (!$escape) {
252
            $escape = function ($table) {
253
                return $this->driver->table($table);
254
            };
255
        }
256
        foreach ($tables as $table) {
257
            if (!$this->execute("$query " . $escape($table))) {
258
                return false;
259
            }
260
        }
261
        return true;
262
    }
263
264
    /**
265
     * @inheritDoc
266
     */
267
    public function values(string $query, $column = 0)
268
    {
269
        $values = [];
270
        $statement = $this->connection->query($query);
271
        if (is_object($statement)) {
272
            while ($row = $statement->fetchRow()) {
273
                $values[] = $row[$column];
274
            }
275
        }
276
        return $values;
277
    }
278
279
    /**
280
     * @inheritDoc
281
     */
282
    public function keyValues(string $query, ConnectionInterface $connection = null, bool $setKeys = true)
283
    {
284
        if (!is_object($connection)) {
285
            $connection = $this->connection;
286
        }
287
        $values = [];
288
        $statement = $connection->query($query);
289
        if (is_object($statement)) {
290
            while ($row = $statement->fetchRow()) {
291
                if ($setKeys) {
292
                    $values[$row[0]] = $row[1];
293
                } else {
294
                    $values[] = $row[0];
295
                }
296
            }
297
        }
298
        return $values;
299
    }
300
301
    /**
302
     * @inheritDoc
303
     */
304
    public function rows(string $query, ConnectionInterface $connection = null)
305
    {
306
        if (!$connection) {
307
            $connection = $this->connection;
308
        }
309
        $statement = $connection->query($query);
310
        if (!is_object($statement)) { // can return true
311
            return [];
312
        }
313
        $rows = [];
314
        while ($row = $statement->fetchAssoc()) {
315
            $rows[] = $row;
316
        }
317
        return $rows;
318
    }
319
320
    /**
321
     * @inheritDoc
322
     */
323
    public function removeDefiner(string $query)
324
    {
325
        return preg_replace('~^([A-Z =]+) DEFINER=`' .
326
            preg_replace('~@(.*)~', '`@`(%|\1)', $this->user()) .
327
            '`~', '\1', $query); //! proper escaping of user
328
    }
329
330
    /**
331
     * @inheritDoc
332
     */
333
    public function begin()
334
    {
335
        return $this->connection->query("BEGIN");
336
    }
337
338
    /**
339
     * @inheritDoc
340
     */
341
    public function commit()
342
    {
343
        return $this->connection->query("COMMIT");
344
    }
345
346
    /**
347
     * @inheritDoc
348
     */
349
    public function rollback()
350
    {
351
        return $this->connection->query("ROLLBACK");
352
    }
353
354
    /**
355
     * @inheritDoc
356
     */
357
    public function countRows(TableEntity $tableStatus, array $where)
358
    {
359
        return null;
360
    }
361
362
    /**
363
     * @inheritDoc
364
     */
365
    public function convertSearch(string $idf, array $val, TableFieldEntity $field)
366
    {
367
        return $idf;
368
    }
369
370
    /**
371
     * @inheritDoc
372
     */
373
    public function view(string $name)
374
    {
375
        return [];
376
    }
377
}
378