Issues (194)

Security Analysis    no request data  

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

src/SQLParser/PHPSQLCreator.php (16 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
/**
4
 * php-sql-creator.php.
5
 *
6
 * A pure PHP SQL creator, which generates SQL from the output of SQLParser.
7
 *
8
 * Copyright (c) 2012, André Rothe <[email protected], [email protected]>
9
 *
10
 * All rights reserved.
11
 *
12
 * Redistribution and use in source and binary forms, with or without modification,
13
 * are permitted provided that the following conditions are met:
14
 *
15
 *   * Redistributions of source code must retain the above copyright notice,
16
 *	 this list of conditions and the following disclaimer.
17
 *   * Redistributions in binary form must reproduce the above copyright notice,
18
 *	 this list of conditions and the following disclaimer in the documentation
19
 *	 and/or other materials provided with the distribution.
20
 *
21
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
22
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
24
 * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
26
 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
27
 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
29
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
30
 * DAMAGE.
31
 */
32
namespace SQLParser;
33
34
class PHPSQLCreator
35
{
36
    public function __construct($parsed = false)
37
    {
38
        if ($parsed) {
39
            $this->create($parsed);
40
        }
41
    }
42
43
    public function create($parsed)
44
    {
45
        $k = key($parsed);
46
        switch ($k) {
47
48
        case 'UNION':
49
        case 'UNION ALL':
50
            throw new UnsupportedFeatureException($k);
51
            break;
0 ignored issues
show
break; does not seem to be reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
52
        case 'SELECT':
53
            $this->created = $this->processSelectStatement($parsed);
0 ignored issues
show
The property created does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
54
            break;
55
        case 'INSERT':
56
            $this->created = $this->processInsertStatement($parsed);
57
            break;
58
        case 'DELETE':
59
            $this->created = $this->processDeleteStatement($parsed);
60
            break;
61
        case 'UPDATE':
62
            $this->created = $this->processUpdateStatement($parsed);
63
            break;
64
        default:
65
            throw new UnsupportedFeatureException($k);
66
            break;
0 ignored issues
show
break; does not seem to be reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
67
        }
68
69
        return $this->created;
70
    }
71
72
    protected function processSelectStatement($parsed)
73
    {
74
        $sql = $this->processSELECT($parsed['SELECT']).' '.$this->processFROM($parsed['FROM']);
75
        if (isset($parsed['WHERE'])) {
76
            $sql .= ' '.$this->processWHERE($parsed['WHERE']);
77
        }
78
        if (isset($parsed['GROUP'])) {
79
            $sql .= ' '.$this->processGROUP($parsed['GROUP']);
80
        }
81
        if (isset($parsed['ORDER'])) {
82
            $sql .= ' '.$this->processORDER($parsed['ORDER']);
83
        }
84
        if (isset($parsed['LIMIT'])) {
85
            $sql .= ' '.$this->processLIMIT($parsed['LIMIT']);
86
        }
87
88
        return $sql;
89
    }
90
91
    protected function processInsertStatement($parsed)
92
    {
93
        return $this->processINSERT($parsed['INSERT']).' '.$this->processVALUES($parsed['VALUES']);
94
        # TODO: subquery?
95
    }
96
97
    protected function processDeleteStatement($parsed)
98
    {
99
        return $this->processDELETE($parsed['DELETE']).' '.$this->processFROM($parsed['FROM']).' '
100
                .$this->processWHERE($parsed['WHERE']);
101
    }
102
103
    protected function processUpdateStatement($parsed)
104
    {
105
        $sql = $this->processUPDATE($parsed['UPDATE']).' '.$this->processSET($parsed['SET']);
106
        if (isset($parsed['WHERE'])) {
107
            $sql .= ' '.$this->processWHERE($parsed['WHERE']);
108
        }
109
110
        return $sql;
111
    }
112
113
    protected function processDELETE($parsed)
114
    {
115
        $sql = 'DELETE';
116
        foreach ($parsed['TABLES'] as $k => $v) {
117
            $sql .= $v.',';
118
        }
119
120
        return substr($sql, 0, -1);
121
    }
122
123 View Code Duplication
    protected function processSELECT($parsed)
0 ignored issues
show
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...
124
    {
125
        $sql = '';
126
        foreach ($parsed as $k => $v) {
127
            $len = strlen($sql);
128
            $sql .= $this->processColRef($v);
129
            $sql .= $this->processSelectExpression($v);
130
            $sql .= $this->processFunction($v);
131
            $sql .= $this->processConstant($v);
132
133
            if ($len == strlen($sql)) {
134
                throw new UnableToCreateSQLException('SELECT', $k, $v, 'expr_type');
135
            }
136
137
            $sql .= ',';
138
        }
139
        $sql = substr($sql, 0, -1);
140
141
        return 'SELECT '.$sql;
142
    }
143
144 View Code Duplication
    protected function processFROM($parsed)
0 ignored issues
show
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...
145
    {
146
        $sql = '';
147
        foreach ($parsed as $k => $v) {
148
            $len = strlen($sql);
149
            $sql .= $this->processTable($v, $k);
150
            $sql .= $this->processTableExpression($v, $k);
151
            $sql .= $this->processSubquery($v, $k);
152
153
            if ($len == strlen($sql)) {
154
                throw new UnableToCreateSQLException('FROM', $k, $v, 'expr_type');
155
            }
156
157
            $sql .= ' ';
158
        }
159
160
        return 'FROM '.substr($sql, 0, -1);
161
    }
162
163
    protected function processORDER($parsed)
164
    {
165
        $sql = '';
166
        foreach ($parsed as $k => $v) {
167
            $len = strlen($sql);
168
            $sql .= $this->processOrderByAlias($v);
169
            $sql .= $this->processColRef($v);
170
171
            if ($len == strlen($sql)) {
172
                throw new UnableToCreateSQLException('ORDER', $k, $v, 'expr_type');
173
            }
174
175
            $sql .= ',';
176
        }
177
        $sql = substr($sql, 0, -1);
178
179
        return 'ORDER BY '.$sql;
180
    }
181
182
    protected function processLIMIT($parsed)
183
    {
184
        $sql = ($parsed['offset'] ? $parsed['offset'].', ' : '').$parsed['rowcount'];
185
        if ($sql === '') {
186
            throw new UnableToCreateSQLException('LIMIT', 'rowcount', $parsed, 'rowcount');
187
        }
188
189
        return 'LIMIT '.$sql;
190
    }
191
192 View Code Duplication
    protected function processGROUP($parsed)
0 ignored issues
show
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...
193
    {
194
        $sql = '';
195
        foreach ($parsed as $k => $v) {
196
            $len = strlen($sql);
197
            $sql .= $this->processColRef($v);
198
199
            if ($len == strlen($sql)) {
200
                throw new UnableToCreateSQLException('GROUP', $k, $v, 'expr_type');
201
            }
202
203
            $sql .= ',';
204
        }
205
        $sql = substr($sql, 0, -1);
206
207
        return 'GROUP BY '.$sql;
208
    }
209
210
    protected function processRecord($parsed)
211
    {
212
        if ($parsed['expr_type'] !== ExpressionType::RECORD) {
213
            return '';
214
        }
215
        $sql = '';
216 View Code Duplication
        foreach ($parsed['data'] as $k => $v) {
0 ignored issues
show
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...
217
            $len = strlen($sql);
218
            $sql .= $this->processConstant($v);
219
            $sql .= $this->processFunction($v);
220
            $sql .= $this->processOperator($v);
221
222
            if ($len == strlen($sql)) {
223
                throw new UnableToCreateSQLException(ExpressionType::RECORD, $k, $v, 'expr_type');
224
            }
225
226
            $sql .= ',';
227
        }
228
        $sql = substr($sql, 0, -1);
229
230
        return '('.$sql.')';
231
    }
232
233 View Code Duplication
    protected function processVALUES($parsed)
0 ignored issues
show
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...
234
    {
235
        $sql = '';
236
        foreach ($parsed as $k => $v) {
237
            $len = strlen($sql);
238
            $sql .= $this->processRecord($v);
239
240
            if ($len == strlen($sql)) {
241
                throw new UnableToCreateSQLException('VALUES', $k, $v, 'expr_type');
242
            }
243
244
            $sql .= ',';
245
        }
246
        $sql = substr($sql, 0, -1);
247
248
        return 'VALUES '.$sql;
249
    }
250
251
    protected function processINSERT($parsed)
252
    {
253
        $sql = 'INSERT INTO '.$parsed['table'];
254
255
        if ($parsed['columns'] === false) {
256
            return $sql;
257
        }
258
259
        $columns = '';
260
        foreach ($parsed['columns'] as $k => $v) {
261
            $len = strlen($columns);
262
            $columns .= $this->processColRef($v);
263
264
            if ($len == strlen($columns)) {
265
                throw new UnableToCreateSQLException('INSERT[columns]', $k, $v, 'expr_type');
266
            }
267
268
            $columns .= ',';
269
        }
270
271
        if ($columns !== '') {
272
            $columns = ' ('.substr($columns, 0, -1).')';
273
        }
274
275
        $sql .= $columns;
276
277
        return $sql;
278
    }
279
280
    protected function processUPDATE($parsed)
281
    {
282
        return 'UPDATE '.$parsed[0]['table'];
283
    }
284
285
    protected function processSetExpression($parsed)
286
    {
287
        if ($parsed['expr_type'] !== ExpressionType::EXPRESSION) {
288
            return '';
289
        }
290
        $sql = '';
291
        foreach ($parsed['sub_tree'] as $k => $v) {
292
            $len = strlen($sql);
293
            $sql .= $this->processColRef($v);
294
            $sql .= $this->processConstant($v);
295
            $sql .= $this->processOperator($v);
296
            $sql .= $this->processFunction($v);
297
298
            if ($len == strlen($sql)) {
299
                throw new UnableToCreateSQLException('SET expression subtree', $k, $v, 'expr_type');
300
            }
301
302
            $sql .= ' ';
303
        }
304
305
        $sql = substr($sql, 0, -1);
306
307
        return $sql;
308
    }
309
310 View Code Duplication
    protected function processSET($parsed)
0 ignored issues
show
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...
311
    {
312
        $sql = '';
313
        foreach ($parsed as $k => $v) {
314
            $len = strlen($sql);
315
            $sql .= $this->processSetExpression($v);
316
317
            if ($len == strlen($sql)) {
318
                throw new UnableToCreateSQLException('SET', $k, $v, 'expr_type');
319
            }
320
321
            $sql .= ',';
322
        }
323
324
        return 'SET '.substr($sql, 0, -1);
325
    }
326
327
    protected function processWHERE($parsed)
328
    {
329
        $sql = 'WHERE ';
330
        foreach ($parsed as $k => $v) {
331
            $len = strlen($sql);
332
333
            $sql .= $this->processOperator($v);
334
            $sql .= $this->processConstant($v);
335
            $sql .= $this->processColRef($v);
336
            $sql .= $this->processSubquery($v);
337
            $sql .= $this->processInList($v);
338
            $sql .= $this->processFunction($v);
339
            $sql .= $this->processWhereExpression($v);
340
            $sql .= $this->processWhereBracketExpression($v);
341
342
            if (strlen($sql) == $len) {
343
                throw new UnableToCreateSQLException('WHERE', $k, $v, 'expr_type');
344
            }
345
346
            $sql .= ' ';
347
        }
348
349
        return substr($sql, 0, -1);
350
    }
351
352 View Code Duplication
    protected function processWhereExpression($parsed)
0 ignored issues
show
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...
353
    {
354
        if ($parsed['expr_type'] !== ExpressionType::EXPRESSION) {
355
            return '';
356
        }
357
        $sql = '';
358
        foreach ($parsed['sub_tree'] as $k => $v) {
359
            $len = strlen($sql);
360
            $sql .= $this->processColRef($v);
361
            $sql .= $this->processConstant($v);
362
            $sql .= $this->processOperator($v);
363
            $sql .= $this->processInList($v);
364
            $sql .= $this->processFunction($v);
365
            $sql .= $this->processWhereExpression($v);
366
            $sql .= $this->processWhereBracketExpression($v);
367
368
            if ($len == strlen($sql)) {
369
                throw new UnableToCreateSQLException('WHERE expression subtree', $k, $v, 'expr_type');
370
            }
371
372
            $sql .= ' ';
373
        }
374
375
        $sql = substr($sql, 0, -1);
376
377
        return $sql;
378
    }
379
380 View Code Duplication
    protected function processWhereBracketExpression($parsed)
0 ignored issues
show
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...
381
    {
382
        if ($parsed['expr_type'] !== ExpressionType::BRACKET_EXPRESSION) {
383
            return '';
384
        }
385
        $sql = '';
386
        foreach ($parsed['sub_tree'] as $k => $v) {
387
            $len = strlen($sql);
388
            $sql .= $this->processColRef($v);
389
            $sql .= $this->processConstant($v);
390
            $sql .= $this->processOperator($v);
391
            $sql .= $this->processInList($v);
392
            $sql .= $this->processFunction($v);
393
            $sql .= $this->processWhereExpression($v);
394
            $sql .= $this->processWhereBracketExpression($v);
395
396
            if ($len == strlen($sql)) {
397
                throw new UnableToCreateSQLException('WHERE expression subtree', $k, $v, 'expr_type');
398
            }
399
400
            $sql .= ' ';
401
        }
402
403
        $sql = '('.substr($sql, 0, -1).')';
404
405
        return $sql;
406
    }
407
408
    protected function processOrderByAlias($parsed)
409
    {
410
        if ($parsed['expr_type'] !== ExpressionType::ALIAS) {
411
            return '';
412
        }
413
414
        return $parsed['base_expr'].$this->processDirection($parsed['direction']);
415
    }
416
417
    protected function processLimitRowCount($key, $value)
418
    {
419
        if ($key != 'rowcount') {
420
            return '';
421
        }
422
423
        return $value;
424
    }
425
426
    protected function processLimitOffset($key, $value)
427
    {
428
        if ($key !== 'offset') {
429
            return '';
430
        }
431
432
        return $value;
433
    }
434
435
    protected function processFunction($parsed)
436
    {
437
        if (($parsed['expr_type'] !== ExpressionType::AGGREGATE_FUNCTION)
438
                && ($parsed['expr_type'] !== ExpressionType::SIMPLE_FUNCTION)) {
439
            return '';
440
        }
441
442
        if ($parsed['sub_tree'] === false) {
443
            return $parsed['base_expr'].'()';
444
        }
445
446
        $sql = '';
447
        foreach ($parsed['sub_tree'] as $k => $v) {
448
            $len = strlen($sql);
449
            $sql .= $this->processFunction($v);
450
            $sql .= $this->processConstant($v);
451
            $sql .= $this->processColRef($v);
452
            $sql .= $this->processReserved($v);
453
454
            if ($len == strlen($sql)) {
455
                throw new UnableToCreateSQLException('function subtree', $k, $v, 'expr_type');
456
            }
457
458
            $sql .= ($this->isReserved($v) ? ' ' : ',');
459
        }
460
461
        return $parsed['base_expr'].'('.substr($sql, 0, -1).')';
462
    }
463
464
    protected function processSelectExpression($parsed)
465
    {
466
        if ($parsed['expr_type'] !== ExpressionType::EXPRESSION) {
467
            return '';
468
        }
469
        $sql = $this->processSubTree($parsed, ' ');
470
        $sql .= $this->processAlias($parsed['alias']);
471
472
        return $sql;
473
    }
474
475 View Code Duplication
    protected function processSelectBracketExpression($parsed)
0 ignored issues
show
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...
476
    {
477
        if ($parsed['expr_type'] !== ExpressionType::BRACKET_EXPRESSION) {
478
            return '';
479
        }
480
        $sql = $this->processSubTree($parsed, ' ');
481
        $sql = '('.$sql.')';
482
483
        return $sql;
484
    }
485
486
    protected function processSubTree($parsed, $delim = ' ')
487
    {
488
        if ($parsed['sub_tree'] === '') {
489
            return '';
490
        }
491
        $sql = '';
492
        foreach ($parsed['sub_tree'] as $k => $v) {
493
            $len = strlen($sql);
494
            $sql .= $this->processFunction($v);
495
            $sql .= $this->processOperator($v);
496
            $sql .= $this->processConstant($v);
497
            $sql .= $this->processSubQuery($v);
498
            $sql .= $this->processSelectBracketExpression($v);
499
500
            if ($len == strlen($sql)) {
501
                throw new UnableToCreateSQLException('expression subtree', $k, $v, 'expr_type');
502
            }
503
504
            $sql .= $delim;
505
        }
506
507
        return substr($sql, 0, -1);
508
    }
509
510
    protected function processRefClause($parsed)
511
    {
512
        if ($parsed === false) {
513
            return '';
514
        }
515
516
        $sql = '';
517 View Code Duplication
        foreach ($parsed as $k => $v) {
0 ignored issues
show
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...
518
            $len = strlen($sql);
519
            $sql .= $this->processColRef($v);
520
            $sql .= $this->processOperator($v);
521
            $sql .= $this->processConstant($v);
522
523
            if ($len == strlen($sql)) {
524
                throw new UnableToCreateSQLException('expression ref_clause', $k, $v, 'expr_type');
525
            }
526
527
            $sql .= ' ';
528
        }
529
530
        return '('.substr($sql, 0, -1).')';
531
    }
532
533
    protected function processAlias($parsed)
534
    {
535
        if ($parsed === false) {
536
            return '';
537
        }
538
        $sql = '';
539
        if ($parsed['as']) {
540
            $sql .= ' as';
541
        }
542
        $sql .= ' '.$parsed['name'];
543
544
        return $sql;
545
    }
546
547
    protected function processJoin($parsed)
548
    {
549
        if ($parsed === 'CROSS') {
550
            return ',';
551
        }
552
        if ($parsed === 'JOIN') {
553
            return 'INNER JOIN';
554
        }
555
        if ($parsed === 'LEFT') {
556
            return 'LEFT JOIN';
557
        }
558
        if ($parsed === 'RIGHT') {
559
            return 'RIGHT JOIN';
560
        }
561
        // TODO: add more
562
        throw new UnsupportedFeatureException($parsed);
563
    }
564
565
    protected function processRefType($parsed)
566
    {
567
        if ($parsed === false) {
568
            return '';
569
        }
570
        if ($parsed === 'ON') {
571
            return ' ON ';
572
        }
573
        if ($parsed === 'USING') {
574
            return ' USING ';
575
        }
576
        // TODO: add more
577
        throw new UnsupportedFeatureException($parsed);
578
    }
579
580
    protected function processTable($parsed, $index)
581
    {
582
        if ($parsed['expr_type'] !== ExpressionType::TABLE) {
583
            return '';
584
        }
585
586
        $sql = $parsed['table'];
587
        $sql .= $this->processAlias($parsed['alias']);
588
589
        if ($index !== 0) {
590
            $sql = $this->processJoin($parsed['join_type']).' '.$sql;
591
            $sql .= $this->processRefType($parsed['ref_type']);
592
            $sql .= $this->processRefClause($parsed['ref_clause']);
593
        }
594
595
        return $sql;
596
    }
597
598 View Code Duplication
    protected function processTableExpression($parsed, $index)
0 ignored issues
show
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...
599
    {
600
        if ($parsed['expr_type'] !== ExpressionType::TABLE_EXPRESSION) {
601
            return '';
602
        }
603
        $sql = substr($this->processFROM($parsed['sub_tree']), 5); // remove FROM keyword
604
        $sql = '('.$sql.')';
605
        $sql .= $this->processAlias($parsed['alias']);
606
607
        if ($index !== 0) {
608
            $sql = $this->processJoin($parsed['join_type']).' '.$sql;
609
            $sql .= $this->processRefType($parsed['ref_type']);
610
            $sql .= $this->processRefClause($parsed['ref_clause']);
611
        }
612
613
        return $sql;
614
    }
615
616 View Code Duplication
    protected function processSubQuery($parsed, $index = 0)
0 ignored issues
show
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...
617
    {
618
        if ($parsed['expr_type'] !== ExpressionType::SUBQUERY) {
619
            return '';
620
        }
621
622
        $sql = $this->processSelectStatement($parsed['sub_tree']);
623
        $sql = '('.$sql.')';
624
625
        if (isset($parsed['alias'])) {
626
            $sql .= $this->processAlias($parsed['alias']);
627
        }
628
629
        if ($index !== 0) {
630
            $sql = $this->processJoin($parsed['join_type']).' '.$sql;
631
            $sql .= $this->processRefType($parsed['ref_type']);
632
            $sql .= $this->processRefClause($parsed['ref_clause']);
633
        }
634
635
        return $sql;
636
    }
637
638
    protected function processOperator($parsed)
639
    {
640
        if ($parsed['expr_type'] !== ExpressionType::OPERATOR) {
641
            return '';
642
        }
643
644
        return $parsed['base_expr'];
645
    }
646
647
    protected function processColRef($parsed)
648
    {
649
        if ($parsed['expr_type'] !== ExpressionType::COLREF) {
650
            return '';
651
        }
652
        $sql = $parsed['base_expr'];
653
        if (isset($parsed['alias'])) {
654
            $sql .= $this->processAlias($parsed['alias']);
655
        }
656
        if (isset($parsed['direction'])) {
657
            $sql .= $this->processDirection($parsed['direction']);
658
        }
659
660
        return $sql;
661
    }
662
663
    protected function processDirection($parsed)
664
    {
665
        $sql = ($parsed ? ' '.$parsed : '');
666
667
        return $sql;
668
    }
669
670
    protected function processReserved($parsed)
671
    {
672
        if (!$this->isReserved($parsed)) {
673
            return '';
674
        }
675
676
        return $parsed['base_expr'];
677
    }
678
679
    protected function isReserved($parsed)
680
    {
681
        return ($parsed['expr_type'] === ExpressionType::RESERVED);
682
    }
683
684
    protected function processConstant($parsed)
685
    {
686
        if ($parsed['expr_type'] !== ExpressionType::CONSTANT) {
687
            return '';
688
        }
689
690
        return $parsed['base_expr'];
691
    }
692
693 View Code Duplication
    protected function processInList($parsed)
0 ignored issues
show
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...
694
    {
695
        if ($parsed['expr_type'] !== ExpressionType::IN_LIST) {
696
            return '';
697
        }
698
        $sql = $this->processSubTree($parsed, ',');
699
700
        return '('.$sql.')';
701
    }
702
} // END CLASS
703
704