Completed
Push — master ( 8abdd4...b2a814 )
by Rasmus
02:25
created

SelectQuery::table()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
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 6
ccs 3
cts 3
cp 1
rs 9.4285
cc 1
eloc 3
nc 1
nop 1
crap 1
1
<?php
2
3
namespace mindplay\sql\model;
4
5
use mindplay\sql\framework\Driver;
6
use mindplay\sql\framework\MapperProvider;
7
use mindplay\sql\framework\TypeProvider;
8
use mindplay\sql\model\components\Mappers;
9
use mindplay\sql\model\components\ReturnVars;
10
11
/**
12
 * This class represents a SELECT query.
13
 *
14
 * This class implements `__toString()` magic, enabling the use of this query builder
15
 * in the SELECT, WHERE or ORDER BY clause of a parent SELECT (or other type of) query.
16
 *
17
 * Note that, when constructing nested queries, parameters must be bound against the
18
 * parent query - binding parameters or applying Mappers against a nested query has no effect.
19
 */
20
class SelectQuery extends ProjectionQuery implements MapperProvider
21
{
22
    use Mappers;
23
24
    /**
25
     * @var ReturnVars
26
     */
27
    protected $return_vars;
28
29
    /**
30
     * @var string[] list of GROUP BY expressions
31
     */
32
    protected $group_by = [];
33
34
    /**
35
     * @var string[] list of HAVING expressions
36
     */
37
    protected $having = [];
38
39
    /**
40
     * @param Table        $root
41
     * @param Driver       $driver
42
     * @param TypeProvider $types
43
     */
44 1
    public function __construct(Table $root, Driver $driver, TypeProvider $types)
45
    {
46 1
        parent::__construct($root, $driver, $types);
47
        
48 1
        $this->return_vars = new ReturnVars($root, $driver, $types);
49 1
    }
50
51
    /**
52
     * Add all the Columns of a full Table to be selected and returned
53
     *
54
     * @param Table $table Table to select and return
55
     *
56
     * @return $this
57
     */
58 1
    public function table(Table $table)
59
    {
60 1
        $this->return_vars->addTable($table);
61
62 1
        return $this;
63
    }
64
65
    /**
66
     * Add one or more Columns to select and return
67
     *
68
     * @param Column|Column[] one or more Columns to select and return
69
     *
70
     * @return $this
71
     */
72 1
    public function columns($cols)
73
    {
74 1
        $this->return_vars->addColumns($cols);
75
76 1
        return $this;
77
    }
78
79
    /**
80
     * Add an SQL expression to select and return
81
     *
82
     * @param string           $expr return expression
83
     * @param string|null      $name return variable name (optional, but usually required)
84
     * @param Type|string|null $type optional Type (or Type class-name)
85
     *
86
     * @return $this
87
     */
88 1
    public function value($expr, $name = null, $type = null)
89
    {
90 1
        $this->return_vars->addValue($expr, $name, $type);
91
92 1
        return $this;
93
    }
94
95
    /**
96
     * Add an expression to apply to a GROUP BY clause
97
     *
98
     * @param Column|string $expr SQL expression (or Column object) to apply to the GROUP BY clause
99
     *
100
     * @return $this
101
     */
102 1
    public function groupBy($expr)
103
    {
104 1
        $this->group_by[] = (string) $expr;
105
106 1
        return $this;
107
    }
108
109
    /**
110
     * @param string|string[] $exprs one or more condition expressions to apply to the HAVING clause
111
     *
112
     * @return $this
113
     */
114 1
    public function having($exprs)
115
    {
116 1
        foreach ((array) $exprs as $expr) {
117 1
            $this->having[] = $expr;
118
        }
119
120 1
        return $this;
121
    }
122
123
    /**
124
     * @inheritdoc
125
     */
126 1
    public function getMappers()
127
    {
128 1
        return array_merge([$this->return_vars->createTypeMapper()], $this->mappers);
129
    }
130
131
    /**
132
     * @inheritdoc
133
     */
134 1
    public function getSQL()
135
    {
136 1
        $select = "SELECT " . $this->return_vars->buildReturnVars();
137
138 1
        $from = "\nFROM " . $this->buildNodes();
139
140 1
        $where = count($this->conditions)
141 1
            ? "\nWHERE " . $this->buildConditions()
142 1
            : ''; // no conditions present
143
        
144 1
        $group_by = count($this->group_by)
145 1
            ? "\nGROUP BY " . implode(", ", $this->group_by)
146 1
            : ""; // no group-by expressions
147
148 1
        $having = count($this->having)
149 1
            ? "\nHAVING " . $this->buildHaving()
150 1
            : ''; // no having clause present
151
        
152 1
        $order = count($this->order)
153 1
            ? "\nORDER BY " . $this->buildOrderTerms()
154 1
            : ''; // no order terms
155
156 1
        $limit = $this->limit !== null
157 1
            ? "\nLIMIT {$this->limit}"
158 1
            . ($this->offset !== null ? " OFFSET {$this->offset}" : '')
159 1
            : ''; // no limit or offset
160
161 1
        return "{$select}{$from}{$where}{$group_by}{$having}{$order}{$limit}";
162
    }
163
    
164
    /**
165
     * @ignore string magic (enables creation of nested SELECT queries)
166
     */
167 1
    public function __toString()
168
    {
169 1
        return "(" . $this->getSQL() . ")";
170
    }
171
172
    /**
173
     * @return string combined condition expression (for use in the WHERE clause of an SQL statement)
174
     */
175 1
    protected function buildHaving()
176
    {
177 1
        return implode(" AND ", $this->having);
178
    }
179
}
180