Passed
Push — master ( dea409...00bef5 )
by Jonas
11:45
created

withRecursiveExpressionAndCycleDetection()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 9
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 5
c 0
b 0
f 0
nc 1
nop 6
dl 0
loc 9
ccs 5
cts 5
cp 1
crap 1
rs 10
1
<?php
2
3
namespace Staudenmeir\LaravelCte\Query;
4
5
use Illuminate\Database\Connection;
6
use Illuminate\Database\Query\Builder as Base;
7
use Illuminate\Database\Query\Grammars\Grammar;
8
use Illuminate\Database\Query\Processors\Processor;
9
use RuntimeException;
10
use Staudenmeir\LaravelCte\Query\Grammars\MySqlGrammar;
11
use Staudenmeir\LaravelCte\Query\Grammars\PostgresGrammar;
12
use Staudenmeir\LaravelCte\Query\Grammars\SQLiteGrammar;
13
use Staudenmeir\LaravelCte\Query\Grammars\SqlServerGrammar;
14
15
class Builder extends Base
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 141
    public function __construct(Connection $connection, Grammar $grammar = null, Processor $processor = null)
54
    {
55 141
        $grammar = $grammar ?: $connection->withTablePrefix($this->getQueryGrammar($connection));
56 141
        $processor = $processor ?: $connection->getPostProcessor();
57
58 141
        parent::__construct($connection, $grammar, $processor);
59
60 141
        $this->bindings = ['expressions' => []] + $this->bindings;
61
    }
62
63
    /**
64
     * Get the query grammar.
65
     *
66
     * @param \Illuminate\Database\Connection $connection
67
     * @return \Illuminate\Database\Query\Grammars\Grammar
68
     */
69 141
    protected function getQueryGrammar(Connection $connection)
70
    {
71 141
        $driver = $connection->getDriverName();
72
73 141
        switch ($driver) {
74 141
            case 'mysql':
75 53
                return new MySqlGrammar();
76 88
            case 'pgsql':
77 32
                return new PostgresGrammar();
78 56
            case 'sqlite':
79 29
                return new SQLiteGrammar();
80 27
            case 'sqlsrv':
81 27
                return new SqlServerGrammar();
82
        }
83
84
        throw new RuntimeException('This database is not supported.'); // @codeCoverageIgnore
85
    }
86
87
    /**
88
     * Add a common table expression to the query.
89
     *
90
     * @param string $name
91
     * @param \Closure|\Illuminate\Database\Query\Builder|string $query
92
     * @param array|null $columns
93
     * @param bool $recursive
94
     * @param bool|null $materialized
95
     * @param array|null $cycle
96
     * @return $this
97
     */
98 126
    public function withExpression($name, $query, array $columns = null, $recursive = false, $materialized = null, array $cycle = null)
99
    {
100 126
        [$query, $bindings] = $this->createSub($query);
101
102 126
        $this->{$this->unions ? 'unionExpressions' : 'expressions'}[] = compact('name', 'query', 'columns', 'recursive', 'materialized', 'cycle');
103
104 126
        $this->addBinding($bindings, 'expressions');
105
106 126
        return $this;
107
    }
108
109
    /**
110
     * Add a recursive common table expression to the query.
111
     *
112
     * @param string $name
113
     * @param \Closure|\Illuminate\Database\Query\Builder|string $query
114
     * @param array|null $columns
115
     * @param array|null $cycle
116
     * @return $this
117
     */
118 32
    public function withRecursiveExpression($name, $query, $columns = null, array $cycle = null)
119
    {
120 32
        return $this->withExpression($name, $query, $columns, true, null, $cycle);
121
    }
122
123
    /**
124
     * Add a recursive common table expression with cycle detection to the query.
125
     *
126
     * @param string $name
127
     * @param \Closure|\Illuminate\Database\Query\Builder|string $query
128
     * @param array|string $cycleColumns
129
     * @param string $markColumn
130
     * @param string $pathColumn
131
     * @param array|null $columns
132
     * @return $this
133
     */
134 2
    public function withRecursiveExpressionAndCycleDetection($name, $query, $cycleColumns, $markColumn = 'is_cycle', $pathColumn = 'path', $columns = null)
135
    {
136 2
        $cycleColumns = (array) $cycleColumns;
137
138 2
        $cycle = [
139
            'columns' => $cycleColumns
140 2
        ] + compact('markColumn', 'pathColumn');
141
142 2
        return $this->withRecursiveExpression($name, $query, $columns, $cycle);
143
    }
144
145
    /**
146
     * Add a materialized common table expression to the query.
147
     *
148
     * @param string $name
149
     * @param \Closure|\Illuminate\Database\Query\Builder|string $query
150
     * @param array|null $columns
151
     * @return $this
152
     */
153 11
    public function withMaterializedExpression($name, $query, $columns = null)
154
    {
155 11
        return $this->withExpression($name, $query, $columns, false, true);
156
    }
157
158
    /**
159
     * Add a non-materialized common table expression to the query.
160
     *
161
     * @param string $name
162
     * @param \Closure|\Illuminate\Database\Query\Builder|string $query
163
     * @param array|null $columns
164
     * @return $this
165
     */
166 11
    public function withNonMaterializedExpression($name, $query, $columns = null)
167
    {
168 11
        return $this->withExpression($name, $query, $columns, false, false);
169
    }
170
171
    /**
172
     * Set the recursion limit of the query.
173
     *
174
     * @param int $value
175
     * @return $this
176
     */
177 15
    public function recursionLimit($value)
178
    {
179 15
        $this->{$this->unions ? 'unionRecursionLimit' : 'recursionLimit'} = $value;
180
181 15
        return $this;
182
    }
183
184
    /**
185
     * Insert new records into the table using a subquery.
186
     *
187
     * @param array $columns
188
     * @param \Closure|\Illuminate\Database\Query\Builder|string $query
189
     * @return int
190
     */
191 10
    public function insertUsing(array $columns, $query)
192
    {
193 10
        $this->applyBeforeQueryCallbacks();
194
195 10
        [$sql, $bindings] = $this->createSub($query);
196
197 10
        $bindings = array_merge($this->bindings['expressions'], $bindings);
198
199 10
        return $this->connection->affectingStatement(
200 10
            $this->grammar->compileInsertUsing($this, $columns, $sql),
201 10
            $this->cleanBindings($bindings)
202
        );
203
    }
204
205
    /**
206
     * Update records in the database.
207
     *
208
     * @param  array  $values
209
     * @return int
210
     */
211 11
    public function update(array $values)
212
    {
213 11
        $this->applyBeforeQueryCallbacks();
214
215 11
        $sql = $this->grammar->compileUpdate($this, $values);
216
217 11
        return $this->connection->update($sql, $this->cleanBindings(
218 11
            $this->grammar->getBindingsForUpdate($this, $this->bindings, $values)
219
        ));
220
    }
221
}
222