• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

codeigniter4 / CodeIgniter4 / 25902734269

15 May 2026 05:51AM UTC coverage: 88.459% (+0.2%) from 88.299%
25902734269

Pull #10159

github

web-flow
Merge f0573f3e0 into 170b89a6e
Pull Request #10159: feat: Add support for callable TTLs in cache handlers

6 of 10 new or added lines in 3 files covered. (60.0%)

446 existing lines in 24 files now uncovered.

24114 of 27260 relevant lines covered (88.46%)

219.07 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

97.01
/system/Database/MySQLi/Builder.php
1
<?php
2

3
declare(strict_types=1);
4

5
/**
6
 * This file is part of CodeIgniter 4 framework.
7
 *
8
 * (c) CodeIgniter Foundation <admin@codeigniter.com>
9
 *
10
 * For the full copyright and license information, please view
11
 * the LICENSE file that was distributed with this source code.
12
 */
13

14
namespace CodeIgniter\Database\MySQLi;
15

16
use CodeIgniter\Database\BaseBuilder;
17
use CodeIgniter\Database\Exceptions\DatabaseException;
18
use CodeIgniter\Database\RawSql;
19

20
/**
21
 * Builder for MySQLi
22
 */
23
class Builder extends BaseBuilder
24
{
25
    /**
26
     * Identifier escape character
27
     *
28
     * @var string
29
     */
30
    protected $escapeChar = '`';
31

32
    /**
33
     * Specifies which sql statements
34
     * support the ignore option.
35
     *
36
     * @var array<string, string>
37
     */
38
    protected $supportedIgnoreStatements = [
39
        'update' => 'IGNORE',
40
        'insert' => 'IGNORE',
41
        'delete' => 'IGNORE',
42
    ];
43

44
    /**
45
     * FROM tables
46
     *
47
     * Groups tables in FROM clauses if needed, so there is no confusion
48
     * about operator precedence.
49
     *
50
     * Note: This is only used (and overridden) by MySQL.
51
     */
52
    protected function _fromTables(): string
53
    {
54
        if ($this->QBJoin !== [] && count($this->QBFrom) > 1) {
855✔
55
            return '(' . implode(', ', $this->QBFrom) . ')';
×
56
        }
57

58
        return implode(', ', $this->QBFrom);
855✔
59
    }
60

61
    /**
62
     * Compile the SELECT lock clause.
63
     */
64
    protected function compileLockForUpdate(): string
65
    {
66
        if (! $this->QBLockForUpdate) {
855✔
67
            return '';
855✔
68
        }
69

70
        foreach ($this->QBFrom as $value) {
1✔
71
            if (str_starts_with($value, '(SELECT')) {
1✔
72
                throw new DatabaseException('MySQLi does not support lockForUpdate() with fromSubquery().');
1✔
73
            }
74
        }
75

UNCOV
76
        return parent::compileLockForUpdate();
×
77
    }
78

79
    /**
80
     * Generates a platform-specific batch update string from the supplied data
81
     */
82
    protected function _updateBatch(string $table, array $keys, array $values): string
83
    {
84
        $sql = $this->QBOptions['sql'] ?? '';
18✔
85

86
        // if this is the first iteration of batch then we need to build skeleton sql
87
        if ($sql === '') {
18✔
88
            $constraints = $this->QBOptions['constraints'] ?? [];
18✔
89

90
            if ($constraints === []) {
18✔
91
                if ($this->db->DBDebug) {
1✔
92
                    throw new DatabaseException('You must specify a constraint to match on for batch updates.'); // @codeCoverageIgnore
93
                }
94

95
                return ''; // @codeCoverageIgnore
96
            }
97

98
            $updateFields = $this->QBOptions['updateFields'] ??
17✔
99
                $this->updateFields($keys, false, $constraints)->QBOptions['updateFields'] ??
17✔
100
                [];
14✔
101

102
            $alias = $this->QBOptions['alias'] ?? '`_u`';
17✔
103

104
            $sql = 'UPDATE ' . $this->compileIgnore('update') . $table . "\n";
17✔
105

106
            $sql .= "INNER JOIN (\n{:_table_:}";
17✔
107

108
            $sql .= ') ' . $alias . "\n";
17✔
109

110
            $sql .= 'ON ' . implode(
17✔
111
                ' AND ',
17✔
112
                array_map(
17✔
113
                    static fn ($key, $value) => (
17✔
114
                        ($value instanceof RawSql && is_string($key))
17✔
115
                        ?
17✔
116
                        $table . '.' . $key . ' = ' . $value
1✔
117
                        :
17✔
118
                        (
17✔
119
                            $value instanceof RawSql
16✔
120
                            ?
16✔
121
                            $value
3✔
122
                            :
16✔
123
                            $table . '.' . $value . ' = ' . $alias . '.' . $value
17✔
124
                        )
17✔
125
                    ),
17✔
126
                    array_keys($constraints),
17✔
127
                    $constraints,
17✔
128
                ),
17✔
129
            ) . "\n";
17✔
130

131
            $sql .= "SET\n";
17✔
132

133
            $sql .= implode(
17✔
134
                ",\n",
17✔
135
                array_map(
17✔
136
                    static fn ($key, $value): string => $table . '.' . $key . ($value instanceof RawSql ?
17✔
137
                        ' = ' . $value :
2✔
138
                        ' = ' . $alias . '.' . $value),
17✔
139
                    array_keys($updateFields),
17✔
140
                    $updateFields,
17✔
141
                ),
17✔
142
            );
17✔
143

144
            $this->QBOptions['sql'] = $sql;
17✔
145
        }
146

147
        if (isset($this->QBOptions['setQueryAsData'])) {
17✔
148
            $data = $this->QBOptions['setQueryAsData'];
1✔
149
        } else {
150
            $data = implode(
16✔
151
                " UNION ALL\n",
16✔
152
                array_map(
16✔
153
                    static fn ($value): string => 'SELECT ' . implode(', ', array_map(
16✔
154
                        static fn ($key, $index): string => $index . ' ' . $key,
16✔
155
                        $keys,
16✔
156
                        $value,
16✔
157
                    )),
16✔
158
                    $values,
16✔
159
                ),
16✔
160
            ) . "\n";
16✔
161
        }
162

163
        return str_replace('{:_table_:}', $data, $sql);
17✔
164
    }
165
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc