Skip to content

Commit 3f6d2c4

Browse files
committed
Fix: Aggressive global FOR UPDATE stripping and AS keyword support for Action Scheduler
1 parent f6ed9dc commit 3f6d2c4

2 files changed

Lines changed: 20 additions & 11 deletions

File tree

.gitignore

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,13 @@ composer.lock
77
._*
88
/wordpress
99
/.claude/settings.local.json
10+
11+
# Local distribution and dev junk
12+
dist/
13+
grammar-tools/
14+
packages/
15+
tests/
16+
wp-setup.sh
17+
phpunit.xml.dist
18+
phpcs.xml.dist
19+
db.copy

integrations/plugin-compatibility/boot.php

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -21,17 +21,14 @@ function wp_sqlite_integration_plugin_compat( $query ) {
2121
return $query;
2222
}
2323

24-
// 1. Intercept known problematic queries and short-circuit if necessary.
25-
// (Previously intercepted information_schema, but that broke WordPress Core Site Health).
26-
27-
// 2. Global fallback for FOR UPDATE / SKIP LOCKED / NOWAIT.
28-
// This ensures the legacy driver natively ignores these locking constraints where SQLite faults.
29-
// We use a non-destructive lookahead for whitespace, semicolon, comments, or LIMIT.
24+
// 1. Heavy cleaning of unsupported MySQL locking clauses.
25+
// SQLite doesn't support FOR UPDATE, SKIP LOCKED, or NOWAIT anywhere.
26+
// We strip these globally (case-insensitive, multi-line) to prevent syntax errors in subqueries.
3027
if ( stripos( $query, 'FOR UPDATE' ) !== false ) {
31-
$query = preg_replace( '/\s+FOR\s+UPDATE(?:\s+(?:SKIP\s+LOCKED|NOWAIT))?(?=\s*(?:;|\/\*|$|\s+LIMIT))/is', '', $query );
28+
$query = preg_replace( '/\s+FOR\s+UPDATE(?:\s+(?:SKIP\s+LOCKED|NOWAIT))?\b/is', '', $query );
3229
}
3330

34-
// 3. Action Scheduler specific compatibility fixes.
31+
// 2. Action Scheduler specific compatibility fixes.
3532
if ( stripos( $query, 'actionscheduler' ) !== false ) {
3633
// Escape the 'group' keyword safely.
3734
// Action Scheduler sometimes queries an unquoted `group` column.
@@ -40,11 +37,13 @@ function wp_sqlite_integration_plugin_compat( $query ) {
4037
// Fix 'INSERT wp_actionscheduler...' syntax to include 'INTO'.
4138
$query = preg_replace( '/INSERT\s+(?!INTO\s+)(wp_actionscheduler_[a-zA-Z0-9_]+)/i', 'INSERT INTO $1', $query );
4239

43-
// Fix 'UPDATE ... JOIN' syntax manually because SQLite requires an 'UPDATE ... FROM' abstraction.
44-
$pattern = '/UPDATE\s+([^\s]+)\s+t1\s+JOIN\s*\((.*?)\)\s*t2\s*ON\s*t1\.action_id\s*=\s*t2\.action_id\s*SET\s*(.*)/is';
40+
// Fix 'UPDATE ... JOIN' syntax manually.
41+
// Handles variants like "UPDATE table t1 JOIN" and "UPDATE table AS t1 JOIN".
42+
$pattern = '/UPDATE\s+([^\s]+)\s+(?:AS\s+)?t1\s+JOIN\s*\((.*?)\)\s*(?:AS\s+)?t2\s*ON\s*t1\.action_id\s*=\s*t2\.action_id\s*SET\s*(.*)/is';
4543
if ( preg_match( $pattern, $query, $matches ) ) {
4644
$set_clause = str_ireplace( 't1.', '', $matches[3] );
47-
$query = "UPDATE {$matches[1]} SET {$set_clause} WHERE action_id IN ({$matches[2]})";
45+
// Extract the SELECT logic from the join to use in an IN clause.
46+
$query = "UPDATE {$matches[1]} SET {$set_clause} WHERE action_id IN ({$matches[2]})";
4847
}
4948
}
5049

0 commit comments

Comments
 (0)