GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.

Connection::platformExecuteHandler()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 10
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 4
c 2
b 0
f 0
dl 0
loc 10
rs 10
cc 2
nc 2
nop 1
1
<?php
2
/**
3
 * This file is part of the O2System Framework package.
4
 *
5
 * For the full copyright and license information, please view the LICENSE
6
 * file that was distributed with this source code.
7
 *
8
 * @author         Steeve Andrian Salim
9
 * @copyright      Copyright (c) Steeve Andrian Salim
10
 */
11
12
// ------------------------------------------------------------------------
13
14
namespace O2System\Database\Sql\Drivers\MySql;
15
16
// ------------------------------------------------------------------------
17
18
use O2System\Database\DataStructures\Config;
19
use O2System\Database\Sql\Abstracts\AbstractConnection;
20
use O2System\Database\Sql\DataStructures\Query;
21
use O2System\Spl\DataStructures\SplArrayObject;
22
use O2System\Spl\Exceptions\RuntimeException;
23
24
/**
25
 * Class Connection
26
 *
27
 * @package O2System\Database\Sql\Drivers\MySql
28
 */
29
class Connection extends AbstractConnection
30
{
31
    /**
32
     * Connection::$isDeleteHack
33
     *
34
     * DELETE hack flag
35
     *
36
     * Whether to use the MySql "delete hack" which allows the number
37
     * of affected rows to be shown. Uses a preg_replace when enabled,
38
     * adding a bit more processing to all queries.
39
     *
40
     * @var    bool
41
     */
42
    public $isDeleteHack = true;
43
44
    /**
45
     * Connection::$platform
46
     *
47
     * Database driver platform name.
48
     *
49
     * @var string
50
     */
51
    protected $platform = 'MySQL';
52
53
    /**
54
     * Connection::$config
55
     *
56
     * Connection configurations.
57
     *
58
     * @var array
59
     */
60
    protected $config
61
        = [
62
            'escapeCharacter'     => '`',
63
            'reservedIdentifiers' => ['*'],
64
            'likeEscapeStatement' => ' ESCAPE \'%s\' ',
65
            'likeEscapeCharacter' => '!',
66
        ];
67
68
    /**
69
     * Connection::$handle
70
     *
71
     * MySqli Connection Instance.
72
     *
73
     * @var \mysqli
74
     */
75
    protected $handle;
76
77
    // ------------------------------------------------------------------------
78
79
    /**
80
     * Connection::isSupported
81
     *
82
     * Check if the platform is supported.
83
     *
84
     * @return bool
85
     */
86
    public function isSupported()
87
    {
88
        return extension_loaded('mysqli');
89
    }
90
91
    // ------------------------------------------------------------------------
92
93
    /**
94
     * Connection::setDatabase
95
     *
96
     * Set a specific database table to use.
97
     *
98
     * @param string $database Database name.
99
     *
100
     * @return static
101
     */
102
    public function setDatabase($database)
103
    {
104
        $database = empty($database)
105
            ? $this->database
106
            : $database;
107
108
        if ($this->handle->select_db($database)) {
109
            $this->database = $database;
110
        }
111
112
        return $this;
113
    }
114
115
    // ------------------------------------------------------------------------
116
117
    /**
118
     * Connection::getDatabases
119
     *
120
     * Get list of current connection databases.
121
     *
122
     * @return array Returns an array.
123
     * @throws \O2System\Spl\Exceptions\RuntimeException
124
     * @throws \Psr\Cache\InvalidArgumentException
125
     */
126
    public function getDatabases()
127
    {
128
        if (empty($this->queriesResultCache[ 'databaseNames' ])) {
129
            $result = $this->query('SHOW DATABASES');
130
131
            if ($result->count()) {
132
                foreach ($result as $row) {
133
134
                    if ( ! isset($key)) {
135
                        if (isset($row[ 'database' ])) {
136
                            $key = 'database';
137
                        } elseif (isset($row[ 'Database' ])) {
138
                            $key = 'Database';
139
                        } elseif (isset($row[ 'DATABASE' ])) {
140
                            $key = 'DATABASE';
141
                        } else {
142
                            /* We have no other choice but to just get the first element's key.
143
                             * Due to array_shift() accepting its argument by reference, if
144
                             * E_STRICT is on, this would trigger a warning. So we'll have to
145
                             * assign it first.
146
                             */
147
                            $key = array_keys($row);
148
                            $key = array_shift($key);
149
                        }
150
                    }
151
152
                    $this->queriesResultCache[ 'databaseNames' ][] = $row->offsetGet($key);
153
                }
154
            }
155
        }
156
157
        return $this->queriesResultCache[ 'databaseNames' ];
158
    }
159
160
    // ------------------------------------------------------------------------
161
162
    /**
163
     * Connection::getTables
164
     *
165
     * Get list of current database tables.
166
     *
167
     * @param bool $prefixLimit If sets TRUE the query will be limit using database table prefix.
168
     *
169
     * @return array Returns an array
170
     * @throws \O2System\Spl\Exceptions\RuntimeException
171
     * @throws \Psr\Cache\InvalidArgumentException
172
     */
173
    public function getTables($prefixLimit = false)
174
    {
175
        if (empty($this->queriesResultCache[ 'tableNames' ])) {
176
177
            $sqlStatement = 'SHOW TABLES FROM ' . $this->escapeIdentifiers($this->config[ 'database' ]);
0 ignored issues
show
Bug introduced by
Are you sure $this->escapeIdentifiers...is->config['database']) of type array|mixed can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

177
            $sqlStatement = 'SHOW TABLES FROM ' . /** @scrutinizer ignore-type */ $this->escapeIdentifiers($this->config[ 'database' ]);
Loading history...
178
179
            if ($prefixLimit !== false && $this->config[ 'tablePrefix' ] !== '') {
180
                $sqlStatement .= " LIKE '" . $this->escapeLikeString($this->config[ 'tablePrefix' ]) . "%'";
0 ignored issues
show
Bug introduced by
Are you sure $this->escapeLikeString(...>config['tablePrefix']) of type array|string can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

180
                $sqlStatement .= " LIKE '" . /** @scrutinizer ignore-type */ $this->escapeLikeString($this->config[ 'tablePrefix' ]) . "%'";
Loading history...
181
            }
182
183
            $result = $this->query($sqlStatement);
184
185
            if ($result->count()) {
186
                foreach ($result as $row) {
187
                    // Do we know from which column to get the table name?
188
                    if ( ! isset($key)) {
189
                        if (isset($row[ 'table_name' ])) {
190
                            $key = 'table_name';
191
                        } elseif (isset($row[ 'TABLE_NAME' ])) {
192
                            $key = 'TABLE_NAME';
193
                        } else {
194
                            /* We have no other choice but to just get the first element's key.
195
                             * Due to array_shift() accepting its argument by reference, if
196
                             * E_STRICT is on, this would trigger a warning. So we'll have to
197
                             * assign it first.
198
                             */
199
                            $key = array_keys($row->getArrayCopy());
200
                            $key = array_shift($key);
201
                        }
202
                    }
203
204
                    $this->queriesResultCache[ 'tableNames' ][] = $row->offsetGet($key);
205
                }
206
            }
207
        }
208
209
        return $this->queriesResultCache[ 'tableNames' ];
210
    }
211
212
    // ------------------------------------------------------------------------
213
214
    /**
215
     * Connection::getColumns
216
     *
217
     * @param string $table The database table name.
218
     *
219
     * @return array
220
     * @throws \O2System\Spl\Exceptions\RuntimeException
221
     * @throws \Psr\Cache\InvalidArgumentException
222
     */
223
    public function getColumns($table)
224
    {
225
        $table = $this->prefixTable($table);
226
227
        if (empty($this->queriesResultCache[ 'tableColumns' ][ $table ])) {
228
            $result = $this->query('SHOW COLUMNS FROM ' . $this->protectIdentifiers($table, true, null, false));
229
230
            if ($result->count()) {
231
                foreach ($result as $row) {
232
                    // Do we know from where to get the column's name?
233
                    if ( ! isset($key)) {
234
                        if (isset($row[ 'column_name' ])) {
235
                            $key = 'column_name';
236
                        } elseif (isset($row[ 'COLUMN_NAME' ])) {
237
                            $key = 'COLUMN_NAME';
238
                        } else {
239
                            /* We have no other choice but to just get the first element's key.
240
                             * Due to array_shift() accepting its argument by reference, if
241
                             * E_STRICT is on, this would trigger a warning. So we'll have to
242
                             * assign it first.
243
                             */
244
                            $key = array_keys($row->getArrayCopy());
245
                            $key = array_shift($key);
246
                        }
247
                    }
248
249
                    $this->queriesResultCache[ 'tableColumns' ][ $table ][ $row->offsetGet($key) ] = $row;
250
                }
251
            }
252
        }
253
254
        return $this->queriesResultCache[ 'tableColumns' ][ $table ];
255
    }
256
257
    // ------------------------------------------------------------------------
258
259
    /**
260
     * Connection::reconnect
261
     *
262
     * Keep or establish the connection if no queries have been sent for
263
     * a length of time exceeding the server's idle timeout.
264
     *
265
     * @return void
266
     */
267
    public function reconnect()
268
    {
269
        if ($this->handle !== false && $this->handle->ping() === false) {
270
            $this->handle = false;
0 ignored issues
show
Documentation Bug introduced by
It seems like false of type false is incompatible with the declared type mysqli of property $handle.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
271
        }
272
    }
273
274
    // ------------------------------------------------------------------------
275
276
    /**
277
     * Connection::getAffectedRows
278
     *
279
     * Get the total number of affected rows from the last query execution.
280
     *
281
     * @return int  Returns total number of affected rows
282
     */
283
    public function getAffectedRows()
284
    {
285
        return $this->handle->affected_rows;
286
    }
287
288
    //--------------------------------------------------------------------
289
290
    /**
291
     * Connection::getLastInsertId
292
     *
293
     * Get last insert id from the last insert query execution.
294
     *
295
     * @return int  Returns total number of affected rows
296
     */
297
    public function getLastInsertId()
298
    {
299
        return $this->handle->insert_id;
300
    }
301
302
    // ------------------------------------------------------------------------
303
304
    /**
305
     * Connection::getLastQuery
306
     *
307
     * Returns the last query's statement object.
308
     *
309
     * @return string
310
     */
311
    public function getLastQuery()
312
    {
313
        $last = end($this->queriesCache);
314
315
        if ($last->getSqlStatement() === 'SELECT FOUND_ROWS() AS numrows;') {
316
            $last = prev($this->queriesCache);
317
        }
318
319
        return $last;
320
    }
321
322
    //--------------------------------------------------------------------
323
324
    /**
325
     * Connection::platformGetPlatformVersionHandler
326
     *
327
     * Platform getting version handler.
328
     *
329
     * @return SplArrayObject
330
     */
331
    protected function platformGetPlatformInfoHandler()
332
    {
333
        $server[ 'version' ][ 'string' ] = $this->handle->server_info;
0 ignored issues
show
Comprehensibility Best Practice introduced by
$server was never initialized. Although not strictly required by PHP, it is generally a good practice to add $server = array(); before regardless.
Loading history...
334
        $server[ 'version' ][ 'number' ] = $this->handle->server_version;
335
        $server[ 'stats' ] = $this->handle->get_connection_stats();
336
337
        $client[ 'version' ][ 'string' ] = $this->handle->client_info;
0 ignored issues
show
Comprehensibility Best Practice introduced by
$client was never initialized. Although not strictly required by PHP, it is generally a good practice to add $client = array(); before regardless.
Loading history...
338
        $client[ 'version' ][ 'number' ] = $this->handle->client_version;
339
        $client[ 'stats' ] = mysqli_get_client_stats();
340
341
        return new SplArrayObject([
342
            'name'     => $this->getPlatform(),
343
            'host'     => $this->handle->host_info,
344
            'state'    => $this->handle->sqlstate,
345
            'protocol' => $this->handle->protocol_version,
346
            'server'   => $server,
347
            'client'   => $client,
348
        ]);
349
    }
350
351
    // ------------------------------------------------------------------------
352
353
    /**
354
     * Connection::platformConnectHandler
355
     *
356
     * Establish the connection.
357
     *
358
     * @param Config $config
359
     *
360
     * @return void
361
     * @throws RuntimeException
362
     */
363
    protected function platformConnectHandler(Config $config)
364
    {
365
        // Do we have a socket path?
366
        if ($config->hostname[ 0 ] === '/') {
0 ignored issues
show
Bug Best Practice introduced by
The property hostname does not exist on O2System\Database\DataStructures\Config. Since you implemented __get, consider adding a @property annotation.
Loading history...
367
            $hostname = null;
368
            $port = null;
369
            $socket = $config->hostname;
370
        } else {
371
            $hostname = ($config->persistent === true)
0 ignored issues
show
Bug Best Practice introduced by
The property persistent does not exist on O2System\Database\DataStructures\Config. Since you implemented __get, consider adding a @property annotation.
Loading history...
372
                ? 'p:' . $config->hostname
373
                : $config->hostname;
374
            $port = empty($config->port)
0 ignored issues
show
Bug Best Practice introduced by
The property port does not exist on O2System\Database\DataStructures\Config. Since you implemented __get, consider adding a @property annotation.
Loading history...
375
                ? null
376
                : $config->port;
377
            $socket = null;
378
        }
379
380
        $flags = ($config->compress === true)
0 ignored issues
show
Bug Best Practice introduced by
The property compress does not exist on O2System\Database\DataStructures\Config. Since you implemented __get, consider adding a @property annotation.
Loading history...
381
            ? MYSQLI_CLIENT_COMPRESS
382
            : 0;
383
        $this->handle = mysqli_init();
384
        //$this->handle->autocommit( ( $this->transactionEnable ? true : false ) );
385
386
        $this->handle->options(MYSQLI_OPT_CONNECT_TIMEOUT, 10);
387
388
        if (isset($config->strictOn)) {
0 ignored issues
show
Bug Best Practice introduced by
The property strictOn does not exist on O2System\Database\DataStructures\Config. Since you implemented __get, consider adding a @property annotation.
Loading history...
389
            if ($config->strictOn) {
390
                $this->handle->options(
391
                    MYSQLI_INIT_COMMAND,
392
                    'SET SESSION Sql_mode = CONCAT(@@Sql_mode, ",", "STRICT_ALL_TABLES")'
393
                );
394
            } else {
395
                $this->handle->options(
396
                    MYSQLI_INIT_COMMAND,
397
                    'SET SESSION Sql_mode =
398
					REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(
399
					@@Sql_mode,
400
					"STRICT_ALL_TABLES,", ""),
401
					",STRICT_ALL_TABLES", ""),
402
					"STRICT_ALL_TABLES", ""),
403
					"STRICT_TRANS_TABLES,", ""),
404
					",STRICT_TRANS_TABLES", ""),
405
					"STRICT_TRANS_TABLES", "")'
406
                );
407
            }
408
        }
409
410
        if (is_array($config->encrypt)) {
0 ignored issues
show
Bug Best Practice introduced by
The property encrypt does not exist on O2System\Database\DataStructures\Config. Since you implemented __get, consider adding a @property annotation.
Loading history...
411
            $ssl = [];
412
            empty($config->encrypt[ 'ssl_key' ]) OR $ssl[ 'key' ] = $config->encrypt[ 'ssl_key' ];
413
            empty($config->encrypt[ 'ssl_cert' ]) OR $ssl[ 'cert' ] = $config->encrypt[ 'ssl_cert' ];
414
            empty($config->encrypt[ 'ssl_ca' ]) OR $ssl[ 'ca' ] = $config->encrypt[ 'ssl_ca' ];
415
            empty($config->encrypt[ 'ssl_capath' ]) OR $ssl[ 'capath' ] = $config->encrypt[ 'ssl_capath' ];
416
            empty($config->encrypt[ 'ssl_cipher' ]) OR $ssl[ 'cipher' ] = $config->encrypt[ 'ssl_cipher' ];
417
418
            if ( ! empty($ssl)) {
419
                if (isset($config->encrypt[ 'ssl_verify' ])) {
420
                    if ($config->encrypt[ 'ssl_verify' ]) {
421
                        defined('MYSQLI_OPT_SSL_VERIFY_SERVER_CERT')
422
                        && $this->handle->options(MYSQLI_OPT_SSL_VERIFY_SERVER_CERT, true);
423
                    }
424
                    // Apparently (when it exists), setting MYSQLI_OPT_SSL_VERIFY_SERVER_CERT
425
                    // to FALSE didn't do anything, so PHP 5.6.16 introduced yet another
426
                    // constant ...
427
                    //
428
                    // https://secure.php.net/ChangeLog-5.php#5.6.16
429
                    // https://bugs.php.net/bug.php?id=68344
430
                    elseif (defined('MYSQLI_CLIENT_SSL_DONT_VERIFY_SERVER_CERT')) {
431
                        $this->handle->options(MYSQLI_CLIENT_SSL_DONT_VERIFY_SERVER_CERT, true);
432
                    }
433
                }
434
435
                $flags |= MYSQLI_CLIENT_SSL;
436
                $this->handle->ssl_set(
437
                    isset($ssl[ 'key' ])
438
                        ? $ssl[ 'key' ]
439
                        : null,
440
                    isset($ssl[ 'cert' ])
441
                        ? $ssl[ 'cert' ]
442
                        : null,
443
                    isset($ssl[ 'ca' ])
444
                        ? $ssl[ 'ca' ]
445
                        : null,
446
                    isset($ssl[ 'capath' ])
447
                        ? $ssl[ 'capath' ]
448
                        : null,
449
                    isset($ssl[ 'cipher' ])
450
                        ? $ssl[ 'cipher' ]
451
                        : null
452
                );
453
            }
454
        }
455
456
        if ($this->handle->real_connect(
457
            $hostname,
458
            $config->username,
0 ignored issues
show
Bug Best Practice introduced by
The property username does not exist on O2System\Database\DataStructures\Config. Since you implemented __get, consider adding a @property annotation.
Loading history...
459
            $config->password,
0 ignored issues
show
Bug Best Practice introduced by
The property password does not exist on O2System\Database\DataStructures\Config. Since you implemented __get, consider adding a @property annotation.
Loading history...
460
            $config->database,
0 ignored issues
show
Bug Best Practice introduced by
The property database does not exist on O2System\Database\DataStructures\Config. Since you implemented __get, consider adding a @property annotation.
Loading history...
461
            $port,
462
            $socket,
463
            $flags
464
        )
465
        ) {
466
            // Prior to version 5.7.3, MySql silently downgrades to an unencrypted connection if SSL setup fails
467
            if (
468
                ($flags & MYSQLI_CLIENT_SSL)
469
                AND version_compare($this->handle->client_info, '5.7.3', '<=')
470
                AND empty($this->handle->query("SHOW STATUS LIKE 'ssl_cipher'")
471
                    ->fetch_object()->Value)
472
            ) {
473
                $this->handle->close();
474
                // 'MySqli was configured for an SSL connection, but got an unencrypted connection instead!';
475
                logger()->error('E_DB_CONNECTION_SSL', [$this->platform]);
476
477
                if ($config->debugEnable) {
0 ignored issues
show
Bug Best Practice introduced by
The property debugEnable does not exist on O2System\Database\DataStructures\Config. Since you implemented __get, consider adding a @property annotation.
Loading history...
478
                    throw new RuntimeException('E_DB_CONNECTION_SSL');
479
                }
480
481
                return;
482
            }
483
484
            if ( ! $this->handle->set_charset($config->charset)) {
0 ignored issues
show
Bug Best Practice introduced by
The property charset does not exist on O2System\Database\DataStructures\Config. Since you implemented __get, consider adding a @property annotation.
Loading history...
485
                // "Database: Unable to set the configured connection charset ('{$this->charset}')."
486
                logger()->error('E_DB_CONNECTION_CHARSET', [$config->charset]);
487
                $this->handle->close();
488
489
                if ($config->debugEnable) {
490
                    // 'Unable to set client connection character set: ' . $this->charset
491
                    throw new RuntimeException('E_DB_CONNECTION_CHARSET', [$config->charset]);
0 ignored issues
show
Bug introduced by
array($config->charset) of type array<integer,mixed> is incompatible with the type integer expected by parameter $code of O2System\Spl\Exceptions\...xception::__construct(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

491
                    throw new RuntimeException('E_DB_CONNECTION_CHARSET', /** @scrutinizer ignore-type */ [$config->charset]);
Loading history...
492
                }
493
            }
494
        }
495
    }
496
497
    // ------------------------------------------------------------------------
498
499
    /**
500
     * Connection::disconnectHandler
501
     *
502
     * Driver dependent way method for closing the connection.
503
     *
504
     * @return mixed
505
     */
506
    protected function platformDisconnectHandler()
507
    {
508
        $this->handle->close();
509
    }
510
511
    // ------------------------------------------------------------------------
512
513
    /**
514
     * Connection::executeHandler
515
     *
516
     * Driver dependent way method for execute the Sql statement.
517
     *
518
     * @param Query\Statement $statement Query object.
519
     *
520
     * @return bool
521
     */
522
    protected function platformExecuteHandler(Query\Statement &$statement)
523
    {
524
        if (false !== $this->handle->query($statement->getSqlFinalStatement())) {
525
            return true;
526
        }
527
528
        // Set query error information
529
        $statement->addError($this->handle->errno, $this->handle->error);
530
531
        return false;
532
533
    }
534
535
    // ------------------------------------------------------------------------
536
537
    /**
538
     * Connection::platformQueryHandler
539
     *
540
     * Driver dependent way method for execute the Sql statement.
541
     *
542
     * @param Query\Statement $statement Query object.
543
     *
544
     * @return array
545
     */
546
    protected function platformQueryHandler(Query\Statement &$statement)
547
    {
548
        $rows = [];
549
550
        if ($result = $this->handle->query($statement->getSqlFinalStatement())) {
551
            $rows = $result->fetch_all(MYSQLI_ASSOC);
552
        } else {
553
            $statement->addError($this->handle->errno, $this->handle->error);
554
        }
555
556
        return $rows;
557
    }
558
559
    //--------------------------------------------------------------------
560
561
    /**
562
     * Connection::platformTransactionBeginHandler
563
     *
564
     * Platform beginning a transaction handler.
565
     *
566
     * @return bool
567
     */
568
    protected function platformTransactionBeginHandler()
569
    {
570
        if ($this->transactionInProgress === false) {
571
            // Begin transaction using autocommit function set to false
572
            $this->handle->autocommit(false);
573
574
            // Flag for there is a transaction progress
575
            $this->transactionInProgress = true;
576
577
            // Flag for error checking
578
            $this->transactionStatus = true;
579
        }
580
581
582
        return $this->transactionInProgress;
583
    }
584
585
    // ------------------------------------------------------------------------
586
587
    /**
588
     * Connection::platformTransactionCommitHandler
589
     *
590
     * Platform committing a transaction handler.
591
     *
592
     * @return bool
593
     */
594
    protected function platformTransactionCommitHandler()
595
    {
596
        if ($this->transactionStatus === true) {
597
            $this->handle->commit();
598
            $this->handle->autocommit(true);
599
            $this->transactionInProgress = false;
600
601
            return true;
602
        }
603
604
        return false;
605
    }
606
607
    // ------------------------------------------------------------------------
608
609
    /**
610
     * Connection::platformTransactionRollBackHandler
611
     *
612
     * Platform rolling back a transaction handler.
613
     *
614
     * @return void
615
     */
616
    protected function platformTransactionRollBackHandler()
617
    {
618
        $this->handle->rollback();
619
        $this->transactionInProgress = false;
620
        $this->handle->autocommit(true);
621
    }
622
623
    // ------------------------------------------------------------------------
624
625
    /**
626
     * Connection::prepareSqlStatement
627
     *
628
     * Platform preparing a Sql statement.
629
     *
630
     * @param string $sqlStatement Sql Statement to be prepared.
631
     * @param array  $options      Preparing Sql statement options.
632
     *
633
     * @return string
634
     */
635
    protected function platformPrepareSqlStatement($sqlStatement, array $options = [])
636
    {
637
        // mysqli_affected_rows() returns 0 for "DELETE FROM TABLE" queries. This hack
638
        // modifies the query so that it a proper number of affected rows is returned.
639
        if ($this->isDeleteHack === true && preg_match('/^\s*DELETE\s+FROM\s+(\S+)\s*$/i', $sqlStatement)) {
640
            return trim($sqlStatement) . ' WHERE 1=1';
641
        }
642
643
        return $sqlStatement;
644
    }
645
646
    // ------------------------------------------------------------------------
647
648
    /**
649
     * Connection::platformEscapeStringHandler
650
     *
651
     * Platform escape string handler.
652
     *
653
     * @param string $string
654
     *
655
     * @return string
656
     */
657
    protected function platformEscapeStringHandler($string)
658
    {
659
        return $this->handle->real_escape_string($string);
660
    }
661
}
662