1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Mattbit\MysqlCompat; |
4
|
|
|
|
5
|
|
|
use Mattbit\MysqlCompat\Exception\NotSupportedException; |
6
|
|
|
use PDO; |
7
|
|
|
use Mattbit\MysqlCompat\Exception\QueryException; |
8
|
|
|
|
9
|
|
|
class Bridge |
10
|
|
|
{ |
11
|
|
|
/** |
12
|
|
|
* MYSQL_CLIENT_COMPRESS |
13
|
|
|
*/ |
14
|
|
|
const CLIENT_COMPRESS = 32; |
15
|
|
|
|
16
|
|
|
/** |
17
|
|
|
* MYSQL_CLIENT_SSL |
18
|
|
|
*/ |
19
|
|
|
const CLIENT_SSL = 2048; |
20
|
|
|
|
21
|
|
|
/** |
22
|
|
|
* MYSQL_CLIENT_INTERACTIVE |
23
|
|
|
*/ |
24
|
|
|
const CLIENT_INTERACTIVE = 1024; |
25
|
|
|
|
26
|
|
|
|
27
|
|
|
/** |
28
|
|
|
* MYSQL_CLIENT_IGNORE_SPACE |
29
|
|
|
*/ |
30
|
|
|
const CLIENT_IGNORE_SPACE = 256; |
31
|
|
|
|
32
|
|
|
/** |
33
|
|
|
* The database manager instance. |
34
|
|
|
* |
35
|
|
|
* @var Manager |
36
|
|
|
*/ |
37
|
|
|
protected $manager; |
38
|
|
|
|
39
|
|
|
/** |
40
|
|
|
* Create a new bridge. |
41
|
|
|
* |
42
|
|
|
* @param Manager $manager |
43
|
|
|
*/ |
44
|
|
|
public function __construct(Manager $manager) |
45
|
|
|
{ |
46
|
|
|
$this->manager = $manager; |
47
|
|
|
} |
48
|
|
|
|
49
|
|
|
public function affectedRows(Connection $linkIdentifier = null) |
50
|
|
|
{ |
51
|
|
|
$connection = $this->manager->getOpenConnectionOrFail($linkIdentifier); |
52
|
|
|
|
53
|
|
|
return $connection->getRowCount(); |
54
|
|
|
} |
55
|
|
|
|
56
|
|
|
public function clientEncoding(Connection $linkIdentifier = null) |
57
|
|
|
{ |
58
|
|
|
$connection = $this->manager->getOpenConnectionOrFail($linkIdentifier); |
59
|
|
|
|
60
|
|
|
return $connection->getCharset(); |
61
|
|
|
} |
62
|
|
|
|
63
|
|
|
public function close(Connection $linkIdentifier = null) |
64
|
|
|
{ |
65
|
|
|
return $this->manager->disconnect($linkIdentifier); |
66
|
|
|
} |
67
|
|
|
|
68
|
|
|
public function connect($server = null, $username = null, $password = null, $newLink = false, $clientFlags = 0) |
69
|
|
|
{ |
70
|
|
|
if ($server === null) $server = ini_get("mysql.default_host"); |
71
|
|
|
if ($username === null) $username = ini_get("mysql.default_user"); |
72
|
|
|
if ($password === null) $password = ini_get("mysql.default_password"); |
73
|
|
|
|
74
|
|
|
$options = $this->parseClientFlags($clientFlags); |
75
|
|
|
|
76
|
|
|
return $this->manager->connect("mysql:host={$server};", $username, $password, $options, $newLink); |
77
|
|
|
} |
78
|
|
|
|
79
|
|
|
protected function parseClientFlags($clientFlags) |
80
|
|
|
{ |
81
|
|
|
$options = []; |
82
|
|
|
|
83
|
|
|
if ($clientFlags & static::CLIENT_COMPRESS) { |
84
|
|
|
$options[PDO::MYSQL_ATTR_COMPRESS] = 1; |
85
|
|
|
} |
86
|
|
|
|
87
|
|
|
if ($clientFlags & static::CLIENT_IGNORE_SPACE) { |
88
|
|
|
$options[PDO::MYSQL_ATTR_IGNORE_SPACE] = 1; |
89
|
|
|
} |
90
|
|
|
|
91
|
|
|
if ($clientFlags & static::CLIENT_SSL) { |
92
|
|
|
throw new NotSupportedException("SSL is not supported. You must create the PDO instance manually."); |
93
|
|
|
} |
94
|
|
|
|
95
|
|
|
if ($clientFlags & static::CLIENT_INTERACTIVE) { |
96
|
|
|
throw new NotSupportedException("Interactive client is not supported by PDO."); |
97
|
|
|
} |
98
|
|
|
|
99
|
|
|
return $options; |
100
|
|
|
} |
101
|
|
|
|
102
|
|
|
public function createDb($databaseName, Connection $linkIdentifier = null) |
|
|
|
|
103
|
|
|
{ |
104
|
|
|
$connection = $this->manager->getOpenConnectionOrFail($linkIdentifier); |
105
|
|
|
|
106
|
|
|
return $connection->parametrizedQuery( |
107
|
|
|
"CREATE DATABASE :databaseName", |
108
|
|
|
[':databaseName' => $databaseName] |
109
|
|
|
); |
110
|
|
|
} |
111
|
|
|
|
112
|
|
|
public function dataSeek() |
113
|
|
|
{ |
114
|
|
|
throw new NotSupportedException("The mysql_data_seek function is not supported. You must refactor your code."); |
115
|
|
|
} |
116
|
|
|
|
117
|
|
|
public function dbName() |
118
|
|
|
{ |
119
|
|
|
// @todo |
120
|
|
|
} |
121
|
|
|
|
122
|
|
|
public function dbQuery($database, $query, Connection $linkIdentifier = null) |
123
|
|
|
{ |
124
|
|
|
$connection = $this->manager->getOpenConnectionOrFail($linkIdentifier); |
125
|
|
|
$connection->useDatabase($database); |
126
|
|
|
|
127
|
|
|
return $connection->query($query); |
128
|
|
|
} |
129
|
|
|
|
130
|
|
|
public function dropDb() |
131
|
|
|
{ |
132
|
|
|
// @todo |
133
|
|
|
} |
134
|
|
|
|
135
|
|
|
/** |
136
|
|
|
* Return the last error number. A value of 0 means no errors. |
137
|
|
|
* |
138
|
|
|
* @param Connection|null $linkIdentifier |
139
|
|
|
* @return int |
140
|
|
|
*/ |
141
|
|
|
public function errno(Connection $linkIdentifier = null) |
142
|
|
|
{ |
143
|
|
|
$connection = $this->manager->getOpenConnectionOrFail($linkIdentifier); |
144
|
|
|
|
145
|
|
|
return (int) $connection->getErrorInfo()[1]; |
146
|
|
|
} |
147
|
|
|
|
148
|
|
|
/** |
149
|
|
|
* Return the last error text. |
150
|
|
|
* |
151
|
|
|
* @param Connection|null $linkIdentifier |
152
|
|
|
* @return string |
153
|
|
|
*/ |
154
|
|
|
public function error(Connection $linkIdentifier = null) |
155
|
|
|
{ |
156
|
|
|
$connection = $this->manager->getOpenConnectionOrFail($linkIdentifier); |
157
|
|
|
|
158
|
|
|
return $connection->getErrorInfo()[2]; |
159
|
|
|
} |
160
|
|
|
|
161
|
|
|
public function escapeString($unescapedString) |
162
|
|
|
{ |
163
|
|
|
return $this->realEscapeString($unescapedString); |
164
|
|
|
} |
165
|
|
|
|
166
|
|
|
/** |
167
|
|
|
* Fetch the next row from the result as an array. |
168
|
|
|
* |
169
|
|
|
* @param Result $result |
170
|
|
|
* @param int $resultType |
171
|
|
|
* @return bool|array |
172
|
|
|
*/ |
173
|
|
|
public function fetchArray(Result $result, $resultType = Result::FETCH_BOTH) |
174
|
|
|
{ |
175
|
|
|
return $result->fetch($resultType); |
176
|
|
|
} |
177
|
|
|
|
178
|
|
|
/** |
179
|
|
|
* Fetch the next row as an associative array. |
180
|
|
|
* |
181
|
|
|
* @param Result $result |
182
|
|
|
* @return bool|array |
183
|
|
|
*/ |
184
|
|
|
public function fetchAssoc(Result $result) |
185
|
|
|
{ |
186
|
|
|
return $this->fetchArray($result, Result::FETCH_ASSOC); |
187
|
|
|
} |
188
|
|
|
|
189
|
|
|
/** |
190
|
|
|
* Fetch the metadata of a column. |
191
|
|
|
* USE WITH CARE! Accuracy of results is not guaranteed. |
192
|
|
|
* |
193
|
|
|
* @param Result $result |
194
|
|
|
* @param int $fieldOffset |
195
|
|
|
* @return bool|object |
196
|
|
|
* @deprecated |
197
|
|
|
*/ |
198
|
|
|
public function fetchField(Result $result, $fieldOffset = 0) |
199
|
|
|
{ |
200
|
|
|
$meta = $result->getColumnMeta($fieldOffset); |
201
|
|
|
|
202
|
|
|
if ($meta === false) { |
203
|
|
|
return false; |
204
|
|
|
} |
205
|
|
|
|
206
|
|
|
$meta = (object) $meta; |
207
|
|
|
|
208
|
|
|
foreach ($meta->flags as $flag) { |
209
|
|
|
$meta->{$flag} = 1; |
210
|
|
|
} |
211
|
|
|
|
212
|
|
|
return $meta; |
213
|
|
|
} |
214
|
|
|
|
215
|
|
|
public function fetchLengths(Result $result) |
216
|
|
|
{ |
217
|
|
|
if (!is_array($result->getLastFetch())) { |
218
|
|
|
return false; |
219
|
|
|
} |
220
|
|
|
|
221
|
|
|
return array_values(array_map('strlen', $result->getLastFetch())); |
222
|
|
|
} |
223
|
|
|
|
224
|
|
|
public function fetchObject(Result $result, $className = 'stdClass', array $params = []) |
225
|
|
|
{ |
226
|
|
|
return $result->fetchObject($className, $params); |
227
|
|
|
} |
228
|
|
|
|
229
|
|
|
public function fetchRow(Result $result) |
230
|
|
|
{ |
231
|
|
|
return $result->fetch(Result::FETCH_NUM); |
232
|
|
|
} |
233
|
|
|
|
234
|
|
|
public function fieldfFlags() |
235
|
|
|
{ |
236
|
|
|
// @todo |
237
|
|
|
} |
238
|
|
|
|
239
|
|
|
public function fieldLen() |
240
|
|
|
{ |
241
|
|
|
// @todo |
242
|
|
|
} |
243
|
|
|
|
244
|
|
|
public function fieldName() |
245
|
|
|
{ |
246
|
|
|
// @todo |
247
|
|
|
} |
248
|
|
|
|
249
|
|
|
public function fieldSeek() |
250
|
|
|
{ |
251
|
|
|
// @todo |
252
|
|
|
} |
253
|
|
|
|
254
|
|
|
public function fieldTable() |
255
|
|
|
{ |
256
|
|
|
// @todo |
257
|
|
|
} |
258
|
|
|
|
259
|
|
|
public function fieldType() |
260
|
|
|
{ |
261
|
|
|
// @todo |
262
|
|
|
} |
263
|
|
|
|
264
|
|
|
public function freeResult() |
265
|
|
|
{ |
266
|
|
|
// @todo |
267
|
|
|
} |
268
|
|
|
|
269
|
|
|
public function getClientInfo() |
270
|
|
|
{ |
271
|
|
|
// @todo |
272
|
|
|
} |
273
|
|
|
|
274
|
|
|
public function getHostInfo() |
275
|
|
|
{ |
276
|
|
|
// @todo |
277
|
|
|
} |
278
|
|
|
|
279
|
|
|
public function getProtoInfo() |
280
|
|
|
{ |
281
|
|
|
// @todo |
282
|
|
|
} |
283
|
|
|
|
284
|
|
|
public function getServerInfo(Connection $linkIdentifier = null) |
285
|
|
|
{ |
286
|
|
|
$connection = $this->manager->getOpenConnectionOrFail($linkIdentifier); |
287
|
|
|
|
288
|
|
|
return $connection->getAttribute(PDO::ATTR_SERVER_VERSION); |
289
|
|
|
} |
290
|
|
|
|
291
|
|
|
public function info() |
292
|
|
|
{ |
293
|
|
|
// @todo |
294
|
|
|
} |
295
|
|
|
|
296
|
|
|
public function insertId(Connection $linkIdentifier = null) |
297
|
|
|
{ |
298
|
|
|
$connection = $this->manager->getOpenConnectionOrFail($linkIdentifier); |
299
|
|
|
|
300
|
|
|
return (int) $connection->getLastInsertId(); |
301
|
|
|
} |
302
|
|
|
|
303
|
|
|
public function listDbs() |
304
|
|
|
{ |
305
|
|
|
// @todo |
306
|
|
|
} |
307
|
|
|
|
308
|
|
|
public function listFields() |
309
|
|
|
{ |
310
|
|
|
// @todo |
311
|
|
|
} |
312
|
|
|
|
313
|
|
|
public function listProcesses() |
314
|
|
|
{ |
315
|
|
|
// @todo |
316
|
|
|
} |
317
|
|
|
|
318
|
|
|
public function listTables($database, Connection $linkIdentifier = null) |
|
|
|
|
319
|
|
|
{ |
320
|
|
|
$connection = $this->manager->getOpenConnectionOrFail($linkIdentifier); |
321
|
|
|
|
322
|
|
|
return $connection->parametrizedQuery( |
323
|
|
|
"SHOW TABLES FROM :database", |
324
|
|
|
[':database' => $database] |
325
|
|
|
); |
326
|
|
|
} |
327
|
|
|
|
328
|
|
|
public function numFields(Result $result) |
329
|
|
|
{ |
330
|
|
|
return $result->getColumnCount(); |
331
|
|
|
} |
332
|
|
|
|
333
|
|
|
public function numRows(Result $result) |
334
|
|
|
{ |
335
|
|
|
$query = $result->getStatement()->queryString; |
336
|
|
|
$matches = 0; |
337
|
|
|
$count = preg_replace("~SELECT (.+) FROM~", "SELECT COUNT(*) FROM", $query, -1, $matches); |
338
|
|
|
|
339
|
|
|
if ($matches === 0) { |
340
|
|
|
return 0; |
341
|
|
|
} |
342
|
|
|
|
343
|
|
|
$countResult = $result->getConnection()->query($count); |
344
|
|
|
|
345
|
|
|
return (int) $countResult->fetch()[0]; |
346
|
|
|
} |
347
|
|
|
|
348
|
|
|
public function pconnect() |
349
|
|
|
{ |
350
|
|
|
// @todo |
351
|
|
|
} |
352
|
|
|
|
353
|
|
|
public function ping() |
354
|
|
|
{ |
355
|
|
|
// @todo |
356
|
|
|
} |
357
|
|
|
|
358
|
|
|
public function query($query, Connection $linkIdentifier = null) |
359
|
|
|
{ |
360
|
|
|
$connection = $this->manager->getOpenConnectionOrFail($linkIdentifier); |
361
|
|
|
|
362
|
|
|
try { |
363
|
|
|
$result = $connection->query($query); |
364
|
|
|
} catch (QueryException $e) { |
365
|
|
|
return false; |
366
|
|
|
} |
367
|
|
|
|
368
|
|
|
return $result; |
369
|
|
|
} |
370
|
|
|
|
371
|
|
|
public function realEscapeString($unescapedString, Connection $linkIdentifier = null) |
372
|
|
|
{ |
373
|
|
|
$connection = $this->manager->getOpenConnectionOrFail($linkIdentifier); |
374
|
|
|
|
375
|
|
|
$escaped = $connection->quote($unescapedString); |
376
|
|
|
// Hack! |
377
|
|
|
if ($escaped[0] === "'" && $escaped[strlen($escaped)-1] === "'") { |
378
|
|
|
return substr($escaped, 1, -1); |
379
|
|
|
} |
380
|
|
|
|
381
|
|
|
throw new \Exception("Cannot escape string"); |
382
|
|
|
} |
383
|
|
|
|
384
|
|
|
public function result(Result $result, $row, $field = 0) |
385
|
|
|
{ |
386
|
|
|
$row = $result->fetch(Result::FETCH_BOTH, \PDO::FETCH_ORI_ABS, $row); |
387
|
|
|
|
388
|
|
|
return $row[$field]; |
389
|
|
|
} |
390
|
|
|
|
391
|
|
|
public function selectDb($databaseName, Connection $linkIdentifier = null) |
392
|
|
|
{ |
393
|
|
|
$connection = $this->manager->getOpenConnectionOrFail($linkIdentifier); |
394
|
|
|
|
395
|
|
|
return (bool) $connection->useDatabase($databaseName); |
396
|
|
|
} |
397
|
|
|
|
398
|
|
|
public function setCharset() |
399
|
|
|
{ |
400
|
|
|
// @todo |
401
|
|
|
} |
402
|
|
|
|
403
|
|
|
public function stat() |
404
|
|
|
{ |
405
|
|
|
// @todo |
406
|
|
|
} |
407
|
|
|
|
408
|
|
|
public function tablename() |
409
|
|
|
{ |
410
|
|
|
// @todo |
411
|
|
|
} |
412
|
|
|
|
413
|
|
|
public function threadId() |
414
|
|
|
{ |
415
|
|
|
// @todo |
416
|
|
|
} |
417
|
|
|
|
418
|
|
|
public function unbufferedQuery() |
419
|
|
|
{ |
420
|
|
|
// @todo |
421
|
|
|
} |
422
|
|
|
} |
423
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.