Skip to content

Quote SQLite identifiers in LOCK TABLES, SHOW TABLES, and compound primary key indexes - #599

Merged
JanJakes merged 2 commits into
WordPress:trunkfrom
0xABCD01:fix/quote-sqlite-identifiers
Nov 2, 2026
Merged

JanJakes merged 2 commits into
WordPress:trunkfrom
0xABCD01:fix/quote-sqlite-identifiers

Conversation

@0xABCD01

@0xABCD01 0xABCD01 commented Nov 1, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Fixes #598.

This PR ensures generated SQLite identifiers are consistently quoted via $this->quote_sqlite_identifier() in three query paths inside WP_MySQL_On_SQLite:

  1. LOCK TABLES (execute_transaction_or_locking_statement()): Quote $table_name in SELECT 1 FROM %s LIMIT 0 so persistent and TEMPORARY tables whose names contain spaces, keywords, or special characters can be locked without falsely raising 1146 Table '...' doesn't exist.
  2. SHOW [FULL] TABLES (execute_show_tables_statement()): Quote the Tables_in_<database> column alias via $this->quote_sqlite_identifier( 'Tables_in_' . $database ) so database identifiers containing escaped backticks do not break the generated SQLite SELECT query.
  3. Compound PRIMARY KEY with AUTO_INCREMENT (get_sqlite_create_table_statement()): Quote self::RESERVED_PREFIX . $sqlite_index_name in CREATE UNIQUE INDEX %s ON %s (%s) (matching regular index generation right below it) so CREATE TABLE and ALTER TABLE table rebuilds succeed on quoted table names.

Testing

Added unit tests in packages/mysql-on-sqlite/tests/WP_MySQL_On_SQLite_Tests.php:

  • testShowTablesWithQuotedDatabaseIdentifier
  • testCompoundPrimaryKeyWithAutoincrementAndQuotedIdentifiers
  • testLockTablesWithQuotedIdentifiers

Summary by CodeRabbit

  • Bug Fixes
    • Improved handling of quoted database and table names when listing tables, locking tables, and using compound primary keys with auto-increment columns.
    • Improved table-lock behavior for names containing dots and for tables that do not exist.

Ensure generated SQLite queries quote identifiers via `quote_sqlite_identifier()` in three places:
- `execute_transaction_or_locking_statement()` when checking table existence for `LOCK TABLES`.
- `execute_show_tables_statement()` when building the `Tables_in_<database>` column alias for `SHOW [FULL] TABLES`.
- `get_sqlite_create_table_statement()` when creating the `_wp_sqlite_<table>__primary` unique index for compound primary keys with `AUTO_INCREMENT`.

Fixes WordPress#598
@coderabbitai

coderabbitai Bot commented Nov 1, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

No actionable comments were generated in the recent review.

Recent review info
Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 21f63c23-1569-4c15-bb51-9624c9bd57f6
Commits

Reviewing files that changed from the base of the PR and between cf386e0 and ff6bcaa.

Files selected for processing: 1
  • packages/mysql-on-sqlite/tests/WP_MySQL_On_SQLite_Tests.php

Included review availability: This review used your included allowance. Your plan provides up to 2 included reviews per hour; 0 remain after this review.

Walkthrough

The change quotes SQLite identifiers in LOCK TABLES, SHOW TABLES, and compound auto-increment primary-key index creation. Tests cover names with spaces, reserved words, and escaped backticks.

Changes: SQLite Identifier Quoting

Layer / File(s) Summary
LOCK TABLES identifier quoting
packages/mysql-on-sqlite/src/sqlite/class-wp-mysql-on-sqlite.php, packages/mysql-on-sqlite/tests/WP_MySQL_On_SQLite_Tests.php
The table existence check quotes the table name. Tests cover quoted names and missing-table errors.
SHOW TABLES alias quoting
packages/mysql-on-sqlite/src/sqlite/class-wp-mysql-on-sqlite.php, packages/mysql-on-sqlite/tests/WP_MySQL_On_SQLite_Tests.php
The generated Tables_in_<database> alias is quoted. Tests cover a database name containing a backtick and a table name containing a space.
Compound primary-key index quoting
packages/mysql-on-sqlite/src/sqlite/class-wp-mysql-on-sqlite.php, packages/mysql-on-sqlite/tests/WP_MySQL_On_SQLite_Tests.php
The generated reserved index name is quoted. Tests cover escaped table and column names, ALTER TABLE, and sequential auto-increment IDs.

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Bug fix · Severity of issue fixed: Low

Suggested reviewers: janjakes

Merge Risk: Minimal · up to ff6bc

The intended identifier-quoting changes are covered by the implementation and tests, with no concrete merge-blocking risk found.

Pre-merge checks: Passed 5
Check name Status Explanation
Description Check Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check Passed The title clearly and concisely identifies the three main changes: quoting SQLite identifiers in LOCK TABLES, SHOW TABLES, and compound primary key indexes.
Linked Issues check Passed Issue #598 requires SQLite identifier quoting in three paths. The source diff quotes $table_name in execute_transaction_or_locking_statement(), quotes the Tables_in_<database> alias in `execute_…
Out of Scope Changes check Passed The production changes are limited to the three identifier-quoting paths in issue #598. The reported tests exercise those paths, including the dot-in-name LOCK TABLES regression. No unrelated produc…
Docstring Coverage Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documentat…
Full details: Linked Issues check

Explanation

Issue #598 requires SQLite identifier quoting in three paths. The source diff quotes $table_name in execute_transaction_or_locking_statement(), quotes the Tables_in_&lt;database&gt; alias in execute_show_tables_statement(), and quotes the reserved compound-primary-key index name in get_sqlite_create_table_statement(). The PR summary reports tests for escaped-backtick database identifiers, compound primary keys with AUTO_INCREMENT and ALTER TABLE, and persistent, temporary, and special-character table names in LOCK TABLES. These changes address the linked issue requirements.

Full details: Out of Scope Changes check

Explanation

The production changes are limited to the three identifier-quoting paths in issue #598. The reported tests exercise those paths, including the dot-in-name LOCK TABLES regression. No unrelated production behavior or unrelated test change is identified.

Full details: Docstring Coverage

Explanation

Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documentation-only edits and deletions within surviving functions are included; unchanged diff context and fully deleted functions are excluded. Analyzed 3 functions across 1 files. (1 skipped: 1 too large.)

Finishing Touches
Generate unit tests (beta)
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Warning

Some tools did not complete. Review the errors below.

PHPStan (2.3.1)

PHPStan reported 1 non-file analysis error(s); analysis is incomplete

PHPMD (3.0.0)
packages/mysql-on-sqlite/tests/WP_MySQL_On_SQLite_Tests.php

PHPMD could not process this file (exit code 255): 0/1 [░░░░░░░░░░░░░░░░░░░░░░░░░░░░] 0%
1/1 [▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓] 100%
PHP Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 2097152 bytes) in phar:///usr/bin/phpmd/vendor/pdepend/pdepend/src/Util/Cache/Driver/FileCacheDriver.php on line 183

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

Share

Without quoting, SQLite read `main.t` as table `t` in the "main" schema,
so locking a missing `main.t` table succeeded when `t` existed.

@JanJakes JanJakes 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.

Thanks, @0xABCD01, this looks good! I added one more test scenario (locking a table named main.t when only t exists).

@JanJakes
JanJakes merged commit 6b22c0e into WordPress:trunk Nov 2, 2026
18 checks passed
@JanJakes JanJakes mentioned this pull request Nov 3, 2026
@JanJakes JanJakes changed the title Quote SQLite identifiers in LOCK TABLES, SHOW TABLES, and compound primary key indexes Quote SQLite identifiers in LOCK TABLES, SHOW TABLES, and compound primary key indexes Nov 3, 2026
JanJakes added a commit that referenced this pull request Nov 3, 2026
## Release `3.1.3`

Version bump and changelog update for release `3.1.3`.

**Changelog draft:**
* Fix `BINARY` and `VARBINARY` column defaults
([#596](#596))
* Quote SQLite identifiers in `LOCK TABLES`, `SHOW TABLES`, and compound
primary key indexes
([#599](#599))
* Name lexer tokens after the MySQL grammar and default to MySQL 8.4.10
([#607](#607))
* Fix MySQL lexer correctness issues
([#584](#584))
* Require MySQL proxy authentication and default to loopback
([#540](#540))
* Speed up PHPUnit and avoid E2E setup timeouts
([#579](#579))
* Fix reserved prefix checks for case variants and foreign keys
([#580](#580))

**Full changelog:**
v3.1.2...release/v3.1.3

## Next steps

1. **Review** the changes in this pull request.
2. **Push** any additional edits to this branch (`release/v3.1.3`).
3. **Merge** this pull request to complete the release.

Merging will automatically build the plugin ZIP, create a [GitHub
release](https://github.com/WordPress/sqlite-database-integration/releases),
and deploy to
[WordPress.org](https://wordpress.org/plugins/sqlite-database-integration/).

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
<!-- coderabbit-ai-generated:v1 -->

## Summary by CodeRabbit

* **Bug Fixes**
* Improved handling of binary column defaults and SQLite identifier
quoting.
  * Corrected MySQL lexer tokens, defaults, and lexer behavior.
* Updated MySQL proxy authentication and loopback defaults, test timing,
and reserved-prefix checks.
* **Release**
  * Updated the plugin and driver version to 3.1.3.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

MySQL on SQLite: Unquoted SQLite identifiers in LOCK TABLES, SHOW TABLES, and compound primary key indexes

2 participants