Repository navigation
v1.4.1
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 makeDROP VIEW ... CASCADEdrop 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_rewriterecursively to find every View / Materialized View (including other schemas) thatDROP VIEW ... CASCADEwould also drop. If any of them is not defined in the schema directory, the plan lists them under[BLOCKED], anddeploy,deploy --dry-runanddiffall exit with code 1 without running any group. To proceed intentionally, use the CLI flag--allow-cascade-drop, the JSON optionoptions.allowCascadeDrop: true, or the WPF setting "Allow CASCADE to drop views outside the schema directory"; the item is then shown as a[!]caution.DeployOrchestrator.ExecuteAsyncre-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 aDrop 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:
SchemaIntrospectornow reads index columns/expressions, DESC flags,INCLUDEcolumns, access method andWHEREpredicate directly frompg_indexinstead of regex-splittingpg_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 INDEXstatements from SQL files keep all clauses (WHERE,INCLUDE,USING,WITH, opclasses, etc.) and are executed verbatim;CONCURRENTLYis removed automatically because deployment groups run inside a transaction.CREATE INDEXtext 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_XandUIX_X_...) the wrong index was operated on. Dry-run showedUIX_...being created whileIX_...was actually executed, the deployment reported success without creating the index, and duplicate keys went unnoticed. TheWHEREclause was also dropped during parsing and SQL generation, and introspection mistookWHERE (...)for the column list, so existing partial indexes were reported as "definition changed" on every deployment. Indexes are now matched by exact name and theirWHEREpredicate 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
;afterCREATE INDEX ... )orCREATE TABLE ... )used to produce only42601: 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-runanddiffexit 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-dropto 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,GetViewDependentsAsyncandGetViewsDependingOnColumnsAsyncwere added;ChangeTypegainsExtendViewat the end, so existing member values are unchanged.