Completed
Pull Request — master (#87)
by Deven
126:59 queued 62:01
created

DeleteStatement::build()   C

Complexity

Conditions 13
Paths 64

Size

Total Lines 26
Code Lines 15

Duplication

Lines 12
Ratio 46.15 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 13
eloc 15
nc 64
nop 0
dl 12
loc 26
rs 5.1234
c 1
b 0
f 0

How to fix   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
        for (; $list->idx < $list->count; ++$list->idx) {
184
            /**
185
             * Token parsed at this moment.
186
             *
187
             * @var Token $token
188
             */
189
            $token = $list->tokens[$list->idx];
190
191
            // End of statement.
192
            if ($token->type === Token::TYPE_DELIMITER) {
193
                break;
194
            }
195
196
            // Skipping whitespaces and comments.
197
            if (($token->type === Token::TYPE_WHITESPACE) || ($token->type === Token::TYPE_COMMENT)) {
198
                continue;
199
            }
200
201
            if ($state === 0) {
202
                if ($token->type === Token::TYPE_KEYWORD
203
                    && $token->value !== 'FROM'
204
                ) {
205
                    $parser->error(__('Unexpected keyword.'), $token);
206
                    break;
207
                } elseif ($token->type === Token::TYPE_KEYWORD
208
                    && $token->value === 'FROM'
209
                ) {
210
                    ++$list->idx; // Skip 'FROM'
211
                    $this->from = ExpressionArray::parse($parser, $list);
212
                    $state = 2;
213
                } else {
214
                    $this->columns = ExpressionArray::parse($parser, $list);
215
                    $state = 1;
216
                }
217
            } elseif ($state === 1) {
218
                if ($token->type === Token::TYPE_KEYWORD
219
                    && $token->value !== 'FROM'
220
                ) {
221
                    $parser->error(__('Unexpected keyword.'), $token);
222
                    break;
223
                } elseif ($token->type === Token::TYPE_KEYWORD
224
                    && $token->value === 'FROM'
225
                ) {
226
                    ++$list->idx; // Skip 'FROM'
227
                    $this->from = ExpressionArray::parse($parser, $list);
228
                    $state = 2;
229
                }  elseif ($token->type === Token::TYPE_KEYWORD) {
230
                    $parser->error(__('Unexpected keyword.'), $token);
231
                    break;
232
                } else {
233
                    $parser->error(__('Unexpected token.'), $token);
234
                    break;
235
                }
236
            } elseif ($state === 2) {
237
                if ($token->type === Token::TYPE_KEYWORD
238
                    && $token->value === 'USING'
239
                ) {
240
                    ++$list->idx; // Skip 'FROM'
241
                    $this->using = ExpressionArray::parse($parser, $list);
242
                    $state = 3;
243
                } elseif ($token->type === Token::TYPE_KEYWORD
244
                    && $token->value === 'WHERE'
245
                ) {
246
                    ++$list->idx; // Skip 'WHERE'
247
                    $this->where = Condition::parse($parser, $list);
248
                    $state = 4;
249
                } elseif ($token->type === Token::TYPE_KEYWORD
250
                    && $token->value === 'ORDER BY'
251
                ) {
252
                    ++$list->idx; // Skip 'ORDER BY'
253
                    $this->order = OrderKeyword::parse($parser, $list);
254
                    $state = 5;
255
                } elseif ($token->type === Token::TYPE_KEYWORD
256
                    && $token->value === 'LIMIT'
257
                ) {
258
                    ++$list->idx; // Skip 'LIMIT'
259
                    $this->limit = Limit::parse($parser, $list);
260
                    $state = 6;
261
                } elseif ($token->type === Token::TYPE_KEYWORD) {
262
                    $parser->error(__('Unexpected keyword.'), $token);
263
                    break;
264
                } else {
265
                    $parser->error(__('Unexpected token.'), $token);
266
                    break;
267
                }
268
            } elseif ($state === 3) {
269
                if ($token->type === Token::TYPE_KEYWORD
270
                    && $token->value === 'WHERE'
271
                ) {
272
                    ++$list->idx; // Skip 'WHERE'
273
                    $this->where = Condition::parse($parser, $list);
274
                    $state = 4;
275
                } elseif ($token->type === Token::TYPE_KEYWORD
276
                    && $token->value === 'ORDER BY'
277
                ) {
278
                    ++$list->idx; // Skip 'ORDER  BY'
279
                    $this->order = OrderKeyword::parse($parser, $list);
280
                    $state = 5;
281
                }  elseif ($token->type === Token::TYPE_KEYWORD
282
                    && $token->value === 'LIMIT'
283
                ) {
284
                    ++$list->idx; // Skip 'LIMIT'
285
                    $this->limit = Limit::parse($parser, $list);
286
                    $state = 6;
287
                } elseif ($token->type === Token::TYPE_KEYWORD) {
288
                    $parser->error(__('Unexpected keyword.'), $token);
289
                    break;
290
                } else {
291
                    $parser->error(__('Unexpected token.'), $token);
292
                    break;
293
                }
294
            } elseif ($state === 4) {
295
                if ($token->type === Token::TYPE_KEYWORD
296
                    && $token->value === 'ORDER BY'
297
                ) {
298
                    ++$list->idx; // Skip 'ORDER  BY'
299
                    $this->order = OrderKeyword::parse($parser, $list);
300
                    $state = 5;
301
                }  elseif ($token->type === Token::TYPE_KEYWORD
302
                    && $token->value === 'LIMIT'
303
                ) {
304
                    ++$list->idx; // Skip 'LIMIT'
305
                    $this->limit = Limit::parse($parser, $list);
306
                    $state = 6;
307
                } elseif ($token->type === Token::TYPE_KEYWORD) {
308
                    $parser->error(__('Unexpected keyword.'), $token);
309
                    break;
310
                } else {
311
                    $parser->error(__('Unexpected token.'), $token);
312
                    break;
313
                }
314
            } elseif ($state === 5) {
315
                if ($token->type === Token::TYPE_KEYWORD
316
                    && $token->value === 'LIMIT'
317
                ) {
318
                    ++$list->idx; // Skip 'LIMIT'
319
                    $this->limit = Limit::parse($parser, $list);
320
                    $state = 6;
321
                } elseif ($token->type === Token::TYPE_KEYWORD) {
322
                    $parser->error(__('Unexpected keyword.'), $token);
323
                    break;
324
                } else {
325
                    $parser->error(__('Unexpected token.'), $token);
326
                    break;
327
                }
328
            }
329
        }
330
331
        if ($state >= 2) {
332
            foreach ($this->from as $from_expr) {
333
                $from_expr->database = $from_expr->table;
334
                $from_expr->table = $from_expr->column;
335
                $from_expr->column = null;
336
            }
337
        }
338
339
        --$list->idx;
340
    }
341
}
342