Completed
Push — resets ( d2f77b...f5109b )
by Paul
04:44 queued 02:34
created

Select::resetGroupBy()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 5
ccs 3
cts 3
cp 1
rs 9.4285
cc 1
eloc 3
nc 1
nop 0
crap 1
1
<?php
2
/**
3
 *
4
 * This file is part of Aura for PHP.
5
 *
6
 * @license http://opensource.org/licenses/bsd-license.php BSD
7
 *
8
 */
9
namespace Aura\SqlQuery\Common;
10
11
use Aura\SqlQuery\AbstractQuery;
12
use Aura\SqlQuery\Exception;
13
14
/**
15
 *
16
 * An object for SELECT queries.
17
 *
18
 * @package Aura.SqlQuery
19
 *
20
 */
21
class Select extends AbstractQuery implements SelectInterface, SubselectInterface
22
{
23
    /**
24
     *
25
     * An array of union SELECT statements.
26
     *
27
     * @var array
28
     *
29
     */
30
    protected $union = array();
31
32
    /**
33
     *
34
     * Is this a SELECT FOR UPDATE?
35
     *
36
     * @var
37
     *
38
     */
39
    protected $for_update = false;
40
41
    /**
42
     *
43
     * The columns to be selected.
44
     *
45
     * @var array
46
     *
47
     */
48
    protected $cols = array();
49
50
    /**
51
     *
52
     * Select from these tables; includes JOIN clauses.
53
     *
54
     * @var array
55
     *
56
     */
57
    protected $from = array();
58
59
    /**
60
     *
61
     * The current key in the `$from` array.
62
     *
63
     * @var int
64
     *
65
     */
66
    protected $from_key = -1;
67
68
    protected $join = array();
69
70
    /**
71
     *
72
     * GROUP BY these columns.
73
     *
74
     * @var array
75
     *
76
     */
77
    protected $group_by = array();
78
79
    /**
80
     *
81
     * The list of HAVING conditions.
82
     *
83
     * @var array
84
     *
85
     */
86
    protected $having = array();
87
88
    /**
89
     *
90
     * The page number to select.
91
     *
92
     * @var int
93
     *
94
     */
95
    protected $page = 0;
96
97
    /**
98
     *
99
     * The number of rows per page.
100
     *
101
     * @var int
102
     *
103
     */
104
    protected $paging = 10;
105
106
    /**
107
     *
108
     * Tracks table references to avoid duplicate identifiers.
109
     *
110
     * @var array
111
     *
112
     */
113
    protected $table_refs = array();
114
115
    /**
116
     *
117
     * Returns this query object as an SQL statement string.
118
     *
119
     * @return string An SQL statement string.
120
     *
121
     */
122 184
    public function getStatement()
123
    {
124 184
        $union = '';
125 184
        if ($this->union) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->union of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
126 15
            $union = implode(PHP_EOL, $this->union) . PHP_EOL;
127
        }
128 184
        return $union . $this->build();
129
    }
130
131
    /**
132
     *
133
     * Sets the number of rows per page.
134
     *
135
     * @param int $paging The number of rows to page at.
136
     *
137
     * @return $this
138
     *
139
     */
140 10
    public function setPaging($paging)
141
    {
142 10
        $this->paging = (int) $paging;
143 10
        if ($this->page) {
144 5
            $this->setPagingLimitOffset();
145
        }
146 10
        return $this;
147
    }
148
149
    /**
150
     *
151
     * Gets the number of rows per page.
152
     *
153
     * @return int The number of rows per page.
154
     *
155
     */
156 10
    public function getPaging()
157
    {
158 10
        return $this->paging;
159
    }
160
161
    /**
162
     *
163
     * Makes the select FOR UPDATE (or not).
164
     *
165
     * @param bool $enable Whether or not the SELECT is FOR UPDATE (default
166
     * true).
167
     *
168
     * @return $this
169
     *
170
     */
171 20
    public function forUpdate($enable = true)
172
    {
173 20
        $this->for_update = (bool) $enable;
174 20
        return $this;
175
    }
176
177
    /**
178
     *
179
     * Makes the select DISTINCT (or not).
180
     *
181
     * @param bool $enable Whether or not the SELECT is DISTINCT (default
182
     * true).
183
     *
184
     * @return $this
185
     *
186
     */
187 16
    public function distinct($enable = true)
188
    {
189 16
        $this->setFlag('DISTINCT', $enable);
190 16
        return $this;
191
    }
192
193
    /**
194
     *
195
     * Adds columns to the query.
196
     *
197
     * Multiple calls to cols() will append to the list of columns, not
198
     * overwrite the previous columns.
199
     *
200
     * @param array $cols The column(s) to add to the query. The elements can be
201
     * any mix of these: `array("col", "col AS alias", "col" => "alias")`
202
     *
203
     * @return $this
204
     *
205
     */
206 224
    public function cols(array $cols)
207
    {
208 224
        foreach ($cols as $key => $val) {
209 224
            $this->addCol($key, $val);
210
        }
211 224
        return $this;
212
    }
213
214
    /**
215
     *
216
     * Adds a column and alias to the columns to be selected.
217
     *
218
     * @param mixed $key If an integer, ignored. Otherwise, the column to be
219
     * added.
220
     *
221
     * @param mixed $val If $key was an integer, the column to be added;
222
     * otherwise, the column alias.
223
     *
224
     * @return null
225
     *
226
     */
227 224
    protected function addCol($key, $val)
228
    {
229 224
        if (is_string($key)) {
230
            // [col => alias]
231 25
            $this->cols[$val] = $key;
232
        } else {
233 214
            $this->addColWithAlias($val);
234
        }
235 224
    }
236
237
    /**
238
     *
239
     * Adds a column with an alias to the columns to be selected.
240
     *
241
     * @param string $spec The column specification: "col alias",
242
     * "col AS alias", or something else entirely.
243
     *
244
     * @return null
245
     *
246
     */
247 214
    protected function addColWithAlias($spec)
248
    {
249 214
        $parts = explode(' ', $spec);
250 214
        $count = count($parts);
251 214
        if ($count == 2) {
252
            // "col alias"
253 5
            $this->cols[$parts[1]] = $parts[0];
254 214
        } elseif ($count == 3 && strtoupper($parts[1]) == 'AS') {
255
            // "col AS alias"
256 5
            $this->cols[$parts[2]] = $parts[0];
257
        } else {
258
            // no recognized alias
259 214
            $this->cols[] = $spec;
260
        }
261 214
    }
262
263
    /**
264
     *
265
     * Remove a column via its alias.
266
     *
267
     * @param string $alias The column to remove
268
     *
269
     * @return null
270
     *
271
     */
272 15
    public function removeCol($alias)
273
    {
274 15
        if (isset($this->cols[$alias])) {
275 5
            unset($this->cols[$alias]);
276
277 5
            return true;
278
        }
279
280 10
        $index = array_search($alias, $this->cols);
281 10
        if ($index !== false) {
282 5
            unset($this->cols[$index]);
283 5
            return true;
284
        }
285
286 5
        return false;
287
    }
288
289
    /**
290
     *
291
     * Does the query have any columns in it?
292
     *
293
     * @return bool
294
     *
295
     */
296 5
    public function hasCols()
297
    {
298 5
        return (bool) $this->cols;
299
    }
300
301
    /**
302
     *
303
     * Returns a list of columns.
304
     *
305
     * @return array
306
     *
307
     */
308 15
    public function getCols()
309
    {
310 15
        return $this->cols;
311
    }
312
313
    /**
314
     *
315
     * Tracks table references.
316
     *
317
     * @param string $type FROM, JOIN, etc.
318
     *
319
     * @param string $spec The table and alias name.
320
     *
321
     * @return null
322
     *
323
     * @throws Exception when the reference has already been used.
324
     *
325
     */
326 149
    protected function addTableRef($type, $spec)
327
    {
328 149
        $name = $spec;
329
330 149
        $pos = strripos($name, ' AS ');
331 149
        if ($pos !== false) {
332 35
            $name = trim(substr($name, $pos + 4));
333
        }
334
335 149
        if (isset($this->table_refs[$name])) {
336 25
            $used = $this->table_refs[$name];
337 25
            throw new Exception("Cannot reference '$type $spec' after '$used'");
338
        }
339
340 149
        $this->table_refs[$name] = "$type $spec";
341 149
    }
342
343
    /**
344
     *
345
     * Adds a FROM element to the query; quotes the table name automatically.
346
     *
347
     * @param string $spec The table specification; "foo" or "foo AS bar".
348
     *
349
     * @return $this
350
     *
351
     */
352 139
    public function from($spec)
353
    {
354 139
        $this->addTableRef('FROM', $spec);
355 139
        return $this->addFrom($this->quoter->quoteName($spec));
356
    }
357
358
    /**
359
     *
360
     * Adds a raw unquoted FROM element to the query; useful for adding FROM
361
     * elements that are functions.
362
     *
363
     * @param string $spec The table specification, e.g. "function_name()".
364
     *
365
     * @return $this
366
     *
367
     */
368 5
    public function fromRaw($spec)
369
    {
370 5
        $this->addTableRef('FROM', $spec);
371 5
        return $this->addFrom($spec);
372
    }
373
374
    /**
375
     *
376
     * Adds to the $from property and increments the key count.
377
     *
378
     * @param string $spec The table specification.
379
     *
380
     * @return $this
381
     *
382
     */
383 149
    protected function addFrom($spec)
384
    {
385 149
        $this->from[] = array($spec);
386 149
        $this->from_key ++;
387 149
        return $this;
388
    }
389
390
    /**
391
     *
392
     * Adds an aliased sub-select to the query.
393
     *
394
     * @param string|Select $spec If a Select object, use as the sub-select;
395
     * if a string, the sub-select string.
396
     *
397
     * @param string $name The alias name for the sub-select.
398
     *
399
     * @return $this
400
     *
401
     */
402 15
    public function fromSubSelect($spec, $name)
403
    {
404 15
        $this->addTableRef('FROM (SELECT ...) AS', $name);
405 10
        $spec = $this->subSelect($spec, '        ');
406 10
        $name = $this->quoter->quoteName($name);
407 10
        return $this->addFrom("({$spec}    ) AS $name");
408
    }
409
410
    /**
411
     *
412
     * Formats a sub-SELECT statement, binding values from a Select object as
413
     * needed.
414
     *
415
     * @param string|SelectInterface $spec A sub-SELECT specification.
416
     *
417
     * @param string $indent Indent each line with this string.
418
     *
419
     * @return string The sub-SELECT string.
420
     *
421
     */
422 25
    protected function subSelect($spec, $indent)
423
    {
424 25
        if ($spec instanceof SelectInterface) {
425 10
            $this->bindValues($spec->getBindValues());
426
        }
427
428 25
        return PHP_EOL . $indent
429 25
            . ltrim(preg_replace('/^/m', $indent, (string) $spec))
430 25
            . PHP_EOL;
431
    }
432
433
    /**
434
     *
435
     * Adds a JOIN table and columns to the query.
436
     *
437
     * @param string $join The join type: inner, left, natural, etc.
438
     *
439
     * @param string $spec The table specification; "foo" or "foo AS bar".
440
     *
441
     * @param string $cond Join on this condition.
442
     *
443
     * @param array $bind Values to bind to ?-placeholders in the condition.
444
     *
445
     * @return $this
446
     *
447
     * @throws Exception
448
     *
449
     */
450 45
    public function join($join, $spec, $cond = null, array $bind = array())
451
    {
452 45
        $join = strtoupper(ltrim("$join JOIN"));
453 45
        $this->addTableRef($join, $spec);
454
455 40
        $spec = $this->quoter->quoteName($spec);
456 40
        $cond = $this->fixJoinCondition($cond, $bind);
457 40
        return $this->addJoin(rtrim("$join $spec $cond"));
458
    }
459
460
    /**
461
     *
462
     * Fixes a JOIN condition to quote names in the condition and prefix it
463
     * with a condition type ('ON' is the default and 'USING' is recognized).
464
     *
465
     * @param string $cond Join on this condition.
466
     *
467
     * @param array $bind Values to bind to ?-placeholders in the condition.
468
     *
469
     * @return string
470
     *
471
     */
472 55
    protected function fixJoinCondition($cond, array $bind)
473
    {
474 55
        if (! $cond) {
475 25
            return;
476
        }
477
478 55
        $cond = $this->quoter->quoteNamesIn($cond);
479 55
        $cond = $this->rebuildCondAndBindValues($cond, $bind);
480
481 55
        if (strtoupper(substr(ltrim($cond), 0, 3)) == 'ON ') {
482 5
            return $cond;
483
        }
484
485 55
        if (strtoupper(substr(ltrim($cond), 0, 6)) == 'USING ') {
486 5
            return $cond;
487
        }
488
489 50
        return 'ON ' . $cond;
490
    }
491
492
    /**
493
     *
494
     * Adds a INNER JOIN table and columns to the query.
495
     *
496
     * @param string $spec The table specification; "foo" or "foo AS bar".
497
     *
498
     * @param string $cond Join on this condition.
499
     *
500
     * @param array $bind Values to bind to ?-placeholders in the condition.
501
     *
502
     * @return $this
503
     *
504
     * @throws Exception
505
     *
506
     */
507 10
    public function innerJoin($spec, $cond = null, array $bind = array())
508
    {
509 10
        return $this->join('INNER', $spec, $cond, $bind);
510
    }
511
512
    /**
513
     *
514
     * Adds a LEFT JOIN table and columns to the query.
515
     *
516
     * @param string $spec The table specification; "foo" or "foo AS bar".
517
     *
518
     * @param string $cond Join on this condition.
519
     *
520
     * @param array $bind Values to bind to ?-placeholders in the condition.
521
     *
522
     * @return $this
523
     *
524
     * @throws Exception
525
     *
526
     */
527 10
    public function leftJoin($spec, $cond = null, array $bind = array())
528
    {
529 10
        return $this->join('LEFT', $spec, $cond, $bind);
530
    }
531
532
    /**
533
     *
534
     * Adds a JOIN to an aliased subselect and columns to the query.
535
     *
536
     * @param string $join The join type: inner, left, natural, etc.
537
     *
538
     * @param string|Select $spec If a Select
539
     * object, use as the sub-select; if a string, the sub-select
540
     * command string.
541
     *
542
     * @param string $name The alias name for the sub-select.
543
     *
544
     * @param string $cond Join on this condition.
545
     *
546
     * @param array $bind Values to bind to ?-placeholders in the condition.
547
     *
548
     * @return $this
549
     *
550
     * @throws Exception
551
     *
552
     */
553 20
    public function joinSubSelect($join, $spec, $name, $cond = null, array $bind = array())
554
    {
555 20
        $join = strtoupper(ltrim("$join JOIN"));
556 20
        $this->addTableRef("$join (SELECT ...) AS", $name);
557
558 15
        $spec = $this->subSelect($spec, '            ');
559 15
        $name = $this->quoter->quoteName($name);
560 15
        $cond = $this->fixJoinCondition($cond, $bind);
561
562 15
        $text = rtrim("$join ($spec        ) AS $name $cond");
563 15
        return $this->addJoin('        ' . $text);
564
    }
565
566 55
    protected function addJoin($spec)
567
    {
568 55
        $from_key = ($this->from_key == -1) ? 0 : $this->from_key;
569 55
        $this->join[$from_key][] = $spec;
570 55
        return $this;
571
    }
572
573
    /**
574
     *
575
     * Adds grouping to the query.
576
     *
577
     * @param array $spec The column(s) to group by.
578
     *
579
     * @return $this
580
     *
581
     */
582 5
    public function groupBy(array $spec)
583
    {
584 5
        foreach ($spec as $col) {
585 5
            $this->group_by[] = $this->quoter->quoteNamesIn($col);
586
        }
587 5
        return $this;
588
    }
589
590
    /**
591
     *
592
     * Adds a HAVING condition to the query by AND. If the condition has
593
     * ?-placeholders, additional arguments to the method will be bound to
594
     * those placeholders sequentially.
595
     *
596
     * @param string $cond The HAVING condition.
597
     *
598
     * @return $this
599
     *
600
     */
601 10
    public function having($cond)
602
    {
603 10
        $this->addClauseCondWithBind('having', 'AND', func_get_args());
604 10
        return $this;
605
    }
606
607
    /**
608
     *
609
     * Adds a HAVING condition to the query by AND. If the condition has
610
     * ?-placeholders, additional arguments to the method will be bound to
611
     * those placeholders sequentially.
612
     *
613
     * @param string $cond The HAVING condition.
614
     *
615
     * @return $this
616
     *
617
     * @see having()
618
     *
619
     */
620 5
    public function orHaving($cond)
621
    {
622 5
        $this->addClauseCondWithBind('having', 'OR', func_get_args());
623 5
        return $this;
624
    }
625
626
    /**
627
     *
628
     * Sets the limit and count by page number.
629
     *
630
     * @param int $page Limit results to this page number.
631
     *
632
     * @return $this
633
     *
634
     */
635 25
    public function page($page)
636
    {
637 25
        $this->page = (int) $page;
638 25
        $this->setPagingLimitOffset();
639 25
        return $this;
640
    }
641
642
    /**
643
     *
644
     * Updates the limit and offset values when changing pagination.
645
     *
646
     * @return null
647
     *
648
     */
649 25
    protected function setPagingLimitOffset()
650
    {
651 25
        $this->limit  = 0;
652 25
        $this->offset = 0;
653 25
        if ($this->page) {
654 10
            $this->limit  = $this->paging;
655 10
            $this->offset = $this->paging * ($this->page - 1);
656
        }
657 25
    }
658
659
    /**
660
     *
661
     * Returns the page number being selected.
662
     *
663
     * @return int
664
     *
665
     */
666 5
    public function getPage()
667
    {
668 5
        return $this->page;
669
    }
670
671
    /**
672
     *
673
     * Takes the current select properties and retains them, then sets
674
     * UNION for the next set of properties.
675
     *
676
     * @return $this
677
     *
678
     */
679 10
    public function union()
680
    {
681 10
        $this->union[] = $this->build() . PHP_EOL . 'UNION';
682 10
        $this->reset();
683 10
        return $this;
684
    }
685
686
    /**
687
     *
688
     * Takes the current select properties and retains them, then sets
689
     * UNION ALL for the next set of properties.
690
     *
691
     * @return $this
692
     *
693
     */
694 5
    public function unionAll()
695
    {
696 5
        $this->union[] = $this->build() . PHP_EOL . 'UNION ALL';
697 5
        $this->reset();
698 5
        return $this;
699
    }
700
701
    /**
702
     *
703
     * Returns the LIMIT value.
704
     *
705
     * @return int
706
     *
707
     */
708 10
    public function getLimit()
709
    {
710 10
        return $this->limit;
711
    }
712
713
    /**
714
     *
715
     * Returns the OFFSET value.
716
     *
717
     * @return int
718
     *
719
     */
720 10
    public function getOffset()
721
    {
722 10
        return $this->offset;
723
    }
724
725
    /**
726
     *
727
     * Clears the current select properties; generally used after adding a
728
     * union.
729
     *
730
     * @return null
731
     *
732
     */
733 15
    protected function reset()
734
    {
735 15
        $this->resetFlags();
736 15
        $this->resetCols();
737 15
        $this->resetTables();
738 15
        $this->resetWhere();
739 15
        $this->resetGroupBy();
740 15
        $this->resetHaving();
741 15
        $this->resetOrderBy();
742 15
        $this->limit(0);
743 15
        $this->offset(0);
744 15
        $this->page(0);
745 15
        $this->forUpdate(false);
746 15
    }
747
748 15
    public function resetCols()
749
    {
750 15
        $this->cols = array();
751 15
        return $this;
752
    }
753
754 15
    public function resetTables()
755
    {
756 15
        $this->from = array();
757 15
        $this->from_key = -1;
758 15
        $this->join = array();
759 15
        $this->table_refs = array();
760 15
        return $this;
761
    }
762
763 15
    public function resetWhere()
764
    {
765 15
        $this->where = array();
766 15
        return $this;
767
    }
768
769 15
    public function resetGroupBy()
770
    {
771 15
        $this->group_by = array();
772 15
        return $this;
773
    }
774
775 15
    public function resetHaving()
776
    {
777 15
        $this->having = array();
778 15
        return $this;
779
    }
780
781 15
    public function resetOrderBy()
782
    {
783 15
        $this->order_by = array();
784 15
        return $this;
785
    }
786
787
    public function resetUnions()
788
    {
789
        $this->union = array();
790
        return $this;
791
    }
792
793
    /**
794
     *
795
     * Builds this query object into a string.
796
     *
797
     * @return string
798
     *
799
     */
800 184
    protected function build()
801
    {
802
        return 'SELECT'
803 184
            . $this->buildFlags()
804 184
            . $this->buildCols()
805 179
            . $this->buildFrom() // includes JOIN
806 179
            . $this->buildWhere()
807 179
            . $this->buildGroupBy()
808 179
            . $this->buildHaving()
809 179
            . $this->buildOrderBy()
810 179
            . $this->buildLimit()
811 179
            . $this->buildForUpdate();
812
    }
813
814
    /**
815
     *
816
     * Builds the columns clause.
817
     *
818
     * @return string
819
     *
820
     * @throws Exception when there are no columns in the SELECT.
821
     *
822
     */
823 184
    protected function buildCols()
824
    {
825 184
        if (! $this->cols) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->cols of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
826 5
            throw new Exception('No columns in the SELECT.');
827
        }
828
829 179
        $cols = array();
830 179
        foreach ($this->cols as $key => $val) {
831 179
            if (is_int($key)) {
832 179
                $cols[] = $this->quoter->quoteNamesIn($val);
833
            } else {
834 179
                $cols[] = $this->quoter->quoteNamesIn("$val AS $key");
835
            }
836
        }
837
838 179
        return $this->indentCsv($cols);
839
    }
840
841
    /**
842
     *
843
     * Builds the FROM clause.
844
     *
845
     * @return string
846
     *
847
     */
848 179
    protected function buildFrom()
849
    {
850 179
        if (! $this->from) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->from of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
851 60
            return ''; // not applicable
852
        }
853
854 119
        $refs = array();
855 119
        foreach ($this->from as $from_key => $from) {
856 119
            if (isset($this->join[$from_key])) {
857 55
                $from = array_merge($from, $this->join[$from_key]);
858
            }
859 119
            $refs[] = implode(PHP_EOL, $from);
860
        }
861 119
        return PHP_EOL . 'FROM' . $this->indentCsv($refs);
862
    }
863
864
    /**
865
     *
866
     * Builds the GROUP BY clause.
867
     *
868
     * @return string
869
     *
870
     */
871 179
    protected function buildGroupBy()
872
    {
873 179
        if (! $this->group_by) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->group_by of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
874 174
            return ''; // not applicable
875
        }
876
877 5
        return PHP_EOL . 'GROUP BY' . $this->indentCsv($this->group_by);
878
    }
879
880
    /**
881
     *
882
     * Builds the HAVING clause.
883
     *
884
     * @return string
885
     *
886
     */
887 179
    protected function buildHaving()
888
    {
889 179
        if (! $this->having) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->having of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
890 164
            return ''; // not applicable
891
        }
892
893 15
        return PHP_EOL . 'HAVING' . $this->indent($this->having);
894
    }
895
896
    /**
897
     *
898
     * Builds the FOR UPDATE clause.
899
     *
900
     * @return string
901
     *
902
     */
903 179
    protected function buildForUpdate()
904
    {
905 179
        if (! $this->for_update) {
906 174
            return ''; // not applicable
907
        }
908
909 5
        return PHP_EOL . 'FOR UPDATE';
910
    }
911
912
    /**
913
     *
914
     * Adds a WHERE condition to the query by AND. If the condition has
915
     * ?-placeholders, additional arguments to the method will be bound to
916
     * those placeholders sequentially.
917
     *
918
     * @param string $cond The WHERE condition.
919
     * @param mixed ...$bind arguments to bind to placeholders
920
     *
921
     * @return $this
922
     *
923
     */
924 30
    public function where($cond)
925
    {
926 30
        $this->addWhere('AND', func_get_args());
927 30
        return $this;
928
    }
929
930
    /**
931
     *
932
     * Adds a WHERE condition to the query by OR. If the condition has
933
     * ?-placeholders, additional arguments to the method will be bound to
934
     * those placeholders sequentially.
935
     *
936
     * @param string $cond The WHERE condition.
937
     * @param mixed ...$bind arguments to bind to placeholders
938
     *
939
     * @return $this
940
     *
941
     * @see where()
942
     *
943
     */
944 5
    public function orWhere($cond)
945
    {
946 5
        $this->addWhere('OR', func_get_args());
947 5
        return $this;
948
    }
949
950
    /**
951
     *
952
     * Sets a limit count on the query.
953
     *
954
     * @param int $limit The number of rows to select.
955
     *
956
     * @return $this
957
     *
958
     */
959 30
    public function limit($limit)
960
    {
961 30
        $this->limit = (int) $limit;
962 30
        if ($this->page) {
963 5
            $this->page = 0;
964 5
            $this->offset = 0;
965
        }
966 30
        return $this;
967
    }
968
969
    /**
970
     *
971
     * Sets a limit offset on the query.
972
     *
973
     * @param int $offset Start returning after this many rows.
974
     *
975
     * @return $this
976
     *
977
     */
978 30
    public function offset($offset)
979
    {
980 30
        $this->offset = (int) $offset;
981 30
        if ($this->page) {
982 5
            $this->page = 0;
983 5
            $this->limit = 0;
984
        }
985 30
        return $this;
986
    }
987
988
    /**
989
     *
990
     * Adds a column order to the query.
991
     *
992
     * @param array $spec The columns and direction to order by.
993
     *
994
     * @return $this
995
     *
996
     */
997 5
    public function orderBy(array $spec)
998
    {
999 5
        return $this->addOrderBy($spec);
1000
    }
1001
}
1002