Completed
Pull Request — 1.1 (#15)
by David
11:22
created

Select::getLimit()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 3
rs 10
cc 1
eloc 2
nc 1
nop 0
1
<?php
2
3
/**
4
 * expression-types.php.
5
 *
6
 *
7
 * Copyright (c) 2010-2013, Justin Swanhart
8
 * with contributions by André Rothe <[email protected], [email protected]>
9
 * and David Négrier <[email protected]>
10
 *
11
 * All rights reserved.
12
 *
13
 * Redistribution and use in source and binary forms, with or without modification,
14
 * are permitted provided that the following conditions are met:
15
 *
16
 *   * Redistributions of source code must retain the above copyright notice,
17
 *     this list of conditions and the following disclaimer.
18
 *   * Redistributions in binary form must reproduce the above copyright notice,
19
 *     this list of conditions and the following disclaimer in the documentation
20
 *     and/or other materials provided with the distribution.
21
 *
22
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
23
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
25
 * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
27
 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
28
 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
31
 * DAMAGE.
32
 */
33
34
namespace SQLParser\Query;
35
36
use Doctrine\DBAL\Connection;
37
use Mouf\MoufInstanceDescriptor;
38
use SQLParser\Node\NodeFactory;
39
use Mouf\MoufManager;
40
use SQLParser\Node\NodeInterface;
41
use SQLParser\Node\Traverser\NodeTraverser;
42
use SQLParser\Node\Traverser\VisitorInterface;
43
44
/**
45
 * This class represents a <code>SELECT</code> query. You can use it to generate a SQL query statement
46
 * using the <code>toSql</code> method.
47
 * You can use the <code>QueryResult</code> class if you want to run the query directly.
48
 *
49
 * @author David Négrier <[email protected]>
50
 * @ExtendedAction {"name":"Generate from SQL", "url":"parseselect/", "default":false}
51
 * @ExtendedAction {"name":"Test query", "url":"parseselect/tryQuery", "default":false}
52
 * @Renderer { "smallLogo":"vendor/mouf/database.querywriter/icons/database_go.png" }
53
 */
54
class Select implements StatementInterface, NodeInterface
55
{
56
    private $distinct;
57
58
    /**
59
     * Returns true if the SELECT is a SELECT DISTINCT.
60
     *
61
     * @return bool
62
     */
63
    public function getDistinct()
64
    {
65
        return $this->distinct;
66
    }
67
68
    /**
69
     * Sets to true if the SELECT is a SELECT DISTINCT.
70
     *
71
     * @param bool $distinct
72
     */
73
    public function setDistinct($distinct)
74
    {
75
        $this->distinct = $distinct;
76
    }
77
78
    private $columns;
79
80
    /**
81
     * Returns the list of columns for this SQL select.
82
     *
83
     * @return NodeInterface[]
84
     */
85
    public function getColumns()
86
    {
87
        return $this->columns;
88
    }
89
90
    /**
91
     * Sets the list of columns for this SQL select.
92
     *
93
     * @param NodeInterface[] $columns
94
     */
95
    public function setColumns($columns)
96
    {
97
        $this->columns = $columns;
98
    }
99
100
    private $from;
101
102
    /**
103
     * Returns the list of tables for this SQL select.
104
     *
105
     * @return NodeInterface[]
106
     */
107
    public function getFrom()
108
    {
109
        return $this->from;
110
    }
111
112
    /**
113
     * Sets the list of tables for this SQL select.
114
     *
115
     * @param NodeInterface[] $from
116
     */
117
    public function setFrom($from)
118
    {
119
        $this->from = $from;
120
    }
121
122
    private $where;
123
124
    /**
125
     * Returns the list of where statements.
126
     *
127
     * @return NodeInterface[]
128
     */
129
    public function getWhere()
130
    {
131
        return $this->where;
132
    }
133
134
    /**
135
     * Sets the list of where statements.
136
     *
137
     * @param NodeInterface[]|NodeInterface $where
138
     */
139
    public function setWhere($where)
140
    {
141
        $this->where = $where;
142
    }
143
144
    private $group;
145
146
    /**
147
     * Returns the list of group statements.
148
     *
149
     * @return NodeInterface[]
150
     */
151
    public function getGroup()
152
    {
153
        return $this->group;
154
    }
155
156
    /**
157
     * Sets the list of group statements.
158
     *
159
     * @param NodeInterface[]|NodeInterface $group
160
     */
161
    public function setGroup($group)
162
    {
163
        $this->group = $group;
164
    }
165
166
    private $having;
167
168
    /**
169
     * Returns the list of having statements.
170
     *
171
     * @return NodeInterface[]|NodeInterface
172
     */
173
    public function getHaving()
174
    {
175
        return $this->having;
176
    }
177
178
    /**
179
     * Sets the list of having statements.
180
     *
181
     * @param NodeInterface[]|NodeInterface $having
182
     */
183
    public function setHaving($having)
184
    {
185
        $this->having = $having;
186
    }
187
188
    private $order;
189
190
    /**
191
     * Returns the list of order statements.
192
     *
193
     * @return NodeInterface[]|NodeInterface
194
     */
195
    public function getOrder()
196
    {
197
        return $this->order;
198
    }
199
200
    /**
201
     * Sets the list of order statements.
202
     *
203
     * @param NodeInterface[]|NodeInterface $order
204
     */
205
    public function setOrder($order)
206
    {
207
        $this->order = $order;
208
    }
209
210
    private $options;
211
212
    /**
213
     * Returns the list of options to be applied just after the "SELECT" keyword.
214
     *
215
     * @return string[]
216
     */
217
    public function getOptions()
218
    {
219
        return $this->options;
220
    }
221
222
    /**
223
     * Sets the list of options to be applied just after the "SELECT" keyword.
224
     *
225
     * @param string[] $options
226
     */
227
    public function setOptions($options)
228
    {
229
        $this->options = $options;
230
    }
231
232
    private $limit;
233
234
    /**
235
     * @return NodeInterface[]|NodeInterface $limit
236
     */
237
    public function getLimit() {
238
        return $this->limit;
239
    }
240
241
    /**
242
     * @param NodeInterface[]|NodeInterface $limit
243
     */
244
    public function setLimit($limit) {
245
        $this->limit = $limit;
246
    }
247
248
    /**
249
     * @param MoufManager $moufManager
250
     *
251
     * @return MoufInstanceDescriptor
252
     */
253 View Code Duplication
    public function toInstanceDescriptor(MoufManager $moufManager)
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...
254
    {
255
        $instanceDescriptor = $moufManager->createInstance(get_called_class());
256
        $instanceDescriptor->getProperty('distinct')->setValue($this->distinct);
257
        $instanceDescriptor->getProperty('columns')->setValue(NodeFactory::nodeToInstanceDescriptor($this->columns, $moufManager));
258
        $instanceDescriptor->getProperty('from')->setValue(NodeFactory::nodeToInstanceDescriptor($this->from, $moufManager));
259
        $instanceDescriptor->getProperty('where')->setValue(NodeFactory::nodeToInstanceDescriptor($this->where, $moufManager));
260
        $instanceDescriptor->getProperty('group')->setValue(NodeFactory::nodeToInstanceDescriptor($this->group, $moufManager));
261
        $instanceDescriptor->getProperty('having')->setValue(NodeFactory::nodeToInstanceDescriptor($this->having, $moufManager));
262
        $instanceDescriptor->getProperty('order')->setValue(NodeFactory::nodeToInstanceDescriptor($this->order, $moufManager));
263
        $instanceDescriptor->getProperty('limit')->setValue(NodeFactory::nodeToInstanceDescriptor($this->limit, $moufManager));
264
        $instanceDescriptor->getProperty('options')->setValue($this->options);
265
266
        return $instanceDescriptor;
267
    }
268
269
    /**
270
     * Configure the $instanceDescriptor describing this object (it must already exist as a Mouf instance).
271
     *
272
     * @param MoufManager $moufManager
273
     *
274
     * @return MoufInstanceDescriptor
275
     */
276 View Code Duplication
    public function overwriteInstanceDescriptor($name, MoufManager $moufManager)
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...
277
    {
278
        //$name = $moufManager->findInstanceName($this);
0 ignored issues
show
Unused Code Comprehensibility introduced by
64% 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...
279
        $instanceDescriptor = $moufManager->getInstanceDescriptor($name);
280
        $instanceDescriptor->getProperty('distinct')->setValue($this->distinct);
281
        $instanceDescriptor->getProperty('columns')->setValue(NodeFactory::nodeToInstanceDescriptor($this->columns, $moufManager));
282
        $instanceDescriptor->getProperty('from')->setValue(NodeFactory::nodeToInstanceDescriptor($this->from, $moufManager));
283
        $instanceDescriptor->getProperty('where')->setValue(NodeFactory::nodeToInstanceDescriptor($this->where, $moufManager));
284
        $instanceDescriptor->getProperty('group')->setValue(NodeFactory::nodeToInstanceDescriptor($this->group, $moufManager));
285
        $instanceDescriptor->getProperty('having')->setValue(NodeFactory::nodeToInstanceDescriptor($this->having, $moufManager));
286
        $instanceDescriptor->getProperty('order')->setValue(NodeFactory::nodeToInstanceDescriptor($this->order, $moufManager));
287
        $instanceDescriptor->getProperty('limit')->setValue(NodeFactory::nodeToInstanceDescriptor($this->limit, $moufManager));
288
        $instanceDescriptor->getProperty('options')->setValue($this->options);
289
290
        return $instanceDescriptor;
291
    }
292
293
    /**
294
     * Renders the object as a SQL string.
295
     *
296
     * @param array $parameters
297
     * @param Connection $dbConnection
298
     * @param int|number $indent
299
     * @param int $conditionsMode
300
     * @return string
301
     */
302
    public function toSql(array $parameters = array(), Connection $dbConnection = null, $indent = 0, $conditionsMode = self::CONDITION_APPLY)
303
    {
304
        $sql = 'SELECT ';
305
        if ($this->distinct) {
306
            $sql .= 'DISTINCT ';
307
        }
308
        if (is_array($this->options)) {
309
            $sql .= implode(' ', $this->options)."\n";
310
        }
311
312 View Code Duplication
        if (!empty($this->columns)) {
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...
313
            $sql .= NodeFactory::toSql($this->columns, $dbConnection, $parameters, ',', false, $indent + 2, $conditionsMode);
314
        }
315
316 View Code Duplication
        if (!empty($this->from)) {
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...
317
            $from = NodeFactory::toSql($this->from, $dbConnection, $parameters, ' ', false, $indent + 2, $conditionsMode);
318
            if ($from) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $from of type null|string 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...
319
                $sql .= "\nFROM ".$from;
320
            }
321
        }
322
323 View Code Duplication
        if (!empty($this->where)) {
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...
324
            $where = NodeFactory::toSql($this->where, $dbConnection, $parameters, ' ', false, $indent + 2, $conditionsMode);
325
            if ($where) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $where of type null|string 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...
326
                $sql .= "\nWHERE ".$where;
327
            }
328
        }
329
330 View Code Duplication
        if (!empty($this->group)) {
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...
331
            $groupBy = NodeFactory::toSql($this->group, $dbConnection, $parameters, ' ', false, $indent + 2, $conditionsMode);
332
            if ($groupBy) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $groupBy of type null|string 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...
333
                $sql .= "\nGROUP BY ".$groupBy;
334
            }
335
        }
336
337 View Code Duplication
        if (!empty($this->having)) {
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...
338
            $having = NodeFactory::toSql($this->having, $dbConnection, $parameters, ' ', false, $indent + 2, $conditionsMode);
339
            if ($having) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $having of type null|string 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...
340
                $sql .= "\nHAVING ".$having;
341
            }
342
        }
343
344 View Code Duplication
        if (!empty($this->order)) {
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...
345
            $order = NodeFactory::toSql($this->order, $dbConnection, $parameters, ',', false, $indent + 2, $conditionsMode);
346
            if ($order) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $order of type null|string 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...
347
                $sql .= "\nORDER BY ".$order;
348
            }
349
        }
350
351 View Code Duplication
        if (!empty($this->limit)) {
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...
352
            $limit = NodeFactory::toSql($this->limit, $dbConnection, $parameters, ',', false, $indent + 2, $conditionsMode);
353
            if ($limit) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $limit of type null|string 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...
354
                $sql .= "\nLIMIT ".$limit;
355
            }
356
        }
357
358
        return $sql;
359
    }
360
361
    /**
362
     * Walks the tree of nodes, calling the visitor passed in parameter.
363
     *
364
     * @param VisitorInterface $visitor
365
     */
366
    public function walk(VisitorInterface $visitor) {
367
        $node = $this;
368
        $result = $visitor->enterNode($node);
369
        if ($result instanceof NodeInterface) {
370
            $node = $result;
371
        }
372
        if ($result !== NodeTraverser::DONT_TRAVERSE_CHILDREN) {
373
            $this->walkChildren($this->columns, $visitor);
374
            $this->walkChildren($this->from, $visitor);
375
            $this->walkChildren($this->where, $visitor);
376
            $this->walkChildren($this->group, $visitor);
377
            $this->walkChildren($this->having, $visitor);
378
            $this->walkChildren($this->order, $visitor);
379
        }
380
        return $visitor->leaveNode($node);
381
    }
382
383
    private function walkChildren(&$children, VisitorInterface $visitor) {
384
        if ($children) {
385
            if (is_array($children)) {
386
                foreach ($children as $key => $operand) {
387
                    if($operand) {
388
                        $result2 = $operand->walk($visitor);
389
                        if ($result2 === NodeTraverser::REMOVE_NODE) {
390
                            unset($children[$key]);
391
                        } elseif ($result2 instanceof NodeInterface) {
392
                            $children[$key] = $result2;
393
                        }
394
                    }
395
                }
396
            } else {
397
                $result2 = $children->walk($visitor);
398
                if ($result2 === NodeTraverser::REMOVE_NODE) {
399
                    $children = null;
400
                } elseif ($result2 instanceof NodeInterface) {
401
                    $children = $result2;
402
                }
403
            }
404
        }
405
    }
406
}
407