Completed
Branch feature/pre-split (ecea15)
by Anton
03:28
created

AbstractSelect::runChunks()   B

Complexity

Conditions 3
Paths 3

Size

Total Lines 24
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 12
nc 3
nop 2
dl 0
loc 24
rs 8.9713
c 0
b 0
f 0
1
<?php
2
/**
3
 * Spiral Framework.
4
 *
5
 * @license   MIT
6
 * @author    Anton Titov (Wolfy-J)
7
 */
8
9
namespace Spiral\Database\Builders\Prototypes;
10
11
use Spiral\Database\Builders\QueryBuilder;
12
use Spiral\Database\Builders\Traits\JoinsTrait;
13
use Spiral\Database\Entities\PDOResult;
14
use Spiral\Database\Entities\QueryCompiler;
15
use Spiral\Database\Exceptions\BuilderException;
16
use Spiral\Database\Exceptions\QueryException;
17
use Spiral\Database\Injections\ExpressionInterface;
18
use Spiral\Database\Injections\FragmentInterface;
19
use Spiral\Database\Injections\Parameter;
20
use Spiral\Database\Injections\ParameterInterface;
21
use Spiral\Pagination\PaginatorAwareInterface;
22
use Spiral\Pagination\Traits\LimitsTrait;
23
use Spiral\Pagination\Traits\PaginatorTrait;
24
25
/**
26
 * Prototype for select queries, include ability to cache, paginate or chunk results. Support WHERE,
27
 * JOIN, HAVING, ORDER BY, GROUP BY, UNION and DISTINCT statements. In addition only desired set
28
 * of columns can be selected. In addition select.
29
 *
30
 * @see AbstractWhere
31
 *
32
 * @method int avg($identifier) Perform aggregation (AVG) based on column or expression value.
33
 * @method int min($identifier) Perform aggregation (MIN) based on column or expression value.
34
 * @method int max($identifier) Perform aggregation (MAX) based on column or expression value.
35
 * @method int sum($identifier) Perform aggregation (SUM) based on column or expression value.
36
 */
37
abstract class AbstractSelect extends AbstractWhere implements
38
    \IteratorAggregate,
39
    PaginatorAwareInterface
40
{
41
    use JoinsTrait, LimitsTrait, PaginatorTrait;
42
43
    /**
44
     * Query type.
45
     */
46
    const QUERY_TYPE = QueryCompiler::SELECT_QUERY;
47
48
    /**
49
     * Sort directions.
50
     */
51
    const SORT_ASC  = 'ASC';
52
    const SORT_DESC = 'DESC';
53
54
    /**
55
     * Query must return only unique rows.
56
     *
57
     * @var bool|string
58
     */
59
    protected $distinct = false;
60
61
    /**
62
     * Columns or expressions to be fetched from database, can include aliases (AS).
63
     *
64
     * @var array
65
     */
66
    protected $columns = ['*'];
67
68
    /**
69
     * Set of generated having tokens, format must be supported by QueryCompilers.
70
     *
71
     * @see AbstractWhere
72
     *
73
     * @var array
74
     */
75
    protected $havingTokens = [];
76
77
    /**
78
     * Parameters collected while generating HAVING tokens, must be in a same order as parameters
79
     * in resulted query.
80
     *
81
     * @see AbstractWhere
82
     *
83
     * @var array
84
     */
85
    protected $havingParameters = [];
86
87
    /**
88
     * Columns/expression associated with their sort direction (ASK|DESC).
89
     *
90
     * @var array
91
     */
92
    protected $ordering = [];
93
94
    /**
95
     * Columns/expressions to group by.
96
     *
97
     * @var array
98
     */
99
    protected $grouping = [];
100
101
    /**
102
     * {@inheritdoc}
103
     */
104 View Code Duplication
    public function getParameters(QueryCompiler $compiler = null): array
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...
105
    {
106
        $compiler = $compiler ?? $this->compiler;
107
108
        return $this->flattenParameters(
109
            $compiler->orderParameters(
110
                self::QUERY_TYPE,
111
                $this->whereParameters,
112
                $this->onParameters,
113
                $this->havingParameters
114
            )
115
        );
116
    }
117
118
    /**
119
     * Mark query to return only distinct results.
120
     *
121
     * @param bool|string $distinct You are only allowed to use string value for Postgres databases.
122
     *
123
     * @return self|$this
124
     */
125
    public function distinct($distinct = true): AbstractSelect
126
    {
127
        $this->distinct = $distinct;
128
129
        return $this;
130
    }
131
132
    /**
133
     * Simple HAVING condition with various set of arguments.
134
     *
135
     * @see AbstractWhere
136
     *
137
     * @param string|mixed $identifier Column or expression.
138
     * @param mixed        $variousA   Operator or value.
139
     * @param mixed        $variousB   Value, if operator specified.
140
     * @param mixed        $variousC   Required only in between statements.
141
     *
142
     * @return self|$this
143
     *
144
     * @throws BuilderException
145
     */
146 View Code Duplication
    public function having(
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...
147
        $identifier,
0 ignored issues
show
Unused Code introduced by
The parameter $identifier is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
148
        $variousA = null,
0 ignored issues
show
Unused Code introduced by
The parameter $variousA is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
149
        $variousB = null,
0 ignored issues
show
Unused Code introduced by
The parameter $variousB is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
150
        $variousC = null
0 ignored issues
show
Unused Code introduced by
The parameter $variousC is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
151
    ): AbstractSelect {
152
        $this->whereToken('AND', func_get_args(), $this->havingTokens, $this->havingWrapper());
153
154
        return $this;
155
    }
156
157
    /**
158
     * Simple AND HAVING condition with various set of arguments.
159
     *
160
     * @see AbstractWhere
161
     *
162
     * @param string|mixed $identifier Column or expression.
163
     * @param mixed        $variousA   Operator or value.
164
     * @param mixed        $variousB   Value, if operator specified.
165
     * @param mixed        $variousC   Required only in between statements.
166
     *
167
     * @return self|$this
168
     *
169
     * @throws BuilderException
170
     */
171 View Code Duplication
    public function andHaving(
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...
172
        $identifier,
0 ignored issues
show
Unused Code introduced by
The parameter $identifier is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
173
        $variousA = null,
0 ignored issues
show
Unused Code introduced by
The parameter $variousA is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
174
        $variousB = null,
0 ignored issues
show
Unused Code introduced by
The parameter $variousB is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
175
        $variousC = null
0 ignored issues
show
Unused Code introduced by
The parameter $variousC is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
176
    ): AbstractSelect {
177
        $this->whereToken('AND', func_get_args(), $this->havingTokens, $this->havingWrapper());
178
179
        return $this;
180
    }
181
182
    /**
183
     * Simple OR HAVING condition with various set of arguments.
184
     *
185
     * @see AbstractWhere
186
     *
187
     * @param string|mixed $identifier Column or expression.
188
     * @param mixed        $variousA   Operator or value.
189
     * @param mixed        $variousB   Value, if operator specified.
190
     * @param mixed        $variousC   Required only in between statements.
191
     *
192
     * @return self|$this
193
     *
194
     * @throws BuilderException
195
     */
196 View Code Duplication
    public function orHaving(
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...
197
        $identifier,
0 ignored issues
show
Unused Code introduced by
The parameter $identifier is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
198
        $variousA = [],
0 ignored issues
show
Unused Code introduced by
The parameter $variousA is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
199
        $variousB = null,
0 ignored issues
show
Unused Code introduced by
The parameter $variousB is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
200
        $variousC = null
0 ignored issues
show
Unused Code introduced by
The parameter $variousC is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
201
    ): AbstractSelect {
202
        $this->whereToken('OR', func_get_args(), $this->havingTokens, $this->havingWrapper());
203
204
        return $this;
205
    }
206
207
    /**
208
     * Sort result by column/expression. You can apply multiple sortings to query via calling method
209
     * few times or by specifying values using array of sort parameters:.
210
     *
211
     * $select->orderBy([
212
     *      'id'   => SelectQuery::SORT_DESC,
213
     *      'name' => SelectQuery::SORT_ASC
214
     * ]);
215
     *
216
     * @param string|array $expression
217
     * @param string       $direction Sorting direction, ASC|DESC.
218
     *
219
     * @return self|$this
220
     */
221
    public function orderBy($expression, $direction = self::SORT_ASC): AbstractSelect
222
    {
223
        if (!is_array($expression)) {
224
            $this->ordering[] = [$expression, $direction];
225
226
            return $this;
227
        }
228
229
        foreach ($expression as $nested => $direction) {
230
            $this->ordering[] = [$nested, $direction];
231
        }
232
233
        return $this;
234
    }
235
236
    /**
237
     * Column or expression to group query by.
238
     *
239
     * @param string $expression
240
     *
241
     * @return self|$this
242
     */
243
    public function groupBy($expression): AbstractSelect
244
    {
245
        $this->grouping[] = $expression;
246
247
        return $this;
248
    }
249
250
    /**
251
     * Applied to every potential parameter while having tokens generation.
252
     *
253
     * @return \Closure
254
     */
255 View Code Duplication
    private function havingWrapper()
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...
256
    {
257
        return function ($parameter) {
258
            if ($parameter instanceof FragmentInterface) {
259
260
                //We are only not creating bindings for plan fragments
261
                if (!$parameter instanceof ParameterInterface && !$parameter instanceof QueryBuilder) {
262
                    return $parameter;
263
                }
264
            }
265
266
            if (is_array($parameter)) {
267
                throw new BuilderException('Arrays must be wrapped with Parameter instance');
268
            }
269
270
            //Wrapping all values with ParameterInterface
271
            if (!$parameter instanceof ParameterInterface && !$parameter instanceof ExpressionInterface) {
272
                $parameter = new Parameter($parameter, Parameter::DETECT_TYPE);
273
            };
274
275
            //Let's store to sent to driver when needed
276
            $this->havingParameters[] = $parameter;
277
278
            return $parameter;
279
        };
280
    }
281
}
282