Passed
Pull Request — 2.x (#231)
by
unknown
20:48
created

MySQLCompiler::upsertQuery()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 26
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 3

Importance

Changes 0
Metric Value
cc 3
eloc 16
nc 3
nop 3
dl 0
loc 26
ccs 11
cts 11
cp 1
crap 3
rs 9.7333
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * This file is part of Cycle ORM package.
5
 *
6
 * For the full copyright and license information, please view the LICENSE
7
 * file that was distributed with this source code.
8
 */
9
10
declare(strict_types=1);
11
12
namespace Cycle\Database\Driver\MySQL;
13
14
use Cycle\Database\Driver\CachingCompilerInterface;
15
use Cycle\Database\Driver\Compiler;
16
use Cycle\Database\Driver\MySQL\Injection\CompileJson;
17
use Cycle\Database\Driver\Quoter;
18
use Cycle\Database\Exception\CompilerException;
19
use Cycle\Database\Injection\FragmentInterface;
20
use Cycle\Database\Injection\Parameter;
21
use Cycle\Database\Query\QueryParameters;
22
23
/**
24
 * MySQL syntax specific compiler.
25
 */
26
class MySQLCompiler extends Compiler implements CachingCompilerInterface
27
{
28
    protected function insertQuery(QueryParameters $params, Quoter $q, array $tokens): string
29
    {
30
        if ($tokens['columns'] === []) {
31
            return \sprintf(
32 46
                'INSERT INTO %s () VALUES ()',
33
                $this->name($params, $q, $tokens['table'], true),
34 46
            );
35 4
        }
36 4
37 4
        return parent::insertQuery($params, $q, $tokens);
38
    }
39
40
    /**
41 42
     * @psalm-return non-empty-string
42
     */
43
    protected function upsertQuery(QueryParameters $params, Quoter $q, array $tokens): string
44
    {
45
        if (\count($tokens['columns']) === 0) {
46
            throw new CompilerException('Upsert query must define at least one column');
47
        }
48
49 326
        $values = [];
50
51 326
        foreach ($tokens['values'] as $value) {
52 310
            $values[] = $this->value($params, $q, $value);
53
        }
54
55 16
        $updates = \array_map(
56 16
            function ($column) use ($params, $q) {
57
                $name   = $this->name($params, $q, $column);
58
                return \sprintf('%s = VALUES(%s)', $name, $name);
59 4
            },
60
            $tokens['columns'],
61 12
        );
62 12
63
        return \sprintf(
64
            'INSERT INTO %s (%s) VALUES %s ON DUPLICATE KEY UPDATE %s',
65 16
            $this->name($params, $q, $tokens['table'], true),
66 10
            $this->columns($params, $q, $tokens['columns']),
67 10
            \implode(', ', $values),
68
            \implode(', ', $updates),
69
        );
70 16
    }
71
72
    /**
73
     *
74
     *
75
     * @link http://dev.mysql.com/doc/refman/5.0/en/select.html#id4651990
76
     */
77
    protected function limit(QueryParameters $params, Quoter $q, ?int $limit = null, ?int $offset = null): string
78
    {
79
        if ($limit === null && $offset === null) {
80
            return '';
81
        }
82
83
        $statement = '';
84
        if ($limit === null) {
85
            // When limit is not provided (or 0) but offset does we can replace
86
            // limit value with PHP_INT_MAX
87
            $statement .= 'LIMIT 18446744073709551615 ';
88
        } else {
89
            $statement .= 'LIMIT ? ';
90
            $params->push(new Parameter($limit));
91
        }
92
93
        if ($offset !== null) {
94
            $statement .= 'OFFSET ?';
95
            $params->push(new Parameter($offset));
96
        }
97
98
        return \trim($statement);
99
    }
100
101
    protected function compileJsonOrderBy(string $path): FragmentInterface
102
    {
103
        return new CompileJson($path);
104
    }
105
}
106