Skip to content

v1.4.1

Choose a tag to compare

@lawrence8358 lawrence8358 released this 03 Nov 05:08
18db18a

Release v1.4.1

發布日期 (Date): 2026-11-03

主要亮點 (Highlights):

  • 修正 partial index(WHERE)部署時會操作到錯誤索引、回報成功卻沒有建立的問題;View 重建時若 DROP VIEW ... CASCADE 會刪除 schema 目錄外的 View,現在會中止部署並回傳錯誤,不再默默刪除。
  • Fixed partial indexes (WHERE) being deployed against the wrong index and reported as successful without being created. When rebuilding a View would make DROP VIEW ... CASCADE drop views outside the schema directory, the deployment is now aborted with an error instead of silently dropping them.

🌟 What's New / 主要更新

🚀 Features / 新功能

  • CASCADE 會刪除 schema 目錄外物件時阻擋部署:View 需要先刪除再重建時,工具會在分析階段透過 pg_depend / pg_rewrite 遞迴找出 DROP VIEW ... CASCADE 會連帶刪除的 View / Materialized View(含其他 schema)。若其中有不在 schema 目錄中的物件,部署計畫會列出 [BLOCKED] 與受影響的物件,deploy、deploy --dry-run、diff 皆回傳 exit code 1,且不執行任何群組。確定要刪除時,可使用 CLI --allow-cascade-drop、JSON 設定 options.allowCascadeDrop: true,或 WPF 設定頁「允許 CASCADE 刪除 schema 目錄外的 View」明確放行,此時改以 [!] caution 顯示。執行階段(DeployOrchestrator.ExecuteAsync)會依當下設定再判斷一次,所有呼叫端都受保護。

    EN: Block deployments when CASCADE would drop objects outside the schema directory: when a View must be dropped and recreated, the analyzer now walks pg_depend / pg_rewrite recursively to find every View / Materialized View (including other schemas) that DROP VIEW ... CASCADE would also drop. If any of them is not defined in the schema directory, the plan lists them under [BLOCKED], and deploy, deploy --dry-run and diff all exit with code 1 without running any group. To proceed intentionally, use the CLI flag --allow-cascade-drop, the JSON option options.allowCascadeDrop: true, or the WPF setting "Allow CASCADE to drop views outside the schema directory"; the item is then shown as a [!] caution. DeployOrchestrator.ExecuteAsync re-evaluates the policy with the settings in effect at execution time, so every host is protected.

  • View 只在尾端新增欄位時不再刪除重建:既有 View 的欄位清單若只是在尾端新增欄位,改以 CREATE OR REPLACE VIEW 直接更新(CLI 顯示 [+VCOL]),不再插入 Drop Views (Pre-Alter),依賴它的其他 View 不受影響。欄位改名、刪除、改順序或在中間插入時仍會先刪除再重建([~VIEW])。

    EN: No drop-and-recreate when a View only appends columns: if an existing View's column list only gains new columns at the end, it is now updated in place with CREATE OR REPLACE VIEW (shown as [+VCOL] in the CLI) without a Drop Views (Pre-Alter) step, so views depending on it are untouched. Renaming, removing, reordering or inserting columns in the middle still drops and recreates the View ([~VIEW]).

  • 在既有資料表建立唯一索引時提示:對既有資料表建立或重建 UNIQUE 索引時列為 [!] caution,提醒若現有資料有重複鍵,部署會失敗並回滾該群組。

    EN: Caution for unique indexes on existing tables: creating or recreating a UNIQUE index on an existing table is now flagged as a [!] caution, warning that the deployment will fail and roll back that group if existing rows contain duplicate keys.

🛠 Refactoring & Improvements / 重構與效能優化

  • 索引內省與比對改寫:SchemaIntrospector 改由 pg_index 直接取得索引的欄位/運算式、DESC、INCLUDE 欄位、存取方法與 WHERE 條件,不再以正規式切割 pg_get_indexdef() 的輸出。比對前,對 SQL 檔與資料庫寫法不同的同名索引(如 IN (...) 被改寫為 = ANY (ARRAY[...])、運算式被補上型別轉換),會在交易內建立暫存表與相同索引,讀回 PostgreSQL 正規化後的定義再比較,最後整個交易回滾、不留下任何物件。因此分析(含 dry-run)需要目標資料庫的 TEMP 權限;沒有權限時退回以 SQL 原文比對。

    EN: Rewritten index introspection and comparison: SchemaIntrospector now reads index columns/expressions, DESC flags, INCLUDE columns, access method and WHERE predicate directly from pg_index instead of regex-splitting pg_get_indexdef(). When a same-named index is written differently in the SQL file and in the database (e.g. IN (...) rewritten as = ANY (ARRAY[...]), or expressions gaining type casts), the analyzer creates a temp table and the same index inside a transaction, reads back PostgreSQL's normalized definition for comparison, and rolls the transaction back so nothing is left behind. Analysis (including dry-run) therefore needs the TEMP privilege on the target database; without it, the comparison falls back to the SQL text as written.

  • 索引定義原樣部署:SQL 檔中的 CREATE INDEX 會完整保留 WHERE、INCLUDE、USING、WITH、opclass 等子句並原樣執行;因部署群組在交易內執行,CONCURRENTLY 會自動移除。註解中的 CREATE INDEX 不再被誤解析為索引。

    EN: Index definitions are deployed as written: CREATE INDEX statements from SQL files keep all clauses (WHERE, INCLUDE, USING, WITH, opclasses, etc.) and are executed verbatim; CONCURRENTLY is removed automatically because deployment groups run inside a transaction. CREATE INDEX text inside comments is no longer parsed as an index.

  • CLI / WPF 顯示補強:CLI 補上 [~CMT](註解變更)、[+VIEW]、[~VIEW]、[+VCOL] 前綴(原本註解與 View 變更顯示為 [?]);WPF 為 View 變更與阻擋項目加上顏色。

    EN: CLI / WPF display improvements: the CLI now shows [~CMT] (comment changes), [+VIEW], [~VIEW] and [+VCOL] prefixes (comment and View changes previously showed [?]); WPF adds colors for View changes and blocked items.

🐛 Bug Fixes / 問題修復

  • 修正 partial index 部署錯誤:建立或重建索引時原本以 Description.Contains(name) 反查索引,名稱互為子字串(如 IX_X 與 UIX_X_...)時會操作到錯誤的索引,導致 dry-run 顯示建立 UIX_...、實際卻執行 IX_...,部署回報成功但索引沒有建立,資料中的重複鍵也不會被發現。此外 WHERE 條件在解析與產生 SQL 時被丟棄,內省時又把 WHERE (...) 誤當成欄位清單,使已存在的 partial index 每次部署都被判定為「定義已變更」。現在改以完全相同的索引名稱比對,並完整保留與比對 WHERE 條件。

    EN: Fixed partial index deployment: index changes were resolved with Description.Contains(name), so when one index name contained another (e.g. IX_X and UIX_X_...) the wrong index was operated on. Dry-run showed UIX_... being created while IX_... was actually executed, the deployment reported success without creating the index, and duplicate keys went unnoticed. The WHERE clause was also dropped during parsing and SQL generation, and introspection mistook WHERE (...) for the column list, so existing partial indexes were reported as "definition changed" on every deployment. Indexes are now matched by exact name and their WHERE predicate is preserved and compared.

  • 修正資料表欄位改型別/刪除時被 View 依賴而部署失敗:schema 目錄中的 View 若(直接或間接)引用本次要變更型別或刪除的資料表欄位,現在會先刪除並於 Views 群組重建,避免 PostgreSQL 拒絕 ALTER TABLE(cannot alter type of a column used by a view or rule)。

    EN: Fixed failures when altering or dropping a column used by a View: Views in the schema directory that (directly or indirectly) reference a table column whose type is being changed or which is being dropped are now dropped first and recreated in the Views group, preventing PostgreSQL from rejecting the ALTER TABLE (cannot alter type of a column used by a view or rule).

  • 修正漏分號時難以定位的錯誤訊息:資料表 SQL 檔整份以單一 command 執行,CREATE INDEX ... ) 或 CREATE TABLE ... ) 漏了 ; 時原本只顯示 42601: syntax error at or near "COMMENT"。現在於解析階段即回報檔名與行號(如 Tables\B_Bad.sql: Line 9: ...),dry-run 就能發現;執行失敗時也會附上來源檔名,語法錯誤可確定位置時附上行號。

    EN: Fixed hard-to-locate errors for missing semicolons: table SQL files are executed as a single command, so a missing ; after CREATE INDEX ... ) or CREATE TABLE ... ) used to produce only 42601: syntax error at or near "COMMENT". The file name and line number are now reported during parsing (e.g. Tables\B_Bad.sql: Line 9: ...), so dry-run catches it; execution failures also include the source file name, plus the line number when the syntax error position can be determined.

⚠️ Breaking Changes / 重大變更

  • CASCADE 會刪除 schema 目錄外的 View 時,部署改為失敗:過去這類部署會照常執行並默默刪除那些 View;v1.4.1 起 deploy、deploy --dry-run、diff 會回傳 exit code 1,CD 流程會因此中止。升級方式:

    • 建議:把被列出的 View 定義檔加入 schema 目錄,之後每次部署都會自動重建。
    • 或確認可以刪除後,在 CLI 加上 --allow-cascade-drop、在 JSON 設定檔加上 "options": { "allowCascadeDrop": true },或在 WPF 設定頁勾選對應選項。

    EN: Deployments now fail when CASCADE would drop views outside the schema directory: previously such deployments ran and silently dropped those views. Starting with v1.4.1, deploy, deploy --dry-run and diff exit with code 1, which stops CD pipelines. Migration:

    • Recommended: add the listed views' definition files to the schema directory so they are recreated on every deployment.
    • Or, once you have confirmed they can be dropped, pass --allow-cascade-drop to the CLI, set "options": { "allowCascadeDrop": true } in the JSON config, or enable the corresponding option in the WPF settings.
  • ISchemaIntrospector 介面新增成員(僅影響自行實作此介面的程式):新增 CanonicalizeIndexesAsync、GetViewDependentsAsync、GetViewsDependingOnColumnsAsync;ChangeType 列舉在最後新增 ExtendView,既有成員數值不變。

    EN: New members on ISchemaIntrospector (affects only custom implementations of this interface): CanonicalizeIndexesAsync, GetViewDependentsAsync and GetViewsDependingOnColumnsAsync were added; ChangeType gains ExtendView at the end, so existing member values are unchanged.