Subversion-Projekte lars-tiefland.laravel_shop

Revision

Zur aktuellen Revision | Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
148 lars 1
<?php
2
 
3
namespace Illuminate\Database\Query\Grammars;
4
 
5
use Illuminate\Database\Query\Builder;
6
use Illuminate\Support\Arr;
7
use Illuminate\Support\Str;
8
 
9
class SQLiteGrammar extends Grammar
10
{
11
    /**
12
     * All of the available clause operators.
13
     *
14
     * @var string[]
15
     */
16
    protected $operators = [
17
        '=', '<', '>', '<=', '>=', '<>', '!=',
18
        'like', 'not like', 'ilike',
19
        '&', '|', '<<', '>>',
20
    ];
21
 
22
    /**
23
     * Compile the lock into SQL.
24
     *
25
     * @param  \Illuminate\Database\Query\Builder  $query
26
     * @param  bool|string  $value
27
     * @return string
28
     */
29
    protected function compileLock(Builder $query, $value)
30
    {
31
        return '';
32
    }
33
 
34
    /**
35
     * Wrap a union subquery in parentheses.
36
     *
37
     * @param  string  $sql
38
     * @return string
39
     */
40
    protected function wrapUnion($sql)
41
    {
42
        return 'select * from ('.$sql.')';
43
    }
44
 
45
    /**
46
     * Compile a "where date" clause.
47
     *
48
     * @param  \Illuminate\Database\Query\Builder  $query
49
     * @param  array  $where
50
     * @return string
51
     */
52
    protected function whereDate(Builder $query, $where)
53
    {
54
        return $this->dateBasedWhere('%Y-%m-%d', $query, $where);
55
    }
56
 
57
    /**
58
     * Compile a "where day" clause.
59
     *
60
     * @param  \Illuminate\Database\Query\Builder  $query
61
     * @param  array  $where
62
     * @return string
63
     */
64
    protected function whereDay(Builder $query, $where)
65
    {
66
        return $this->dateBasedWhere('%d', $query, $where);
67
    }
68
 
69
    /**
70
     * Compile a "where month" clause.
71
     *
72
     * @param  \Illuminate\Database\Query\Builder  $query
73
     * @param  array  $where
74
     * @return string
75
     */
76
    protected function whereMonth(Builder $query, $where)
77
    {
78
        return $this->dateBasedWhere('%m', $query, $where);
79
    }
80
 
81
    /**
82
     * Compile a "where year" clause.
83
     *
84
     * @param  \Illuminate\Database\Query\Builder  $query
85
     * @param  array  $where
86
     * @return string
87
     */
88
    protected function whereYear(Builder $query, $where)
89
    {
90
        return $this->dateBasedWhere('%Y', $query, $where);
91
    }
92
 
93
    /**
94
     * Compile a "where time" clause.
95
     *
96
     * @param  \Illuminate\Database\Query\Builder  $query
97
     * @param  array  $where
98
     * @return string
99
     */
100
    protected function whereTime(Builder $query, $where)
101
    {
102
        return $this->dateBasedWhere('%H:%M:%S', $query, $where);
103
    }
104
 
105
    /**
106
     * Compile a date based where clause.
107
     *
108
     * @param  string  $type
109
     * @param  \Illuminate\Database\Query\Builder  $query
110
     * @param  array  $where
111
     * @return string
112
     */
113
    protected function dateBasedWhere($type, Builder $query, $where)
114
    {
115
        $value = $this->parameter($where['value']);
116
 
117
        return "strftime('{$type}', {$this->wrap($where['column'])}) {$where['operator']} cast({$value} as text)";
118
    }
119
 
120
    /**
121
     * Compile a "JSON length" statement into SQL.
122
     *
123
     * @param  string  $column
124
     * @param  string  $operator
125
     * @param  string  $value
126
     * @return string
127
     */
128
    protected function compileJsonLength($column, $operator, $value)
129
    {
130
        [$field, $path] = $this->wrapJsonFieldAndPath($column);
131
 
132
        return 'json_array_length('.$field.$path.') '.$operator.' '.$value;
133
    }
134
 
135
    /**
136
     * Compile a "JSON contains key" statement into SQL.
137
     *
138
     * @param  string  $column
139
     * @return string
140
     */
141
    protected function compileJsonContainsKey($column)
142
    {
143
        [$field, $path] = $this->wrapJsonFieldAndPath($column);
144
 
145
        return 'json_type('.$field.$path.') is not null';
146
    }
147
 
148
    /**
149
     * Compile an update statement into SQL.
150
     *
151
     * @param  \Illuminate\Database\Query\Builder  $query
152
     * @param  array  $values
153
     * @return string
154
     */
155
    public function compileUpdate(Builder $query, array $values)
156
    {
157
        if (isset($query->joins) || isset($query->limit)) {
158
            return $this->compileUpdateWithJoinsOrLimit($query, $values);
159
        }
160
 
161
        return parent::compileUpdate($query, $values);
162
    }
163
 
164
    /**
165
     * Compile an insert ignore statement into SQL.
166
     *
167
     * @param  \Illuminate\Database\Query\Builder  $query
168
     * @param  array  $values
169
     * @return string
170
     */
171
    public function compileInsertOrIgnore(Builder $query, array $values)
172
    {
173
        return Str::replaceFirst('insert', 'insert or ignore', $this->compileInsert($query, $values));
174
    }
175
 
176
    /**
177
     * Compile the columns for an update statement.
178
     *
179
     * @param  \Illuminate\Database\Query\Builder  $query
180
     * @param  array  $values
181
     * @return string
182
     */
183
    protected function compileUpdateColumns(Builder $query, array $values)
184
    {
185
        $jsonGroups = $this->groupJsonColumnsForUpdate($values);
186
 
187
        return collect($values)->reject(function ($value, $key) {
188
            return $this->isJsonSelector($key);
189
        })->merge($jsonGroups)->map(function ($value, $key) use ($jsonGroups) {
190
            $column = last(explode('.', $key));
191
 
192
            $value = isset($jsonGroups[$key]) ? $this->compileJsonPatch($column, $value) : $this->parameter($value);
193
 
194
            return $this->wrap($column).' = '.$value;
195
        })->implode(', ');
196
    }
197
 
198
    /**
199
     * Compile an "upsert" statement into SQL.
200
     *
201
     * @param  \Illuminate\Database\Query\Builder  $query
202
     * @param  array  $values
203
     * @param  array  $uniqueBy
204
     * @param  array  $update
205
     * @return string
206
     */
207
    public function compileUpsert(Builder $query, array $values, array $uniqueBy, array $update)
208
    {
209
        $sql = $this->compileInsert($query, $values);
210
 
211
        $sql .= ' on conflict ('.$this->columnize($uniqueBy).') do update set ';
212
 
213
        $columns = collect($update)->map(function ($value, $key) {
214
            return is_numeric($key)
215
                ? $this->wrap($value).' = '.$this->wrapValue('excluded').'.'.$this->wrap($value)
216
                : $this->wrap($key).' = '.$this->parameter($value);
217
        })->implode(', ');
218
 
219
        return $sql.$columns;
220
    }
221
 
222
    /**
223
     * Group the nested JSON columns.
224
     *
225
     * @param  array  $values
226
     * @return array
227
     */
228
    protected function groupJsonColumnsForUpdate(array $values)
229
    {
230
        $groups = [];
231
 
232
        foreach ($values as $key => $value) {
233
            if ($this->isJsonSelector($key)) {
234
                Arr::set($groups, str_replace('->', '.', Str::after($key, '.')), $value);
235
            }
236
        }
237
 
238
        return $groups;
239
    }
240
 
241
    /**
242
     * Compile a "JSON" patch statement into SQL.
243
     *
244
     * @param  string  $column
245
     * @param  mixed  $value
246
     * @return string
247
     */
248
    protected function compileJsonPatch($column, $value)
249
    {
250
        return "json_patch(ifnull({$this->wrap($column)}, json('{}')), json({$this->parameter($value)}))";
251
    }
252
 
253
    /**
254
     * Compile an update statement with joins or limit into SQL.
255
     *
256
     * @param  \Illuminate\Database\Query\Builder  $query
257
     * @param  array  $values
258
     * @return string
259
     */
260
    protected function compileUpdateWithJoinsOrLimit(Builder $query, array $values)
261
    {
262
        $table = $this->wrapTable($query->from);
263
 
264
        $columns = $this->compileUpdateColumns($query, $values);
265
 
266
        $alias = last(preg_split('/\s+as\s+/i', $query->from));
267
 
268
        $selectSql = $this->compileSelect($query->select($alias.'.rowid'));
269
 
270
        return "update {$table} set {$columns} where {$this->wrap('rowid')} in ({$selectSql})";
271
    }
272
 
273
    /**
274
     * Prepare the bindings for an update statement.
275
     *
276
     * @param  array  $bindings
277
     * @param  array  $values
278
     * @return array
279
     */
280
    public function prepareBindingsForUpdate(array $bindings, array $values)
281
    {
282
        $groups = $this->groupJsonColumnsForUpdate($values);
283
 
284
        $values = collect($values)->reject(function ($value, $key) {
285
            return $this->isJsonSelector($key);
286
        })->merge($groups)->map(function ($value) {
287
            return is_array($value) ? json_encode($value) : $value;
288
        })->all();
289
 
290
        $cleanBindings = Arr::except($bindings, 'select');
291
 
292
        return array_values(
293
            array_merge($values, Arr::flatten($cleanBindings))
294
        );
295
    }
296
 
297
    /**
298
     * Compile a delete statement into SQL.
299
     *
300
     * @param  \Illuminate\Database\Query\Builder  $query
301
     * @return string
302
     */
303
    public function compileDelete(Builder $query)
304
    {
305
        if (isset($query->joins) || isset($query->limit)) {
306
            return $this->compileDeleteWithJoinsOrLimit($query);
307
        }
308
 
309
        return parent::compileDelete($query);
310
    }
311
 
312
    /**
313
     * Compile a delete statement with joins or limit into SQL.
314
     *
315
     * @param  \Illuminate\Database\Query\Builder  $query
316
     * @return string
317
     */
318
    protected function compileDeleteWithJoinsOrLimit(Builder $query)
319
    {
320
        $table = $this->wrapTable($query->from);
321
 
322
        $alias = last(preg_split('/\s+as\s+/i', $query->from));
323
 
324
        $selectSql = $this->compileSelect($query->select($alias.'.rowid'));
325
 
326
        return "delete from {$table} where {$this->wrap('rowid')} in ({$selectSql})";
327
    }
328
 
329
    /**
330
     * Compile a truncate table statement into SQL.
331
     *
332
     * @param  \Illuminate\Database\Query\Builder  $query
333
     * @return array
334
     */
335
    public function compileTruncate(Builder $query)
336
    {
337
        return [
338
            'delete from sqlite_sequence where name = ?' => [$query->from],
339
            'delete from '.$this->wrapTable($query->from) => [],
340
        ];
341
    }
342
 
343
    /**
344
     * Wrap the given JSON selector.
345
     *
346
     * @param  string  $value
347
     * @return string
348
     */
349
    protected function wrapJsonSelector($value)
350
    {
351
        [$field, $path] = $this->wrapJsonFieldAndPath($value);
352
 
353
        return 'json_extract('.$field.$path.')';
354
    }
355
}