Skip to content

Commit

Permalink
Merge pull request #7265 from kai890707/4.4
Browse files Browse the repository at this point in the history
Enhance: [MySQLi] use MYSQLI_OPT_INT_AND_FLOAT_NATIVE.
  • Loading branch information
kenjis authored Feb 22, 2023
2 parents c6a7eb8 + 0a8c971 commit 51ad7e6
Show file tree
Hide file tree
Showing 5 changed files with 180 additions and 60 deletions.
35 changes: 18 additions & 17 deletions app/Config/Database.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,23 +25,24 @@ class Database extends Config
* The default database connection.
*/
public array $default = [
'DSN' => '',
'hostname' => 'localhost',
'username' => '',
'password' => '',
'database' => '',
'DBDriver' => 'MySQLi',
'DBPrefix' => '',
'pConnect' => false,
'DBDebug' => true,
'charset' => 'utf8',
'DBCollat' => 'utf8_general_ci',
'swapPre' => '',
'encrypt' => false,
'compress' => false,
'strictOn' => false,
'failover' => [],
'port' => 3306,
'DSN' => '',
'hostname' => 'localhost',
'username' => '',
'password' => '',
'database' => '',
'DBDriver' => 'MySQLi',
'DBPrefix' => '',
'pConnect' => false,
'DBDebug' => true,
'charset' => 'utf8',
'DBCollat' => 'utf8_general_ci',
'swapPre' => '',
'encrypt' => false,
'compress' => false,
'strictOn' => false,
'failover' => [],
'port' => 3306,
'numberNative' => false,
];

/**
Expand Down
11 changes: 11 additions & 0 deletions system/Database/MySQLi/Connection.php
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,13 @@ class Connection extends BaseConnection
*/
public $resultMode = MYSQLI_STORE_RESULT;

/**
* Use MYSQLI_OPT_INT_AND_FLOAT_NATIVE
*
* @var bool
*/
public $numberNative = false;

/**
* Connect to the database.
*
Expand Down Expand Up @@ -99,6 +106,10 @@ public function connect(bool $persistent = false)

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

if ($this->numberNative === true) {
$this->mysqli->options(MYSQLI_OPT_INT_AND_FLOAT_NATIVE, 1);
}

if (isset($this->strictOn)) {
if ($this->strictOn) {
$this->mysqli->options(
Expand Down
102 changes: 102 additions & 0 deletions tests/system/Database/Live/MySQLi/NumberNativeTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
<?php

/**
* This file is part of CodeIgniter 4 framework.
*
* (c) CodeIgniter Foundation <[email protected]>
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/

namespace CodeIgniter\Database\Live\MySQLi;

use CodeIgniter\Test\CIUnitTestCase;
use CodeIgniter\Test\DatabaseTestTrait;
use Config\Database;
use Tests\Support\Database\Seeds\CITestSeeder;

/**
* @group DatabaseLive
*
* @internal
*/
final class NumberNativeTest extends CIUnitTestCase
{
use DatabaseTestTrait;

private $tests;
protected $refresh = true;
protected $seed = CITestSeeder::class;

protected function setUp(): void
{
parent::setUp();

$config = config('Database');

$this->tests = $config->tests;
}

public function testEnableNumberNative()
{
$this->tests['numberNative'] = true;

$db1 = Database::connect($this->tests);

if ($db1->DBDriver !== 'MySQLi') {
$this->markTestSkipped('Only MySQLi can complete this test.');
}

$this->assertTrue($db1->numberNative);
}

public function testDisableNumberNative()
{
$this->tests['numberNative'] = false;

$db1 = Database::connect($this->tests);

if ($db1->DBDriver !== 'MySQLi') {
$this->markTestSkipped('Only MySQLi can complete this test.');
}

$this->assertFalse($db1->numberNative);
}

public function testQueryDataAfterEnableNumberNative()
{
$this->tests['numberNative'] = true;

$db1 = Database::connect($this->tests);

if ($db1->DBDriver !== 'MySQLi') {
$this->markTestSkipped('Only MySQLi can complete this test.');
}

$data = $db1->table('db_type_test')
->get()
->getRow();

$this->assertIsFloat($data->type_float);
$this->assertIsInt($data->type_integer);
}

public function testQueryDataAfterDisableNumberNative()
{
$this->tests['numberNative'] = false;

$db1 = Database::connect($this->tests);

if ($db1->DBDriver !== 'MySQLi') {
$this->markTestSkipped('Only MySQLi can complete this test.');
}

$data = $db1->table('db_type_test')
->get()
->getRow();

$this->assertIsString($data->type_float);
$this->assertIsString($data->type_integer);
}
}
3 changes: 3 additions & 0 deletions user_guide_src/source/changelogs/v4.4.0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,9 @@ Forge
Others
------

- **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.
See :ref:`Database Configuration <database-configuration-explanation-of-values>`.

Model
=====

Expand Down
89 changes: 46 additions & 43 deletions user_guide_src/source/database/configuration.rst
Original file line number Diff line number Diff line change
Expand Up @@ -104,53 +104,56 @@ default group's configuration settings. The values should be name following this
database.default.password = '';
database.default.database = 'ci4';

.. _database-configuration-explanation-of-values:

**********************
Explanation of Values:
**********************

=============== ===========================================================================================================
Name Config Description
=============== ===========================================================================================================
**dsn** The DSN connect string (an all-in-one configuration sequence).
**hostname** The hostname of your database server. Often this is 'localhost'.
**username** The username used to connect to the database. (``SQLite3`` does not use this.)
**password** The password used to connect to the database. (``SQLite3`` does not use this.)
**database** The name of the database you want to connect to.

.. note:: CodeIgniter doesn't support dots (``.``) in the database, table, and column names.
**DBDriver** The database driver name. e.g.,: ``MySQLi``, ``Postgres``, etc. The case must match the driver name.
You can set a fully qualified classname to use your custom driver.
**DBPrefix** An optional table prefix which will added to the table name when running
:doc:`Query Builder <query_builder>` queries. This permits multiple CodeIgniter
installations to share one database.
**pConnect** true/false (boolean) - Whether to use a persistent connection.
**DBDebug** true/false (boolean) - Whether to throw exceptions or not when database errors occur.
**charset** The character set used in communicating with the database.
**DBCollat** The character collation used in communicating with the database (``MySQLi`` only).
**swapPre** A default table prefix that should be swapped with ``DBPrefix``. This is useful for distributed
applications where you might run manually written queries, and need the prefix to still be
customizable by the end user.
**schema** The database schema, default value varies by driver. (Used by ``Postgres`` and ``SQLSRV``.)
**encrypt** Whether or not to use an encrypted connection.
``SQLSRV`` driver accepts true/false
``MySQLi`` driver accepts an array with the following options:
* ``ssl_key`` - Path to the private key file
* ``ssl_cert`` - Path to the public key certificate file
* ``ssl_ca`` - Path to the certificate authority file
* ``ssl_capath`` - Path to a directory containing trusted CA certificates in PEM format
* ``ssl_cipher`` - List of *allowed* ciphers to be used for the encryption, separated by colons (``:``)
* ``ssl_verify`` - true/false; Whether to verify the server certificate or not (``MySQLi`` only)
**compress** Whether or not to use client compression (``MySQLi`` only).
**strictOn** true/false (boolean) - Whether to force "Strict Mode" connections, good for ensuring strict SQL
while developing an application (``MySQLi`` only).
**port** The database port number.
**foreignKeys** true/false (boolean) - Whether or not to enable Foreign Key constraint (``SQLite3`` only).

.. important:: SQLite3 Foreign Key constraint is disabled by default.
See `SQLite documentation <https://www.sqlite.org/pragma.html#pragma_foreign_keys>`_.
To enforce Foreign Key constraint, set this config item to true.
**busyTimeout** milliseconds (int) - Sleeps for a specified amount of time when a table is locked (``SQLite3`` only).
=============== ===========================================================================================================
================ ===========================================================================================================
Name Config Description
================ ===========================================================================================================
**dsn** The DSN connect string (an all-in-one configuration sequence).
**hostname** The hostname of your database server. Often this is 'localhost'.
**username** The username used to connect to the database. (``SQLite3`` does not use this.)
**password** The password used to connect to the database. (``SQLite3`` does not use this.)
**database** The name of the database you want to connect to.

.. note:: CodeIgniter doesn't support dots (``.``) in the database, table, and column names.
**DBDriver** The database driver name. e.g.,: ``MySQLi``, ``Postgres``, etc. The case must match the driver name.
You can set a fully qualified classname to use your custom driver.
**DBPrefix** An optional table prefix which will added to the table name when running
:doc:`Query Builder <query_builder>` queries. This permits multiple CodeIgniter
installations to share one database.
**pConnect** true/false (boolean) - Whether to use a persistent connection.
**DBDebug** true/false (boolean) - Whether to throw exceptions or not when database errors occur.
**charset** The character set used in communicating with the database.
**DBCollat** The character collation used in communicating with the database (``MySQLi`` only).
**swapPre** A default table prefix that should be swapped with ``DBPrefix``. This is useful for distributed
applications where you might run manually written queries, and need the prefix to still be
customizable by the end user.
**schema** The database schema, default value varies by driver. (Used by ``Postgres`` and ``SQLSRV``.)
**encrypt** Whether or not to use an encrypted connection.
``SQLSRV`` driver accepts true/false
``MySQLi`` driver accepts an array with the following options:
* ``ssl_key`` - Path to the private key file
* ``ssl_cert`` - Path to the public key certificate file
* ``ssl_ca`` - Path to the certificate authority file
* ``ssl_capath`` - Path to a directory containing trusted CA certificates in PEM format
* ``ssl_cipher`` - List of *allowed* ciphers to be used for the encryption, separated by colons (``:``)
* ``ssl_verify`` - true/false; Whether to verify the server certificate or not (``MySQLi`` only)
**compress** Whether or not to use client compression (``MySQLi`` only).
**strictOn** true/false (boolean) - Whether to force "Strict Mode" connections, good for ensuring strict SQL
while developing an application (``MySQLi`` only).
**port** The database port number.
**foreignKeys** true/false (boolean) - Whether or not to enable Foreign Key constraint (``SQLite3`` only).

.. important:: SQLite3 Foreign Key constraint is disabled by default.
See `SQLite documentation <https://www.sqlite.org/pragma.html#pragma_foreign_keys>`_.
To enforce Foreign Key constraint, set this config item to true.
**busyTimeout** milliseconds (int) - Sleeps for a specified amount of time when a table is locked (``SQLite3`` only).
**numberNative** true/false (boolean) - Whether or not to enable MYSQLI_OPT_INT_AND_FLOAT_NATIVE (``MySQLi`` only).
================ ===========================================================================================================

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

0 comments on commit 51ad7e6

Please sign in to comment.