PostgreSQL SPI 中的錯誤處理

PostgreSQL SPI 用於在 C 或是其餘編程語言編寫的擴展函數(存儲過程)中調用數據庫自己的解析器、規劃器和執行器的功能,以及對 SQL 語句進行執行。數據庫

在最重要的一個函數 SPI_execute 的文檔中,說明了發生錯誤時,將會返回下列負值之一:編程

SPI_ERROR_ARGUMENT 若是command爲NULL或者count小於 0編程語言

SPI_ERROR_COPY 若是嘗試COPY TO stdout或者COPY FROM stdin函數

SPI_ERROR_TRANSACTION 若是嘗試了一個事務操縱命令( BEGIN、 COMMIT、 ROLLBACK、 SAVEPOINT、 PREPARE TRANSACTION、 COMMIT PREPARED、 ROLLBACK PREPARED或者其餘變體)日誌

SPI_ERROR_OPUNKNOWN 若是命令類型位置(不該該會發生)code

SPI_ERROR_UNCONNECTED 若是調用過程未鏈接事務

你必定會奇怪,爲何只有這麼幾個呢?還有其餘的不少狀況呢?好比傳進去的 SQL 有語法錯誤,或是實際執行時報錯,這些狀況下會返回什麼呢?開發

而後文檔中又說:注意若是一個經過 SPI 調用的命令失敗,那麼控制將不會返回到你的過程當中。固然啦,你的過程所在的事務或者子事務將被回滾(這可能看起來使人驚訝,由於據文檔所說 SPI 函數大多數都有錯誤返回約定。可是那些約定只適用於在 SPI 函數自己內部檢測到的錯誤)。經過在可能失敗的 SPI 調用周圍創建本身的子事務能夠在錯誤以後恢復控制。當前文檔中並未記載這些,由於所需的機制仍然在變化中。文檔

原來檢查 SPI_execute 的源代碼可知,只有發生了上面幾種狀況的錯誤時,SPI 會返回給你錯誤代碼;而其餘更內部的地方發生的全部錯誤,程序都是直接調用的 ereport 方法,若是錯誤級別達到 ERROR 及以上時,會中斷程序的執行,將事務回滾,並將錯誤信息:一、記到日誌中;二、返回給客戶端。it

所以,其餘狀況的錯誤,你根本就沒必要處理,PG 也不給你機會處理。你只有在客戶端才能看到具體的報錯信息。

若是你是在一個很大的邏輯裏,不想整個事務被回滾掉,想出錯後控制還返回給程序,能夠用 PG_TRYPG_CATCHPG_END_TRY 幾個宏來通知 ereport 將控制返回給程序,同時用一個子事務把對 SPI 的調用包起來,參考 PL/Python 源代碼 plpy_spi.c 中,PLy_spi_subtransaction_<begin/commit/abort> 等方法的處理。

這也是由於 PostgreSQL 是用 C 語言開發的,一個不夠強的地方。假如未來用 Rust 重寫,

相關文章
相關標籤/搜索