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\Str;
7
 
8
class MySqlGrammar extends Grammar
9
{
10
    /**
11
     * The grammar specific operators.
12
     *
13
     * @var string[]
14
     */
15
    protected $operators = ['sounds like'];
16
 
17
    /**
18
     * Add a "where null" clause to the query.
19
     *
20
     * @param  \Illuminate\Database\Query\Builder  $query
21
     * @param  array  $where
22
     * @return string
23
     */
24
    protected function whereNull(Builder $query, $where)
25
    {
26
        if ($this->isJsonSelector($where['column'])) {
27
            [$field, $path] = $this->wrapJsonFieldAndPath($where['column']);
28
 
29
            return '(json_extract('.$field.$path.') is null OR json_type(json_extract('.$field.$path.')) = \'NULL\')';
30
        }
31
 
32
        return parent::whereNull($query, $where);
33
    }
34
 
35
    /**
36
     * Add a "where not null" clause to the query.
37
     *
38
     * @param  \Illuminate\Database\Query\Builder  $query
39
     * @param  array  $where
40
     * @return string
41
     */
42
    protected function whereNotNull(Builder $query, $where)
43
    {
44
        if ($this->isJsonSelector($where['column'])) {
45
            [$field, $path] = $this->wrapJsonFieldAndPath($where['column']);
46
 
47
            return '(json_extract('.$field.$path.') is not null AND json_type(json_extract('.$field.$path.')) != \'NULL\')';
48
        }
49
 
50
        return parent::whereNotNull($query, $where);
51
    }
52
 
53
    /**
54
     * Compile a "where fulltext" clause.
55
     *
56
     * @param  \Illuminate\Database\Query\Builder  $query
57
     * @param  array  $where
58
     * @return string
59
     */
60
    public function whereFullText(Builder $query, $where)
61
    {
62
        $columns = $this->columnize($where['columns']);
63
 
64
        $value = $this->parameter($where['value']);
65
 
66
        $mode = ($where['options']['mode'] ?? []) === 'boolean'
67
            ? ' in boolean mode'
68
            : ' in natural language mode';
69
 
70
        $expanded = ($where['options']['expanded'] ?? []) && ($where['options']['mode'] ?? []) !== 'boolean'
71
            ? ' with query expansion'
72
            : '';
73
 
74
        return "match ({$columns}) against (".$value."{$mode}{$expanded})";
75
    }
76
 
77
    /**
621 lars 78
     * Compile the index hints for the query.
79
     *
80
     * @param  \Illuminate\Database\Query\Builder  $query
81
     * @param  \Illuminate\Database\Query\IndexHint  $indexHint
82
     * @return string
83
     */
84
    protected function compileIndexHint(Builder $query, $indexHint)
85
    {
86
        return match ($indexHint->type) {
87
            'hint' => "use index ({$indexHint->index})",
88
            'force' => "force index ({$indexHint->index})",
89
            default => "ignore index ({$indexHint->index})",
90
        };
91
    }
92
 
93
    /**
148 lars 94
     * Compile an insert ignore statement into SQL.
95
     *
96
     * @param  \Illuminate\Database\Query\Builder  $query
97
     * @param  array  $values
98
     * @return string
99
     */
100
    public function compileInsertOrIgnore(Builder $query, array $values)
101
    {
102
        return Str::replaceFirst('insert', 'insert ignore', $this->compileInsert($query, $values));
103
    }
104
 
105
    /**
106
     * Compile a "JSON contains" statement into SQL.
107
     *
108
     * @param  string  $column
109
     * @param  string  $value
110
     * @return string
111
     */
112
    protected function compileJsonContains($column, $value)
113
    {
114
        [$field, $path] = $this->wrapJsonFieldAndPath($column);
115
 
116
        return 'json_contains('.$field.', '.$value.$path.')';
117
    }
118
 
119
    /**
120
     * Compile a "JSON contains key" statement into SQL.
121
     *
122
     * @param  string  $column
123
     * @return string
124
     */
125
    protected function compileJsonContainsKey($column)
126
    {
127
        [$field, $path] = $this->wrapJsonFieldAndPath($column);
128
 
129
        return 'ifnull(json_contains_path('.$field.', \'one\''.$path.'), 0)';
130
    }
131
 
132
    /**
133
     * Compile a "JSON length" statement into SQL.
134
     *
135
     * @param  string  $column
136
     * @param  string  $operator
137
     * @param  string  $value
138
     * @return string
139
     */
140
    protected function compileJsonLength($column, $operator, $value)
141
    {
142
        [$field, $path] = $this->wrapJsonFieldAndPath($column);
143
 
144
        return 'json_length('.$field.$path.') '.$operator.' '.$value;
145
    }
146
 
147
    /**
148
     * Compile a "JSON value cast" statement into SQL.
149
     *
150
     * @param  string  $value
151
     * @return string
152
     */
153
    public function compileJsonValueCast($value)
154
    {
155
        return 'cast('.$value.' as json)';
156
    }
157
 
158
    /**
159
     * Compile the random statement into SQL.
160
     *
161
     * @param  string|int  $seed
162
     * @return string
163
     */
164
    public function compileRandom($seed)
165
    {
166
        return 'RAND('.$seed.')';
167
    }
168
 
169
    /**
170
     * Compile the lock into SQL.
171
     *
172
     * @param  \Illuminate\Database\Query\Builder  $query
173
     * @param  bool|string  $value
174
     * @return string
175
     */
176
    protected function compileLock(Builder $query, $value)
177
    {
178
        if (! is_string($value)) {
179
            return $value ? 'for update' : 'lock in share mode';
180
        }
181
 
182
        return $value;
183
    }
184
 
185
    /**
186
     * Compile an insert statement into SQL.
187
     *
188
     * @param  \Illuminate\Database\Query\Builder  $query
189
     * @param  array  $values
190
     * @return string
191
     */
192
    public function compileInsert(Builder $query, array $values)
193
    {
194
        if (empty($values)) {
195
            $values = [[]];
196
        }
197
 
198
        return parent::compileInsert($query, $values);
199
    }
200
 
201
    /**
202
     * Compile the columns for an update statement.
203
     *
204
     * @param  \Illuminate\Database\Query\Builder  $query
205
     * @param  array  $values
206
     * @return string
207
     */
208
    protected function compileUpdateColumns(Builder $query, array $values)
209
    {
210
        return collect($values)->map(function ($value, $key) {
211
            if ($this->isJsonSelector($key)) {
212
                return $this->compileJsonUpdateColumn($key, $value);
213
            }
214
 
215
            return $this->wrap($key).' = '.$this->parameter($value);
216
        })->implode(', ');
217
    }
218
 
219
    /**
220
     * Compile an "upsert" statement into SQL.
221
     *
222
     * @param  \Illuminate\Database\Query\Builder  $query
223
     * @param  array  $values
224
     * @param  array  $uniqueBy
225
     * @param  array  $update
226
     * @return string
227
     */
228
    public function compileUpsert(Builder $query, array $values, array $uniqueBy, array $update)
229
    {
230
        $useUpsertAlias = $query->connection->getConfig('use_upsert_alias');
231
 
232
        $sql = $this->compileInsert($query, $values);
233
 
234
        if ($useUpsertAlias) {
235
            $sql .= ' as laravel_upsert_alias';
236
        }
237
 
238
        $sql .= ' on duplicate key update ';
239
 
240
        $columns = collect($update)->map(function ($value, $key) use ($useUpsertAlias) {
241
            if (! is_numeric($key)) {
242
                return $this->wrap($key).' = '.$this->parameter($value);
243
            }
244
 
245
            return $useUpsertAlias
246
                ? $this->wrap($value).' = '.$this->wrap('laravel_upsert_alias').'.'.$this->wrap($value)
247
                : $this->wrap($value).' = values('.$this->wrap($value).')';
248
        })->implode(', ');
249
 
250
        return $sql.$columns;
251
    }
252
 
253
    /**
254
     * Prepare a JSON column being updated using the JSON_SET function.
255
     *
256
     * @param  string  $key
257
     * @param  mixed  $value
258
     * @return string
259
     */
260
    protected function compileJsonUpdateColumn($key, $value)
261
    {
262
        if (is_bool($value)) {
263
            $value = $value ? 'true' : 'false';
264
        } elseif (is_array($value)) {
265
            $value = 'cast(? as json)';
266
        } else {
267
            $value = $this->parameter($value);
268
        }
269
 
270
        [$field, $path] = $this->wrapJsonFieldAndPath($key);
271
 
272
        return "{$field} = json_set({$field}{$path}, {$value})";
273
    }
274
 
275
    /**
276
     * Compile an update statement without joins into SQL.
277
     *
278
     * @param  \Illuminate\Database\Query\Builder  $query
279
     * @param  string  $table
280
     * @param  string  $columns
281
     * @param  string  $where
282
     * @return string
283
     */
284
    protected function compileUpdateWithoutJoins(Builder $query, $table, $columns, $where)
285
    {
286
        $sql = parent::compileUpdateWithoutJoins($query, $table, $columns, $where);
287
 
288
        if (! empty($query->orders)) {
289
            $sql .= ' '.$this->compileOrders($query, $query->orders);
290
        }
291
 
292
        if (isset($query->limit)) {
293
            $sql .= ' '.$this->compileLimit($query, $query->limit);
294
        }
295
 
296
        return $sql;
297
    }
298
 
299
    /**
300
     * Prepare the bindings for an update statement.
301
     *
302
     * Booleans, integers, and doubles are inserted into JSON updates as raw values.
303
     *
304
     * @param  array  $bindings
305
     * @param  array  $values
306
     * @return array
307
     */
308
    public function prepareBindingsForUpdate(array $bindings, array $values)
309
    {
310
        $values = collect($values)->reject(function ($value, $column) {
311
            return $this->isJsonSelector($column) && is_bool($value);
312
        })->map(function ($value) {
313
            return is_array($value) ? json_encode($value) : $value;
314
        })->all();
315
 
316
        return parent::prepareBindingsForUpdate($bindings, $values);
317
    }
318
 
319
    /**
320
     * Compile a delete query that does not use joins.
321
     *
322
     * @param  \Illuminate\Database\Query\Builder  $query
323
     * @param  string  $table
324
     * @param  string  $where
325
     * @return string
326
     */
327
    protected function compileDeleteWithoutJoins(Builder $query, $table, $where)
328
    {
329
        $sql = parent::compileDeleteWithoutJoins($query, $table, $where);
330
 
331
        // When using MySQL, delete statements may contain order by statements and limits
332
        // so we will compile both of those here. Once we have finished compiling this
333
        // we will return the completed SQL statement so it will be executed for us.
334
        if (! empty($query->orders)) {
335
            $sql .= ' '.$this->compileOrders($query, $query->orders);
336
        }
337
 
338
        if (isset($query->limit)) {
339
            $sql .= ' '.$this->compileLimit($query, $query->limit);
340
        }
341
 
342
        return $sql;
343
    }
344
 
345
    /**
346
     * Wrap a single string in keyword identifiers.
347
     *
348
     * @param  string  $value
349
     * @return string
350
     */
351
    protected function wrapValue($value)
352
    {
353
        return $value === '*' ? $value : '`'.str_replace('`', '``', $value).'`';
354
    }
355
 
356
    /**
357
     * Wrap the given JSON selector.
358
     *
359
     * @param  string  $value
360
     * @return string
361
     */
362
    protected function wrapJsonSelector($value)
363
    {
364
        [$field, $path] = $this->wrapJsonFieldAndPath($value);
365
 
366
        return 'json_unquote(json_extract('.$field.$path.'))';
367
    }
368
 
369
    /**
370
     * Wrap the given JSON selector for boolean values.
371
     *
372
     * @param  string  $value
373
     * @return string
374
     */
375
    protected function wrapJsonBooleanSelector($value)
376
    {
377
        [$field, $path] = $this->wrapJsonFieldAndPath($value);
378
 
379
        return 'json_extract('.$field.$path.')';
380
    }
381
}