Passed
Pull Request — 5.1 (#1748)
by guanguans
09:27
created

Builder::parseNull()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 6
dl 0
loc 4
rs 10
c 0
b 0
f 0
1
<?php
2
// +----------------------------------------------------------------------
1 ignored issue
show
Coding Style introduced by
You must use "/**" style comments for a file comment
Loading history...
3
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
4
// +----------------------------------------------------------------------
5
// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
6
// +----------------------------------------------------------------------
7
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
8
// +----------------------------------------------------------------------
9
// | Author: liu21st <[email protected]>
10
// +----------------------------------------------------------------------
11
12
namespace think\db;
13
14
use PDO;
15
use think\Exception;
16
17
abstract class Builder
1 ignored issue
show
Coding Style introduced by
Missing class doc comment
Loading history...
18
{
19
    // connection对象实例
20
    protected $connection;
21
22
    // 查询表达式映射
23
    protected $exp = ['EQ' => '=', 'NEQ' => '<>', 'GT' => '>', 'EGT' => '>=', 'LT' => '<', 'ELT' => '<=', 'NOTLIKE' => 'NOT LIKE', 'NOTIN' => 'NOT IN', 'NOTBETWEEN' => 'NOT BETWEEN', 'NOTEXISTS' => 'NOT EXISTS', 'NOTNULL' => 'NOT NULL', 'NOTBETWEEN TIME' => 'NOT BETWEEN TIME'];
24
25
    // 查询表达式解析
26
    protected $parser = [
27
        'parseCompare'     => ['=', '<>', '>', '>=', '<', '<='],
28
        'parseLike'        => ['LIKE', 'NOT LIKE'],
29
        'parseBetween'     => ['NOT BETWEEN', 'BETWEEN'],
30
        'parseIn'          => ['NOT IN', 'IN'],
31
        'parseExp'         => ['EXP'],
32
        'parseNull'        => ['NOT NULL', 'NULL'],
33
        'parseBetweenTime' => ['BETWEEN TIME', 'NOT BETWEEN TIME'],
34
        'parseTime'        => ['< TIME', '> TIME', '<= TIME', '>= TIME'],
35
        'parseExists'      => ['NOT EXISTS', 'EXISTS'],
36
        'parseColumn'      => ['COLUMN'],
37
    ];
38
39
    // SQL表达式
40
    protected $selectSql = 'SELECT%DISTINCT% %FIELD% FROM %TABLE%%FORCE%%JOIN%%WHERE%%GROUP%%HAVING%%UNION%%ORDER%%LIMIT% %LOCK%%COMMENT%';
41
42
    protected $insertSql = '%INSERT% INTO %TABLE% (%FIELD%) VALUES (%DATA%) %COMMENT%';
43
44
    protected $insertAllSql = '%INSERT% INTO %TABLE% (%FIELD%) %DATA% %COMMENT%';
45
46
    protected $updateSql = 'UPDATE %TABLE% SET %SET%%JOIN%%WHERE%%ORDER%%LIMIT% %LOCK%%COMMENT%';
47
48
    protected $deleteSql = 'DELETE FROM %TABLE%%USING%%JOIN%%WHERE%%ORDER%%LIMIT% %LOCK%%COMMENT%';
49
50
    /**
51
     * 架构函数
52
     * @access public
53
     * @param  Connection    $connection 数据库连接对象实例
54
     */
55
    public function __construct(Connection $connection)
56
    {
57
        $this->connection = $connection;
58
    }
59
60
    /**
61
     * 获取当前的连接对象实例
62
     * @access public
63
     * @return Connection
64
     */
65
    public function getConnection()
66
    {
67
        return $this->connection;
68
    }
69
70
    /**
71
     * 注册查询表达式解析
72
     * @access public
73
     * @param  string    $name   解析方法
74
     * @param  array     $parser 匹配表达式数据
75
     * @return $this
76
     */
77
    public function bindParser($name, $parser)
78
    {
79
        $this->parser[$name] = $parser;
80
        return $this;
81
    }
82
83
    /**
84
     * 数据分析
85
     * @access protected
86
     * @param  Query     $query     查询对象
0 ignored issues
show
Coding Style introduced by
Expected 2 spaces after parameter name; 5 found
Loading history...
87
     * @param  array     $data      数据
0 ignored issues
show
Coding Style introduced by
Expected 3 spaces after parameter name; 6 found
Loading history...
88
     * @param  array     $fields    字段信息
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 4 found
Loading history...
89
     * @param  array     $bind      参数绑定
0 ignored issues
show
Coding Style introduced by
Expected 3 spaces after parameter name; 6 found
Loading history...
90
     * @return array
91
     */
92
    protected function parseData(Query $query, $data = [], $fields = [], $bind = [])
93
    {
94
        if (empty($data)) {
95
            return [];
96
        }
97
98
        $options = $query->getOptions();
99
100
        // 获取绑定信息
101
        if (empty($bind)) {
102
            $bind = $this->connection->getFieldsBind($options['table']);
103
        }
104
105
        if (empty($fields)) {
106
            if ('*' == $options['field']) {
107
                $fields = array_keys($bind);
108
            } else {
109
                $fields = $options['field'];
110
            }
111
        }
112
113
        $result = [];
114
115
        foreach ($data as $key => $val) {
116
            if ('*' != $options['field'] && !in_array($key, $fields, true)) {
117
                continue;
118
            }
119
120
            $item = $this->parseKey($query, $key, true);
121
122
            if ($val instanceof Expression) {
123
                $result[$item] = $val->getValue();
124
                continue;
125
            } elseif (!is_scalar($val) && (in_array($key, (array) $query->getOptions('json')) || 'json' == $this->connection->getFieldsType($options['table'], $key))) {
126
                $val = json_encode($val, JSON_UNESCAPED_UNICODE);
127
            } elseif (is_object($val) && method_exists($val, '__toString')) {
128
                // 对象数据写入
129
                $val = $val->__toString();
130
            }
131
132
            if (false !== strpos($key, '->')) {
133
                list($key, $name) = explode('->', $key);
134
                $item             = $this->parseKey($query, $key);
135
                $result[$item]    = 'json_set(' . $item . ', \'$.' . $name . '\', ' . $this->parseDataBind($query, $key, $val, $bind) . ')';
136
            } elseif ('*' == $options['field'] && false === strpos($key, '.') && !in_array($key, $fields, true)) {
137
                if ($options['strict']) {
138
                    throw new Exception('fields not exists:[' . $key . ']');
139
                }
140
            } elseif (is_null($val)) {
141
                $result[$item] = 'NULL';
142
            } elseif (is_array($val) && !empty($val)) {
143
                switch (strtoupper($val[0])) {
144
                    case 'INC':
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 16 spaces, found 20
Loading history...
145
                        $result[$item] = $item . ' + ' . floatval($val[1]);
146
                        break;
147
                    case 'DEC':
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 16 spaces, found 20
Loading history...
148
                        $result[$item] = $item . ' - ' . floatval($val[1]);
149
                        break;
150
                    case 'EXP':
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 16 spaces, found 20
Loading history...
151
                        throw new Exception('not support data:[' . $val[0] . ']');
152
                }
153
            } elseif (is_scalar($val)) {
154
                // 过滤非标量数据
155
                $result[$item] = $this->parseDataBind($query, $key, $val, $bind);
156
            }
157
        }
158
159
        return $result;
160
    }
161
162
    /**
163
     * 数据绑定处理
164
     * @access protected
165
     * @param  Query     $query     查询对象
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 5 found
Loading history...
166
     * @param  string    $key       字段名
0 ignored issues
show
Coding Style introduced by
Expected 3 spaces after parameter name; 7 found
Loading history...
167
     * @param  mixed     $data      数据
0 ignored issues
show
Coding Style introduced by
Expected 2 spaces after parameter name; 6 found
Loading history...
168
     * @param  array     $bind      绑定数据
0 ignored issues
show
Coding Style introduced by
Expected 2 spaces after parameter name; 6 found
Loading history...
169
     * @return string
170
     */
171
    protected function parseDataBind(Query $query, $key, $data, $bind = [])
172
    {
173
        if ($data instanceof Expression) {
174
            return $data->getValue();
175
        }
176
177
        $name = $query->bind($data, isset($bind[$key]) ? $bind[$key] : PDO::PARAM_STR);
178
179
        return ':' . $name;
0 ignored issues
show
Bug introduced by
Are you sure $name of type string|think\db\Query can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

179
        return ':' . /** @scrutinizer ignore-type */ $name;
Loading history...
180
    }
181
182
    /**
183
     * 字段名分析
184
     * @access public
185
     * @param  Query  $query    查询对象
0 ignored issues
show
Coding Style introduced by
Expected 2 spaces after parameter name; 4 found
Loading history...
186
     * @param  mixed  $key      字段名
0 ignored issues
show
Coding Style introduced by
Expected 4 spaces after parameter name; 6 found
Loading history...
187
     * @param  bool   $strict   严格检测
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 3 found
Loading history...
188
     * @return string
189
     */
190
    public function parseKey(Query $query, $key, $strict = false)
191
    {
192
        return $key instanceof Expression ? $key->getValue() : $key;
193
    }
194
195
    /**
196
     * field分析
0 ignored issues
show
Coding Style introduced by
Doc comment short description must start with a capital letter
Loading history...
197
     * @access protected
198
     * @param  Query     $query     查询对象
0 ignored issues
show
Coding Style introduced by
Expected 2 spaces after parameter name; 5 found
Loading history...
199
     * @param  mixed     $fields    字段名
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 4 found
Loading history...
200
     * @return string
201
     */
202
    protected function parseField(Query $query, $fields)
203
    {
204
        if ('*' == $fields || empty($fields)) {
205
            $fieldsStr = '*';
206
        } elseif (is_array($fields)) {
207
            // 支持 'field1'=>'field2' 这样的字段别名定义
208
            $array = [];
209
210
            foreach ($fields as $key => $field) {
211
                if (!is_numeric($key)) {
212
                    $array[] = $this->parseKey($query, $key) . ' AS ' . $this->parseKey($query, $field, true);
213
                } else {
214
                    $array[] = $this->parseKey($query, $field);
215
                }
216
            }
217
218
            $fieldsStr = implode(',', $array);
219
        }
220
221
        return $fieldsStr;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $fieldsStr does not seem to be defined for all execution paths leading up to this point.
Loading history...
222
    }
223
224
    /**
225
     * table分析
0 ignored issues
show
Coding Style introduced by
Doc comment short description must start with a capital letter
Loading history...
226
     * @access protected
227
     * @param  Query     $query         查询对象
0 ignored issues
show
Coding Style introduced by
Expected 2 spaces after parameter name; 9 found
Loading history...
228
     * @param  mixed     $tables        表名
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 8 found
Loading history...
229
     * @return string
230
     */
231
    protected function parseTable(Query $query, $tables)
232
    {
233
        $item    = [];
234
        $options = $query->getOptions();
235
236
        foreach ((array) $tables as $key => $table) {
237
            if (!is_numeric($key)) {
238
                $key    = $this->connection->parseSqlTable($key);
239
                $item[] = $this->parseKey($query, $key) . ' ' . $this->parseKey($query, $table);
240
            } else {
241
                $table = $this->connection->parseSqlTable($table);
242
243
                if (isset($options['alias'][$table])) {
244
                    $item[] = $this->parseKey($query, $table) . ' ' . $this->parseKey($query, $options['alias'][$table]);
245
                } else {
246
                    $item[] = $this->parseKey($query, $table);
247
                }
248
            }
249
        }
250
251
        return implode(',', $item);
252
    }
253
254
    /**
255
     * where分析
0 ignored issues
show
Coding Style introduced by
Doc comment short description must start with a capital letter
Loading history...
256
     * @access protected
257
     * @param  Query     $query   查询对象
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 3 found
Loading history...
258
     * @param  mixed     $where   查询条件
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 3 found
Loading history...
259
     * @return string
260
     */
261
    protected function parseWhere(Query $query, $where)
262
    {
263
        $options  = $query->getOptions();
264
        $whereStr = $this->buildWhere($query, $where);
265
266
        if (!empty($options['soft_delete'])) {
267
            // 附加软删除条件
268
            list($field, $condition) = $options['soft_delete'];
269
270
            $binds    = $this->connection->getFieldsBind($options['table']);
271
            $whereStr = $whereStr ? '( ' . $whereStr . ' ) AND ' : '';
272
            $whereStr = $whereStr . $this->parseWhereItem($query, $field, $condition, '', $binds);
273
        }
274
275
        return empty($whereStr) ? '' : ' WHERE ' . $whereStr;
276
    }
277
278
    /**
279
     * 生成查询条件SQL
280
     * @access public
281
     * @param  Query     $query     查询对象
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 5 found
Loading history...
282
     * @param  mixed     $where     查询条件
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 5 found
Loading history...
283
     * @return string
284
     */
285
    public function buildWhere(Query $query, $where)
286
    {
287
        if (empty($where)) {
288
            $where = [];
289
        }
290
291
        $whereStr = '';
292
        $binds    = $this->connection->getFieldsBind($query->getOptions('table'));
293
294
        foreach ($where as $logic => $val) {
295
            $str = [];
296
297
            foreach ($val as $value) {
298
                if ($value instanceof Expression) {
299
                    $str[] = ' ' . $logic . ' ( ' . $value->getValue() . ' )';
300
                    continue;
301
                }
302
303
                if (is_array($value)) {
304
                    if (key($value) !== 0) {
305
                        throw new Exception('where express error:' . var_export($value, true));
306
                    }
307
                    $field = array_shift($value);
308
                } elseif (!($value instanceof \Closure)) {
309
                    throw new Exception('where express error:' . var_export($value, true));
310
                }
311
312
                if ($value instanceof \Closure) {
313
                    // 使用闭包查询
314
                    $newQuery = $query->newQuery()->setConnection($this->connection);
315
                    $value($newQuery);
316
                    $whereClause = $this->buildWhere($query, $newQuery->getOptions('where'));
317
318
                    if (!empty($whereClause)) {
319
                        $str[] = ' ' . $logic . ' ( ' . $whereClause . ' )';
320
                    }
321
                } elseif (is_array($field)) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $field does not seem to be defined for all execution paths leading up to this point.
Loading history...
322
                    array_unshift($value, $field);
323
                    $str2 = [];
324
                    foreach ($value as $item) {
325
                        $str2[] = $this->parseWhereItem($query, array_shift($item), $item, $logic, $binds);
326
                    }
327
328
                    $str[] = ' ' . $logic . ' ( ' . implode(' AND ', $str2) . ' )';
329
                } elseif (strpos($field, '|')) {
330
                    // 不同字段使用相同查询条件(OR)
331
                    $array = explode('|', $field);
332
                    $item  = [];
333
334
                    foreach ($array as $k) {
335
                        $item[] = $this->parseWhereItem($query, $k, $value, '', $binds);
336
                    }
337
338
                    $str[] = ' ' . $logic . ' ( ' . implode(' OR ', $item) . ' )';
339
                } elseif (strpos($field, '&')) {
340
                    // 不同字段使用相同查询条件(AND)
341
                    $array = explode('&', $field);
342
                    $item  = [];
343
344
                    foreach ($array as $k) {
345
                        $item[] = $this->parseWhereItem($query, $k, $value, '', $binds);
346
                    }
347
348
                    $str[] = ' ' . $logic . ' ( ' . implode(' AND ', $item) . ' )';
349
                } else {
350
                    // 对字段使用表达式查询
351
                    $field = is_string($field) ? $field : '';
352
                    $str[] = ' ' . $logic . ' ' . $this->parseWhereItem($query, $field, $value, $logic, $binds);
353
                }
354
            }
355
356
            $whereStr .= empty($whereStr) ? substr(implode(' ', $str), strlen($logic) + 1) : implode(' ', $str);
357
        }
358
359
        return $whereStr;
360
    }
361
362
    // where子单元分析
363
    protected function parseWhereItem(Query $query, $field, $val, $rule = '', $binds = [])
0 ignored issues
show
Coding Style introduced by
You must use "/**" style comments for a function comment
Loading history...
364
    {
365
        // 字段分析
366
        $key = $field ? $this->parseKey($query, $field, true) : '';
367
368
        // 查询规则和条件
369
        if (!is_array($val)) {
370
            $val = is_null($val) ? ['NULL', ''] : ['=', $val];
371
        }
372
373
        list($exp, $value) = $val;
374
375
        // 对一个字段使用多个查询条件
376
        if (is_array($exp)) {
377
            $item = array_pop($val);
378
379
            // 传入 or 或者 and
380
            if (is_string($item) && in_array($item, ['AND', 'and', 'OR', 'or'])) {
381
                $rule = $item;
382
            } else {
383
                array_push($val, $item);
384
            }
385
386
            foreach ($val as $k => $item) {
387
                $str[] = $this->parseWhereItem($query, $field, $item, $rule, $binds);
388
            }
389
390
            return '( ' . implode(' ' . $rule . ' ', $str) . ' )';
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $str seems to be defined by a foreach iteration on line 386. Are you sure the iterator is never empty, otherwise this variable is not defined?
Loading history...
391
        }
392
393
        // 检测操作符
394
        $exp = strtoupper($exp);
395
        if (isset($this->exp[$exp])) {
396
            $exp = $this->exp[$exp];
397
        }
398
399
        if ($value instanceof Expression) {
400
401
        } elseif (is_object($value) && method_exists($value, '__toString')) {
402
            // 对象数据写入
403
            $value = $value->__toString();
404
        }
405
406
        if (strpos($field, '->')) {
407
            $jsonType = $query->getJsonFieldType($field);
408
            $bindType = $this->connection->getFieldBindType($jsonType);
409
        } else {
410
            $bindType = isset($binds[$field]) ? $binds[$field] : PDO::PARAM_STR;
411
        }
412
413
        if (is_scalar($value) && !in_array($exp, ['EXP', 'NOT NULL', 'NULL', 'IN', 'NOT IN', 'BETWEEN', 'NOT BETWEEN']) && strpos($exp, 'TIME') === false) {
414
            if (0 === strpos($value, ':') && $query->isBind(substr($value, 1))) {
415
            } else {
416
                $name  = $query->bind($value, $bindType);
417
                $value = ':' . $name;
0 ignored issues
show
Bug introduced by
Are you sure $name of type string|think\db\Query can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

417
                $value = ':' . /** @scrutinizer ignore-type */ $name;
Loading history...
418
            }
419
        }
420
421
        // 解析查询表达式
422
        foreach ($this->parser as $fun => $parse) {
423
            if (in_array($exp, $parse)) {
424
                $whereStr = $this->$fun($query, $key, $exp, $value, $field, $bindType, isset($val[2]) ? $val[2] : 'AND');
425
                break;
426
            }
427
        }
428
429
        if (!isset($whereStr)) {
430
            throw new Exception('where express error:' . $exp);
431
        }
432
433
        return $whereStr;
434
    }
435
436
    /**
437
     * 模糊查询
438
     * @access protected
439
     * @param  Query     $query        查询对象
0 ignored issues
show
Coding Style introduced by
Expected 4 spaces after parameter name; 8 found
Loading history...
440
     * @param  string    $key
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
441
     * @param  string    $exp
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
442
     * @param  mixed     $value
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
443
     * @param  string    $field
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
444
     * @param  integer   $bindType
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
445
     * @param  string    $logic
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
446
     * @return string
447
     */
448
    protected function parseLike(Query $query, $key, $exp, $value, $field, $bindType, $logic)
449
    {
450
        // 模糊匹配
451
        if (is_array($value)) {
452
            foreach ($value as $item) {
453
                $name    = $query->bind($item, $bindType);
454
                $array[] = $key . ' ' . $exp . ' :' . $name;
0 ignored issues
show
Bug introduced by
Are you sure $name of type string|think\db\Query can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

454
                $array[] = $key . ' ' . $exp . ' :' . /** @scrutinizer ignore-type */ $name;
Loading history...
455
            }
456
457
            $whereStr = '(' . implode(' ' . strtoupper($logic) . ' ', $array) . ')';
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $array seems to be defined by a foreach iteration on line 452. Are you sure the iterator is never empty, otherwise this variable is not defined?
Loading history...
458
        } else {
459
            $whereStr = $key . ' ' . $exp . ' ' . $value;
460
        }
461
462
        return $whereStr;
463
    }
464
465
    /**
466
     * 表达式查询
467
     * @access protected
468
     * @param  Query        $query        查询对象
0 ignored issues
show
Coding Style introduced by
Expected 4 spaces after parameter name; 8 found
Loading history...
469
     * @param  string       $key
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
470
     * @param  string       $exp
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
471
     * @param  array        $value
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
472
     * @param  string       $field
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
473
     * @param  integer      $bindType
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
474
     * @return string
475
     */
476
    protected function parseColumn(Query $query, $key, $exp, array $value, $field, $bindType)
477
    {
478
        // 字段比较查询
479
        list($op, $field2) = $value;
480
481
        if (!in_array($op, ['=', '<>', '>', '>=', '<', '<='])) {
482
            throw new Exception('where express error:' . var_export($value, true));
483
        }
484
485
        return '( ' . $key . ' ' . $op . ' ' . $this->parseKey($query, $field2, true) . ' )';
486
    }
487
488
    /**
489
     * 表达式查询
490
     * @access protected
491
     * @param  Query        $query        查询对象
0 ignored issues
show
Coding Style introduced by
Expected 4 spaces after parameter name; 8 found
Loading history...
492
     * @param  string       $key
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
493
     * @param  string       $exp
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
494
     * @param  Expression   $value
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
495
     * @param  string       $field
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
496
     * @param  integer      $bindType
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
497
     * @return string
498
     */
499
    protected function parseExp(Query $query, $key, $exp, Expression $value, $field, $bindType)
500
    {
501
        // 表达式查询
502
        return '( ' . $key . ' ' . $value->getValue() . ' )';
503
    }
504
505
    /**
506
     * Null查询
507
     * @access protected
508
     * @param  Query     $query        查询对象
0 ignored issues
show
Coding Style introduced by
Expected 4 spaces after parameter name; 8 found
Loading history...
509
     * @param  string    $key
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
510
     * @param  string    $exp
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
511
     * @param  mixed     $value
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
512
     * @param  string    $field
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
513
     * @param  integer   $bindType
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
514
     * @return string
515
     */
516
    protected function parseNull(Query $query, $key, $exp, $value, $field, $bindType)
517
    {
518
        // NULL 查询
519
        return $key . ' IS ' . $exp;
520
    }
521
522
    /**
523
     * 范围查询
524
     * @access protected
525
     * @param  Query     $query        查询对象
0 ignored issues
show
Coding Style introduced by
Expected 4 spaces after parameter name; 8 found
Loading history...
526
     * @param  string    $key
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
527
     * @param  string    $exp
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
528
     * @param  mixed     $value
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
529
     * @param  string    $field
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
530
     * @param  integer   $bindType
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
531
     * @return string
532
     */
533
    protected function parseBetween(Query $query, $key, $exp, $value, $field, $bindType)
534
    {
535
        // BETWEEN 查询
536
        $data = is_array($value) ? $value : explode(',', $value);
537
538
        $min = $query->bind($data[0], $bindType);
539
        $max = $query->bind($data[1], $bindType);
540
541
        return $key . ' ' . $exp . ' :' . $min . ' AND :' . $max . ' ';
0 ignored issues
show
Bug introduced by
Are you sure $max of type string|think\db\Query can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

541
        return $key . ' ' . $exp . ' :' . $min . ' AND :' . /** @scrutinizer ignore-type */ $max . ' ';
Loading history...
Bug introduced by
Are you sure $min of type string|think\db\Query can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

541
        return $key . ' ' . $exp . ' :' . /** @scrutinizer ignore-type */ $min . ' AND :' . $max . ' ';
Loading history...
542
    }
543
544
    /**
545
     * Exists查询
546
     * @access protected
547
     * @param  Query     $query        查询对象
0 ignored issues
show
Coding Style introduced by
Expected 4 spaces after parameter name; 8 found
Loading history...
548
     * @param  string    $key
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
549
     * @param  string    $exp
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
550
     * @param  mixed     $value
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
551
     * @param  string    $field
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
552
     * @param  integer   $bindType
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
553
     * @return string
554
     */
555
    protected function parseExists(Query $query, $key, $exp, $value, $field, $bindType)
556
    {
557
        // EXISTS 查询
558
        if ($value instanceof \Closure) {
559
            $value = $this->parseClosure($query, $value, false);
560
        } elseif ($value instanceof Expression) {
561
            $value = $value->getValue();
562
        } else {
563
            throw new Exception('where express error:' . $value);
564
        }
565
566
        return $exp . ' (' . $value . ')';
567
    }
568
569
    /**
570
     * 时间比较查询
571
     * @access protected
572
     * @param  Query     $query        查询对象
0 ignored issues
show
Coding Style introduced by
Expected 4 spaces after parameter name; 8 found
Loading history...
573
     * @param  string    $key
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
574
     * @param  string    $exp
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
575
     * @param  mixed     $value
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
576
     * @param  string    $field
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
577
     * @param  integer   $bindType
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
578
     * @return string
579
     */
580
    protected function parseTime(Query $query, $key, $exp, $value, $field, $bindType)
581
    {
582
        return $key . ' ' . substr($exp, 0, 2) . ' ' . $this->parseDateTime($query, $value, $field, $bindType);
583
    }
584
585
    /**
586
     * 大小比较查询
587
     * @access protected
588
     * @param  Query     $query        查询对象
0 ignored issues
show
Coding Style introduced by
Expected 4 spaces after parameter name; 8 found
Loading history...
589
     * @param  string    $key
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
590
     * @param  string    $exp
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
591
     * @param  mixed     $value
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
592
     * @param  string    $field
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
593
     * @param  integer   $bindType
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
594
     * @return string
595
     */
596
    protected function parseCompare(Query $query, $key, $exp, $value, $field, $bindType)
597
    {
598
        if (is_array($value)) {
599
            throw new Exception('where express error:' . $exp . var_export($value, true));
600
        }
601
602
        // 比较运算
603
        if ($value instanceof \Closure) {
604
            $value = $this->parseClosure($query, $value);
605
        }
606
607
        return $key . ' ' . $exp . ' ' . $value;
608
    }
609
610
    /**
611
     * 时间范围查询
612
     * @access protected
613
     * @param  Query     $query        查询对象
0 ignored issues
show
Coding Style introduced by
Expected 4 spaces after parameter name; 8 found
Loading history...
614
     * @param  string    $key
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
615
     * @param  string    $exp
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
616
     * @param  mixed     $value
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
617
     * @param  string    $field
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
618
     * @param  integer   $bindType
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
619
     * @return string
620
     */
621
    protected function parseBetweenTime(Query $query, $key, $exp, $value, $field, $bindType)
622
    {
623
        if (is_string($value)) {
624
            $value = explode(',', $value);
625
        }
626
627
        return $key . ' ' . substr($exp, 0, -4)
628
        . $this->parseDateTime($query, $value[0], $field, $bindType)
629
        . ' AND '
630
        . $this->parseDateTime($query, $value[1], $field, $bindType);
631
632
    }
633
634
    /**
635
     * IN查询
636
     * @access protected
637
     * @param  Query     $query        查询对象
0 ignored issues
show
Coding Style introduced by
Expected 4 spaces after parameter name; 8 found
Loading history...
638
     * @param  string    $key
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
639
     * @param  string    $exp
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
640
     * @param  mixed     $value
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
641
     * @param  string    $field
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
642
     * @param  integer   $bindType
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
643
     * @return string
644
     */
645
    protected function parseIn(Query $query, $key, $exp, $value, $field, $bindType)
646
    {
647
        // IN 查询
648
        if ($value instanceof \Closure) {
649
            $value = $this->parseClosure($query, $value, false);
650
        } elseif ($value instanceof Expression) {
651
            $value = $value->getValue();
652
        } else {
653
            $value = array_unique(is_array($value) ? $value : explode(',', $value));
654
655
            $array = [];
656
657
            foreach ($value as $k => $v) {
658
                $name    = $query->bind($v, $bindType);
659
                $array[] = ':' . $name;
0 ignored issues
show
Bug introduced by
Are you sure $name of type string|think\db\Query can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

659
                $array[] = ':' . /** @scrutinizer ignore-type */ $name;
Loading history...
660
            }
661
662
            $zone = implode(',', $array);
663
664
            $value = empty($zone) ? "''" : $zone;
665
        }
666
667
        return $key . ' ' . $exp . ' (' . $value . ')';
668
    }
669
670
    /**
671
     * 闭包子查询
672
     * @access protected
673
     * @param  Query     $query        查询对象
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 8 found
Loading history...
674
     * @param  \Closure  $call
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
675
     * @param  bool      $show
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
676
     * @return string
677
     */
678
    protected function parseClosure(Query $query, $call, $show = true)
679
    {
680
        $newQuery = $query->newQuery()->setConnection($this->connection);
681
        $call($newQuery);
682
683
        return $newQuery->buildSql($show);
684
    }
685
686
    /**
687
     * 日期时间条件解析
688
     * @access protected
689
     * @param  Query     $query        查询对象
0 ignored issues
show
Coding Style introduced by
Expected 4 spaces after parameter name; 8 found
Loading history...
690
     * @param  string    $value
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
691
     * @param  string    $key
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
692
     * @param  integer   $bindType
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
693
     * @return string
694
     */
695
    protected function parseDateTime(Query $query, $value, $key, $bindType = null)
696
    {
697
        $options = $query->getOptions();
698
699
        // 获取时间字段类型
700
        if (strpos($key, '.')) {
701
            list($table, $key) = explode('.', $key);
702
703
            if (isset($options['alias']) && $pos = array_search($table, $options['alias'])) {
704
                $table = $pos;
705
            }
706
        } else {
707
            $table = $options['table'];
708
        }
709
710
        $type = $this->connection->getTableInfo($table, 'type');
711
712
        if (isset($type[$key])) {
713
            $info = $type[$key];
714
        }
715
716
        if (isset($info)) {
717
            if (is_string($value)) {
0 ignored issues
show
introduced by
The condition is_string($value) is always true.
Loading history...
718
                $value = strtotime($value) ?: $value;
719
            }
720
721
            if (preg_match('/(datetime|timestamp)/is', $info)) {
722
                // 日期及时间戳类型
723
                $value = date('Y-m-d H:i:s', $value);
0 ignored issues
show
Bug introduced by
It seems like $value can also be of type string; however, parameter $timestamp of date() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

723
                $value = date('Y-m-d H:i:s', /** @scrutinizer ignore-type */ $value);
Loading history...
724
            } elseif (preg_match('/(date)/is', $info)) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $info does not seem to be defined for all execution paths leading up to this point.
Loading history...
725
                // 日期及时间戳类型
726
                $value = date('Y-m-d', $value);
727
            }
728
        }
729
730
        $name = $query->bind($value, $bindType);
731
732
        return ':' . $name;
733
    }
734
735
    /**
736
     * limit分析
0 ignored issues
show
Coding Style introduced by
Doc comment short description must start with a capital letter
Loading history...
737
     * @access protected
738
     * @param  Query     $query        查询对象
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 8 found
Loading history...
739
     * @param  mixed     $limit
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
740
     * @return string
741
     */
742
    protected function parseLimit(Query $query, $limit)
743
    {
744
        return (!empty($limit) && false === strpos($limit, '(')) ? ' LIMIT ' . $limit . ' ' : '';
745
    }
746
747
    /**
748
     * join分析
0 ignored issues
show
Coding Style introduced by
Doc comment short description must start with a capital letter
Loading history...
749
     * @access protected
750
     * @param  Query     $query        查询对象
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 8 found
Loading history...
751
     * @param  array     $join
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
752
     * @return string
753
     */
754
    protected function parseJoin(Query $query, $join)
755
    {
756
        $joinStr = '';
757
758
        if (!empty($join)) {
759
            foreach ($join as $item) {
760
                list($table, $type, $on) = $item;
761
762
                $condition = [];
763
764
                foreach ((array) $on as $val) {
765
                    if ($val instanceof Expression) {
766
                        $condition[] = $val->getValue();
767
                    } elseif (strpos($val, '=')) {
768
                        list($val1, $val2) = explode('=', $val, 2);
769
770
                        $condition[] = $this->parseKey($query, $val1) . '=' . $this->parseKey($query, $val2);
771
                    } else {
772
                        $condition[] = $val;
773
                    }
774
                }
775
776
                $table = $this->parseTable($query, $table);
777
778
                $joinStr .= ' ' . $type . ' JOIN ' . $table . ' ON ' . implode(' AND ', $condition);
779
            }
780
        }
781
782
        return $joinStr;
783
    }
784
785
    /**
786
     * order分析
0 ignored issues
show
Coding Style introduced by
Doc comment short description must start with a capital letter
Loading history...
787
     * @access protected
788
     * @param  Query     $query        查询对象
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 8 found
Loading history...
789
     * @param  mixed     $order
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
790
     * @return string
791
     */
792
    protected function parseOrder(Query $query, $order)
793
    {
794
        foreach ($order as $key => $val) {
795
            if ($val instanceof Expression) {
796
                $array[] = $val->getValue();
797
            } elseif (is_array($val) && preg_match('/^[\w\.]+$/', $key)) {
798
                $array[] = $this->parseOrderField($query, $key, $val);
799
            } elseif ('[rand]' == $val) {
800
                $array[] = $this->parseRand($query);
0 ignored issues
show
Bug introduced by
The method parseRand() does not exist on think\db\Builder. Did you maybe mean parseIn()? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

800
                /** @scrutinizer ignore-call */ 
801
                $array[] = $this->parseRand($query);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
801
            } elseif (is_string($val)) {
802
                if (is_numeric($key)) {
803
                    list($key, $sort) = explode(' ', strpos($val, ' ') ? $val : $val . ' ');
804
                } else {
805
                    $sort = $val;
806
                }
807
808
                if (preg_match('/^[\w\.]+$/', $key)) {
809
                    $sort    = strtoupper($sort);
810
                    $sort    = in_array($sort, ['ASC', 'DESC'], true) ? ' ' . $sort : '';
811
                    $array[] = $this->parseKey($query, $key, true) . $sort;
812
                } else {
813
                    throw new Exception('order express error:' . $key);
814
                }
815
            }
816
        }
817
818
        return empty($array) ? '' : ' ORDER BY ' . implode(',', $array);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $array seems to be defined by a foreach iteration on line 794. Are you sure the iterator is never empty, otherwise this variable is not defined?
Loading history...
819
    }
820
821
    /**
822
     * orderField分析
0 ignored issues
show
Coding Style introduced by
Doc comment short description must start with a capital letter
Loading history...
823
     * @access protected
824
     * @param  Query     $query        查询对象
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 8 found
Loading history...
825
     * @param  mixed     $key
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
826
     * @param  array     $val
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
827
     * @return string
828
     */
829
    protected function parseOrderField($query, $key, $val)
830
    {
831
        if (isset($val['sort'])) {
832
            $sort = $val['sort'];
833
            unset($val['sort']);
834
        } else {
835
            $sort = '';
836
        }
837
838
        $sort = strtoupper($sort);
839
        $sort = in_array($sort, ['ASC', 'DESC'], true) ? ' ' . $sort : '';
840
841
        $options = $query->getOptions();
842
        $bind    = $this->connection->getFieldsBind($options['table']);
843
844
        foreach ($val as $k => $item) {
845
            $val[$k] = $this->parseDataBind($query, $key, $item, $bind);
846
        }
847
848
        return 'field(' . $this->parseKey($query, $key, true) . ',' . implode(',', $val) . ')' . $sort;
849
    }
850
851
    /**
852
     * group分析
0 ignored issues
show
Coding Style introduced by
Doc comment short description must start with a capital letter
Loading history...
853
     * @access protected
854
     * @param  Query     $query        查询对象
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 8 found
Loading history...
855
     * @param  mixed     $group
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
856
     * @return string
857
     */
858
    protected function parseGroup(Query $query, $group)
859
    {
860
        if (empty($group)) {
861
            return '';
862
        }
863
864
        if (is_string($group)) {
865
            $group = explode(',', $group);
866
        }
867
868
        foreach ($group as $key) {
869
            $val[] = $this->parseKey($query, $key);
870
        }
871
872
        return ' GROUP BY ' . implode(',', $val);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $val seems to be defined by a foreach iteration on line 868. Are you sure the iterator is never empty, otherwise this variable is not defined?
Loading history...
873
    }
874
875
    /**
876
     * having分析
0 ignored issues
show
Coding Style introduced by
Doc comment short description must start with a capital letter
Loading history...
877
     * @access protected
878
     * @param  Query  $query        查询对象
0 ignored issues
show
Coding Style introduced by
Expected 2 spaces after parameter name; 8 found
Loading history...
879
     * @param  string $having
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
880
     * @return string
881
     */
882
    protected function parseHaving(Query $query, $having)
883
    {
884
        return !empty($having) ? ' HAVING ' . $having : '';
885
    }
886
887
    /**
888
     * comment分析
0 ignored issues
show
Coding Style introduced by
Doc comment short description must start with a capital letter
Loading history...
889
     * @access protected
890
     * @param  Query  $query        查询对象
0 ignored issues
show
Coding Style introduced by
Expected 3 spaces after parameter name; 8 found
Loading history...
891
     * @param  string $comment
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
892
     * @return string
893
     */
894
    protected function parseComment(Query $query, $comment)
895
    {
896
        if (false !== strpos($comment, '*/')) {
897
            $comment = strstr($comment, '*/', true);
898
        }
899
900
        return !empty($comment) ? ' /* ' . $comment . ' */' : '';
901
    }
902
903
    /**
904
     * distinct分析
0 ignored issues
show
Coding Style introduced by
Doc comment short description must start with a capital letter
Loading history...
905
     * @access protected
906
     * @param  Query     $query        查询对象
0 ignored issues
show
Coding Style introduced by
Expected 4 spaces after parameter name; 8 found
Loading history...
907
     * @param  mixed     $distinct
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
908
     * @return string
909
     */
910
    protected function parseDistinct(Query $query, $distinct)
911
    {
912
        return !empty($distinct) ? ' DISTINCT ' : '';
913
    }
914
915
    /**
916
     * union分析
0 ignored issues
show
Coding Style introduced by
Doc comment short description must start with a capital letter
Loading history...
917
     * @access protected
918
     * @param  Query     $query        查询对象
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 8 found
Loading history...
919
     * @param  mixed     $union
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
920
     * @return string
921
     */
922
    protected function parseUnion(Query $query, $union)
923
    {
924
        if (empty($union)) {
925
            return '';
926
        }
927
928
        $type = $union['type'];
929
        unset($union['type']);
930
931
        foreach ($union as $u) {
932
            if ($u instanceof \Closure) {
933
                $sql[] = $type . ' ' . $this->parseClosure($query, $u);
934
            } elseif (is_string($u)) {
935
                $sql[] = $type . ' ( ' . $this->connection->parseSqlTable($u) . ' )';
936
            }
937
        }
938
939
        return ' ' . implode(' ', $sql);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $sql seems to be defined by a foreach iteration on line 931. Are you sure the iterator is never empty, otherwise this variable is not defined?
Loading history...
940
    }
941
942
    /**
943
     * index分析,可在操作链中指定需要强制使用的索引
0 ignored issues
show
Coding Style introduced by
Doc comment short description must start with a capital letter
Loading history...
944
     * @access protected
945
     * @param  Query     $query        查询对象
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 8 found
Loading history...
946
     * @param  mixed     $index
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
947
     * @return string
948
     */
949
    protected function parseForce(Query $query, $index)
950
    {
951
        if (empty($index)) {
952
            return '';
953
        }
954
955
        return sprintf(" FORCE INDEX ( %s ) ", is_array($index) ? implode(',', $index) : $index);
956
    }
957
958
    /**
959
     * 设置锁机制
960
     * @access protected
961
     * @param  Query         $query        查询对象
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 8 found
Loading history...
962
     * @param  bool|string   $lock
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
963
     * @return string
964
     */
965
    protected function parseLock(Query $query, $lock = false)
966
    {
967
        if (is_bool($lock)) {
968
            return $lock ? ' FOR UPDATE ' : '';
969
        } elseif (is_string($lock) && !empty($lock)) {
970
            return ' ' . trim($lock) . ' ';
971
        }
972
    }
973
974
    /**
975
     * 生成查询SQL
976
     * @access public
977
     * @param  Query  $query  查询对象
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
978
     * @return string
979
     */
980
    public function select(Query $query)
981
    {
982
        $options = $query->getOptions();
983
984
        return str_replace(
985
            ['%TABLE%', '%DISTINCT%', '%FIELD%', '%JOIN%', '%WHERE%', '%GROUP%', '%HAVING%', '%ORDER%', '%LIMIT%', '%UNION%', '%LOCK%', '%COMMENT%', '%FORCE%'],
986
            [
987
                $this->parseTable($query, $options['table']),
988
                $this->parseDistinct($query, $options['distinct']),
989
                $this->parseField($query, $options['field']),
990
                $this->parseJoin($query, $options['join']),
991
                $this->parseWhere($query, $options['where']),
992
                $this->parseGroup($query, $options['group']),
993
                $this->parseHaving($query, $options['having']),
994
                $this->parseOrder($query, $options['order']),
995
                $this->parseLimit($query, $options['limit']),
996
                $this->parseUnion($query, $options['union']),
997
                $this->parseLock($query, $options['lock']),
998
                $this->parseComment($query, $options['comment']),
999
                $this->parseForce($query, $options['force']),
1000
            ],
1001
            $this->selectSql);
0 ignored issues
show
Coding Style introduced by
This line of the multi-line function call does not seem to be indented correctly. Expected 8 spaces, but found 12.
Loading history...
Coding Style introduced by
For multi-line function calls, the closing parenthesis should be on a new line.

If a function call spawns multiple lines, the coding standard suggests to move the closing parenthesis to a new line:

someFunctionCall(
    $firstArgument,
    $secondArgument,
    $thirdArgument
); // Closing parenthesis on a new line.
Loading history...
1002
    }
1003
1004
    /**
1005
     * 生成Insert SQL
1006
     * @access public
1007
     * @param  Query     $query   查询对象
1008
     * @param  bool      $replace 是否replace
1009
     * @return string
1010
     */
1011
    public function insert(Query $query, $replace = false)
1012
    {
1013
        $options = $query->getOptions();
1014
1015
        // 分析并处理数据
1016
        $data = $this->parseData($query, $options['data']);
1017
        if (empty($data)) {
1018
            return '';
1019
        }
1020
1021
        $fields = array_keys($data);
1022
        $values = array_values($data);
1023
1024
        return str_replace(
1025
            ['%INSERT%', '%TABLE%', '%FIELD%', '%DATA%', '%COMMENT%'],
1026
            [
1027
                $replace ? 'REPLACE' : 'INSERT',
1028
                $this->parseTable($query, $options['table']),
1029
                implode(' , ', $fields),
1030
                implode(' , ', $values),
1031
                $this->parseComment($query, $options['comment']),
1032
            ],
1033
            $this->insertSql);
0 ignored issues
show
Coding Style introduced by
This line of the multi-line function call does not seem to be indented correctly. Expected 8 spaces, but found 12.
Loading history...
Coding Style introduced by
For multi-line function calls, the closing parenthesis should be on a new line.

If a function call spawns multiple lines, the coding standard suggests to move the closing parenthesis to a new line:

someFunctionCall(
    $firstArgument,
    $secondArgument,
    $thirdArgument
); // Closing parenthesis on a new line.
Loading history...
1034
    }
1035
1036
    /**
1037
     * 生成insertall SQL
1038
     * @access public
1039
     * @param  Query     $query   查询对象
1040
     * @param  array     $dataSet 数据集
1041
     * @param  bool      $replace 是否replace
1042
     * @return string
1043
     */
1044
    public function insertAll(Query $query, $dataSet, $replace = false)
1045
    {
1046
        $options = $query->getOptions();
1047
1048
        // 获取合法的字段
1049
        if ('*' == $options['field']) {
1050
            $allowFields = $this->connection->getTableFields($options['table']);
1051
        } else {
1052
            $allowFields = $options['field'];
1053
        }
1054
1055
        // 获取绑定信息
1056
        $bind = $this->connection->getFieldsBind($options['table']);
1057
1058
        foreach ($dataSet as $data) {
1059
            $data = $this->parseData($query, $data, $allowFields, $bind);
1060
1061
            $values[] = 'SELECT ' . implode(',', array_values($data));
1062
1063
            if (!isset($insertFields)) {
1064
                $insertFields = array_keys($data);
1065
            }
1066
        }
1067
1068
        $fields = [];
1069
1070
        foreach ($insertFields as $field) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $insertFields seems to be defined by a foreach iteration on line 1058. Are you sure the iterator is never empty, otherwise this variable is not defined?
Loading history...
1071
            $fields[] = $this->parseKey($query, $field);
1072
        }
1073
1074
        return str_replace(
1075
            ['%INSERT%', '%TABLE%', '%FIELD%', '%DATA%', '%COMMENT%'],
1076
            [
1077
                $replace ? 'REPLACE' : 'INSERT',
1078
                $this->parseTable($query, $options['table']),
1079
                implode(' , ', $fields),
1080
                implode(' UNION ALL ', $values),
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $values seems to be defined by a foreach iteration on line 1058. Are you sure the iterator is never empty, otherwise this variable is not defined?
Loading history...
1081
                $this->parseComment($query, $options['comment']),
1082
            ],
1083
            $this->insertAllSql);
0 ignored issues
show
Coding Style introduced by
This line of the multi-line function call does not seem to be indented correctly. Expected 8 spaces, but found 12.
Loading history...
Coding Style introduced by
For multi-line function calls, the closing parenthesis should be on a new line.

If a function call spawns multiple lines, the coding standard suggests to move the closing parenthesis to a new line:

someFunctionCall(
    $firstArgument,
    $secondArgument,
    $thirdArgument
); // Closing parenthesis on a new line.
Loading history...
1084
    }
1085
1086
    /**
1087
     * 生成slect insert SQL
1088
     * @access public
1089
     * @param  Query     $query  查询对象
1090
     * @param  array     $fields 数据
1091
     * @param  string    $table  数据表
1092
     * @return string
1093
     */
1094
    public function selectInsert(Query $query, $fields, $table)
1095
    {
1096
        if (is_string($fields)) {
0 ignored issues
show
introduced by
The condition is_string($fields) is always false.
Loading history...
1097
            $fields = explode(',', $fields);
1098
        }
1099
1100
        foreach ($fields as &$field) {
1101
            $field = $this->parseKey($query, $field, true);
1102
        }
1103
1104
        return 'INSERT INTO ' . $this->parseTable($query, $table) . ' (' . implode(',', $fields) . ') ' . $this->select($query);
1105
    }
1106
1107
    /**
1108
     * 生成update SQL
1109
     * @access public
1110
     * @param  Query     $query  查询对象
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
1111
     * @return string
1112
     */
1113
    public function update(Query $query)
1114
    {
1115
        $options = $query->getOptions();
1116
1117
        $data = $this->parseData($query, $options['data']);
1118
1119
        if (empty($data)) {
1120
            return '';
1121
        }
1122
1123
        foreach ($data as $key => $val) {
1124
            $set[] = $key . ' = ' . $val;
1125
        }
1126
1127
        return str_replace(
1128
            ['%TABLE%', '%SET%', '%JOIN%', '%WHERE%', '%ORDER%', '%LIMIT%', '%LOCK%', '%COMMENT%'],
1129
            [
1130
                $this->parseTable($query, $options['table']),
1131
                implode(' , ', $set),
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $set seems to be defined by a foreach iteration on line 1123. Are you sure the iterator is never empty, otherwise this variable is not defined?
Loading history...
1132
                $this->parseJoin($query, $options['join']),
1133
                $this->parseWhere($query, $options['where']),
1134
                $this->parseOrder($query, $options['order']),
1135
                $this->parseLimit($query, $options['limit']),
1136
                $this->parseLock($query, $options['lock']),
1137
                $this->parseComment($query, $options['comment']),
1138
            ],
1139
            $this->updateSql);
0 ignored issues
show
Coding Style introduced by
This line of the multi-line function call does not seem to be indented correctly. Expected 8 spaces, but found 12.
Loading history...
Coding Style introduced by
For multi-line function calls, the closing parenthesis should be on a new line.

If a function call spawns multiple lines, the coding standard suggests to move the closing parenthesis to a new line:

someFunctionCall(
    $firstArgument,
    $secondArgument,
    $thirdArgument
); // Closing parenthesis on a new line.
Loading history...
1140
    }
1141
1142
    /**
1143
     * 生成delete SQL
1144
     * @access public
1145
     * @param  Query  $query  查询对象
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
1146
     * @return string
1147
     */
1148
    public function delete(Query $query)
1149
    {
1150
        $options = $query->getOptions();
1151
1152
        return str_replace(
1153
            ['%TABLE%', '%USING%', '%JOIN%', '%WHERE%', '%ORDER%', '%LIMIT%', '%LOCK%', '%COMMENT%'],
1154
            [
1155
                $this->parseTable($query, $options['table']),
1156
                !empty($options['using']) ? ' USING ' . $this->parseTable($query, $options['using']) . ' ' : '',
1157
                $this->parseJoin($query, $options['join']),
1158
                $this->parseWhere($query, $options['where']),
1159
                $this->parseOrder($query, $options['order']),
1160
                $this->parseLimit($query, $options['limit']),
1161
                $this->parseLock($query, $options['lock']),
1162
                $this->parseComment($query, $options['comment']),
1163
            ],
1164
            $this->deleteSql);
0 ignored issues
show
Coding Style introduced by
This line of the multi-line function call does not seem to be indented correctly. Expected 8 spaces, but found 12.
Loading history...
Coding Style introduced by
For multi-line function calls, the closing parenthesis should be on a new line.

If a function call spawns multiple lines, the coding standard suggests to move the closing parenthesis to a new line:

someFunctionCall(
    $firstArgument,
    $secondArgument,
    $thirdArgument
); // Closing parenthesis on a new line.
Loading history...
1165
    }
1166
}
1167