Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
37 / 37
100.00% covered (success)
100.00%
28 / 28
CRAP
100.00% covered (success)
100.00%
1 / 1
MydbOptions
100.00% covered (success)
100.00%
37 / 37
100.00% covered (success)
100.00%
28 / 28
36
100.00% covered (success)
100.00%
1 / 1
 getNonInteractiveTimeout
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setNonInteractiveTimeout
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getServerSideSelectTimeout
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setServerSideSelectTimeout
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getConnectTimeout
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setConnectTimeout
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getErrorReporting
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setErrorReporting
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getReadTimeout
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setReadTimeout
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getNetworkBufferSize
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setNetworkBufferSize
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
3
 getNetworkReadBuffer
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setNetworkReadBuffer
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
3
 getClientErrorLevel
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setClientErrorLevel
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
3
 getTimeZone
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setTimeZone
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 isAutocommit
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setAutocommit
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getCharset
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setCharset
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 isPersistent
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setPersistent
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 isReadonly
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setReadonly
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getTransactionIsolationLevel
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
3
 setTransactionIsolationLevel
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2/**
3 * This file is part of the sshilko/php-sql-mydb package.
4 *
5 * (c) Sergei Shilko <contact@sshilko.com>
6 *
7 * MIT License
8 *
9 * For the full copyright and license information, please view the LICENSE
10 * file that was distributed with this source code.
11 * @license https://opensource.org/licenses/mit-license.php MIT
12 */
13
14declare(strict_types = 1);
15
16namespace sql;
17
18use sql\MydbException\OptionException;
19use const E_ALL;
20use const E_NOTICE;
21use const E_WARNING;
22
23/**
24 * @author Sergei Shilko <contact@sshilko.com>
25 * @license https://opensource.org/licenses/mit-license.php MIT
26 * @see https://github.com/sshilko/php-sql-mydb
27 */
28class MydbOptions implements MydbOptionsInterface
29{
30    protected const NET_CMD_BUFFER_SIZE_MIN = 4096;
31
32    protected const NET_CMD_BUFFER_SIZE_MAX = 16384;
33
34    protected const NET_READ_BUFFER_MIN = 8192;
35
36    protected const NET_READ_BUFFER_MAX = 131072;
37
38    /**
39     * The execution timeout ONLY APPLIES TO "SELECT" statements, seconds
40     * X > 0, enabled
41     * X = 0, not enabled.
42     *
43     * @see https://dev.mysql.com/doc/refman/5.7/en/server-system-variables.html#sysvar_max_execution_time
44     */
45    protected int $serverSideSelectTimeout = 89;
46
47    /**
48     * MySql client connection timeout, seconds
49     */
50    protected int $connectTimeout = 5;
51
52    protected int $errorReporting = E_ALL & ~E_WARNING & ~E_NOTICE;
53
54    /**
55     * The timeout in seconds for each attempt to read from the server.
56     * @see https://dev.mysql.com/doc/c-api/8.0/en/mysql-options.html
57     * @see https://github.com/php/php-src/blob/12ab4cbd00e0dae52a5db98dda6da885acb408f6/
58     *      ext/mysqli/mysqli.c#L654
59     * @see https://github.com/php/php-src/blob/a03c1ed7aa2325d91595dcf9371297ab45543517/
60     *      ext/mysqli/tests/mysqli_constants.phpt#L24
61     */
62    protected int $readTimeout = 90;
63
64    /**
65     * Internal network buffer of mysqlnd.net_cmd_buffer_size bytes for every connection
66     *
67     * Scope: connection.
68     *
69     * Number of network command buffer extensions while sending commands from PHP to MySQL.
70     *
71     * mysqlnd allocates an internal command/network buffer of mysqlnd.net_cmd_buffer_size (php.ini) bytes
72     * for every connection.
73     * If a MySQL Client Server protocol command, for example, COM_QUERY ("normal&quot query),
74     * does not fit into the buffer, mysqlnd will grow the buffer to what is needed for sending the command.
75     * Whenever the buffer gets extended for one connection command_buffer_too_small will be incremented by one.
76     *
77     * If mysqlnd has to grow the buffer beyond its initial size of mysqlnd.net_cmd_buffer_size (php.ini) bytes
78     * for almost every connection, you should consider to increase the default size to avoid re-allocations.
79     *
80     * The default can set either through the php.ini setting mysqlnd.net_cmd_buffer_size
81     * or using mysqli_options(MYSQLI_OPT_NET_CMD_BUFFER_SIZE, int size).
82     *
83     * It is recommended to set the buffer size to no less than 4096 bytes because mysqlnd also uses
84     * it when reading certain communication packet from MySQL.
85     *
86     * As of PHP 5.3.2 mysqlnd does not allow setting buffers smaller than 4096 bytes.
87     *
88     * Default 4096
89     *
90     * More memory usage, in exchange for better performance
91     * @see mysqlnd.net_cmd_buffer_size
92     * @see http://php.net/manual/en/mysqlnd.config.php
93     */
94    protected int $networkBufferSize = 6144;
95
96    /**
97     * More memory for better performance
98     *
99     * Maximum read chunk size in bytes when reading the body of a MySQL command packet
100     * The MySQL client server protocol encapsulates all its commands in packets.
101     * The packets consist of a small header and a body with the actual payload
102     *
103     * If a packet body is larger than mysqlnd.net_read_buffer_size bytes,
104     * mysqlnd has to call read() multiple times
105     *
106     * This buffer controls how many bytes mysqlnd fetches from the PHP streams with one call.
107     * If a result set has less than 32kB in size, mysqlnd will call the PHP streams network
108     * functions only once, if it is larger more calls are needed
109     *
110     * Default 32768
111     *
112     * @see mysqlnd.net_read_buffer_size
113     * @see http://php.net/manual/en/mysqlnd.config.php
114     * @see http://blog.ulf-wendel.de/2007/php-mysqlnd-saves-40-memory-finally-new-tuning-options/
115     */
116    protected int $networkReadBuffer = 49152;
117
118    /**
119     * Sets mysqli error reporting mode
120     *
121     * >=8.1.0 The default value is now MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT.
122     * < 8.1.0 MYSQLI_REPORT_OFF.
123     *
124     * MYSQLI_REPORT_OFF Turns reporting off
125     * MYSQLI_REPORT_ERROR Report errors from mysqli function calls
126     * MYSQLI_REPORT_STRICT Throw mysqli_sql_exception for errors instead of warnings
127     * MYSQLI_REPORT_INDEX Report if no index or bad index was used in a query
128     * MYSQLI_REPORT_ALL Set all options (report all)
129     *
130     * @see https://www.php.net/manual/en/function.mysqli-report.php
131     */
132    protected int $clientErrorLevel = MydbMysqli::MYSQLI_REPORT_ALL ^
133                                      MydbMysqli::MYSQLI_REPORT_STRICT ^
134                                      MydbMysqli::MYSQLI_REPORT_INDEX;
135
136    /**
137     * Transaction isolation is one of the foundations of database processing.
138     * Isolation is the I in the acronym ACID; the isolation level is the setting that fine-tunes
139     * the balance between performance and reliability, consistency, and reproducibility of results
140     * when multiple transactions are making changes and performing queries at the same time.
141     *
142     * @see https://dev.mysql.com/doc/refman/8.0/en/innodb-transaction-isolation-levels.html
143     */
144    protected ?string $transactionIsolationLevel = null;
145
146    /**
147     * Set session time zone
148     *
149     * SET time_zone = timezone;
150     *
151     * - As the value 'SYSTEM', indicating that the server time zone is the same as the system time zone.
152     * - As a string, an offset from UTC of the form [H]H:MM, prefixed with a + or -, such as '+10:00', '-6:00'
153     *   Prior to MySQL 8.0.19, this value had to be in the range '-12:59' to '+13:00'
154     * - As a named time zone, such as 'Europe/Helsinki', 'US/Eastern', 'MET', or 'UTC'.
155     *
156     * @see https://dev.mysql.com/doc/refman/8.0/en/time-zone-support.html
157     */
158    protected string $timeZone = 'UTC';
159
160    /**
161     * The number of seconds the server waits for activity
162     * on a non-interactive TCP/IP or UNIX File connection before closing it
163     */
164    protected int $nonInteractiveTimeout = 7200;
165
166    /**
167     * Recommended defaults:
168     * false for rw connection
169     * true for ro connection
170     * true for async connection
171     */
172    protected bool $autocommit = false;
173
174    protected string $charset = 'utf8mb4';
175
176    /**
177     * Transaction block will also carry over to the next script
178     * which uses that connection if script execution ends before the transaction block does
179     *
180     * @see http://php.net/manual/en/features.persistent-connections.php
181     */
182    protected bool $persistent = false;
183
184    /**
185     * Readonly connection
186     */
187    protected bool $readonly = false;
188
189    public function getNonInteractiveTimeout(): int
190    {
191        return $this->nonInteractiveTimeout;
192    }
193
194    public function setNonInteractiveTimeout(int $nonInteractiveTimeout): void
195    {
196        $this->nonInteractiveTimeout = $nonInteractiveTimeout;
197    }
198
199    public function getServerSideSelectTimeout(): int
200    {
201        return $this->serverSideSelectTimeout;
202    }
203
204    public function setServerSideSelectTimeout(int $seconds): void
205    {
206        $this->serverSideSelectTimeout = $seconds;
207    }
208
209    public function getConnectTimeout(): int
210    {
211        return $this->connectTimeout;
212    }
213
214    public function setConnectTimeout(int $seconds): void
215    {
216        $this->connectTimeout = $seconds;
217    }
218
219    public function getErrorReporting(): int
220    {
221        return $this->errorReporting;
222    }
223
224    public function setErrorReporting(int $errorReporting): void
225    {
226        $this->errorReporting = $errorReporting;
227    }
228
229    public function getReadTimeout(): int
230    {
231        return $this->readTimeout;
232    }
233
234    public function setReadTimeout(int $seconds): void
235    {
236        $this->readTimeout = $seconds;
237    }
238
239    public function getNetworkBufferSize(): int
240    {
241        return $this->networkBufferSize;
242    }
243
244    /**
245     * @param int $bytes bytes
246     * @throws \sql\MydbException\OptionException
247     */
248    public function setNetworkBufferSize(int $bytes): void
249    {
250        if ($bytes < self::NET_CMD_BUFFER_SIZE_MIN || $bytes > self::NET_CMD_BUFFER_SIZE_MAX) {
251            throw new OptionException();
252        }
253        $this->networkBufferSize = $bytes;
254    }
255
256    public function getNetworkReadBuffer(): int
257    {
258        return $this->networkReadBuffer;
259    }
260
261    /**
262     * @throws \sql\MydbException\OptionException
263     */
264    public function setNetworkReadBuffer(int $bytes): void
265    {
266        if ($bytes < self::NET_READ_BUFFER_MIN || $bytes > self::NET_READ_BUFFER_MAX) {
267            throw new OptionException();
268        }
269        $this->networkReadBuffer = $bytes;
270    }
271
272    public function getClientErrorLevel(): int
273    {
274        return $this->clientErrorLevel;
275    }
276
277    /**
278     * @throws \sql\MydbException\OptionException
279     */
280    public function setClientErrorLevel(int $mysqliReport): void
281    {
282        if ($mysqliReport > 255 || $mysqliReport < 0) {
283            throw new OptionException();
284        }
285        $this->clientErrorLevel = $mysqliReport;
286    }
287
288    public function getTimeZone(): string
289    {
290        return $this->timeZone;
291    }
292
293    public function setTimeZone(string $timeZone): void
294    {
295        $this->timeZone = $timeZone;
296    }
297
298    public function isAutocommit(): bool
299    {
300        return $this->autocommit;
301    }
302
303    public function setAutocommit(bool $autocommit): void
304    {
305        $this->autocommit = $autocommit;
306    }
307
308    public function getCharset(): string
309    {
310        return $this->charset;
311    }
312
313    public function setCharset(string $charset): void
314    {
315        $this->charset = $charset;
316    }
317
318    public function isPersistent(): bool
319    {
320        return $this->persistent;
321    }
322
323    public function setPersistent(bool $persistent): void
324    {
325        $this->persistent = $persistent;
326    }
327
328    public function isReadonly(): bool
329    {
330        return $this->readonly;
331    }
332
333    public function setReadonly(bool $readonly): void
334    {
335        $this->readonly = $readonly;
336    }
337
338    public function getTransactionIsolationLevel(): ?string
339    {
340        $userLevel = $this->transactionIsolationLevel;
341        if (null === $userLevel && $this->isReadonly()) {
342            /**
343             * Optimal defaults for readonly connection
344             */
345            return self::TRANSACTION_ISOLATION_LEVEL_READ_COMMITTED;
346        }
347
348        return $userLevel;
349    }
350
351    public function setTransactionIsolationLevel(string $isolationLevel): void
352    {
353        $this->transactionIsolationLevel = $isolationLevel;
354    }
355}