Skip to content

fix: strip the table prefix correctly when rebuilding a SQLite3 table - #10509

Merged
paulbalandan merged 1 commit into
codeigniter4:developfrom
karlgray:fix-sqlite-table-rebuild-fk-prefix
Sep 5, 2026
Merged

fix: strip the table prefix correctly when rebuilding a SQLite3 table#10509
paulbalandan merged 1 commit into
codeigniter4:developfrom
karlgray:fix-sqlite-table-rebuild-fk-prefix

Conversation

@karlgray

@karlgray karlgray commented Aug 30, 2026

Copy link
Copy Markdown
Contributor

Fixes #10508
SQLite cannot alter or drop a column in place, so SQLite3\Table rebuilds the whole table and recreates its foreign keys from the metadata it collected. That metadata holds prefixed table names, and createTable() stripped the prefix with trim($name, $this->db->DBPrefix).

trim()'s second argument is a set of characters, not a prefix. It removes any of those characters from either end of the string, repeatedly, so with the prefix db_ it turns db_bandit_fk into andit_fk — the leading b of the table's own name is eaten as well, and characters are stripped from the end too.

The rebuilt table's foreign keys then reference tables that do not exist. Nothing fails at that point, because foreign key enforcement is off for the duration of the rebuild; the error surfaces at the next write to the referenced table, naming a table that appears nowhere in the schema. Whether a given table is affected depends on which characters its name happens to begin and end with, so most tables come through untouched.

Strip the prefix the way fromTable() in the same class already does.

The existing tests could not catch this: AlterTableTest builds its own connection without a DBPrefix, and the damage is invisible until the constraint is used. The regression test therefore sets a prefix and names the referenced table so that it begins with a character the prefix also contains, which is what makes the bug reproduce.

Description
Explain what you have changed, and why.

Checklist:

  • Securely signed commits
  • Component(s) with PHPDoc blocks, only if necessary or adds value (without duplication)
  • Unit testing, with >80% coverage
  • User guide updated
  • Conforms to style guide

@mergeable

mergeable Bot commented Aug 30, 2026

Copy link
Copy Markdown

Hi there, karlgray! 👋

Thank you for sending this PR!

We expect the following in all Pull Requests (PRs).

Important

We expect all code changes or bug-fixes to be accompanied by one or more tests added to our test suite to prove the code works.

If pull requests do not comply with the above, they will likely be closed. Since we are a team of volunteers, we don't have any more time to work
on the framework than you do. Please make it as painless for your contributions to be included as possible.

See https://github.com/codeigniter4/CodeIgniter4/blob/develop/contributing/pull_request.md

Sincerely, the mergeable bot 🤖

@michalsn michalsn left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall, it looks good. Thank you!

Comment thread system/Database/SQLite3/Table.php Outdated
@michalsn michalsn added the bug Verified issues on the current code behavior or pull requests that will fix them label Sep 4, 2026
@github-actions github-actions Bot added the stale Pull requests with conflicts label Sep 5, 2026
@github-actions

This comment was marked as outdated.

@paulbalandan

Copy link
Copy Markdown
Member

Please rebase and fix conflicts.

@karlgray
karlgray force-pushed the fix-sqlite-table-rebuild-fk-prefix branch from fed993c to 7bf79ac Compare September 5, 2026 13:15
@karlgray

karlgray commented Sep 5, 2026

Copy link
Copy Markdown
Contributor Author

Please rebase and fix conflicts.

The conflict is now resolved. It was the changelog.

@paulbalandan

Copy link
Copy Markdown
Member

Hi @karlgray , sorry it conflicted again.

@karlgray

karlgray commented Sep 5, 2026

Copy link
Copy Markdown
Contributor Author

Hi @karlgray , sorry it conflicted again.

Sorry this is my first PR. Do I need to do something here in github or something on my local branch/fork?

SQLite cannot alter or drop a column in place, so `SQLite3\Table` rebuilds
the whole table and recreates its foreign keys from the metadata it
collected. That metadata holds prefixed table names, and `createTable()`
stripped the prefix with `trim($name, $this->db->DBPrefix)`.

`trim()`'s second argument is a set of characters, not a prefix. It removes
any of those characters from either end of the string, repeatedly, so with
the prefix `db_` it turns `db_bandit_fk` into `andit_fk` — the leading `b`
of the table's own name is eaten as well, and characters are stripped from
the end too.

The rebuilt table's foreign keys then reference tables that do not exist.
Nothing fails at that point, because foreign key enforcement is off for the
duration of the rebuild; the error surfaces at the next write to the
referenced table, naming a table that appears nowhere in the schema. Whether
a given table is affected depends on which characters its name happens to
begin and end with, so most tables come through untouched.

Strip the prefix the way `fromTable()` in the same class already does.

The existing tests could not catch this: `AlterTableTest` builds its own
connection without a `DBPrefix`, and the damage is invisible until the
constraint is used. The regression test therefore sets a prefix and names
the referenced table so that it begins with a character the prefix also
contains, which is what makes the bug reproduce.
@paulbalandan

Copy link
Copy Markdown
Member

Better on your fork, to pull the latest develop and rebase again.

@karlgray
karlgray force-pushed the fix-sqlite-table-rebuild-fk-prefix branch from 7bf79ac to 3b9a261 Compare September 5, 2026 13:23
@karlgray

karlgray commented Sep 5, 2026

Copy link
Copy Markdown
Contributor Author

Better on your fork, to pull the latest develop and rebase again.

ok, done. It was the changelog again. Seems I am aiming at a moving target?

@paulbalandan

Copy link
Copy Markdown
Member

Thanks. The recent merges caused the conflicts.

@paulbalandan paulbalandan removed the stale Pull requests with conflicts label Sep 5, 2026
@paulbalandan
paulbalandan merged commit cc882d6 into codeigniter4:develop Sep 5, 2026
57 checks passed
@paulbalandan

Copy link
Copy Markdown
Member

Thank you, @karlgray

@karlgray

karlgray commented Sep 5, 2026

Copy link
Copy Markdown
Contributor Author

@paulbalandan and @michalsn thank you for helping me through my first PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Verified issues on the current code behavior or pull requests that will fix them

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bug: trim() takes a character set, not a prefix, so with db_ set the rebuilt table's foreign keys point at tables that don't exist.

3 participants