Completed
Pull Request — master (#39)
by Robbie
01:28
created

DebugBarDatabaseNewProxy::__construct()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 13
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 13
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 9
nc 2
nop 1
1
<?php
2
3
/**
4
 * A proxy database to log queries (compatible with 3.2+)
5
 *
6
 * @author Koala
7
 */
8
class DebugBarDatabaseNewProxy extends SS_Database
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
9
{
10
    /** @var MySQLDatabase */
11
    protected $realConn;
12
    protected $findSource;
13
14
    /** @var array */
15
    protected $queries;
16
    protected $connector;
17
    protected $schemaManager;
18
    protected $queryBuilder;
19
    protected $showQueries = false;
20
21
    /**
22
     * @param MySQLDatabase|array $realConn
23
     */
24
    public function __construct($realConn)
25
    {
26
        // Some service hooks pass $databaseConfig to constructor
27
        if (is_array($realConn)) {
28
            $realConn = DB::connect($realConn);
29
        }
30
        $this->realConn      = $realConn;
31
        $this->connector     = $realConn->getConnector();
32
        $this->schemaManager = $realConn->getSchemaManager();
33
        $this->queryBuilder  = $realConn->getQueryBuilder();
34
        $this->queries       = array();
35
        $this->findSource    = DebugBar::config()->find_source;
36
    }
37
38
    public function getShowQueries()
39
    {
40
        return $this->showQueries;
41
    }
42
43
    public function setShowQueries($showQueries)
44
    {
45
        $this->showQueries = $showQueries;
46
        return $this;
47
    }
48
49
    /**
50
     * Get the current connector
51
     *
52
     * @return DBConnector
53
     */
54
    public function getConnector()
55
    {
56
        return $this->realConn->getConnector();
57
    }
58
59
    /**
60
     * Injector injection point for connector dependency
61
     *
62
     * @param DBConnector $connector
63
     */
64
    public function setConnector(DBConnector $connector)
65
    {
66
        parent::setConnector($connector);
67
        $this->realConn->setConnector($connector);
68
    }
69
70
    /**
71
     * Returns the current schema manager
72
     *
73
     * @return DBSchemaManager
74
     */
75
    public function getSchemaManager()
76
    {
77
        return $this->realConn->getSchemaManager();
78
    }
79
80
    /**
81
     * Injector injection point for schema manager
82
     *
83
     * @param DBSchemaManager $schemaManager
84
     */
85
    public function setSchemaManager(DBSchemaManager $schemaManager)
86
    {
87
        parent::setSchemaManager($schemaManager);
88
        $this->realConn->setSchemaManager($schemaManager);
89
    }
90
91
    /**
92
     * Returns the current query builder
93
     *
94
     * @return DBQueryBuilder
95
     */
96
    public function getQueryBuilder()
97
    {
98
        return $this->realConn->getQueryBuilder();
99
    }
100
101
    /**
102
     * Injector injection point for schema manager
103
     *
104
     * @param DBQueryBuilder $queryBuilder
105
     */
106
    public function setQueryBuilder(DBQueryBuilder $queryBuilder)
107
    {
108
        parent::setQueryBuilder($queryBuilder);
109
        $this->realConn->setQueryBuilder($queryBuilder);
110
    }
111
112
    /**
113
     * Determines if the query should be previewed, and thus interrupted silently.
114
     * If so, this function also displays the query via the debuging system.
115
     * Subclasess should respect the results of this call for each query, and not
116
     * execute any queries that generate a true response.
117
     *
118
     * @param string $sql The query to be executed
119
     * @return boolean Flag indicating that the query was previewed
120
     */
121 View Code Duplication
    protected function previewWrite($sql)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
Coding Style introduced by
previewWrite uses the super-global variable $_REQUEST which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

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

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
122
    {
123
        // Only preview if previewWrite is set, we are in dev mode, and
124
        // the query is mutable
125
        if (isset($_REQUEST['previewwrite']) && Director::isDev() && $this->connector->isQueryMutable($sql)
126
        ) {
127
            // output preview message
128
            Debug::message("Will execute: $sql");
129
            return true;
130
        } else {
131
            return false;
132
        }
133
    }
134
135
    /**
136
     * Allows the display and benchmarking of queries as they are being run
137
     *
138
     * @param string $sql Query to run, and single parameter to callback
139
     * @param callable $callback Callback to execute code
140
     * @param array $parameters
141
     * @return mixed Result of query
142
     */
143
    protected function benchmarkQuery($sql, $callback, $parameters = array())
144
    {
145
        $starttime   = microtime(true);
146
        $startmemory = memory_get_usage(true);
147
148
        if (is_array($sql)) {
149
            $parameters = $sql[1];
150
            $sql        = $sql[0];
151
        }
152
153 View Code Duplication
        if ($this->showQueries && Director::isDev()) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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.

Loading history...
154
            $starttime = microtime(true);
155
            $result    = $callback($sql);
156
            $endtime   = round(microtime(true) - $starttime, 4);
157
158
            $formattedSql = JdornSqlFormatter::format($sql);
159
            $rows         = $result->numRecords();
160
            echo '<pre>The following query took <b>'.$endtime.'</b>s an returned <b>'.$rows."</b> row(s) \n";
161
            echo 'Triggered by: <i>'.$this->findSource().'</i></pre>';
162
            echo $formattedSql;
163
164
            $results = iterator_to_array($result);
165
            if ($rows > 0) {
166
                if ($rows == 1) {
167
                    dump($results[0]);
168
                } else {
169
                    $linearValues = count($results[0]);
170
                    if ($linearValues) {
171
                        dump(implode(
172
                            ',',
173
                            array_map(
174
                                function ($item) {
175
                                    return $item[key($item)];
176
                                },
177
                                $results
178
                            )
179
                        ));
180
                    } else {
181
                        if ($rows < 20) {
182
                            dump($results);
183
                        } else {
184
                            dump("Too many results to display");
185
                        }
186
                    }
187
                }
188
            }
189
            echo '<hr/>';
190
191
            $handle = $result;
192
            $handle->rewind(); // Rewind the results
193
        } else {
194
            /* @var $handle PDOQuery */
195
            $handle = $callback($sql);
196
        }
197
        $endtime   = microtime(true);
198
        $endmemory = memory_get_usage(true);
199
200
201
        $rawsql = $sql;
202
203
        $select = null;
0 ignored issues
show
Unused Code introduced by
$select is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
204
205
206
        // Prepared query are not so readable
207
        if (!empty($parameters)) {
208
            foreach ($parameters as $param) {
209
                $pos = strpos($sql, '?');
210
                if ($pos !== false) {
211
                    $param = '"'.$param.'"';
212
                    $sql   = substr_replace($sql, $param, $pos, 1);
213
                }
214
            }
215
        }
216
217
218
        // Sometimes, ugly spaces are there
219
        $sql = preg_replace('/[[:blank:]]+/', ' ', trim($sql));
220
221
        $shortsql = $sql;
222
223
        // Sometimes, the select statement can be very long and unreadable
224
        $matches = null;
225
        preg_match_all('/SELECT(.+?) FROM/is', $sql, $matches);
226
        $select  = empty($matches[1]) ? null : trim($matches[1][0]);
227 View Code Duplication
        if (strlen($select) > 100) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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.

Loading history...
228
            $shortsql = str_replace($select, '"ClickToShowFields"', $sql);
229
        } else {
230
            $select = null;
231
        }
232
233
        $this->queries[] = array(
234
            'raw_query' => $rawsql,
235
            'short_query' => $shortsql,
236
            'select' => $select,
237
            'query' => $sql,
238
            'start_time' => $starttime,
239
            'end_time' => $endtime,
240
            'duration' => $endtime - $starttime,
241
            'memory' => $endmemory - $startmemory,
242
            'rows' => $handle ? $handle->numRecords() : null,
243
            'success' => $handle ? true : false,
244
            'database' => $this->getSelectedDatabase(),
245
            'source' => $this->findSource ? $this->findSource() : null
246
        );
247
        return $handle;
248
    }
249
250 View Code Duplication
    protected function findSource()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
251
    {
252
        $traces = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS | DEBUG_BACKTRACE_PROVIDE_OBJECT);
253
254
        // Not relevant to determine source
255
        $internalClasses = array(
256
            'DB', 'SQLExpression', 'DataList', 'DataObject',
257
            'DataQuery', 'SQLSelect', 'SQLQuery', 'SS_Map', 'SS_ListDecorator', 'Object'
258
        );
259
260
        $viewerClasses = array(
261
            'SSViewer_DataPresenter', 'SSViewer_Scope', 'SSViewer',
262
            'ViewableData'
263
        );
264
265
        $sources = array();
266
        foreach ($traces as $trace) {
267
            $class    = isset($trace['class']) ? $trace['class'] : null;
268
            $line     = isset($trace['line']) ? $trace['line'] : null;
269
            $function = isset($trace['function']) ? $trace['function'] : null;
270
            $type     = isset($trace['type']) ? $trace['type'] : '::';
271
272
            /* @var $object SSViewer */
273
            $object = isset($trace['object']) ? $trace['object'] : null;
274
275
            if (!$class) {
276
                continue;
277
            }
278
            if ($function && $function == '{closure}') {
279
                continue;
280
            }
281
            if (strpos($class, 'DebugBar') === 0) {
282
                continue;
283
            }
284
            if (in_array($class, $internalClasses)) {
285
                continue;
286
            }
287
            if (in_array($class, $viewerClasses)) {
288
                if ($function == 'includeGeneratedTemplate') {
289
                    $templates = $object->templates();
290
291
                    $template = null;
292
                    if (isset($templates['main'])) {
293
                        $template = basename($templates['main']);
294
                    } else {
295
                        $keys = array_keys($templates);
296
                        $key  = reset($keys);
297
                        if (isset($templates[$key])) {
298
                            $template = $key.':'.basename($templates[$key]);
299
                        }
300
                    }
301
                    if ($template) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $template of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
302
                        $sources[] = $template;
303
                    }
304
                }
305
                continue;
306
            }
307
308
            $name = $class;
309
            if ($function) {
310
                $name .= $type.$function;
311
            }
312
            if ($line) {
313
                $name .= ':'.$line;
314
            }
315
316
            $sources[] = $name;
317
318
            if (count($sources) > 3) {
319
                break;
320
            }
321
322
323
            // We reached a Controller, exit loop
324
            if ($object && $object instanceof Controller) {
325
                break;
326
            }
327
        }
328
329
        if (empty($sources)) {
330
            return 'Undefined source';
331
        }
332
        return implode(' > ', $sources);
333
    }
334
335
    /**
336
     * Execute the given SQL query.
337
     *
338
     * @param string $sql The SQL query to execute
339
     * @param int $errorLevel The level of error reporting to enable for the query
340
     * @return SS_Query
341
     */
342 View Code Duplication
    public function query($sql, $errorLevel = E_USER_ERROR)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
343
    {
344
        // Check if we should only preview this query
345
        if ($this->previewWrite($sql)) {
346
            return;
347
        }
348
349
        if (!$this->connector) {
350
            $self = $this;
351
            return $this->benchmarkQuery(
352
                $sql,
353
                function ($sql) use ($self, $errorLevel) {
354
                    return $self->oldQuery($sql, $errorLevel);
355
                }
356
            );
357
        }
358
359
        // Benchmark query
360
        $connector = $this->connector;
361
        return $this->benchmarkQuery(
362
            $sql,
363
            function ($sql) use ($connector, $errorLevel) {
364
                return $connector->query($sql, $errorLevel);
365
            }
366
        );
367
    }
368
369
    public function oldQuery($sql, $errorLevel = E_USER_ERROR)
370
    {
371
        return $this->realConn->query($sql, $errorLevel);
372
    }
373
374
    /**
375
     * Execute the given SQL parameterised query with the specified arguments
376
     *
377
     * @param string $sql The SQL query to execute. The ? character will denote parameters.
378
     * @param array $parameters An ordered list of arguments.
379
     * @param int $errorLevel The level of error reporting to enable for the query
380
     * @return SS_Query
381
     */
382 View Code Duplication
    public function preparedQuery($sql, $parameters, $errorLevel = E_USER_ERROR)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
383
    {
384
        // Check if we should only preview this query
385
        if ($this->previewWrite($sql)) {
386
            return;
387
        }
388
389
        // Benchmark query
390
        $connector = $this->connector;
391
        return $this->benchmarkQuery(
392
            array($sql, $parameters),
0 ignored issues
show
Documentation introduced by
array($sql, $parameters) is of type array<integer,string|arr...:"string","1":"array"}>, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
393
            function ($sql) use ($connector, $parameters, $errorLevel) {
394
                return $connector->preparedQuery($sql, $parameters, $errorLevel);
395
            }
396
        );
397
    }
398
399
    /**
400
     * @return array
401
     */
402
    public function getQueries()
403
    {
404
        return $this->queries;
405
    }
406
407
    /**
408
     * @param string $name
409
     * @param array $arguments
410
     * @return mixed
411
     */
412
    public function __call($name, $arguments)
413
    {
414
        //return call_user_func_array([$this->realConn, __FUNCTION__],            func_get_args());
0 ignored issues
show
Unused Code Comprehensibility introduced by
69% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
415
        return call_user_func_array(array($this->realConn, $name), $arguments);
416
    }
417
418
    public function addslashes($val)
419
    {
420
        return call_user_func_array(
421
            array($this->realConn, __FUNCTION__),
422
            func_get_args()
423
        );
424
    }
425
426 View Code Duplication
    public function alterTable(
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
427
        $table,
428
        $newFields = null,
429
        $newIndexes = null,
430
        $alteredFields = null,
431
        $alteredIndexes = null,
432
        $alteredOptions = null,
433
        $advancedOptions = null
434
    ) {
435
        return call_user_func_array(
436
            array($this->realConn, __FUNCTION__),
437
            func_get_args()
438
        );
439
    }
440
441 View Code Duplication
    public function comparisonClause(
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
442
        $field,
443
        $value,
444
        $exact = false,
445
        $negate = false,
446
        $caseSensitive = false,
447
        $parameterised = false
448
    ) {
449
        return call_user_func_array(
450
            array($this->realConn, __FUNCTION__),
451
            func_get_args()
452
        );
453
    }
454
455
    public function createDatabase()
456
    {
457
        return call_user_func_array(
458
            array($this->realConn, __FUNCTION__),
459
            func_get_args()
460
        );
461
    }
462
463
    public function createField($table, $field, $spec)
464
    {
465
        return call_user_func_array(
466
            array($this->realConn, __FUNCTION__),
467
            func_get_args()
468
        );
469
    }
470
471 View Code Duplication
    public function createTable(
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
472
        $table,
473
        $fields = null,
474
        $indexes = null,
475
        $options = null,
476
        $advancedOptions = null
477
    ) {
478
        return call_user_func_array(
479
            array($this->realConn, __FUNCTION__),
480
            func_get_args()
481
        );
482
    }
483
484
    public function datetimeDifferenceClause($date1, $date2)
485
    {
486
        return call_user_func_array(
487
            array($this->realConn, __FUNCTION__),
488
            func_get_args()
489
        );
490
    }
491
492
    public function datetimeIntervalClause($date, $interval)
493
    {
494
        return call_user_func_array(
495
            array($this->realConn, __FUNCTION__),
496
            func_get_args()
497
        );
498
    }
499
500
    public function enumValuesForField($tableName, $fieldName)
501
    {
502
        return call_user_func_array(
503
            array($this->realConn, __FUNCTION__),
504
            func_get_args()
505
        );
506
    }
507
508
    public function fieldList($table)
509
    {
510
        return call_user_func_array(
511
            array($this->realConn, __FUNCTION__),
512
            func_get_args()
513
        );
514
    }
515
516
    public function formattedDatetimeClause($date, $format)
517
    {
518
        return call_user_func_array(
519
            array($this->realConn, __FUNCTION__),
520
            func_get_args()
521
        );
522
    }
523
524
    public function getConnect($parameters)
525
    {
526
        return call_user_func_array(
527
            array($this->realConn, __FUNCTION__),
528
            func_get_args()
529
        );
530
    }
531
532
    public function getGeneratedID($table)
533
    {
534
        return call_user_func_array(
535
            array($this->realConn, __FUNCTION__),
536
            func_get_args()
537
        );
538
    }
539
540
    public function hasTable($tableName)
541
    {
542
        return call_user_func_array(
543
            array($this->realConn, __FUNCTION__),
544
            func_get_args()
545
        );
546
    }
547
548
    public function isActive()
549
    {
550
        return call_user_func_array(
551
            array($this->realConn, __FUNCTION__),
552
            func_get_args()
553
        );
554
    }
555
556
    public function renameField($tableName, $oldName, $newName)
557
    {
558
        return call_user_func_array(
559
            array($this->realConn, __FUNCTION__),
560
            func_get_args()
561
        );
562
    }
563
564
    public function renameTable($oldTableName, $newTableName)
565
    {
566
        return call_user_func_array(
567
            array($this->realConn, __FUNCTION__),
568
            func_get_args()
569
        );
570
    }
571
572
    public function supportsTimezoneOverride()
573
    {
574
        return call_user_func_array(
575
            array($this->realConn, __FUNCTION__),
576
            func_get_args()
577
        );
578
    }
579
580
    public function supportsTransactions()
581
    {
582
        return call_user_func_array(
583
            array($this->realConn, __FUNCTION__),
584
            func_get_args()
585
        );
586
    }
587
588
    public function tableList()
589
    {
590
        return call_user_func_array(
591
            array($this->realConn, __FUNCTION__),
592
            func_get_args()
593
        );
594
    }
595
596
    public function transactionEnd($chain = false)
597
    {
598
        return call_user_func_array(
599
            array($this->realConn, __FUNCTION__),
600
            func_get_args()
601
        );
602
    }
603
604
    public function transactionRollback($savepoint = false)
605
    {
606
        return call_user_func_array(
607
            array($this->realConn, __FUNCTION__),
608
            func_get_args()
609
        );
610
    }
611
612
    public function transactionSavepoint($savepoint)
613
    {
614
        return call_user_func_array(
615
            array($this->realConn, __FUNCTION__),
616
            func_get_args()
617
        );
618
    }
619
620
    public function transactionStart($transaction_mode = false, $session_characteristics = false)
621
    {
622
        return call_user_func_array(
623
            array($this->realConn, __FUNCTION__),
624
            func_get_args()
625
        );
626
    }
627
628
    public function clearTable($table)
629
    {
630
        return call_user_func_array(
631
            array($this->realConn, __FUNCTION__),
632
            func_get_args()
633
        );
634
    }
635
636
    public function getDatabaseServer()
637
    {
638
        return call_user_func_array(
639
            array($this->realConn, __FUNCTION__),
640
            func_get_args()
641
        );
642
    }
643
644
    public function now()
645
    {
646
        return call_user_func_array(
647
            array($this->realConn, __FUNCTION__),
648
            func_get_args()
649
        );
650
    }
651
652
    public function random()
653
    {
654
        return call_user_func_array(
655
            array($this->realConn, __FUNCTION__),
656
            func_get_args()
657
        );
658
    }
659
660
    public function searchEngine(
661
        $classesToSearch,
662
        $keywords,
663
        $start,
664
        $pageLength,
665
        $sortBy = "Relevance DESC",
666
        $extraFilter = "",
667
        $booleanSearch = false,
668
        $alternativeFileFilter = "",
669
        $invertedMatch = false
670
    ) {
671
        return call_user_func_array(
672
            array($this->realConn, __FUNCTION__),
673
            func_get_args()
674
        );
675
    }
676
677
    public function supportsCollations()
678
    {
679
        return call_user_func_array(
680
            array($this->realConn, __FUNCTION__),
681
            func_get_args()
682
        );
683
    }
684
}
685