SelectTest   A
last analyzed

Complexity

Total Complexity 6

Size/Duplication

Total Lines 199
Duplicated Lines 0 %

Importance

Changes 5
Bugs 0 Features 0
Metric Value
wmc 6
eloc 145
c 5
b 0
f 0
dl 0
loc 199
rs 10

6 Methods

Rating   Name   Duplication   Size   Complexity  
A testToStringModifiers() 0 13 1
A testToStringComplex() 0 25 1
A getSut() 0 3 1
A testToStringComplexWithUnion() 0 44 1
A testToStringComplexWithIntersect() 0 44 1
A testToStringComplexWithUnionAndExcept() 0 53 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace QB\PostgreSQL\Statement;
6
7
use QB\Generic\Clause\Column;
8
use QB\Generic\Clause\Table;
9
use QB\Generic\Expr\Expr;
10
use QB\Generic\Statement\SelectTest as GenericSelectTest;
11
use QB\PostgreSQL\Clause\Lock;
12
13
class SelectTest extends GenericSelectTest
14
{
15
    public function testToStringModifiers()
16
    {
17
        $sql = (string)$this->getSut('foo')
18
            ->modifier(Select::ALL, Select::DISTINCT)
19
            ->columns('id', 'bar_id');
20
21
        $parts   = [];
22
        $parts[] = 'SELECT ALL DISTINCT id, bar_id';
23
        $parts[] = 'FROM foo';
24
25
        $expectedSql = implode(PHP_EOL, $parts);
26
27
        $this->assertSame($expectedSql, $sql);
28
    }
29
30
    public function testToStringComplex()
31
    {
32
        $unionQuery = $this->getSut('baz')
33
            ->columns('id');
34
35
        $sql = (string)$this->getSut('foo')
36
            ->columns('id')
37
            ->union($unionQuery)
38
            ->outerOffset(20)
39
            ->outerLimit(10)
40
            ->outerOrderBy('id', Select::DIRECTION_DESC);
41
42
        $parts   = [];
43
        $parts[] = '(SELECT id';
44
        $parts[] = 'FROM foo';
45
        $parts[] = 'UNION';
46
        $parts[] = 'SELECT id';
47
        $parts[] = 'FROM baz)';
48
        $parts[] = 'ORDER BY id DESC';
49
        $parts[] = 'LIMIT 10';
50
        $parts[] = 'OFFSET 20 ROWS';
51
52
        $expectedSql = implode(PHP_EOL, $parts);
53
54
        $this->assertSame($expectedSql, $sql);
55
    }
56
57
    public function testToStringComplexWithUnion()
58
    {
59
        $columnQuery = $this->getSut('quix')
60
            ->columns('b')
61
            ->where(new Expr('id = ?', [7]));
62
63
        $columnExpr = new Expr('NOW()');
64
65
        $unionQuery = $this->getSut('baz')
66
            ->columns('b', 'f');
67
68
        $sql = (string)$this->getSut('foo', 'bar')
69
            ->modifier('DISTINCT')
70
            ->columns('COUNT(DISTINCT baz) AS baz_count', new Column($columnQuery, 'quix_b'))
71
            ->columns(new Column($columnExpr, 'now'))
72
            ->columns(new Column('bar.id', 'bar_id'))
73
            ->innerJoin(new Table('quix', 'q'), 'foo.id = q.foo_id')
74
            ->where('foo.bar = "foo-bar"', new Expr('bar.foo = ?', ['bar-foo']))
75
            ->groupBy('q.foo_id', new Expr('q.bar.id'))
76
            ->having('baz_count > 0')
77
            ->orderBy('baz_count', 'ASC')
78
            ->lock(new Lock(Lock::FOR_UPDATE, [], Lock::MODIFIER_NOWAIT))
79
            ->limit(10)
80
            ->offset(20)
81
            ->union($unionQuery);
82
83
        $parts   = [];
84
        $parts[] = 'SELECT DISTINCT COUNT(DISTINCT baz) AS baz_count, (SELECT b FROM quix WHERE id = ?) AS quix_b, NOW() AS now, bar.id AS bar_id'; // nolint
85
        $parts[] = 'FROM foo, bar';
86
        $parts[] = 'INNER JOIN quix AS q ON foo.id = q.foo_id';
87
        $parts[] = 'WHERE foo.bar = "foo-bar" AND bar.foo = ?';
88
        $parts[] = 'GROUP BY q.foo_id, q.bar.id';
89
        $parts[] = 'HAVING baz_count > 0';
90
        $parts[] = 'ORDER BY baz_count ASC';
91
        $parts[] = 'OFFSET 20 ROWS';
92
        $parts[] = 'FETCH FIRST 10 ROWS ONLY';
93
        $parts[] = 'FOR UPDATE NOWAIT';
94
        $parts[] = 'UNION';
95
        $parts[] = 'SELECT b, f';
96
        $parts[] = 'FROM baz';
97
98
        $expectedSql = implode(PHP_EOL, $parts);
99
100
        $this->assertSame($expectedSql, $sql);
101
    }
102
103
    public function testToStringComplexWithIntersect()
104
    {
105
        $columnQuery = $this->getSut('quix')
106
            ->columns('b')
107
            ->where(new Expr('id = ?', [7]));
108
109
        $columnExpr = new Expr('NOW()');
110
111
        $intersectQuery = $this->getSut('baz')
112
            ->columns('b', 'f');
113
114
        $sql = (string)$this->getSut('foo', 'bar')
115
            ->modifier('DISTINCT')
116
            ->columns('COUNT(DISTINCT baz) AS baz_count', new Column($columnQuery, 'quix_b'))
117
            ->columns(new Column($columnExpr, 'now'))
118
            ->columns(new Column('bar.id', 'bar_id'))
119
            ->innerJoin(new Table('quix', 'q'), 'foo.id = q.foo_id')
120
            ->where('foo.bar = "foo-bar"', new Expr('bar.foo = ?', ['bar-foo']))
121
            ->groupBy('q.foo_id', new Expr('q.bar.id'))
122
            ->having('baz_count > 0')
123
            ->orderBy('baz_count', 'ASC')
124
            ->lock(new Lock(Lock::FOR_UPDATE, ['foo'], Lock::MODIFIER_NOWAIT))
125
            ->limit(10)
126
            ->offset(20)
127
            ->intersect($intersectQuery);
128
129
        $parts   = [];
130
        $parts[] = 'SELECT DISTINCT COUNT(DISTINCT baz) AS baz_count, (SELECT b FROM quix WHERE id = ?) AS quix_b, NOW() AS now, bar.id AS bar_id'; // nolint
131
        $parts[] = 'FROM foo, bar';
132
        $parts[] = 'INNER JOIN quix AS q ON foo.id = q.foo_id';
133
        $parts[] = 'WHERE foo.bar = "foo-bar" AND bar.foo = ?';
134
        $parts[] = 'GROUP BY q.foo_id, q.bar.id';
135
        $parts[] = 'HAVING baz_count > 0';
136
        $parts[] = 'ORDER BY baz_count ASC';
137
        $parts[] = 'OFFSET 20 ROWS';
138
        $parts[] = 'FETCH FIRST 10 ROWS ONLY';
139
        $parts[] = 'FOR UPDATE OF foo NOWAIT';
140
        $parts[] = 'INTERSECT';
141
        $parts[] = 'SELECT b, f';
142
        $parts[] = 'FROM baz';
143
144
        $expectedSql = implode(PHP_EOL, $parts);
145
146
        $this->assertSame($expectedSql, $sql);
147
    }
148
149
    public function testToStringComplexWithUnionAndExcept()
150
    {
151
        $columnQuery = $this->getSut('quix')
152
            ->columns('b')
153
            ->where(new Expr('id = ?', [7]));
154
155
        $columnExpr = new Expr('NOW()');
156
157
        $unionQuery = $this->getSut('baz')
158
            ->columns('b', 'f');
159
160
        $exceptQuery = $this->getSut('sec')
161
            ->columns('v', 'w');
162
163
        $sql = (string)$this->getSut('foo', 'bar')
164
            ->modifier('DISTINCT')
165
            ->columns('COUNT(DISTINCT baz) AS baz_count', new Column($columnQuery, 'quix_b'))
166
            ->columns(new Column($columnExpr, 'now'))
167
            ->columns(new Column('bar.id', 'bar_id'))
168
            ->innerJoin(new Table('quix', 'q'), 'foo.id = q.foo_id')
169
            ->where('foo.bar = "foo-bar"', new Expr('bar.foo = ?', ['bar-foo']))
170
            ->groupBy('q.foo_id', new Expr('q.bar.id'))
171
            ->having('baz_count > 0')
172
            ->orderBy('baz_count', 'ASC')
173
            ->lock(new Lock(Lock::FOR_KEY_SHARE))
174
            ->limit(10)
175
            ->offset(20)
176
            ->union($unionQuery)
177
            ->except($exceptQuery)
178
            ->outerLimit(100);
179
180
        $parts   = [];
181
        $parts[] = '(SELECT DISTINCT COUNT(DISTINCT baz) AS baz_count, (SELECT b FROM quix WHERE id = ?) AS quix_b, NOW() AS now, bar.id AS bar_id'; // nolint
182
        $parts[] = 'FROM foo, bar';
183
        $parts[] = 'INNER JOIN quix AS q ON foo.id = q.foo_id';
184
        $parts[] = 'WHERE foo.bar = "foo-bar" AND bar.foo = ?';
185
        $parts[] = 'GROUP BY q.foo_id, q.bar.id';
186
        $parts[] = 'HAVING baz_count > 0';
187
        $parts[] = 'ORDER BY baz_count ASC';
188
        $parts[] = 'OFFSET 20 ROWS';
189
        $parts[] = 'FETCH FIRST 10 ROWS ONLY';
190
        $parts[] = 'FOR KEY SHARE';
191
        $parts[] = 'UNION';
192
        $parts[] = 'SELECT b, f';
193
        $parts[] = 'FROM baz';
194
        $parts[] = 'EXCEPT';
195
        $parts[] = 'SELECT v, w';
196
        $parts[] = 'FROM sec)';
197
        $parts[] = 'LIMIT 100';
198
199
        $expectedSql = implode(PHP_EOL, $parts);
200
201
        $this->assertSame($expectedSql, $sql);
202
    }
203
204
    /**
205
     * @param Table|string ...$tables
206
     *
207
     * @return Select
208
     */
209
    protected function getSut(Table|string ...$tables): Select
210
    {
211
        return (new Select())->from(...$tables);
212
    }
213
}
214