Skip to content

Commit 40bdc78

Browse files
authored
Allow double underscores in index names (#136)
See: #133 (comment) When creating new tables in SQLite, original index names are prefixed with the table name. This is because unlike MySQL, SQLite does not allow identical index names across the database. Adding a table prefix ensures the index names are unique. When running a `show create table` query, we restore the original index name by removing the table prefix. We split on double underscores but we did not take into account that the original index name can also contain `__`. This PR fixes an issue where we explode without a limit. We only want to explode on the first occurrence of `__`. Unit tests have been added to ensure this behavior.
1 parent 00f31b4 commit 40bdc78

File tree

2 files changed

+35
-6
lines changed

2 files changed

+35
-6
lines changed

tests/WP_SQLite_Translator_Tests.php

+32-2
Original file line numberDiff line numberDiff line change
@@ -377,7 +377,8 @@ public function testCreateTablseWithIdenticalIndexNames() {
377377
ID BIGINT PRIMARY KEY AUTO_INCREMENT NOT NULL,
378378
option_name VARCHAR(255) default '',
379379
option_value TEXT NOT NULL,
380-
KEY `option_name` (`option_name`)
380+
KEY `option_name` (`option_name`),
381+
KEY `double__underscores` (`option_name`, `ID`)
381382
);"
382383
);
383384

@@ -386,11 +387,40 @@ public function testCreateTablseWithIdenticalIndexNames() {
386387
ID BIGINT PRIMARY KEY AUTO_INCREMENT NOT NULL,
387388
option_name VARCHAR(255) default '',
388389
option_value TEXT NOT NULL,
389-
KEY `option_name` (`option_name`)
390+
KEY `option_name` (`option_name`),
391+
KEY `double__underscores` (`option_name`, `ID`)
390392
);"
391393
);
392394
}
393395

396+
public function testShowCreateTablePreservesDoubleUnderscoreKeyNames() {
397+
$this->assertQuery(
398+
"CREATE TABLE _tmp__table (
399+
ID BIGINT PRIMARY KEY AUTO_INCREMENT NOT NULL,
400+
option_name VARCHAR(255) default '',
401+
option_value TEXT NOT NULL,
402+
KEY `option_name` (`option_name`),
403+
KEY `double__underscores` (`option_name`, `ID`)
404+
);"
405+
);
406+
407+
$this->assertQuery(
408+
'SHOW CREATE TABLE _tmp__table;'
409+
);
410+
$results = $this->engine->get_query_results();
411+
$this->assertEquals(
412+
'CREATE TABLE `_tmp__table` (
413+
`ID` bigint NOT NULL AUTO_INCREMENT,
414+
`option_name` varchar(255) DEFAULT \'\',
415+
`option_value` text NOT NULL DEFAULT \'\',
416+
PRIMARY KEY (`ID`),
417+
KEY `double__underscores` (`option_name`, `ID`),
418+
KEY `option_name` (`option_name`)
419+
);',
420+
$results[0]->{'Create Table'}
421+
);
422+
}
423+
394424
public function testShowCreateTableWithPrimaryKeyColumnsReverseOrdered() {
395425
$this->assertQuery(
396426
'CREATE TABLE `_tmp_table` (

wp-includes/sqlite/class-wp-sqlite-translator.php

+3-4
Original file line numberDiff line numberDiff line change
@@ -3570,9 +3570,7 @@ private function get_key_definitions( $table_name, $columns ) {
35703570
$key_definition[] = 'KEY';
35713571

35723572
// Remove the prefix from the index name if there is any. We use __ as a separator.
3573-
$index_name = strstr( $key['index']['name'], '__' )
3574-
? explode( '__', $key['index']['name'] )[1]
3575-
: $key['index']['name'];
3573+
$index_name = explode( '__', $key['index']['name'], 2 )[1] ?? $key['index']['name'];
35763574

35773575
$key_definition[] = sprintf( '`%s`', $index_name );
35783576

@@ -4214,7 +4212,8 @@ public function rollback() {
42144212
* @return string
42154213
*/
42164214
private function generate_index_name( $table, $original_index_name ) {
4217-
// Strip the occurrences of 2 or more consecutive underscores to allow easier splitting on __ later.
4215+
// Strip the occurrences of 2 or more consecutive underscores from the table name
4216+
// to allow easier splitting on __ later.
42184217
return preg_replace( '/_{2,}/', '_', $table ) . '__' . $original_index_name;
42194218
}
42204219
}

0 commit comments

Comments
 (0)