Subversion-Projekte lars-tiefland.laravel_shop

Revision

Revision 148 | Details | Vergleich mit vorheriger | 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
    /**
621 lars 121
     * Compile the index hints for the query.
122
     *
123
     * @param  \Illuminate\Database\Query\Builder  $query
124
     * @param  \Illuminate\Database\Query\IndexHint  $indexHint
125
     * @return string
126
     */
127
    protected function compileIndexHint(Builder $query, $indexHint)
128
    {
129
        return $indexHint->type === 'force'
130
                ? "indexed by {$indexHint->index}"
131
                : '';
132
    }
133
 
134
    /**
148 lars 135
     * Compile a "JSON length" statement into SQL.
136
     *
137
     * @param  string  $column
138
     * @param  string  $operator
139
     * @param  string  $value
140
     * @return string
141
     */
142
    protected function compileJsonLength($column, $operator, $value)
143
    {
144
        [$field, $path] = $this->wrapJsonFieldAndPath($column);
145
 
146
        return 'json_array_length('.$field.$path.') '.$operator.' '.$value;
147
    }
148
 
149
    /**
150
     * Compile a "JSON contains key" statement into SQL.
151
     *
152
     * @param  string  $column
153
     * @return string
154
     */
155
    protected function compileJsonContainsKey($column)
156
    {
157
        [$field, $path] = $this->wrapJsonFieldAndPath($column);
158
 
159
        return 'json_type('.$field.$path.') is not null';
160
    }
161
 
162
    /**
163
     * Compile an update statement into SQL.
164
     *
165
     * @param  \Illuminate\Database\Query\Builder  $query
166
     * @param  array  $values
167
     * @return string
168
     */
169
    public function compileUpdate(Builder $query, array $values)
170
    {
171
        if (isset($query->joins) || isset($query->limit)) {
172
            return $this->compileUpdateWithJoinsOrLimit($query, $values);
173
        }
174
 
175
        return parent::compileUpdate($query, $values);
176
    }
177
 
178
    /**
179
     * Compile an insert ignore statement into SQL.
180
     *
181
     * @param  \Illuminate\Database\Query\Builder  $query
182
     * @param  array  $values
183
     * @return string
184
     */
185
    public function compileInsertOrIgnore(Builder $query, array $values)
186
    {
187
        return Str::replaceFirst('insert', 'insert or ignore', $this->compileInsert($query, $values));
188
    }
189
 
190
    /**
191
     * Compile the columns for an update statement.
192
     *
193
     * @param  \Illuminate\Database\Query\Builder  $query
194
     * @param  array  $values
195
     * @return string
196
     */
197
    protected function compileUpdateColumns(Builder $query, array $values)
198
    {
199
        $jsonGroups = $this->groupJsonColumnsForUpdate($values);
200
 
201
        return collect($values)->reject(function ($value, $key) {
202
            return $this->isJsonSelector($key);
203
        })->merge($jsonGroups)->map(function ($value, $key) use ($jsonGroups) {
204
            $column = last(explode('.', $key));
205
 
206
            $value = isset($jsonGroups[$key]) ? $this->compileJsonPatch($column, $value) : $this->parameter($value);
207
 
208
            return $this->wrap($column).' = '.$value;
209
        })->implode(', ');
210
    }
211
 
212
    /**
213
     * Compile an "upsert" statement into SQL.
214
     *
215
     * @param  \Illuminate\Database\Query\Builder  $query
216
     * @param  array  $values
217
     * @param  array  $uniqueBy
218
     * @param  array  $update
219
     * @return string
220
     */
221
    public function compileUpsert(Builder $query, array $values, array $uniqueBy, array $update)
222
    {
223
        $sql = $this->compileInsert($query, $values);
224
 
225
        $sql .= ' on conflict ('.$this->columnize($uniqueBy).') do update set ';
226
 
227
        $columns = collect($update)->map(function ($value, $key) {
228
            return is_numeric($key)
229
                ? $this->wrap($value).' = '.$this->wrapValue('excluded').'.'.$this->wrap($value)
230
                : $this->wrap($key).' = '.$this->parameter($value);
231
        })->implode(', ');
232
 
233
        return $sql.$columns;
234
    }
235
 
236
    /**
237
     * Group the nested JSON columns.
238
     *
239
     * @param  array  $values
240
     * @return array
241
     */
242
    protected function groupJsonColumnsForUpdate(array $values)
243
    {
244
        $groups = [];
245
 
246
        foreach ($values as $key => $value) {
247
            if ($this->isJsonSelector($key)) {
248
                Arr::set($groups, str_replace('->', '.', Str::after($key, '.')), $value);
249
            }
250
        }
251
 
252
        return $groups;
253
    }
254
 
255
    /**
256
     * Compile a "JSON" patch statement into SQL.
257
     *
258
     * @param  string  $column
259
     * @param  mixed  $value
260
     * @return string
261
     */
262
    protected function compileJsonPatch($column, $value)
263
    {
264
        return "json_patch(ifnull({$this->wrap($column)}, json('{}')), json({$this->parameter($value)}))";
265
    }
266
 
267
    /**
268
     * Compile an update statement with joins or limit into SQL.
269
     *
270
     * @param  \Illuminate\Database\Query\Builder  $query
271
     * @param  array  $values
272
     * @return string
273
     */
274
    protected function compileUpdateWithJoinsOrLimit(Builder $query, array $values)
275
    {
276
        $table = $this->wrapTable($query->from);
277
 
278
        $columns = $this->compileUpdateColumns($query, $values);
279
 
280
        $alias = last(preg_split('/\s+as\s+/i', $query->from));
281
 
282
        $selectSql = $this->compileSelect($query->select($alias.'.rowid'));
283
 
284
        return "update {$table} set {$columns} where {$this->wrap('rowid')} in ({$selectSql})";
285
    }
286
 
287
    /**
288
     * Prepare the bindings for an update statement.
289
     *
290
     * @param  array  $bindings
291
     * @param  array  $values
292
     * @return array
293
     */
294
    public function prepareBindingsForUpdate(array $bindings, array $values)
295
    {
296
        $groups = $this->groupJsonColumnsForUpdate($values);
297
 
298
        $values = collect($values)->reject(function ($value, $key) {
299
            return $this->isJsonSelector($key);
300
        })->merge($groups)->map(function ($value) {
301
            return is_array($value) ? json_encode($value) : $value;
302
        })->all();
303
 
304
        $cleanBindings = Arr::except($bindings, 'select');
305
 
306
        return array_values(
307
            array_merge($values, Arr::flatten($cleanBindings))
308
        );
309
    }
310
 
311
    /**
312
     * Compile a delete statement into SQL.
313
     *
314
     * @param  \Illuminate\Database\Query\Builder  $query
315
     * @return string
316
     */
317
    public function compileDelete(Builder $query)
318
    {
319
        if (isset($query->joins) || isset($query->limit)) {
320
            return $this->compileDeleteWithJoinsOrLimit($query);
321
        }
322
 
323
        return parent::compileDelete($query);
324
    }
325
 
326
    /**
327
     * Compile a delete statement with joins or limit into SQL.
328
     *
329
     * @param  \Illuminate\Database\Query\Builder  $query
330
     * @return string
331
     */
332
    protected function compileDeleteWithJoinsOrLimit(Builder $query)
333
    {
334
        $table = $this->wrapTable($query->from);
335
 
336
        $alias = last(preg_split('/\s+as\s+/i', $query->from));
337
 
338
        $selectSql = $this->compileSelect($query->select($alias.'.rowid'));
339
 
340
        return "delete from {$table} where {$this->wrap('rowid')} in ({$selectSql})";
341
    }
342
 
343
    /**
344
     * Compile a truncate table statement into SQL.
345
     *
346
     * @param  \Illuminate\Database\Query\Builder  $query
347
     * @return array
348
     */
349
    public function compileTruncate(Builder $query)
350
    {
351
        return [
352
            'delete from sqlite_sequence where name = ?' => [$query->from],
353
            'delete from '.$this->wrapTable($query->from) => [],
354
        ];
355
    }
356
 
357
    /**
358
     * Wrap the given JSON selector.
359
     *
360
     * @param  string  $value
361
     * @return string
362
     */
363
    protected function wrapJsonSelector($value)
364
    {
365
        [$field, $path] = $this->wrapJsonFieldAndPath($value);
366
 
367
        return 'json_extract('.$field.$path.')';
368
    }
369
}