- flat_first and the copy route share ties_on_post_id(): a posts.ID term
alone (optionally with a direction) reads the flat post_id; posts.ID inside
an expression a plugin added (FIELD(), IN) is left alone — inserting a
direction there made the SQL invalid and the page empty
- PCRE failures return the text given instead of '' (the query kept its
shape rather than becoming an empty request)
- Found in the 2.4 correctness review (Medium) and security review (Low L1)
- Verify: 2 new integration tests (the flat-first one runs the SQL), router suites 69 OK
- PR: PR-131
- a group index may end with the entity ID column (post_id, ...)
- flat-first rewrites the posts.ID tie-breaks once, in the sort's direction:
with a (column, post_id) index MySQL returns rows in order instead of
sorting the whole match. dev36 (1.3M listings), price range sorted by price:
850 ms filesort -> 2 ms. Ties are ordered by ID the same way as the column
(natively ID DESC); pagination stays stable, result sets are unchanged
- Verify: EntityRegistryIndexesTest, PostQueryRouterFoundRowsTest (ASC
tie-break, single tie-break), unit 704, integration 589, phpcs, stan;
dev36 with the HivePress indexes (PR-119)
- PR: PR-118
- cached counts followed posts' last_changed, which WordPress moves on any
post meta write; themes write meta on page views (on dev36 Blocksy saved a
dynamic-CSS descriptor for each listing a crawler visited), so the cache
was invalidated every few seconds and keyword/filter searches recounted
- counts now follow their own last_changed group (tmdo_posts), bumped on
clean_post_cache (post saved or deleted; hooked in every mode) and on flat
writes through the Hook Bus, plus terms' last_changed; a routed search reads
no unmanaged meta
- Verify: PostQueryRouterFoundRowsTest (unrelated meta write keeps the count,
save or flat write recounts), integration 588, unit 703, phpcs, stan;
dev36 front-end
- PR: PR-117 (2.3 acceptance)
- keyword searches carry wpdb's placeholder escape for "%" ({<hash>}), which
is new in every request, so md5(count SQL) never matched across requests
and every keyword search recounted (the 2.2 "keyword + filter routed slower
than native" finding). The key now uses remove_placeholder_escape()
- found in the 2.3 acceptance: dev36 keyword + price routed 6.2 s vs native
4.9 s; PR-091's in-process check reused one process, one escape
- Verify: PostQueryRouterFoundRowsTest (two escapes, one COUNT), integration
588, unit 703, phpcs, stan; dev36 front-end
- PR: PR-116 (2.3 acceptance)
- a changed group definition no longer runs dbDelta on an existing table
inside a web request (seconds to minutes on a large table, and every
concurrent request tried it): the group is recorded in tmdo_schema_deferred
and tmdo_ensure_group_indexes is scheduled, whose request upgrades it
- meanwhile the group stays native: Hook Bus field lookups return no field and
the router treats it as drifting; afterwards a drift fix
(tmdo_drift_resync) rebuilds the writes that skipped the flat table
- new tables are still created at once; aeav_only upgrades at once (the flat
table is the only copy); doctor lists deferred groups
- Verify: SchemaUpgradeDeferralTest, Hook Bus and router tests, integration
582, unit 701, phpcs, stan; dev36 live cycle in the 2.3 acceptance
- PR: PR-107
- a routed search with post__not_in (HivePress sends a random set per page)
caches the COUNT without the exclusion and subtracts a live primary-key
count of the excluded posts that match; the total stays exact
- the excluded count drops STRAIGHT_JOIN so MySQL starts from posts.ID
- Verify: PostQueryRouterFoundRowsTest, unit 698, integration 577, phpcs, stan;
dev36 live router suite and keyword + price search
- PR: PR-091
- A filtered search ordered by a flat column is rewritten to SELECT STRAIGHT_JOIN … FROM flat INNER JOIN wp_posts, with posts.ID tie-breaks (ours and plugin-appended) read as the equal flat post_id, so MariaDB sorts one table instead of looking every post up and sorting in a temporary table
- Only when the routed conditions already require a flat row on the sort group, without the copy route or a selective post filter; filter tmdo_router_flat_first turns it off; split_the_query compares with the same rewrite
- Verify: tests/live/run.php router (13/13); integration 522; dev36 page SQL Q07 263→147 ms, Q15 250→142 ms; fe.sh hourly_rate__desc 850→367 ms, ids == native
- PR: PR-062c
- posts_request only drops SQL_CALC_FOUND_ROWS, but WordPress then treated the request as filtered and selected full post rows through a temporary table; split_the_query now keeps the ID-first split for routed searches when nothing else changed the request, and posts_request_ids drops SQL_CALC_FOUND_ROWS from the split ID query
- Verify: tests/live/run.php router (12/12, IDs-first request, found_posts == native); dev36 fe.sh price 589→340 ms, price__asc 961→427 ms, rating__desc 1724→872 ms, hourly_rate__desc 855→884 ms (was 1206)
- PR: PR-062b
- Leave the query to WordPress on OR, nested groups with registered keys, several post types, orderby on a named routed clause, and compare/type pairs whose flat-column semantics differ from native (untyped numeric ranges, CHAR on decimals, NUMERIC on text)
- Wrap LIKE values as %esc_like%; hook pre_get_posts at priority 1000 so plugin clauses (HivePress) are seen
- Verify: wp eval-file tests/live/run.php router (7/7); qbench Q04/Q06/Q08/Q14/Q16 == native on dev36
- PR: PR-060
- TMDO_Post_Query_Router drops SQL_CALC_FOUND_ROWS from routed searches
(posts_request) and answers found_posts_query from a COUNT(*) of the
same query, cached in the object cache under posts' last_changed.
- Hook Bus flat post writes and deletes move posts' last_changed: in
aeav_only they skip update_metadata()'s own hooks, so query caches
would otherwise outlive the write.
- Bench (1M): cached page 8 ms (was 694 / 363 ms for scenarios 1 / 2);
after invalidation 8 ms + COUNT 608 / 344 ms, on par with before.
- REST X-WP-Total COUNT is on the frozen Hot zone path (ADR-003): not
changed.
- Verify: core unit 659 / integration 475, HP 142/49, WC 10/22 green,
phpcs clean
- PR: PR-030