Skip to content

Commit 51ad7e6

Browse files
authored
Merge pull request #7265 from kai890707/4.4
Enhance: [MySQLi] use MYSQLI_OPT_INT_AND_FLOAT_NATIVE.
2 parents c6a7eb8 + 0a8c971 commit 51ad7e6

File tree

5 files changed

+180
-60
lines changed

5 files changed

+180
-60
lines changed

Diff for: app/Config/Database.php

+18-17
Original file line numberDiff line numberDiff line change
@@ -25,23 +25,24 @@ class Database extends Config
2525
* The default database connection.
2626
*/
2727
public array $default = [
28-
'DSN' => '',
29-
'hostname' => 'localhost',
30-
'username' => '',
31-
'password' => '',
32-
'database' => '',
33-
'DBDriver' => 'MySQLi',
34-
'DBPrefix' => '',
35-
'pConnect' => false,
36-
'DBDebug' => true,
37-
'charset' => 'utf8',
38-
'DBCollat' => 'utf8_general_ci',
39-
'swapPre' => '',
40-
'encrypt' => false,
41-
'compress' => false,
42-
'strictOn' => false,
43-
'failover' => [],
44-
'port' => 3306,
28+
'DSN' => '',
29+
'hostname' => 'localhost',
30+
'username' => '',
31+
'password' => '',
32+
'database' => '',
33+
'DBDriver' => 'MySQLi',
34+
'DBPrefix' => '',
35+
'pConnect' => false,
36+
'DBDebug' => true,
37+
'charset' => 'utf8',
38+
'DBCollat' => 'utf8_general_ci',
39+
'swapPre' => '',
40+
'encrypt' => false,
41+
'compress' => false,
42+
'strictOn' => false,
43+
'failover' => [],
44+
'port' => 3306,
45+
'numberNative' => false,
4546
];
4647

4748
/**

Diff for: system/Database/MySQLi/Connection.php

+11
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,13 @@ class Connection extends BaseConnection
7272
*/
7373
public $resultMode = MYSQLI_STORE_RESULT;
7474

75+
/**
76+
* Use MYSQLI_OPT_INT_AND_FLOAT_NATIVE
77+
*
78+
* @var bool
79+
*/
80+
public $numberNative = false;
81+
7582
/**
7683
* Connect to the database.
7784
*
@@ -99,6 +106,10 @@ public function connect(bool $persistent = false)
99106

100107
$this->mysqli->options(MYSQLI_OPT_CONNECT_TIMEOUT, 10);
101108

109+
if ($this->numberNative === true) {
110+
$this->mysqli->options(MYSQLI_OPT_INT_AND_FLOAT_NATIVE, 1);
111+
}
112+
102113
if (isset($this->strictOn)) {
103114
if ($this->strictOn) {
104115
$this->mysqli->options(
+102
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
<?php
2+
3+
/**
4+
* This file is part of CodeIgniter 4 framework.
5+
*
6+
* (c) CodeIgniter Foundation <[email protected]>
7+
*
8+
* For the full copyright and license information, please view
9+
* the LICENSE file that was distributed with this source code.
10+
*/
11+
12+
namespace CodeIgniter\Database\Live\MySQLi;
13+
14+
use CodeIgniter\Test\CIUnitTestCase;
15+
use CodeIgniter\Test\DatabaseTestTrait;
16+
use Config\Database;
17+
use Tests\Support\Database\Seeds\CITestSeeder;
18+
19+
/**
20+
* @group DatabaseLive
21+
*
22+
* @internal
23+
*/
24+
final class NumberNativeTest extends CIUnitTestCase
25+
{
26+
use DatabaseTestTrait;
27+
28+
private $tests;
29+
protected $refresh = true;
30+
protected $seed = CITestSeeder::class;
31+
32+
protected function setUp(): void
33+
{
34+
parent::setUp();
35+
36+
$config = config('Database');
37+
38+
$this->tests = $config->tests;
39+
}
40+
41+
public function testEnableNumberNative()
42+
{
43+
$this->tests['numberNative'] = true;
44+
45+
$db1 = Database::connect($this->tests);
46+
47+
if ($db1->DBDriver !== 'MySQLi') {
48+
$this->markTestSkipped('Only MySQLi can complete this test.');
49+
}
50+
51+
$this->assertTrue($db1->numberNative);
52+
}
53+
54+
public function testDisableNumberNative()
55+
{
56+
$this->tests['numberNative'] = false;
57+
58+
$db1 = Database::connect($this->tests);
59+
60+
if ($db1->DBDriver !== 'MySQLi') {
61+
$this->markTestSkipped('Only MySQLi can complete this test.');
62+
}
63+
64+
$this->assertFalse($db1->numberNative);
65+
}
66+
67+
public function testQueryDataAfterEnableNumberNative()
68+
{
69+
$this->tests['numberNative'] = true;
70+
71+
$db1 = Database::connect($this->tests);
72+
73+
if ($db1->DBDriver !== 'MySQLi') {
74+
$this->markTestSkipped('Only MySQLi can complete this test.');
75+
}
76+
77+
$data = $db1->table('db_type_test')
78+
->get()
79+
->getRow();
80+
81+
$this->assertIsFloat($data->type_float);
82+
$this->assertIsInt($data->type_integer);
83+
}
84+
85+
public function testQueryDataAfterDisableNumberNative()
86+
{
87+
$this->tests['numberNative'] = false;
88+
89+
$db1 = Database::connect($this->tests);
90+
91+
if ($db1->DBDriver !== 'MySQLi') {
92+
$this->markTestSkipped('Only MySQLi can complete this test.');
93+
}
94+
95+
$data = $db1->table('db_type_test')
96+
->get()
97+
->getRow();
98+
99+
$this->assertIsString($data->type_float);
100+
$this->assertIsString($data->type_integer);
101+
}
102+
}

Diff for: user_guide_src/source/changelogs/v4.4.0.rst

+3
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,9 @@ Forge
5959
Others
6060
------
6161

62+
- **MySQLi:** Added the ``numberNative`` attribute to the Database Config to keep the variable type obtained after SQL Query consistent with the type set in the database.
63+
See :ref:`Database Configuration <database-configuration-explanation-of-values>`.
64+
6265
Model
6366
=====
6467

Diff for: user_guide_src/source/database/configuration.rst

+46-43
Original file line numberDiff line numberDiff line change
@@ -104,53 +104,56 @@ default group's configuration settings. The values should be name following this
104104
database.default.password = '';
105105
database.default.database = 'ci4';
106106

107+
.. _database-configuration-explanation-of-values:
108+
107109
**********************
108110
Explanation of Values:
109111
**********************
110112

111-
=============== ===========================================================================================================
112-
Name Config Description
113-
=============== ===========================================================================================================
114-
**dsn** The DSN connect string (an all-in-one configuration sequence).
115-
**hostname** The hostname of your database server. Often this is 'localhost'.
116-
**username** The username used to connect to the database. (``SQLite3`` does not use this.)
117-
**password** The password used to connect to the database. (``SQLite3`` does not use this.)
118-
**database** The name of the database you want to connect to.
119-
120-
.. note:: CodeIgniter doesn't support dots (``.``) in the database, table, and column names.
121-
**DBDriver** The database driver name. e.g.,: ``MySQLi``, ``Postgres``, etc. The case must match the driver name.
122-
You can set a fully qualified classname to use your custom driver.
123-
**DBPrefix** An optional table prefix which will added to the table name when running
124-
:doc:`Query Builder <query_builder>` queries. This permits multiple CodeIgniter
125-
installations to share one database.
126-
**pConnect** true/false (boolean) - Whether to use a persistent connection.
127-
**DBDebug** true/false (boolean) - Whether to throw exceptions or not when database errors occur.
128-
**charset** The character set used in communicating with the database.
129-
**DBCollat** The character collation used in communicating with the database (``MySQLi`` only).
130-
**swapPre** A default table prefix that should be swapped with ``DBPrefix``. This is useful for distributed
131-
applications where you might run manually written queries, and need the prefix to still be
132-
customizable by the end user.
133-
**schema** The database schema, default value varies by driver. (Used by ``Postgres`` and ``SQLSRV``.)
134-
**encrypt** Whether or not to use an encrypted connection.
135-
``SQLSRV`` driver accepts true/false
136-
``MySQLi`` driver accepts an array with the following options:
137-
* ``ssl_key`` - Path to the private key file
138-
* ``ssl_cert`` - Path to the public key certificate file
139-
* ``ssl_ca`` - Path to the certificate authority file
140-
* ``ssl_capath`` - Path to a directory containing trusted CA certificates in PEM format
141-
* ``ssl_cipher`` - List of *allowed* ciphers to be used for the encryption, separated by colons (``:``)
142-
* ``ssl_verify`` - true/false; Whether to verify the server certificate or not (``MySQLi`` only)
143-
**compress** Whether or not to use client compression (``MySQLi`` only).
144-
**strictOn** true/false (boolean) - Whether to force "Strict Mode" connections, good for ensuring strict SQL
145-
while developing an application (``MySQLi`` only).
146-
**port** The database port number.
147-
**foreignKeys** true/false (boolean) - Whether or not to enable Foreign Key constraint (``SQLite3`` only).
148-
149-
.. important:: SQLite3 Foreign Key constraint is disabled by default.
150-
See `SQLite documentation <https://www.sqlite.org/pragma.html#pragma_foreign_keys>`_.
151-
To enforce Foreign Key constraint, set this config item to true.
152-
**busyTimeout** milliseconds (int) - Sleeps for a specified amount of time when a table is locked (``SQLite3`` only).
153-
=============== ===========================================================================================================
113+
================ ===========================================================================================================
114+
Name Config Description
115+
================ ===========================================================================================================
116+
**dsn** The DSN connect string (an all-in-one configuration sequence).
117+
**hostname** The hostname of your database server. Often this is 'localhost'.
118+
**username** The username used to connect to the database. (``SQLite3`` does not use this.)
119+
**password** The password used to connect to the database. (``SQLite3`` does not use this.)
120+
**database** The name of the database you want to connect to.
121+
122+
.. note:: CodeIgniter doesn't support dots (``.``) in the database, table, and column names.
123+
**DBDriver** The database driver name. e.g.,: ``MySQLi``, ``Postgres``, etc. The case must match the driver name.
124+
You can set a fully qualified classname to use your custom driver.
125+
**DBPrefix** An optional table prefix which will added to the table name when running
126+
:doc:`Query Builder <query_builder>` queries. This permits multiple CodeIgniter
127+
installations to share one database.
128+
**pConnect** true/false (boolean) - Whether to use a persistent connection.
129+
**DBDebug** true/false (boolean) - Whether to throw exceptions or not when database errors occur.
130+
**charset** The character set used in communicating with the database.
131+
**DBCollat** The character collation used in communicating with the database (``MySQLi`` only).
132+
**swapPre** A default table prefix that should be swapped with ``DBPrefix``. This is useful for distributed
133+
applications where you might run manually written queries, and need the prefix to still be
134+
customizable by the end user.
135+
**schema** The database schema, default value varies by driver. (Used by ``Postgres`` and ``SQLSRV``.)
136+
**encrypt** Whether or not to use an encrypted connection.
137+
``SQLSRV`` driver accepts true/false
138+
``MySQLi`` driver accepts an array with the following options:
139+
* ``ssl_key`` - Path to the private key file
140+
* ``ssl_cert`` - Path to the public key certificate file
141+
* ``ssl_ca`` - Path to the certificate authority file
142+
* ``ssl_capath`` - Path to a directory containing trusted CA certificates in PEM format
143+
* ``ssl_cipher`` - List of *allowed* ciphers to be used for the encryption, separated by colons (``:``)
144+
* ``ssl_verify`` - true/false; Whether to verify the server certificate or not (``MySQLi`` only)
145+
**compress** Whether or not to use client compression (``MySQLi`` only).
146+
**strictOn** true/false (boolean) - Whether to force "Strict Mode" connections, good for ensuring strict SQL
147+
while developing an application (``MySQLi`` only).
148+
**port** The database port number.
149+
**foreignKeys** true/false (boolean) - Whether or not to enable Foreign Key constraint (``SQLite3`` only).
150+
151+
.. important:: SQLite3 Foreign Key constraint is disabled by default.
152+
See `SQLite documentation <https://www.sqlite.org/pragma.html#pragma_foreign_keys>`_.
153+
To enforce Foreign Key constraint, set this config item to true.
154+
**busyTimeout** milliseconds (int) - Sleeps for a specified amount of time when a table is locked (``SQLite3`` only).
155+
**numberNative** true/false (boolean) - Whether or not to enable MYSQLI_OPT_INT_AND_FLOAT_NATIVE (``MySQLi`` only).
156+
================ ===========================================================================================================
154157

155158
.. note:: Depending on what database driver you are using (``MySQLi``, ``Postgres``,
156159
etc.) not all values will be needed. For example, when using ``SQLite3`` you

0 commit comments

Comments
 (0)