Skip to content

Commit

Permalink
Fix adding foreign keys with only string fields (#4988)
Browse files Browse the repository at this point in the history
  • Loading branch information
paulbalandan authored and MGatner committed Sep 7, 2021
1 parent 25e628e commit d2990b8
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 5 deletions.
19 changes: 16 additions & 3 deletions system/Database/Forge.php
Original file line number Diff line number Diff line change
Expand Up @@ -351,12 +351,25 @@ public function addField($field)
throw new InvalidArgumentException('Field information is required for that operation.');
}

$this->fields[] = $field;
$fieldName = explode(' ', $field, 2)[0];
$fieldName = trim($fieldName, '`\'"');

$this->fields[$fieldName] = $field;
}
}

if (is_array($field)) {
$this->fields = array_merge($this->fields, $field);
foreach ($field as $idx => $f) {
if (is_string($f)) {
$this->addField($f);

continue;
}

if (is_array($f)) {
$this->fields = array_merge($this->fields, [$idx => $f]);
}
}
}

return $this;
Expand Down Expand Up @@ -761,7 +774,7 @@ protected function _processFields(bool $createTable = false): array
$fields = [];

foreach ($this->fields as $key => $attributes) {
if (is_int($key) && ! is_array($attributes)) {
if (! is_array($attributes)) {
$fields[] = ['_literal' => $attributes];

continue;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,6 @@ public function up()
'data' => ['type' => 'BLOB', 'null' => false],
]);
$this->forge->addKey('id', true);
$this->forge->addKey('timestamp');
$this->forge->createTable('ci_sessions', true);
}

Expand All @@ -149,7 +148,6 @@ public function up()
"data bytea DEFAULT '' NOT NULL",
]);
$this->forge->addKey('id', true);
$this->forge->addKey('timestamp');
$this->forge->createTable('ci_sessions', true);
}
}
Expand Down
37 changes: 37 additions & 0 deletions tests/system/Database/Live/ForgeTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -427,6 +427,43 @@ public function testForeignKey()
$this->forge->dropTable('forge_test_users', true);
}

/**
* @see https://github.com/codeigniter4/CodeIgniter4/issues/4986
*/
public function testForeignKeyAddingWithStringFields()
{
if ($this->db->DBDriver !== 'MySQLi') {
$this->markTestSkipped('Testing only on MySQLi but fix expands to all DBs.');
}

$attributes = ['ENGINE' => 'InnoDB'];

$this->forge->addField([
'`id` INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY',
'`name` VARCHAR(255) NOT NULL',
])->createTable('forge_test_users', true, $attributes);

$this->forge
->addField([
'`id` INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY',
'`users_id` INT(11) NOT NULL',
'`name` VARCHAR(255) NOT NULL',
])
->addForeignKey('users_id', 'forge_test_users', 'id', 'CASCADE', 'CASCADE')
->createTable('forge_test_invoices', true, $attributes);

$foreignKeyData = $this->db->getForeignKeyData('forge_test_invoices')[0];

$this->assertSame($this->db->DBPrefix . 'forge_test_invoices_users_id_foreign', $foreignKeyData->constraint_name);
$this->assertSame('users_id', $foreignKeyData->column_name);
$this->assertSame('id', $foreignKeyData->foreign_column_name);
$this->assertSame($this->db->DBPrefix . 'forge_test_invoices', $foreignKeyData->table_name);
$this->assertSame($this->db->DBPrefix . 'forge_test_users', $foreignKeyData->foreign_table_name);

$this->forge->dropTable('forge_test_invoices', true);
$this->forge->dropTable('forge_test_users', true);
}

public function testForeignKeyFieldNotExistException()
{
$this->expectException(DatabaseException::class);
Expand Down

0 comments on commit d2990b8

Please sign in to comment.