From 6ee59bd3486d1c4cf9dd9243b8312e1616b37111 Mon Sep 17 00:00:00 2001 From: kenjis Date: Fri, 26 Jan 2024 15:58:14 +0900 Subject: [PATCH 1/4] fix: SQLite3 getFieldData() returns incorrect `primary_key` values The return type is integer, not boolean. --- system/Database/SQLite3/Connection.php | 2 +- tests/system/Database/Live/ForgeTest.php | 8 ++++---- .../Database/Live/SQLite3/GetFieldDataTest.php | 14 +++++++------- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/system/Database/SQLite3/Connection.php b/system/Database/SQLite3/Connection.php index f41c8e4de792..1a682646e83d 100644 --- a/system/Database/SQLite3/Connection.php +++ b/system/Database/SQLite3/Connection.php @@ -273,7 +273,7 @@ protected function _fieldData(string $table): array $retVal[$i]->type = $query[$i]->type; $retVal[$i]->max_length = null; $retVal[$i]->default = $query[$i]->dflt_value; - $retVal[$i]->primary_key = isset($query[$i]->pk) && (bool) $query[$i]->pk; + $retVal[$i]->primary_key = $query[$i]->pk ?? false; $retVal[$i]->nullable = isset($query[$i]->notnull) && ! (bool) $query[$i]->notnull; } diff --git a/tests/system/Database/Live/ForgeTest.php b/tests/system/Database/Live/ForgeTest.php index 626660ee7246..93524a5b39fb 100644 --- a/tests/system/Database/Live/ForgeTest.php +++ b/tests/system/Database/Live/ForgeTest.php @@ -986,7 +986,7 @@ public function testAddFields(): void 'type' => 'INTEGER', 'max_length' => null, 'default' => null, - 'primary_key' => true, + 'primary_key' => 1, 'nullable' => true, ], 1 => [ @@ -994,7 +994,7 @@ public function testAddFields(): void 'type' => 'VARCHAR', 'max_length' => null, 'default' => null, - 'primary_key' => false, + 'primary_key' => 0, 'nullable' => false, ], 2 => [ @@ -1002,7 +1002,7 @@ public function testAddFields(): void 'type' => 'VARCHAR', 'max_length' => null, 'default' => null, - 'primary_key' => false, + 'primary_key' => 0, 'nullable' => true, ], 3 => [ @@ -1010,7 +1010,7 @@ public function testAddFields(): void 'type' => 'INTEGER', 'max_length' => null, 'default' => '0', - 'primary_key' => false, + 'primary_key' => 0, 'nullable' => false, ], ]; diff --git a/tests/system/Database/Live/SQLite3/GetFieldDataTest.php b/tests/system/Database/Live/SQLite3/GetFieldDataTest.php index 70586f10fbdd..621083a061c3 100644 --- a/tests/system/Database/Live/SQLite3/GetFieldDataTest.php +++ b/tests/system/Database/Live/SQLite3/GetFieldDataTest.php @@ -47,7 +47,7 @@ public function testGetFieldData(): void 'type' => 'INTEGER', 'max_length' => null, 'default' => null, // The default value is not defined. - 'primary_key' => true, + 'primary_key' => 1, 'nullable' => true, ], (object) [ @@ -55,7 +55,7 @@ public function testGetFieldData(): void 'type' => 'VARCHAR', 'max_length' => null, 'default' => null, // The default value is not defined. - 'primary_key' => false, + 'primary_key' => 0, 'nullable' => false, ], (object) [ @@ -63,7 +63,7 @@ public function testGetFieldData(): void 'type' => 'VARCHAR', 'max_length' => null, 'default' => null, // The default value is not defined. - 'primary_key' => false, + 'primary_key' => 0, 'nullable' => true, ], (object) [ @@ -71,7 +71,7 @@ public function testGetFieldData(): void 'type' => 'INT', 'max_length' => null, 'default' => '0', // int 0 - 'primary_key' => false, + 'primary_key' => 0, 'nullable' => false, ], (object) [ @@ -79,7 +79,7 @@ public function testGetFieldData(): void 'type' => 'VARCHAR', 'max_length' => null, 'default' => 'NULL', // NULL value - 'primary_key' => false, + 'primary_key' => 0, 'nullable' => true, ], (object) [ @@ -87,7 +87,7 @@ public function testGetFieldData(): void 'type' => 'VARCHAR', 'max_length' => null, 'default' => "'null'", // string "null" - 'primary_key' => false, + 'primary_key' => 0, 'nullable' => false, ], (object) [ @@ -95,7 +95,7 @@ public function testGetFieldData(): void 'type' => 'VARCHAR', 'max_length' => null, 'default' => "'abc'", // string "abc" - 'primary_key' => false, + 'primary_key' => 0, 'nullable' => false, ], ]), From 055c5ad8262d1b11882f60a0500a99b2412a83a9 Mon Sep 17 00:00:00 2001 From: kenjis Date: Fri, 26 Jan 2024 16:04:01 +0900 Subject: [PATCH 2/4] docs: replace MySQL with MySQLi --- user_guide_src/source/database/metadata.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/user_guide_src/source/database/metadata.rst b/user_guide_src/source/database/metadata.rst index 607a1025be8b..5a499bad496d 100644 --- a/user_guide_src/source/database/metadata.rst +++ b/user_guide_src/source/database/metadata.rst @@ -105,7 +105,7 @@ database: - name - column name - type - the type of the column - max_length - maximum length of the column -- primary_key - integer ``1`` if the column is a primary key (all integer ``1``, even if there are multiple primary keys), otherwise integer ``0`` (This field is currently only available for MySQL and SQLite3) +- primary_key - integer ``1`` if the column is a primary key (all integer ``1``, even if there are multiple primary keys), otherwise integer ``0`` (This field is currently only available for MySQLi and SQLite3) - nullable - boolean ``true`` if the column is nullable, otherwise boolean ``false`` - default - the default value From c86ddc54340ab8f2e038a2d31554fe6743b4933b Mon Sep 17 00:00:00 2001 From: kenjis Date: Fri, 26 Jan 2024 16:05:05 +0900 Subject: [PATCH 3/4] docs: decorate text --- user_guide_src/source/database/metadata.rst | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/user_guide_src/source/database/metadata.rst b/user_guide_src/source/database/metadata.rst index 5a499bad496d..1845a0440b7a 100644 --- a/user_guide_src/source/database/metadata.rst +++ b/user_guide_src/source/database/metadata.rst @@ -102,12 +102,12 @@ supplying the table name: The following data is available from this function if supported by your database: -- name - column name -- type - the type of the column -- max_length - maximum length of the column -- primary_key - integer ``1`` if the column is a primary key (all integer ``1``, even if there are multiple primary keys), otherwise integer ``0`` (This field is currently only available for MySQLi and SQLite3) -- nullable - boolean ``true`` if the column is nullable, otherwise boolean ``false`` -- default - the default value +- ``name`` - column name +- ``type`` - the type of the column +- ``max_length`` - maximum length of the column +- ``primary_key`` - integer ``1`` if the column is a primary key (all integer ``1``, even if there are multiple primary keys), otherwise integer ``0`` (This field is currently only available for ``MySQLi`` and ``SQLite3``) +- ``nullable`` - boolean ``true`` if the column is nullable, otherwise boolean ``false`` +- ``default`` - the default value .. note:: Since v4.4.0, SQLSRV supported ``nullable``. From 4a949b373b06e7855335534d1d842ac0d3b6f3d5 Mon Sep 17 00:00:00 2001 From: kenjis Date: Sat, 27 Jan 2024 08:42:22 +0900 Subject: [PATCH 4/4] fix: primary_key value --- system/Database/SQLite3/Connection.php | 13 ++-- .../Live/SQLite3/GetFieldDataTest.php | 59 +++++++++++++++++++ 2 files changed, 67 insertions(+), 5 deletions(-) diff --git a/system/Database/SQLite3/Connection.php b/system/Database/SQLite3/Connection.php index 1a682646e83d..b4b3b668f8b6 100644 --- a/system/Database/SQLite3/Connection.php +++ b/system/Database/SQLite3/Connection.php @@ -269,11 +269,14 @@ protected function _fieldData(string $table): array for ($i = 0, $c = count($query); $i < $c; $i++) { $retVal[$i] = new stdClass(); - $retVal[$i]->name = $query[$i]->name; - $retVal[$i]->type = $query[$i]->type; - $retVal[$i]->max_length = null; - $retVal[$i]->default = $query[$i]->dflt_value; - $retVal[$i]->primary_key = $query[$i]->pk ?? false; + $retVal[$i]->name = $query[$i]->name; + $retVal[$i]->type = $query[$i]->type; + $retVal[$i]->max_length = null; + $retVal[$i]->default = $query[$i]->dflt_value; + // "pk" (either zero for columns that are not part of the primary key, + // or the 1-based index of the column within the primary key). + // https://www.sqlite.org/pragma.html#pragma_table_info + $retVal[$i]->primary_key = ($query[$i]->pk === 0) ? 0 : 1; $retVal[$i]->nullable = isset($query[$i]->notnull) && ! (bool) $query[$i]->notnull; } diff --git a/tests/system/Database/Live/SQLite3/GetFieldDataTest.php b/tests/system/Database/Live/SQLite3/GetFieldDataTest.php index 621083a061c3..4b8b9bcd6432 100644 --- a/tests/system/Database/Live/SQLite3/GetFieldDataTest.php +++ b/tests/system/Database/Live/SQLite3/GetFieldDataTest.php @@ -102,4 +102,63 @@ public function testGetFieldData(): void json_encode($fields) ); } + + protected function createTableCompositePrimaryKey() + { + $this->forge->dropTable('test1', true); + + $this->forge->addField([ + 'pk1' => [ + 'type' => 'VARCHAR', + 'constraint' => 64, + ], + 'pk2' => [ + 'type' => 'VARCHAR', + 'constraint' => 64, + ], + 'text' => [ + 'type' => 'VARCHAR', + 'constraint' => 64, + ], + ]); + $this->forge->addPrimaryKey(['pk1', 'pk2']); + $this->forge->createTable('test1'); + } + + public function testGetFieldDataCompositePrimaryKey(): void + { + $this->createTableCompositePrimaryKey(); + + $fields = $this->db->getFieldData('test1'); + + $this->assertJsonStringEqualsJsonString( + json_encode([ + (object) [ + 'name' => 'pk1', + 'type' => 'VARCHAR', + 'max_length' => null, + 'default' => null, + 'primary_key' => 1, + 'nullable' => false, + ], + (object) [ + 'name' => 'pk2', + 'type' => 'VARCHAR', + 'max_length' => null, + 'default' => null, + 'primary_key' => 1, + 'nullable' => false, + ], + (object) [ + 'name' => 'text', + 'type' => 'VARCHAR', + 'max_length' => null, + 'default' => null, + 'primary_key' => 0, + 'nullable' => false, + ], + ]), + json_encode($fields) + ); + } }