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\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
    /**
78
     * Compile an insert ignore statement into SQL.
79
     *
80
     * @param  \Illuminate\Database\Query\Builder  $query
81
     * @param  array  $values
82
     * @return string
83
     */
84
    public function compileInsertOrIgnore(Builder $query, array $values)
85
    {
86
        return Str::replaceFirst('insert', 'insert ignore', $this->compileInsert($query, $values));
87
    }
88
 
89
    /**
90
     * Compile a "JSON contains" statement into SQL.
91
     *
92
     * @param  string  $column
93
     * @param  string  $value
94
     * @return string
95
     */
96
    protected function compileJsonContains($column, $value)
97
    {
98
        [$field, $path] = $this->wrapJsonFieldAndPath($column);
99
 
100
        return 'json_contains('.$field.', '.$value.$path.')';
101
    }
102
 
103
    /**
104
     * Compile a "JSON contains key" statement into SQL.
105
     *
106
     * @param  string  $column
107
     * @return string
108
     */
109
    protected function compileJsonContainsKey($column)
110
    {
111
        [$field, $path] = $this->wrapJsonFieldAndPath($column);
112
 
113
        return 'ifnull(json_contains_path('.$field.', \'one\''.$path.'), 0)';
114
    }
115
 
116
    /**
117
     * Compile a "JSON length" statement into SQL.
118
     *
119
     * @param  string  $column
120
     * @param  string  $operator
121
     * @param  string  $value
122
     * @return string
123
     */
124
    protected function compileJsonLength($column, $operator, $value)
125
    {
126
        [$field, $path] = $this->wrapJsonFieldAndPath($column);
127
 
128
        return 'json_length('.$field.$path.') '.$operator.' '.$value;
129
    }
130
 
131
    /**
132
     * Compile a "JSON value cast" statement into SQL.
133
     *
134
     * @param  string  $value
135
     * @return string
136
     */
137
    public function compileJsonValueCast($value)
138
    {
139
        return 'cast('.$value.' as json)';
140
    }
141
 
142
    /**
143
     * Compile the random statement into SQL.
144
     *
145
     * @param  string|int  $seed
146
     * @return string
147
     */
148
    public function compileRandom($seed)
149
    {
150
        return 'RAND('.$seed.')';
151
    }
152
 
153
    /**
154
     * Compile the lock into SQL.
155
     *
156
     * @param  \Illuminate\Database\Query\Builder  $query
157
     * @param  bool|string  $value
158
     * @return string
159
     */
160
    protected function compileLock(Builder $query, $value)
161
    {
162
        if (! is_string($value)) {
163
            return $value ? 'for update' : 'lock in share mode';
164
        }
165
 
166
        return $value;
167
    }
168
 
169
    /**
170
     * Compile an insert statement into SQL.
171
     *
172
     * @param  \Illuminate\Database\Query\Builder  $query
173
     * @param  array  $values
174
     * @return string
175
     */
176
    public function compileInsert(Builder $query, array $values)
177
    {
178
        if (empty($values)) {
179
            $values = [[]];
180
        }
181
 
182
        return parent::compileInsert($query, $values);
183
    }
184
 
185
    /**
186
     * Compile the columns for an update statement.
187
     *
188
     * @param  \Illuminate\Database\Query\Builder  $query
189
     * @param  array  $values
190
     * @return string
191
     */
192
    protected function compileUpdateColumns(Builder $query, array $values)
193
    {
194
        return collect($values)->map(function ($value, $key) {
195
            if ($this->isJsonSelector($key)) {
196
                return $this->compileJsonUpdateColumn($key, $value);
197
            }
198
 
199
            return $this->wrap($key).' = '.$this->parameter($value);
200
        })->implode(', ');
201
    }
202
 
203
    /**
204
     * Compile an "upsert" statement into SQL.
205
     *
206
     * @param  \Illuminate\Database\Query\Builder  $query
207
     * @param  array  $values
208
     * @param  array  $uniqueBy
209
     * @param  array  $update
210
     * @return string
211
     */
212
    public function compileUpsert(Builder $query, array $values, array $uniqueBy, array $update)
213
    {
214
        $useUpsertAlias = $query->connection->getConfig('use_upsert_alias');
215
 
216
        $sql = $this->compileInsert($query, $values);
217
 
218
        if ($useUpsertAlias) {
219
            $sql .= ' as laravel_upsert_alias';
220
        }
221
 
222
        $sql .= ' on duplicate key update ';
223
 
224
        $columns = collect($update)->map(function ($value, $key) use ($useUpsertAlias) {
225
            if (! is_numeric($key)) {
226
                return $this->wrap($key).' = '.$this->parameter($value);
227
            }
228
 
229
            return $useUpsertAlias
230
                ? $this->wrap($value).' = '.$this->wrap('laravel_upsert_alias').'.'.$this->wrap($value)
231
                : $this->wrap($value).' = values('.$this->wrap($value).')';
232
        })->implode(', ');
233
 
234
        return $sql.$columns;
235
    }
236
 
237
    /**
238
     * Prepare a JSON column being updated using the JSON_SET function.
239
     *
240
     * @param  string  $key
241
     * @param  mixed  $value
242
     * @return string
243
     */
244
    protected function compileJsonUpdateColumn($key, $value)
245
    {
246
        if (is_bool($value)) {
247
            $value = $value ? 'true' : 'false';
248
        } elseif (is_array($value)) {
249
            $value = 'cast(? as json)';
250
        } else {
251
            $value = $this->parameter($value);
252
        }
253
 
254
        [$field, $path] = $this->wrapJsonFieldAndPath($key);
255
 
256
        return "{$field} = json_set({$field}{$path}, {$value})";
257
    }
258
 
259
    /**
260
     * Compile an update statement without joins into SQL.
261
     *
262
     * @param  \Illuminate\Database\Query\Builder  $query
263
     * @param  string  $table
264
     * @param  string  $columns
265
     * @param  string  $where
266
     * @return string
267
     */
268
    protected function compileUpdateWithoutJoins(Builder $query, $table, $columns, $where)
269
    {
270
        $sql = parent::compileUpdateWithoutJoins($query, $table, $columns, $where);
271
 
272
        if (! empty($query->orders)) {
273
            $sql .= ' '.$this->compileOrders($query, $query->orders);
274
        }
275
 
276
        if (isset($query->limit)) {
277
            $sql .= ' '.$this->compileLimit($query, $query->limit);
278
        }
279
 
280
        return $sql;
281
    }
282
 
283
    /**
284
     * Prepare the bindings for an update statement.
285
     *
286
     * Booleans, integers, and doubles are inserted into JSON updates as raw values.
287
     *
288
     * @param  array  $bindings
289
     * @param  array  $values
290
     * @return array
291
     */
292
    public function prepareBindingsForUpdate(array $bindings, array $values)
293
    {
294
        $values = collect($values)->reject(function ($value, $column) {
295
            return $this->isJsonSelector($column) && is_bool($value);
296
        })->map(function ($value) {
297
            return is_array($value) ? json_encode($value) : $value;
298
        })->all();
299
 
300
        return parent::prepareBindingsForUpdate($bindings, $values);
301
    }
302
 
303
    /**
304
     * Compile a delete query that does not use joins.
305
     *
306
     * @param  \Illuminate\Database\Query\Builder  $query
307
     * @param  string  $table
308
     * @param  string  $where
309
     * @return string
310
     */
311
    protected function compileDeleteWithoutJoins(Builder $query, $table, $where)
312
    {
313
        $sql = parent::compileDeleteWithoutJoins($query, $table, $where);
314
 
315
        // When using MySQL, delete statements may contain order by statements and limits
316
        // so we will compile both of those here. Once we have finished compiling this
317
        // we will return the completed SQL statement so it will be executed for us.
318
        if (! empty($query->orders)) {
319
            $sql .= ' '.$this->compileOrders($query, $query->orders);
320
        }
321
 
322
        if (isset($query->limit)) {
323
            $sql .= ' '.$this->compileLimit($query, $query->limit);
324
        }
325
 
326
        return $sql;
327
    }
328
 
329
    /**
330
     * Wrap a single string in keyword identifiers.
331
     *
332
     * @param  string  $value
333
     * @return string
334
     */
335
    protected function wrapValue($value)
336
    {
337
        return $value === '*' ? $value : '`'.str_replace('`', '``', $value).'`';
338
    }
339
 
340
    /**
341
     * Wrap the given JSON selector.
342
     *
343
     * @param  string  $value
344
     * @return string
345
     */
346
    protected function wrapJsonSelector($value)
347
    {
348
        [$field, $path] = $this->wrapJsonFieldAndPath($value);
349
 
350
        return 'json_unquote(json_extract('.$field.$path.'))';
351
    }
352
 
353
    /**
354
     * Wrap the given JSON selector for boolean values.
355
     *
356
     * @param  string  $value
357
     * @return string
358
     */
359
    protected function wrapJsonBooleanSelector($value)
360
    {
361
        [$field, $path] = $this->wrapJsonFieldAndPath($value);
362
 
363
        return 'json_extract('.$field.$path.')';
364
    }
365
}