Description
PHP Version
8.1
CodeIgniter4 Version
4.4.4
CodeIgniter4 Installation Method
Composer (using codeigniter4/appstarter
)
Which operating systems have you tested for this bug?
Linux
Which server did you use?
cli-server (PHP built-in webserver)
Database
SQLite3
What happened?
Changing a single table column name results in modifications of multiple columns, both column constraints (for example, turning NOT NULL fields to NULL) and defaults (0 to '0', NULL to 'NULL', etc) get changed.
Steps to Reproduce
Start with empty project.
Rename env
to .env
, change these lines in it to the values:
app.baseURL = 'http://localhost:8080/'
database.default.database = ci4
database.default.DBDriver = SQLite3
Add a cli route in app/Config/Routes.php:
$routes->cli('home', 'Home::index');
Add migration for a table:
php spark make:migration CreateTestTable
Replace up() and down() methods with:
public function up()
{
$this->forge->addField([
'id' => [
'type' => 'INT',
'constraint' => 10,
'auto_increment' => true,
'null' => false,
],
'user_id' => [
'type' => 'INT',
'constraint' => 10,
'null' => false,
],
'month' => [
'type' => 'VARCHAR',
'constraint' => 7,
'null' => false,
],
'invoice_series' => [
'type' => 'VARCHAR',
'constraint' => 10,
'null' => false,
],
'total' => [
'type' => 'DECIMAL',
'null' => false,
],
'paid' => [
'type' => 'TINYINT',
'default' => 0,
],
'paid_date' => [
'type' => 'VARCHAR',
'constraint' => 10,
'default' => null,
],
'created_at' => [
'type' => 'DATETIME',
'null' => false,
],
'updated_at' => [
'type' => 'DATETIME',
'null' => false,
],
]);
$this->forge->addKey('id', true);
$this->forge->createTable('invoices');
}
public function down()
{
$this->forge->dropTable('invoices');
}
Add test code to the Home controller, replace the index() method with:
public function index()
{
$forge = \Config\Database::forge();
$fields = [
'invoice_series' => [
'name' => 'series',
'type' => 'VARCHAR',
'constraint' => 10,
'null' => false,
],
];
$forge->modifyColumn('invoices', $fields);
}
Now you can run the tests; here is what I do and what I get:
dg@tvenkinys:~/Programavimas/MOK/ci4bugDemo$ php spark migrate
CodeIgniter v4.4.4 Command Line Tool - Server Time: 2024-01-10 22:14:45 UTC+00:00
Running all new migrations...
Running: (App) 2024-01-10-214032_App\Database\Migrations\CreateTestTable
Migrations complete.
dg@tvenkinys:~/Programavimas/MOK/ci4bugDemo$ php spark db:table invoices --metadata
CodeIgniter v4.4.4 Command Line Tool - Server Time: 2024-01-10 22:14:56 UTC+00:00
List of Metadata Information in Table "invoices":
+----------------+----------+------------+----------+---------+-------------+
| Field Name | Type | Max Length | Nullable | Default | Primary Key |
+----------------+----------+------------+----------+---------+-------------+
| id | INTEGER | | Yes | | Yes |
| user_id | INT | | No | | No |
| month | VARCHAR | | No | | No |
| invoice_series | VARCHAR | | No | | No |
| total | DECIMAL | | No | | No |
| paid | TINYINT | | No | 0 | No |
| paid_date | VARCHAR | | Yes | NULL | No |
| created_at | DATETIME | | No | | No |
| updated_at | DATETIME | | No | | No |
+----------------+----------+------------+----------+---------+-------------+
dg@tvenkinys:~/Programavimas/MOK/ci4bugDemo$ php public/index.php home
dg@tvenkinys:~/Programavimas/MOK/ci4bugDemo$ php spark db:table invoices --metadata
CodeIgniter v4.4.4 Command Line Tool - Server Time: 2024-01-10 22:15:25 UTC+00:00
List of Metadata Information in Table "invoices":
+------------+----------+------------+----------+---------+-------------+
| Field Name | Type | Max Length | Nullable | Default | Primary Key |
+------------+----------+------------+----------+---------+-------------+
| id | INTEGER | | Yes | NULL | Yes |
| user_id | INT | | Yes | NULL | No |
| month | VARCHAR | | Yes | NULL | No |
| series | VARCHAR | | No | '' | No |
| total | DECIMAL | | Yes | NULL | No |
| paid | TINYINT | | No | '0' | No |
| paid_date | VARCHAR | | Yes | 'NULL' | No |
| created_at | DATETIME | | Yes | NULL | No |
| updated_at | DATETIME | | Yes | NULL | No |
+------------+----------+------------+----------+---------+-------------+
Note that the only table field that had to change (and only in it's name) was invoice_series -> series, and not the massive changes in Nullable and Default columns.
Another strange thing: if I shorten the test code to this, omitting the array items for everything but the table column name:
$fields = [
'invoice_series' => [
'name' => 'series',
],
];
The table name does not get changed (and nothing is corrupted). But then I add
'type' => 'VARCHAR',
and boom, all the damage is done after running the code.
Expected Output
I expect only the table column name to change.
Anything else?
I have not tested the other DB's, but I expect this to be an issue only in SQLite3 case (though someone might run my code on mysql to be sure).