Completed
Pull Request — master (#87)
by Deven
63:47
created

DeleteStatement::parse()   D

Complexity

Conditions 45
Paths 30

Size

Total Lines 200
Code Lines 127

Duplication

Lines 50
Ratio 25 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 45
eloc 127
nc 30
nop 2
dl 50
loc 200
rs 4.1818
c 1
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/**
4
 * `DELETE` statement.
5
 *
6
 * @package    SqlParser
7
 * @subpackage Statements
8
 */
9
namespace SqlParser\Statements;
10
11
use SqlParser\Statement;
12
use SqlParser\Parser;
13
use SqlParser\Token;
14
use SqlParser\TokensList;
15
use SqlParser\Components\ArrayObj;
16
use SqlParser\Components\Expression;
17
use SqlParser\Components\ExpressionArray;
18
use SqlParser\Components\Limit;
19
use SqlParser\Components\OrderKeyword;
20
use SqlParser\Components\Condition;
21
use SqlParser\Components\OptionsArray;
22
23
/**
24
 * `DELETE` statement.
25
 *
26
 * DELETE [LOW_PRIORITY] [QUICK] [IGNORE] FROM tbl_name
27
 *     [PARTITION (partition_name,...)]
28
 *     [WHERE where_condition]
29
 *     [ORDER BY ...]
30
 *     [LIMIT row_count]
31
 *
32
 * Multi-table syntax
33
 *
34
 * DELETE [LOW_PRIORITY] [QUICK] [IGNORE]
35
 *   tbl_name[.*] [, tbl_name[.*]] ...
36
 *   FROM table_references
37
 *   [WHERE where_condition]
38
 *
39
 * OR
40
 *
41
 * DELETE [LOW_PRIORITY] [QUICK] [IGNORE]
42
 *   FROM tbl_name[.*] [, tbl_name[.*]] ...
43
 *   USING table_references
44
 *   [WHERE where_condition]
45
 *
46
 *
47
 * @category   Statements
48
 * @package    SqlParser
49
 * @subpackage Statements
50
 * @author     Dan Ungureanu <[email protected]>
51
 * @license    http://opensource.org/licenses/GPL-2.0 GNU Public License
52
 */
53
class DeleteStatement extends Statement
54
{
55
56
    /**
57
     * Options for `DELETE` statements.
58
     *
59
     * @var array
60
     */
61
    public static $OPTIONS = array(
62
        'LOW_PRIORITY'                  => 1,
63
        'QUICK'                         => 2,
64
        'IGNORE'                        => 3,
65
    );
66
67
    /**
68
     * Table(s) used as sources for this statement.
69
     *
70
     * @var Expression[]
71
     */
72
    public $from;
73
74
    /**
75
     * Tables used as sources for this statement
76
     *
77
     * @var Expression[]
78
     */
79
    public $using;
80
81
    /**
82
     * Columns used in this statement
83
     *
84
     * @var Expression[]
85
     */
86
    public $columns;
87
88
    /**
89
     * Partitions used as source for this statement.
90
     *
91
     * @var ArrayObj
92
     */
93
    public $partition;
94
95
    /**
96
     * Conditions used for filtering each row of the result set.
97
     *
98
     * @var Condition[]
99
     */
100
    public $where;
101
102
    /**
103
     * Specifies the order of the rows in the result set.
104
     *
105
     * @var OrderKeyword[]
106
     */
107
    public $order;
108
109
    /**
110
     * Conditions used for limiting the size of the result set.
111
     *
112
     * @var Limit
113
     */
114
    public $limit;
115
116
117
    /**
118
     * @return string
119
     */
120
    public function build()
121
    {
122
        $ret = 'DELETE ' . OptionsArray::build($this->options);
123
124 View Code Duplication
        if ($this->columns != NULL && count($this->columns) > 0) {
125
            $ret .= ' ' . ExpressionArray::build($this->columns);
126
        }
127 View Code Duplication
        if ($this->from != NULL && count($this->from) > 0) {
128
            $ret .= ' FROM ' . ExpressionArray::build($this->from);
129
        }
130 View Code Duplication
        if ($this->using != NULL && count($this->using) > 0) {
131
            $ret .= ' USING ' . ExpressionArray::build($this->using);
132
        }
133
        if ($this->where != NULL && count($this->where) > 0) {
134
            $ret .= ' WHERE ' . Condition::build($this->where);
135
        }
136 View Code Duplication
        if ($this->order != NULL && count($this->order) > 0) {
137
            $ret .= ' ORDER BY ' . ExpressionArray::build($this->order);
0 ignored issues
show
Documentation introduced by
$this->order is of type array<integer,object<Sql...mponents\OrderKeyword>>, but the function expects a array<integer,object<Sql...Components\Expression>>.

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...
138
        }
139
        if ($this->limit != NULL && count($this->limit) > 0) {
140
            $ret .= ' LIMIT ' . Limit::build($this->limit);
141
        }
142
143
        return $ret;
144
145
    }
146
147
148
    /**
149
     * @param Parser     $parser The instance that requests parsing.
150
     * @param TokensList $list   The list of tokens to be parsed.
151
     *
152
     * @return void
153
     */
154
    public function parse(Parser $parser, TokensList $list)
155
    {
156
        ++$list->idx; // Skipping `DELETE`.
157
158
        // parse any options if provided
159
        $this->options = OptionsArray::parse(
160
            $parser,
161
            $list,
162
            static::$OPTIONS
163
        );
164
        ++$list->idx;
165
166
        /**
167
         * The state of the parser.
168
         *
169
         * Below are the states of the parser.
170
         *
171
         *      0 ---------------------------------[ FROM ]----------------------------------> 2
172
         *      0 ------------------------------[ table[.*] ]--------------------------------> 1
173
         *      1 ---------------------------------[ FROM ]----------------------------------> 2
174
         *      2 --------------------------------[ USING ]----------------------------------> 3
175
         *      2 --------------------------------[ WHERE ]----------------------------------> 4
176
         *      2 --------------------------------[ ORDER ]----------------------------------> 5
177
         *      2 --------------------------------[ LIMIT ]----------------------------------> 6
178
         *
179
         * @var int $state
180
         */
181
        $state = 0;
182
183
        /**
184
         * If the query is multi-table or not
185
         *
186
         * @var bool $multiTable
187
         */
188
        $multiTable = false;
189
190
        for (; $list->idx < $list->count; ++$list->idx) {
191
            /**
192
             * Token parsed at this moment.
193
             *
194
             * @var Token $token
195
             */
196
            $token = $list->tokens[$list->idx];
197
198
            // End of statement.
199
            if ($token->type === Token::TYPE_DELIMITER) {
200
                break;
201
            }
202
203
            // Skipping whitespaces and comments.
204
            if (($token->type === Token::TYPE_WHITESPACE) || ($token->type === Token::TYPE_COMMENT)) {
205
                continue;
206
            }
207
208
            if ($state === 0) {
209
                if ($token->type === Token::TYPE_KEYWORD
210
                    && $token->value !== 'FROM'
211
                ) {
212
                    $parser->error(__('Unexpected keyword.'), $token);
213
                    break;
214
                } elseif ($token->type === Token::TYPE_KEYWORD
215
                    && $token->value === 'FROM'
216
                ) {
217
                    ++$list->idx; // Skip 'FROM'
218
                    $this->from = ExpressionArray::parse($parser, $list);
219
                    $state = 2;
220
                } else {
221
                    $this->columns = ExpressionArray::parse($parser, $list);
222
                    $state = 1;
223
                }
224 View Code Duplication
            } elseif ($state === 1) {
225
                if ($token->type === Token::TYPE_KEYWORD
226
                    && $token->value !== 'FROM'
227
                ) {
228
                    $parser->error(__('Unexpected keyword.'), $token);
229
                    break;
230
                } elseif ($token->type === Token::TYPE_KEYWORD
231
                    && $token->value === 'FROM'
232
                ) {
233
                    ++$list->idx; // Skip 'FROM'
234
                    $this->from = ExpressionArray::parse($parser, $list);
235
                    $state = 2;
236
                } else {
237
                    $parser->error(__('Unexpected token.'), $token);
238
                    break;
239
                }
240
            } elseif ($state === 2) {
241
                if ($token->type === Token::TYPE_KEYWORD
242
                    && $token->value === 'USING'
243
                ) {
244
                    ++$list->idx; // Skip 'USING'
245
                    $this->using = ExpressionArray::parse($parser, $list);
246
                    $state = 3;
247
248
                    $multiTable = true;
249
                } elseif ($token->type === Token::TYPE_KEYWORD
250
                    && $token->value === 'WHERE'
251
                ) {
252
                    ++$list->idx; // Skip 'WHERE'
253
                    $this->where = Condition::parse($parser, $list);
254
                    $state = 4;
255
                } elseif ($token->type === Token::TYPE_KEYWORD
256
                    && $token->value === 'ORDER BY'
257
                ) {
258
                    ++$list->idx; // Skip 'ORDER BY'
259
                    $this->order = OrderKeyword::parse($parser, $list);
260
                    $state = 5;
261
                } elseif ($token->type === Token::TYPE_KEYWORD
262
                    && $token->value === 'LIMIT'
263
                ) {
264
                    ++$list->idx; // Skip 'LIMIT'
265
                    $this->limit = Limit::parse($parser, $list);
266
                    $state = 6;
267
                } elseif ($token->type === Token::TYPE_KEYWORD) {
268
                    $parser->error(__('Unexpected keyword.'), $token);
269
                    break;
270
                } else {
271
                    $parser->error(__('Unexpected token.'), $token);
272
                    break;
273
                }
274 View Code Duplication
            } elseif ($state === 3) {
275
                if ($token->type === Token::TYPE_KEYWORD
276
                    && $token->value === 'WHERE'
277
                ) {
278
                    ++$list->idx; // Skip 'WHERE'
279
                    $this->where = Condition::parse($parser, $list);
280
                    $state = 4;
281
                } elseif ($token->type === Token::TYPE_KEYWORD) {
282
                    $parser->error(__('Unexpected keyword.'), $token);
283
                    break;
284
                } else {
285
                    $parser->error(__('Unexpected token.'), $token);
286
                    break;
287
                }
288
            } elseif ($state === 4) {
289 View Code Duplication
                if ($multiTable === true
290
                    && $token->type === Token::TYPE_KEYWORD
291
                ) {
292
                    $parser->error(
293
                        __('This type of clause is not valid in Multi-table queries.'),
294
                        $token
295
                    );
296
                    break;
297
                }
298
299
                if ($token->type === Token::TYPE_KEYWORD
300
                    && $token->value === 'ORDER BY'
301
                ) {
302
                    ++$list->idx; // Skip 'ORDER  BY'
303
                    $this->order = OrderKeyword::parse($parser, $list);
304
                    $state = 5;
305
                }  elseif ($token->type === Token::TYPE_KEYWORD
306
                    && $token->value === 'LIMIT'
307
                ) {
308
                    ++$list->idx; // Skip 'LIMIT'
309
                    $this->limit = Limit::parse($parser, $list);
310
                    $state = 6;
311
                } elseif ($token->type === Token::TYPE_KEYWORD) {
312
                    $parser->error(__('Unexpected keyword.'), $token);
313
                    break;
314
                } else {
315
                    $parser->error(__('Unexpected token.'), $token);
316
                    break;
317
                }
318
            } elseif ($state === 5) {
319 View Code Duplication
                if ($multiTable === true
320
                    && $token->type === Token::TYPE_KEYWORD
321
                ) {
322
                    $parser->error(
323
                        __('This type of clause is not valid in Multi-table queries.'),
324
                        $token
325
                    );
326
                    break;
327
                }
328
329
                if ($token->type === Token::TYPE_KEYWORD
330
                    && $token->value === 'LIMIT'
331
                ) {
332
                    ++$list->idx; // Skip 'LIMIT'
333
                    $this->limit = Limit::parse($parser, $list);
334
                    $state = 6;
335
                } elseif ($token->type === Token::TYPE_KEYWORD) {
336
                    $parser->error(__('Unexpected keyword.'), $token);
337
                    break;
338
                } else {
339
                    break;
340
                }
341
            }
342
        }
343
344
        if ($state >= 2) {
345
            foreach ($this->from as $from_expr) {
346
                $from_expr->database = $from_expr->table;
347
                $from_expr->table = $from_expr->column;
348
                $from_expr->column = null;
349
            }
350
        }
351
352
        --$list->idx;
353
    }
354
}
355