| PostgreSQL 7.4 文檔 | ||||
|---|---|---|---|---|
| Prev | Fast Backward | Chapter 45. PostgreSQL 源代碼 | Fast Forward | Next |
在服務器代碼裡生成的錯誤,警告以及日志信息應該用 ereport,或者它的老前輩 elog 創建。 這個函數的使用已經復雜得足夠我們做些解釋了。
每條消息都有兩個必須的要素:一個嚴重級別(範圍從 DEBUG 到 PANIC)和一個主要消息文本。 除此之外還有可選的元素,最常見的就是一個遵循 SQL 標準的 SQLSTATE 習慣的錯誤標識碼。 ereport 本身只是一個殼函數,它的存在主要是為了便于讓消息生成看起來像 C 代碼裡的函數調用。 ereport 直接接受的唯一參數是嚴重級別。 主消息文本和任何附加消息元素都是通過在 ereport 調用裡調用輔助函數,比如 errmsg,生成的。
典型的調用 ereport 的方式看起來可能像下面這樣:
ereport(ERROR,
(errcode(ERRCODE_DIVISION_BY_ZERO),
errmsg("division by zero")));這樣就聲明了嚴重級別 ERROR (一個錯誤)。 調用 errcode 則使用一個定義在 src/include/utils/errcodes.h 裡面的宏聲明 SQLSTATE 錯誤代碼。 errmsg 調用提供主要的消息文本。請注意額外的圓括弧包圍在輔助函數調用週圍 ── 這麼做雖然煩人,但是與法上是必須的。
然後是一個更復雜的例子:
ereport(ERROR,
(errcode(ERRCODE_AMBIGUOUS_FUNCTION),
errmsg("function %s is not unique",
func_signature_string(funcname, nargs,
actual_arg_types)),
errhint("Unable to choose a best candidate function. "
"You may need to add explicit typecasts.")));這個例子演示了使用格式化代碼把運行時數值嵌入一個消息文本的用法。 同樣,還提供了一個可選的"暗示"信息。
ereport 可用的附屬過程有:
errcode(sqlerrcode) 為該條件聲明 SQLSTATE 錯誤標識符代碼。 如果沒有調用這個過程,並且錯誤嚴重級別是 ERROR 或更高,那麼錯誤標識符缺省是 ERRCODE_INTERNAL_ERROR, 如果錯誤嚴重級別是 WARNING,則為 ERRCODE_WARNING, 否則(用于 NOTICE 或者更低級別)為 ERRCODE_SUCCESSFUL_COMPLETION。 雖然這些缺省都很方便,但是最好還是在省略 errcode() 調用之前三思。
errmsg(const char *msg, ...) 聲明主錯誤消息文本,以及可能的插入其中的運行時數值。 插入是使用 sprintf 風格的格式代碼插入的。 除了 sprintf 接受的標準格式代碼,還接受 %m 用于插入 strerror 為當前 errno 值返回的錯誤信息。 [1] %m 並不要求在 errmsg 的參數列表裡有任何對應的項目。 請注意這個消息字串在格式代碼得到處理之前將不會通過 gettext 運行獲取合適的本地化。
errmsg_internal(const char *msg, ...) 和 errmsg 一樣, 只是消息字串將不會包含在國際化消息字典裡。 這個函數應該用于"不可能發生"的情況,也就是不值得展開進行翻譯的場合。
errdetail(const char *msg, ...) 提供一個可選的"詳細"信息; 在存在額外的的信息,並且很適合放在主消息裡面的時候使用這個函數。 消息字串處理的方法和 errmsg 完全一樣。
errhint(const char *msg, ...) 提供一個可選的"暗示"消息; 這個函數用于提供如何修補問題的建議,而不是提供錯誤的事實。 消息字串處理的方式和 errmsg 一樣。
errcontext(const char *msg, ...) 通常不會直接從 ereport 消息點裡直接調用; 而是用在 error_context_stack 回調函數裡提供有關錯誤發生的環境的信息, 比如,當前的位置是在一個 PL 函數裡等等。 消息字串的處理和 errmsg 完全一樣。 和其它輔助函數不同,這個函數在一次 ereport 調用裡可以調用多次; 隨後的調用生成的字串將帶著各自的換行符連接在原來的字串上。
errposition(int cursorpos) 聲明一個錯誤在查詢字串裡的文本位置。 目前它只是在匯報查詢處理過程中的詞法和語法分析階段檢測到的錯誤有用。
errcode_for_file_access() 是一個便利函數,它可以為一個文件訪問類的系統調用選擇一個合適的 SQLSTATE 錯誤標識符。 它利用保存下來的 errno 判斷生成哪個錯誤代碼。 通常它應該和主消息文本裡的 %m 結合使用。
errcode_for_socket_access() 是一個便利函數,它可以為一個套接字相關的系統調用選擇一個合適的 SQLSTATE 錯誤標識符。
還有一個老一些的 elog 函數,仍然在頻繁使用。 一個 elog 調用
elog(level, "format string", ...);
完全等效于
ereport(level, (errmsg_internal("format string", ...)));請注意 SQLSTATE 錯誤代碼總是缺省的,並且消息字串並沒有包含在國際化信息字典裡。 因此,elog 應該只用于內部錯誤以及低層的調試日志。 任何普通用戶感興趣的消息都應該通過 ereport 生成。 當然,還有大量內部的"不可能發生"的錯誤檢查使用 elog; 因為這些信息最好還是表示得簡單些好。
書寫好的錯誤消息的建議可以在 Section 45.3 找到。
| [1] | 也就是說,在到達 ereport 調用的時候當前的數值; 在附屬報告過程裡對 errno 的修改將不會影響他。 但是如果你在 errmsg 的參數列表裡明確地寫 strerror(errno), 這一點就不能保證了,因此,請不要這麼做。 |