Skip to content

Commit

Permalink
Merge pull request #8031 from michalsn/fix/processIndexes
Browse files Browse the repository at this point in the history
fix: add a primary key to an existing table
  • Loading branch information
kenjis authored Oct 13, 2023
2 parents 07d3ef8 + c61d8e7 commit ce62326
Show file tree
Hide file tree
Showing 4 changed files with 90 additions and 9 deletions.
2 changes: 1 addition & 1 deletion phpstan-baseline.php
Original file line number Diff line number Diff line change
Expand Up @@ -1238,7 +1238,7 @@
];
$ignoreErrors[] = [
'message' => '#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#',
'count' => 16,
'count' => 13,
'path' => __DIR__ . '/system/Database/Forge.php',
];
$ignoreErrors[] = [
Expand Down
14 changes: 6 additions & 8 deletions system/Database/Forge.php
Original file line number Diff line number Diff line change
Expand Up @@ -1073,7 +1073,7 @@ public function processIndexes(string $table): bool
$sqls = [];
$fk = $this->foreignKeys;

if (empty($this->fields)) {
if ($this->fields === []) {
$this->fields = array_flip(array_map(
static fn ($columnName) => $columnName->name,
$this->db->getFieldData($this->db->DBPrefix . $table)
Expand All @@ -1082,20 +1082,18 @@ public function processIndexes(string $table): bool

$fields = $this->fields;

if (! empty($this->keys)) {
if ($this->keys !== []) {
$sqls = $this->_processIndexes($this->db->DBPrefix . $table, true);
}

$pk = $this->_processPrimaryKeys($table, true);

if ($pk !== '') {
$sqls[] = $pk;
}
if ($this->primaryKeys !== []) {
$sqls[] = $this->_processPrimaryKeys($table, true);
}

$this->foreignKeys = $fk;
$this->fields = $fields;

if (! empty($this->foreignKeys)) {
if ($this->foreignKeys !== []) {
$sqls = array_merge($sqls, $this->_processForeignKeys($table, true));
}

Expand Down
81 changes: 81 additions & 0 deletions tests/system/Database/Live/ForgeTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -1657,6 +1657,87 @@ public function testProcessIndexes(): void
$this->forge->dropTable('user2', true);
}

public function testProcessIndexesWithKeyOnly(): void
{
// make sure tables don't exist
$this->forge->dropTable('actions', true);

$this->createActionsTable();
$this->forge->addKey('name', false, false, 'db_actions_name');

// create indexes
$this->forge->processIndexes('actions');

// get a list of all indexes
$allIndexes = $this->db->getIndexData('actions');

// check that db_actions_name key exists
$indexes = array_filter(
$allIndexes,
static fn ($index) => ($index->name === 'db_actions_name')
&& ($index->fields === [0 => 'name'])
);
$this->assertCount(1, $indexes);

// drop tables to avoid any future conflicts
$this->forge->dropTable('actions', true);
}

public function testProcessIndexesWithPrimaryKeyOnly(): void
{
// make sure tables don't exist
$this->forge->dropTable('actions', true);

$this->createActionsTable();
$this->forge->addPrimaryKey('id');

// create indexes
$this->forge->processIndexes('actions');

// get a list of all indexes
$allIndexes = $this->db->getIndexData('actions');

// check that the primary key exists
$indexes = array_filter(
$allIndexes,
static fn ($index) => $index->type === 'PRIMARY'
);
$this->assertCount(1, $indexes);

// drop tables to avoid any future conflicts
$this->forge->dropTable('actions', true);
}

public function testProcessIndexesWithForeignKeyOnly(): void
{
// make sure tables don't exist
$this->forge->dropTable('actions', true);
$this->forge->dropTable('user2', true);

$this->createUser2TableWithKeys();
$this->populateUser2Table();
$this->createActionsTable();

// SQLite does not support custom foreign key name
if ($this->db->DBDriver === 'SQLite3') {
$this->forge->addForeignKey('userid', 'user', 'id');
$this->forge->addForeignKey('userid2', 'user2', 'id');
} else {
$this->forge->addForeignKey('userid', 'user', 'id', '', '', 'db_actions_userid_foreign');
$this->forge->addForeignKey('userid2', 'user2', 'id', '', '', 'db_actions_userid2_foreign');
}

// create indexes
$this->forge->processIndexes('actions');

// check that the two foreign keys exist
$this->assertCount(2, $this->db->getForeignKeyData('actions'));

// drop tables to avoid any future conflicts
$this->forge->dropTable('actions', true);
$this->forge->dropTable('user2', true);
}

private function createUser2TableWithKeys(): void
{
$fields = [
Expand Down
2 changes: 2 additions & 0 deletions user_guide_src/source/changelogs/v4.4.2.rst
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ Bugs Fixed
Page Not Found.
- **Spark:** Fixed a bug that caused spark to not display exceptions in the
production mode or to display backtrace in json when an exception occurred.
- **Forge:** Fixed a bug where adding a Primary Key to an existing table was
ignored if there were no other Keys added too.

See the repo's
`CHANGELOG.md <https://github.com/codeigniter4/CodeIgniter4/blob/develop/CHANGELOG.md>`_
Expand Down

0 comments on commit ce62326

Please sign in to comment.