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

dg / dibi / 23992579605

05 Apr 2026 02:31AM UTC coverage: 77.838%. Remained the same
23992579605

push

github

dg
drivers: escape*() methods moved to Engine [WIP]

101 of 113 new or added lines in 8 files covered. (89.38%)

162 existing lines in 9 files now uncovered.

1721 of 2211 relevant lines covered (77.84%)

0.78 hits per line

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

82.76
/src/Dibi/Drivers/SQLite3/Connection.php
1
<?php declare(strict_types=1);
2

3
/**
4
 * This file is part of the Dibi, smart database abstraction layer (https://dibi.nette.org)
5
 * Copyright (c) 2005 David Grudl (https://davidgrudl.com)
6
 */
7

8
namespace Dibi\Drivers\SQLite3;
9

10
use Dibi;
11
use Dibi\Drivers;
12
use Dibi\Helpers;
13
use SQLite3;
14

15

16
/**
17
 * The driver for SQLite v3 database.
18
 *
19
 * Driver options:
20
 *   - database (or file) => the filename of the SQLite3 database
21
 *   - formatDate => how to format date in SQL (@see date)
22
 *   - formatDateTime => how to format datetime in SQL (@see date)
23
 *   - resource (SQLite3) => existing connection resource
24
 */
25
class Connection implements Drivers\Connection
26
{
27
        private SQLite3 $connection;
28
        private string $fmtDate;
29
        private string $fmtDateTime;
30

31

32
        /**
33
         * @param  array<string, mixed>  $config
34
         * @throws Dibi\NotSupportedException
35
         */
36
        public function __construct(array $config)
1✔
37
        {
38
                if (!extension_loaded('sqlite3')) {
1✔
39
                        throw new Dibi\NotSupportedException("PHP extension 'sqlite3' is not loaded.");
×
40
                }
41

42
                if (isset($config['dbcharset']) || isset($config['charset'])) {
1✔
43
                        throw new Dibi\NotSupportedException('Options dbcharset and charset are not longer supported.');
×
44
                }
45

46
                Helpers::alias($config, 'database', 'file');
1✔
47
                $this->fmtDate = $config['formatDate'] ?? 'U';
1✔
48
                $this->fmtDateTime = $config['formatDateTime'] ?? 'U';
1✔
49

50
                if (isset($config['resource']) && $config['resource'] instanceof SQLite3) {
1✔
51
                        $this->connection = $config['resource'];
×
52
                } else {
53
                        try {
54
                                $this->connection = new SQLite3($config['database']);
1✔
55
                        } catch (\Throwable $e) {
×
56
                                throw new Dibi\DriverException($e->getMessage(), $e->getCode());
×
57
                        }
58
                }
59

60
                // enable foreign keys support (defaultly disabled; if disabled then foreign key constraints are not enforced)
61
                $this->query('PRAGMA foreign_keys = ON');
1✔
62
        }
1✔
63

64

65
        /**
66
         * Disconnects from a database.
67
         */
68
        public function disconnect(): void
69
        {
70
                $this->connection->close();
1✔
71
        }
1✔
72

73

74
        /**
75
         * Executes the SQL query.
76
         * @throws Dibi\DriverException
77
         */
78
        public function query(string $sql): ?Result
1✔
79
        {
80
                $res = @$this->connection->query($sql); // intentionally @
1✔
81
                if ($code = $this->connection->lastErrorCode()) {
1✔
82
                        throw static::createException($this->connection->lastErrorMsg(), $code, $sql);
1✔
83

84
                } elseif ($res instanceof \SQLite3Result && $res->numColumns()) {
1✔
85
                        return $this->createResultDriver($res);
1✔
86
                }
87

88
                return null;
1✔
89
        }
90

91

92
        public static function createException(string $message, int|string $code, string $sql): Dibi\DriverException
1✔
93
        {
94
                if ($code !== 19) {
1✔
95
                        return new Dibi\DriverException($message, $code, $sql);
1✔
96

97
                } elseif (str_contains($message, 'must be unique')
1✔
98
                        || str_contains($message, 'is not unique')
1✔
99
                        || str_contains($message, 'UNIQUE constraint failed')
1✔
100
                ) {
101
                        return new Dibi\UniqueConstraintViolationException($message, $code, $sql);
1✔
102

103
                } elseif (str_contains($message, 'may not be null')
1✔
104
                        || str_contains($message, 'NOT NULL constraint failed')
1✔
105
                ) {
106
                        return new Dibi\NotNullConstraintViolationException($message, $code, $sql);
1✔
107

108
                } elseif (str_contains($message, 'foreign key constraint failed')
1✔
109
                        || str_contains($message, 'FOREIGN KEY constraint failed')
1✔
110
                ) {
111
                        return new Dibi\ForeignKeyConstraintViolationException($message, $code, $sql);
1✔
112

113
                } else {
114
                        return new Dibi\ConstraintViolationException($message, $code, $sql);
×
115
                }
116
        }
117

118

119
        /**
120
         * Gets the number of affected rows by the last INSERT, UPDATE or DELETE query.
121
         */
122
        public function getAffectedRows(): ?int
123
        {
124
                return $this->connection->changes();
1✔
125
        }
126

127

128
        /**
129
         * Retrieves the ID generated for an AUTO_INCREMENT column by the previous INSERT query.
130
         */
131
        public function getInsertId(?string $sequence): ?int
132
        {
133
                return $this->connection->lastInsertRowID() ?: null;
×
134
        }
135

136

137
        /**
138
         * Begins a transaction (if supported).
139
         * @throws Dibi\DriverException
140
         */
141
        public function begin(?string $savepoint = null): void
1✔
142
        {
143
                $this->query($savepoint ? "SAVEPOINT $savepoint" : 'BEGIN');
1✔
144
        }
1✔
145

146

147
        /**
148
         * Commits statements in a transaction.
149
         * @throws Dibi\DriverException
150
         */
151
        public function commit(?string $savepoint = null): void
1✔
152
        {
153
                $this->query($savepoint ? "RELEASE SAVEPOINT $savepoint" : 'COMMIT');
1✔
154
        }
1✔
155

156

157
        /**
158
         * Rollback changes in a transaction.
159
         * @throws Dibi\DriverException
160
         */
161
        public function rollback(?string $savepoint = null): void
1✔
162
        {
163
                $this->query($savepoint ? "ROLLBACK TO SAVEPOINT $savepoint" : 'ROLLBACK');
1✔
164
        }
1✔
165

166

167
        /**
168
         * Returns the connection resource.
169
         */
170
        public function getResource(): ?SQLite3
171
        {
172
                return $this->connection;
1✔
173
        }
174

175

176
        /**
177
         * Returns the connection reflector.
178
         */
179
        public function getReflector(): Drivers\Engine
180
        {
181
                return new Drivers\Engines\SQLiteEngine($this, $this->fmtDate, $this->fmtDateTime);
1✔
182
        }
183

184

185
        /**
186
         * Result set driver factory.
187
         */
188
        public function createResultDriver(\SQLite3Result $result): Result
1✔
189
        {
190
                return new Result($result);
1✔
191
        }
192

193

194
        /********************* SQL ****************d*g**/
195

196

197
        /**
198
         * Encodes data for use in a SQL statement.
199
         */
200
        public function escapeText(string $value): string
1✔
201
        {
202
                return "'" . $this->connection->escapeString($value) . "'";
1✔
203
        }
204

205

206
        public function escapeBinary(string $value): string
207
        {
208
                return "X'" . bin2hex($value) . "'";
×
209
        }
210

211

212
        /********************* user defined functions ****************d*g**/
213

214

215
        /**
216
         * Registers an user defined function for use in SQL statements.
217
         * @param  callable(mixed...): mixed  $callback
218
         */
219
        public function registerFunction(string $name, callable $callback, int $numArgs = -1): void
220
        {
UNCOV
221
                $this->connection->createFunction($name, $callback, $numArgs);
×
222
        }
223

224

225
        /**
226
         * Registers an aggregating user defined function for use in SQL statements.
227
         * @param  callable(mixed, int, mixed...): mixed  $rowCallback
228
         * @param  callable(mixed, int): mixed  $agrCallback
229
         */
230
        public function registerAggregateFunction(
231
                string $name,
232
                callable $rowCallback,
233
                callable $agrCallback,
234
                int $numArgs = -1,
235
        ): void
236
        {
UNCOV
237
                $this->connection->createAggregate($name, $rowCallback, $agrCallback, $numArgs);
×
238
        }
239
}
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