Passed
Pull Request — master (#48)
by
unknown
14:13
created

BuildsExpressionQueries   A

Complexity

Total Complexity 16

Size/Duplication

Total Lines 224
Duplicated Lines 0 %

Test Coverage

Coverage 91.07%

Importance

Changes 2
Bugs 0 Features 0
Metric Value
wmc 16
eloc 48
dl 0
loc 224
ccs 51
cts 56
cp 0.9107
rs 10
c 2
b 0
f 0

11 Methods

Rating   Name   Duplication   Size   Complexity  
A withMaterializedExpression() 0 3 1
A update() 0 8 1
A withRecursiveExpressionAndCycleDetection() 0 9 1
A __construct() 0 8 3
A recursionLimit() 0 5 2
A withExpression() 0 9 2
A insertUsing() 0 11 1
A updateFrom() 0 8 1
A withNonMaterializedExpression() 0 3 1
A getQueryGrammar() 0 19 2
A withRecursiveExpression() 0 3 1
1
<?php
2
3
namespace Staudenmeir\LaravelCte\Query\Traits;
4
5
use Illuminate\Database\Connection;
6
use Illuminate\Database\Query\Grammars\Grammar;
7
use Illuminate\Database\Query\Processors\Processor;
8
use RuntimeException;
9
use Staudenmeir\LaravelCte\Query\Grammars\MySqlGrammar;
10
use Staudenmeir\LaravelCte\Query\Grammars\PostgresGrammar;
11
use Staudenmeir\LaravelCte\Query\Grammars\SingleStoreGrammar;
12
use Staudenmeir\LaravelCte\Query\Grammars\SQLiteGrammar;
13
use Staudenmeir\LaravelCte\Query\Grammars\SqlServerGrammar;
14
15
trait BuildsExpressionQueries
16
{
17
    /**
18
     * The common table expressions.
19
     *
20
     * @var array
21
     */
22
    public $expressions = [];
23
24
    /**
25
     * The common table expressions for union queries.
26
     *
27
     * @var array
28
     */
29
    public $unionExpressions = [];
30
31
    /**
32
     * The recursion limit.
33
     *
34
     * @var int
35
     */
36
    public $recursionLimit;
37
38
    /**
39
     * The recursion limit for union queries.
40
     *
41
     * @var int
42
     */
43
    public $unionRecursionLimit;
44
45
    /**
46
     * Create a new query builder instance.
47
     *
48
     * @param \Illuminate\Database\Connection $connection
49
     * @param \Illuminate\Database\Query\Grammars\Grammar|null $grammar
50
     * @param \Illuminate\Database\Query\Processors\Processor|null $processor
51
     * @return void
52
     */
53 169
    public function __construct(Connection $connection, Grammar $grammar = null, Processor $processor = null)
54
    {
55 169
        $grammar = $grammar ?: $connection->withTablePrefix($this->getQueryGrammar($connection));
56 169
        $processor = $processor ?: $connection->getPostProcessor();
57
58 169
        parent::__construct($connection, $grammar, $processor);
59
60 169
        $this->bindings = ['expressions' => []] + $this->bindings;
0 ignored issues
show
Bug Best Practice introduced by
The property bindings does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
61
    }
62
63
    /**
64
     * Get the query grammar.
65
     *
66
     * @param \Illuminate\Database\Connection $connection
67
     * @return \Illuminate\Database\Query\Grammars\Grammar
68
     */
69 169
    protected function getQueryGrammar(Connection $connection)
70
    {
71 169
        $driver = $connection->getDriverName();
72
73 169
        $grammar = match ($driver) {
74 169
            'mysql' => new MySqlGrammar(),
75 169
            'pgsql' => new PostgresGrammar(),
76 169
            'sqlite' => new SQLiteGrammar(),
77 169
            'sqlsrv' => new SqlServerGrammar(),
78 169
            'singlestore' => new SingleStoreGrammar(),
79
            default => throw new RuntimeException('This database is not supported.'), // @codeCoverageIgnore
80 169
        };
81
82
        // TODO[L11]
83 169
        if (method_exists($grammar, 'setConnection')) {
84 169
            $grammar->setConnection($connection);
85
        }
86
87 169
        return $grammar;
88
    }
89
90
    /**
91
     * Add a common table expression to the query.
92
     *
93
     * @param string $name
94
     * @param \Closure|\Illuminate\Database\Query\Builder|string $query
95
     * @param array|null $columns
96
     * @param bool $recursive
97
     * @param bool|null $materialized
98
     * @param array|null $cycle
99
     * @return $this
100
     */
101 154
    public function withExpression($name, $query, array $columns = null, $recursive = false, $materialized = null, array $cycle = null)
102
    {
103 154
        [$query, $bindings] = $this->createSub($query);
0 ignored issues
show
Bug introduced by
It seems like createSub() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

103
        /** @scrutinizer ignore-call */ 
104
        [$query, $bindings] = $this->createSub($query);
Loading history...
104
105 154
        $this->{$this->unions ? 'unionExpressions' : 'expressions'}[] = compact('name', 'query', 'columns', 'recursive', 'materialized', 'cycle');
106
107 154
        $this->addBinding($bindings, 'expressions');
0 ignored issues
show
Bug introduced by
It seems like addBinding() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

107
        $this->/** @scrutinizer ignore-call */ 
108
               addBinding($bindings, 'expressions');
Loading history...
108
109 154
        return $this;
110
    }
111
112
    /**
113
     * Add a recursive common table expression to the query.
114
     *
115
     * @param string $name
116
     * @param \Closure|\Illuminate\Database\Query\Builder|string $query
117
     * @param array|null $columns
118
     * @param array|null $cycle
119
     * @return $this
120
     */
121 32
    public function withRecursiveExpression($name, $query, $columns = null, array $cycle = null)
122
    {
123 32
        return $this->withExpression($name, $query, $columns, true, null, $cycle);
124
    }
125
126
    /**
127
     * Add a recursive common table expression with cycle detection to the query.
128
     *
129
     * @param string $name
130
     * @param \Closure|\Illuminate\Database\Query\Builder|string $query
131
     * @param array|string $cycleColumns
132
     * @param string $markColumn
133
     * @param string $pathColumn
134
     * @param array|null $columns
135
     * @return $this
136
     */
137 2
    public function withRecursiveExpressionAndCycleDetection($name, $query, $cycleColumns, $markColumn = 'is_cycle', $pathColumn = 'path', $columns = null)
138
    {
139 2
        $cycleColumns = (array) $cycleColumns;
140
141 2
        $cycle = [
142 2
            'columns' => $cycleColumns
143 2
        ] + compact('markColumn', 'pathColumn');
144
145 2
        return $this->withRecursiveExpression($name, $query, $columns, $cycle);
146
    }
147
148
    /**
149
     * Add a materialized common table expression to the query.
150
     *
151
     * @param string $name
152
     * @param \Closure|\Illuminate\Database\Query\Builder|string $query
153
     * @param array|null $columns
154
     * @return $this
155
     */
156 10
    public function withMaterializedExpression($name, $query, $columns = null)
157
    {
158 10
        return $this->withExpression($name, $query, $columns, false, true);
159
    }
160
161
    /**
162
     * Add a non-materialized common table expression to the query.
163
     *
164
     * @param string $name
165
     * @param \Closure|\Illuminate\Database\Query\Builder|string $query
166
     * @param array|null $columns
167
     * @return $this
168
     */
169 10
    public function withNonMaterializedExpression($name, $query, $columns = null)
170
    {
171 10
        return $this->withExpression($name, $query, $columns, false, false);
172
    }
173
174
    /**
175
     * Set the recursion limit of the query.
176
     *
177
     * @param int $value
178
     * @return $this
179
     */
180 15
    public function recursionLimit($value)
181
    {
182 15
        $this->{$this->unions ? 'unionRecursionLimit' : 'recursionLimit'} = $value;
183
184 15
        return $this;
185
    }
186
187
    /**
188
     * Insert new records into the table using a subquery.
189
     *
190
     * @param array $columns
191
     * @param \Closure|\Illuminate\Database\Query\Builder|string $query
192
     * @return int
193
     */
194 15
    public function insertUsing(array $columns, $query)
195
    {
196 15
        $this->applyBeforeQueryCallbacks();
0 ignored issues
show
Bug introduced by
It seems like applyBeforeQueryCallbacks() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

196
        $this->/** @scrutinizer ignore-call */ 
197
               applyBeforeQueryCallbacks();
Loading history...
197
198 15
        [$sql, $bindings] = $this->createSub($query);
199
200 15
        $bindings = array_merge($this->bindings['expressions'], $bindings);
201
202 15
        return $this->connection->affectingStatement(
203 15
            $this->grammar->compileInsertUsing($this, $columns, $sql),
204 15
            $this->cleanBindings($bindings)
0 ignored issues
show
Bug introduced by
It seems like cleanBindings() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

204
            $this->/** @scrutinizer ignore-call */ 
205
                   cleanBindings($bindings)
Loading history...
205 15
        );
206
    }
207
208
    /**
209
     * Update records in the database.
210
     *
211
     * @param array $values
212
     * @return int
213
     */
214 21
    public function update(array $values)
215
    {
216 21
        $this->applyBeforeQueryCallbacks();
217
218 21
        $sql = $this->grammar->compileUpdate($this, $values);
219
220 21
        return $this->connection->update($sql, $this->cleanBindings(
221 21
            $this->grammar->getBindingsForUpdate($this, $this->bindings, $values)
222 21
        ));
223
    }
224
225
    /**
226
     * Update records in a PostgreSQL database using the update from syntax.
227
     *
228
     * @param array $values
229
     * @return int
230
     */
231
    public function updateFrom(array $values)
232
    {
233
        $this->applyBeforeQueryCallbacks();
234
235
        $sql = $this->grammar->compileUpdateFrom($this, $values);
236
237
        return $this->connection->update($sql, $this->cleanBindings(
238
            $this->grammar->prepareBindingsForUpdateFrom($this->bindings, $values)
239
        ));
240
    }
241
}
242