docs(2meet-data-optimizer): ADR-004 search-index mode and 1.1.0 release notes
- ADR-004: HivePress / WooCommerce sites keep native meta as the source of truth and use flat tables as its search index; records the 2.1 write order, shadow_read, Promotion Guard, restore policy and router rules, with known limits - CONTEXT.md Entity Bridge, BENCHMARK-SCALE.md front-end and write-chain measurements (dev36), CHANGELOG and readme for 1.1.0; version 1.1.0 - composer phpcs uses phpcs.xml like CI (was --standard=WordPress with 2312 false errors) - Verify: composer phpcs (0); composer test; composer stan - PR: PR-064
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
* Plugin Name: 2meet Data Optimizer
|
||||
* Plugin URI: https://2meet.io/2meet-data-optimizer
|
||||
* Description: 通用 WordPress 反 EAV 引擎:將 postmeta / usermeta / termmeta / commentmeta 自動分流至四象限扁平表(Hot / Warm / Cold / Archive),大幅提升搜尋與篩選效能。從 wp-data-optimizer v2.16.0 提煉的純核心,整合層交給 11 個 AddOn。
|
||||
* Version: 1.0.2
|
||||
* Version: 1.1.0
|
||||
* Requires at least: 6.0
|
||||
* Tested up to: 6.9.4
|
||||
* Requires PHP: 8.1
|
||||
@@ -26,7 +26,7 @@ if ( ! defined( 'ABSPATH' ) ) {
|
||||
}
|
||||
|
||||
// ── Constants ──────────────────────────────────────────────────────────────
|
||||
define( 'TMDO_VERSION', '1.0.2' );
|
||||
define( 'TMDO_VERSION', '1.1.0' );
|
||||
define( 'TMDO_DB_VERSION', '2.1.0' );
|
||||
define( 'TMDO_PATH', plugin_dir_path( __FILE__ ) );
|
||||
define( 'TMDO_URL', plugin_dir_url( __FILE__ ) );
|
||||
|
||||
@@ -7,6 +7,57 @@ Versioning follows [Semantic Versioning](https://semver.org/).
|
||||
|
||||
---
|
||||
|
||||
## [1.1.0] — 2026-09-26 — HivePress / WooCommerce 搜尋索引模式(hardening 2.1)
|
||||
|
||||
**性質**:資料正確性修正 + 查詢改寫補強。無 schema 變更。決策與設計見
|
||||
`docs/adr-004-search-index-mode-for-hp-wc.md`;搭配 HivePress AddOn 0.2.0。
|
||||
|
||||
### Added
|
||||
|
||||
- **Promotion Guard**(`TMDO_Promotion_Guard`):HivePress 啟用時 post / user / term /
|
||||
comment、WooCommerce 啟用時 post / user 不得升到 aeav_only 或執行 cleanup
|
||||
(`WP_Error( 'promotion_guarded' )`,filter `tmdo_promotion_guard_allow`);已在
|
||||
aeav_only 的站只顯示後台 notice。(PR-053)
|
||||
- **`wp tmdo repair-array-literals [--entity] [--confirm]`**:把扁平表中的 `"Array"`
|
||||
從原生修回;原生也被污染的列出清單。(PR-055)
|
||||
- **`bridge-restore-native --overwrite / --only-missing`**:預設依模式(aeav_only 覆寫、
|
||||
其他只補缺);報告新增 `missing` / `differs` / `same` / `default_skipped`。(PR-058)
|
||||
- **live 測試層** `tests/live/`(在真實站台以 `wp eval-file` 執行):suites
|
||||
`shadow_write`、`serialized`、`resync`、`router`、`zero_side_effect`,以及 qbench /
|
||||
fe.sh 等量測工具。(PR-052)
|
||||
|
||||
### Changed
|
||||
|
||||
- **Hook Bus 寫入順序**:dual_write / shadow_read 由 WordPress 寫原生,扁平表在
|
||||
`added_ / updated_ / deleted_{type}_meta` 從原生重新同步(含 `delete_all`、
|
||||
`update_metadata_by_mid` 改 key)。(PR-057)
|
||||
- **shadow_read** 讀原生,並抽樣比對扁平值(`tmdo_shadow_compare_sample_rate`)。(PR-056)
|
||||
- **Post query router**:
|
||||
- 全有或全無:OR、多 post type、含已註冊 key 的巢狀 group、type 語意與欄位不符的
|
||||
clause 讓整個查詢維持原生;LIKE 包 `%esc_like%`;`pre_get_posts` priority 1000。(PR-060)
|
||||
- 每個 group 各自 JOIN、不加 GROUP BY;NOT EXISTS 不走狀態 / 日期副本路由。(PR-061)
|
||||
- meta orderby:HivePress `_sort`(NOT EXISTS + EXISTS)形狀、具名 clause、
|
||||
`meta_key` + `meta_value_num`。(PR-062)
|
||||
- routed 搜尋維持 WordPress 的 split query(ID-first)。(PR-062b)
|
||||
- `composer phpcs` 改用 `phpcs.xml`(與 CI 相同)。
|
||||
|
||||
### Fixed
|
||||
|
||||
- shadow_read 下 `update_*_meta()` 回傳 false、原生沒有寫入(資料遺失)。(PR-056)
|
||||
- 陣列 / 物件存進 text 欄位變成 `"Array"`;text 超過 255 字元改存 NULL 並記錄
|
||||
`text_overflow`。(PR-055)
|
||||
- `bridge-restore-native` 覆蓋較新的原生值(WC 庫存)、替每個 user 捏造預設值列。(PR-058)
|
||||
- Cold / Hot 表不存在時,`save_post`、`loop_start`、刪除文章仍查詢它們(DB error)。(PR-054、PR-054b)
|
||||
- Router:Q05(wp_core 與另一 group 的 key 並用)`Unknown column`;OR / 多 post type /
|
||||
無 type 數值比較 / 具名 orderby 的結果與原生不同。(PR-060〜062)
|
||||
|
||||
### Docs
|
||||
|
||||
- ADR-004、`CONTEXT.md` Entity Bridge(寫入順序、shadow_read、搜尋索引模式、Router 規則)、
|
||||
`docs/BENCHMARK-SCALE.md` 前台與寫入鏈實測。(PR-064)
|
||||
|
||||
---
|
||||
|
||||
## [1.0.2] — 2026-08-15 — NinjaFirewall 相容性:WAF 設定選項保護
|
||||
|
||||
**性質**:防禦性修正 + 文件。無 schema 變更,無破壞性變更。
|
||||
|
||||
+23
@@ -135,6 +135,29 @@ Newer anti-EAV system (v2.5+) covering user, term, comment, and post entities vi
|
||||
The Entity Bridge and the Zone system coexist; the Sync Bridge's
|
||||
`is_owned_by_entity_bridge()` guard prevents duplicate writes.
|
||||
|
||||
**Write order (v1.1.0).** In `dual_write` / `shadow_read` the Hook Bus pre-filters
|
||||
only decide the route and return `null`: WordPress writes native meta itself, and the
|
||||
flat value is then re-synced *from native* in `added_/updated_/deleted_{type}_meta`
|
||||
(priority 1) — `TMDO_Hook_Bus::sync_from_native()` reads the first native row with
|
||||
direct SQL; no native row → flat NULL. `aeav_only` keeps the pre-filter short-circuit.
|
||||
|
||||
**shadow_read** reads native meta (WordPress meta cache) and compares a sample of reads
|
||||
with the flat value (`tmdo_shadow_compare_sample_rate`, default 0.1). Flat tables serve
|
||||
queries only: `TMDO_Post_Query_Router` is active from `shadow_read` up.
|
||||
|
||||
**Search-index mode** (ADR-004). On HivePress / WooCommerce sites native meta is the
|
||||
source of truth and flat tables are its search index: `TMDO_Promotion_Guard` refuses
|
||||
`aeav_only` and cleanup there (post/user/term/comment with HivePress, post/user with
|
||||
WooCommerce), because both read meta with an empty key and WooCommerce updates stock
|
||||
and sales with direct SQL. Override: filter `tmdo_promotion_guard_allow`.
|
||||
|
||||
**Post query router rules.** A query is rewritten only when the flat table returns
|
||||
what native `meta_query` would: every registered clause routable (else the whole query
|
||||
stays native), AND relation, one post type, column type matching the clause's CAST
|
||||
semantics, LIKE as `%esc_like%`. Meta ordering (the HivePress `_sort` NOT EXISTS/EXISTS
|
||||
shape, a named clause, `meta_key` + `meta_value_num`) is routed only as the sole
|
||||
`orderby` on a column that orders like native.
|
||||
|
||||
---
|
||||
|
||||
## Migration Phase (Strategy pattern)
|
||||
|
||||
+1
-1
@@ -36,7 +36,7 @@
|
||||
"scripts": {
|
||||
"test": "phpunit --configuration phpunit.xml",
|
||||
"test:integration": "phpunit --configuration phpunit-integration.xml",
|
||||
"phpcs": "phpcs --standard=WordPress includes/ admin/ cli/ modules/ 2meet-data-optimizer.php uninstall.php",
|
||||
"phpcs": "phpcs --standard=phpcs.xml",
|
||||
"stan": "phpstan analyse --no-progress",
|
||||
"stan:baseline": "phpstan analyse --no-progress --generate-baseline=phpstan-baseline.neon"
|
||||
},
|
||||
|
||||
@@ -63,6 +63,38 @@ SQL 的形狀與實際程式一致:原生是 WP_Query 的 meta_query(每個
|
||||
6. **dual_write 的寫入成本約為兩倍(0.22 ms 對 0.12 ms)**,絕對值很小,不是瓶頸。
|
||||
7. **Hot 表和 Entity 表儲存了同一份 listing 資料**(合計約 608 MB),兩者功能重疊。
|
||||
|
||||
## 前台與寫入鏈實測(dev36,Release 2.1,2026-09-26)
|
||||
|
||||
上面的數字是純 SQL。這一節是真實站台(dev36:HivePress 1.7.31 + Marketplace、WooCommerce 11.1.2、Redis object cache、listing 約 10 萬筆)上的整頁與整條寫入鏈,決策背景見 `adr-004-search-index-mode-for-hp-wc.md`。
|
||||
|
||||
**前台搜尋**(`tests/live/tools/fe.sh`:每個 URL 5 次取中位數,`X-S36-Ms` = 整個請求到 `template_redirect`)。「routed」是 post 模式 shadow_read + 核心 2.1 router + HivePress AddOn 0.2.0;「1.0.x」是整合測試當時的 router(報告 `notes/tmdo-integration-test-dev36-2026-09-26.md`)。
|
||||
|
||||
| URL | 原生 ms | 1.0.x ms | 2.1 routed ms | ids 與原生相同 |
|
||||
|---|---:|---:|---:|---|
|
||||
| listing 價格區間 | 606 | 496 | **311** | 是(found 差 1 為扁平漂移) |
|
||||
| listing 價格區間 + `_sort=price__asc` | 949 | 1,062 | **428** | 是 |
|
||||
| listing 時薪區間 + `_sort=hourly_rate__desc` | 843 | — | 873 | 是 |
|
||||
| listing `_sort=rating__desc` | 1,717 | 1,720 | **870** | 是 |
|
||||
| listing 關鍵字 + 價格區間 | 748 | — | 743 | 是 |
|
||||
| vendor 時薪區間 | 102 | — | 86 | 是(found 差 21 為扁平漂移) |
|
||||
| WC 商店價格篩選 / 價格排序 | 90 / 107 | 88–94 | 102 / 118 | 是(WC 用 lookup 表,不經 router) |
|
||||
|
||||
- HivePress 搜尋仍帶 tax_query(排除一個 term),WordPress 因此加上 `GROUP BY posts.ID`,排序需要 temporary + filesort;這是目前 311–428 ms 的主要成本,尚未達到 R-2.1 的 300 ms 目標。
|
||||
- PR-062b 之前,routed 搜尋因 `posts_request` 改寫而失去 WordPress 的 split query,改撈整列 `posts.*`:同一條 SQL 撈 `*` 要 590 ms,只撈 ID 為 312 ms。
|
||||
- 量測 gotcha:symlink 切換(`plugins/` → `plugins-dev`)後,PHP-FPM 的 opcache(`revalidate_path=0`)仍執行舊目標的程式,WP-CLI 不受影響;前台數字要先確認實際載入的檔案。
|
||||
|
||||
**WP_Query**(`tests/live/tools/qbench.php`,`fields=ids`,20 筆一頁):價格區間 296→76 ms、價格 + verified 360→53 ms、rating ≥ 4.5 248→33 ms、rate + `_thumbnail_id` EXISTS 24→9 ms;OR、多 post type、無 type 數值比較等維持原生,結果與原生相同。
|
||||
|
||||
**寫入鏈開銷**(單一程序,disabled 與 dual_write 交替兩輪取平均):
|
||||
|
||||
| 寫入 | disabled | dual_write | 增加 |
|
||||
|---|---:|---:|---:|
|
||||
| HP listing | 754 ms / 348 q | 976 ms / 434 q | +29% |
|
||||
| WC product | 215 ms / 129 q | 489 ms / 206 q | +127% |
|
||||
| vendor(user + post) | 444 ms / 162 q | 630 ms / 230 q | +42% |
|
||||
|
||||
WC product 的成本來自 `wc_product` 群組,Release 2.2 移除 WC 扁平化後消失。
|
||||
|
||||
## 優化候選(待使用者確認後排入 backlog)
|
||||
|
||||
| # | 候選 | 針對 | 預期效果 |
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
# ADR-004:HivePress / WooCommerce 站採「搜尋索引模式」
|
||||
|
||||
- **狀態**:已接受(2026-09-26)
|
||||
- **日期**:2026-09-26
|
||||
- **相關**:dev36 整合測試報告(`notes/tmdo-integration-test-dev36-2026-09-26.md`)、ADR-001、ADR-003、backlog PR-052〜PR-063(Release 2.1)
|
||||
|
||||
## 背景
|
||||
|
||||
2026-09-26 在 dev36(HivePress 1.7.31 + Marketplace + 10 個擴充、WooCommerce 11.1.2、Redis、10 萬筆 listing)做整合與壓力測試,確認:
|
||||
|
||||
1. **HivePress model 與 WC data store 用空 key 讀 meta**(`get_post_meta( $id )`),1.0.x 的 Hook Bus 對空 key 放行、只讀原生。所以 aeav_only 或 cleanup 之後,HP 的 verified / rating、WC 的價格與顧客資料讀成空值(dev20 / dev21 盤點:WC 商品 0/20 可購買)。
|
||||
2. **WC 以直接 SQL 更新 `_stock`、`total_sales`**,扁平表跟不上。
|
||||
3. **shadow_read 會遺失寫入**:WP 的 `update_metadata()` 經 `get_metadata_raw` 讀舊值,攔截器從扁平表回答,新舊相同就不寫原生。
|
||||
4. **Router 在 OR、LIKE、多 post type、跨 group、具名 orderby 上結果錯誤**,HivePress 的 `_sort` 沒被改寫,前台搜尋幾乎沒有變快。
|
||||
5. **陣列值被存成 `"Array"`**。
|
||||
|
||||
帶 key 的單筆讀取本來就沒有速度優勢:`update_meta_cache()` 一次載入全部 key,之後都是記憶體讀取。扁平表真正的價值在**搜尋與篩選**(`BENCHMARK-SCALE.md` 結論 1、2)。
|
||||
|
||||
## 決策(使用者 2026-09-26)
|
||||
|
||||
1. **HP / WC 站採「搜尋索引模式」**:原生 meta 是唯一真實資料來源,扁平表是它的搜尋索引。模式最高到 `shadow_read`;`aeav_only` 與 cleanup 由 Promotion Guard 擋下。
|
||||
2. **移除 WC 扁平化**(Release 2.2:core 的 `post/wc_product` 群組、WC AddOn 的 user `hot` 群組與 hot-zone 欄位)。
|
||||
3. **既有 aeav_only 站(dev20 / 21 / 22)先唯讀盤點**,處置由使用者決定(`notes/ops-aeav-sites-audit-2026-09-26.md`)。
|
||||
4. **分兩版**:2.1 = 止血 + 資料正確性 + Router 與 HP 排序;2.2 = 範圍收斂 + 漂移偵測 + CLI 與診斷。
|
||||
|
||||
## 設計(Release 2.1)
|
||||
|
||||
### 寫入:扁平表跟隨原生
|
||||
|
||||
- **dual_write / shadow_read** 下,pre-filter(`update_/add_/delete_{type}_metadata`)只做路由判斷後回 `null`,讓 WordPress 自己寫原生。
|
||||
- 扁平表在 `added_ / updated_ / deleted_{type}_meta` action(priority 1)裡**從原生重新同步**:直接 SQL 讀原生第一筆 row(`ORDER BY meta_id LIMIT 1`,不經 filter),扁平值 = `to_db( maybe_unserialize( v ) )`,原生沒有 row 時設為 NULL(`TMDO_Hook_Bus::sync_from_native()`)。
|
||||
- `delete_metadata( …, $delete_all )`:`deleted_` action 拿到的 object id 是 0,所以在 `delete_{type}_meta` 先記下 object ids。
|
||||
- `update_metadata_by_mid()` 改 key:新舊兩個 key 都重新同步。
|
||||
- **aeav_only** 保留原本的 pre-filter short-circuit(非 HP / WC 站仍可使用)。
|
||||
|
||||
### 讀取:shadow_read = 讀原生、抽樣比對扁平
|
||||
|
||||
`intercept_get` 在 shadow_read 回 `$check`(讓 WordPress 讀原生),並以 `tmdo_shadow_compare_sample_rate`(預設 0.1)抽樣比對扁平值、記錄差異。查詢加速不受影響,因為 Router 仍由 `reads_from_flat()`(shadow_read 以上)控制。
|
||||
|
||||
### Promotion Guard
|
||||
|
||||
`TMDO_Promotion_Guard`,由 `TMDO_Mode_Manager::set()`、`TMDO_Post_Migration::cleanup()` 與 `TMDO_Phase_Cleanup::execute()` 呼叫:
|
||||
|
||||
- HivePress 啟用時,post / user / term / comment 不得升到 aeav_only 或執行 cleanup;WooCommerce 啟用時,post / user 不得。
|
||||
- 回傳 `WP_Error( 'promotion_guarded' )`;特殊情況用 filter `tmdo_promotion_guard_allow` 放行。
|
||||
- 已經在 aeav_only 的站**讀取時不強制降級**(降級會讀到空的原生),只在後台顯示 notice。處置用 `wp tmdo bridge-restore-native <entity> --demote`。
|
||||
|
||||
### 回寫原生(bridge-restore-native)
|
||||
|
||||
依模式決定策略:aeav_only 預設 `overwrite`(寫入只到扁平表、原生已過期),其他模式預設 `only_missing`(原生可能較新,例如 WC 直接 SQL 寫庫存)。相同的值不重寫;扁平值等於欄位 default 且原生沒有 row 時不寫(不捏造預設值)。
|
||||
|
||||
### 序列化值
|
||||
|
||||
`text` / `textarea` 遇到陣列或物件時 `maybe_serialize()`,讀出時 `TMDO_Safe_Unserialize`;`text`(VARCHAR(255))超長存 NULL 並記 `text_overflow`。既有的 `"Array"` 由 `wp tmdo repair-array-literals` 從原生修復。
|
||||
|
||||
### Router:只在語意與原生相同時路由
|
||||
|
||||
`TMDO_Post_Query_Router`(`pre_get_posts` priority 1000,排在外掛於預設 priority 加的條件之後):
|
||||
|
||||
- **全有或全無**:任何一個已註冊 key 的 clause 不能路由,整個查詢交回 WordPress。不能路由的情況:
|
||||
- top-level OR
|
||||
- 含已註冊 key 的巢狀 group(排序形狀除外)
|
||||
- 多個 post type
|
||||
- 白名單以外的 compare
|
||||
- type 與欄位語意不同:無 type(CHAR)的數值範圍比較、decimal 欄位的 CHAR 比較、text 欄位用 NUMERIC
|
||||
- **LIKE** 包成 `%esc_like%`。
|
||||
- **每個 group 各自 LEFT JOIN**;扁平表一文章一列(UNIQUE `post_id`),不加 GROUP BY。
|
||||
- 狀態 / 日期副本路由遇到 NOT EXISTS 時停用:INNER JOIN 會漏掉沒有扁平列的文章。
|
||||
- **排序**(`wpdo_post_sort`):
|
||||
- **HivePress `_sort` 形狀**:OR 裡剛好是同 key、同 type 的 NOT EXISTS + EXISTS,其中一個具名,並且是唯一的 orderby。這個 group 從 meta_query 移除,改成 LEFT JOIN 扁平表並 `ORDER BY col, ID DESC`;ASC 時 NULL 排最前,與原生相同。
|
||||
- **具名 clause** 作為唯一的 orderby。
|
||||
- **`meta_key` + `meta_value_num`**(字串欄位用 `meta_value`),加上 `col IS NOT NULL`(原生是 INNER JOIN)。
|
||||
- 欄位排序不等於 `CAST( meta_value AS type )` 時退回原生。
|
||||
- **維持 WordPress 的 split query**:`posts_request` 移除 `SQL_CALC_FOUND_ROWS`(總數改由快取的 COUNT 回答)會讓 WordPress 以為 request 被改過而撈整列。`split_the_query` 對 routed 查詢恢復 ID-first,`posts_request_ids` 再移除一次 `SQL_CALC_FOUND_ROWS`。
|
||||
|
||||
HivePress AddOn 0.2.0 在 post router 啟用時不再綁定舊的 hot-zone `optimize_query` / `optimize_search`。
|
||||
|
||||
## 後果
|
||||
|
||||
**好處**
|
||||
|
||||
- 資料正確性回到 WordPress 原生語意:HP / WC 的空 key 讀取、直接 SQL 寫入都不再造成資料不一致或遺失。
|
||||
- 查詢加速保留,而且擴及 HivePress 前台的篩選與排序(實測見 `BENCHMARK-SCALE.md`「前台與寫入鏈實測」)。
|
||||
- 任何時候都可以降回 disabled,原生資料完整。
|
||||
|
||||
**代價與限制**
|
||||
|
||||
- **寫入開銷**:dual_write / shadow_read 每次 meta 寫入多一次原生讀取與一次扁平寫入。dev36 實測 HP listing 整條寫入鏈 +29%、WC product +127%(後者在 2.2 移除 WC 扁平化後消失)。
|
||||
- **沒有讀取加速**:帶 key 的單筆讀取仍走原生(WordPress meta cache)。
|
||||
- **漂移**:繞過 meta API 的寫入(直接 SQL、Hook Bus 關閉期間的匯入)會讓扁平表過期,Router 會回傳過期的篩選結果。2.2 的 `drift-check` 與重新啟用時的增量 backfill(E01 / E02)處理;在那之前,大量匯入後要重新 backfill。
|
||||
- **decimal 欄位搭配 NUMERIC / DECIMAL**:原生先 CAST 成整數(`DECIMAL` 預設 (10,0)),扁平表精確比較,因此帶小數的值在區間邊界上可能不同。dev36 資料沒有這種值。
|
||||
- **text 欄位超過 255 字元**存 NULL,這類值的篩選結果會與原生不同(有 `text_overflow` 記錄)。
|
||||
- HivePress 搜尋 p50 目前最快 311–428 ms(原生 606–949 ms),尚未達到 R-2.1 的 300 ms 目標。剩餘成本主要是 WordPress 因 tax_query 加的 `GROUP BY posts.ID` 與 filesort。
|
||||
|
||||
## 不在範圍內
|
||||
|
||||
- aeav_only 的空 key 讀取合併(B02):HP / WC 站不再使用 aeav_only,是否實作依其他站需求決定。
|
||||
- Hot zone 的移除(ADR-003 的後續步驟)。
|
||||
+11
-1
@@ -4,7 +4,7 @@ Tags: performance, database, postmeta, optimization, hivepress
|
||||
Requires at least: 6.0
|
||||
Tested up to: 6.9
|
||||
Requires PHP: 8.1
|
||||
Stable tag: 1.0.0
|
||||
Stable tag: 1.1.0
|
||||
License: GPLv2 or later
|
||||
License URI: https://www.gnu.org/licenses/gpl-2.0.html
|
||||
|
||||
@@ -107,6 +107,16 @@ The Classifier tab analyzes your existing `wp_postmeta` data (access frequency,
|
||||
|
||||
== Changelog ==
|
||||
|
||||
= 1.1.0 =
|
||||
* Search-index mode for HivePress / WooCommerce sites (docs/adr-004): native meta stays the source of truth, flat tables are its search index
|
||||
* Promotion Guard: aeav_only and cleanup are refused while HivePress or WooCommerce is active (filter `tmdo_promotion_guard_allow`)
|
||||
* shadow_read reads native meta and samples a flat comparison — fixes lost native writes
|
||||
* dual_write / shadow_read: flat values follow native after every write (added_/updated_/deleted_ meta actions, delete_all, key change by meta_id)
|
||||
* Arrays in text fields are stored serialized, never "Array"; `wp tmdo repair-array-literals`
|
||||
* `wp tmdo bridge-restore-native`: overwrite in aeav_only, only-missing otherwise; no invented default rows
|
||||
* Post query router: routes only when the result equals native (OR, several post types, untyped numeric compares stay native), LIKE wildcards, one join per group, no GROUP BY, HivePress `_sort` / named / meta_value_num ordering, WordPress split query kept
|
||||
* Zone tables that were never created are never queried
|
||||
|
||||
= 1.0.0 =
|
||||
* Supersedes `wp-data-optimizer` v3.4.6 — that plugin is retired; this one is the single unified engine
|
||||
* Version numbering restarts at 1.0.0; entries below 3.4.6 are the predecessor's history, kept for archaeology
|
||||
|
||||
Reference in New Issue
Block a user