Postgresql 中文操作指南

56.3. Error Message Style Guide #

提供此风格指南,旨在使 PostgreSQL 生成的所有消息始终保持一致、对用户友好。

This style guide is offered in the hope of maintaining a consistent, user-friendly style throughout all the messages generated by PostgreSQL.

What Goes Where #

主要消息应简短、真实,并避免提及实现细节,例如特定函数名称。“简短”意味着“在正常情况下应放在一行上”。在需要时使用详细消息来保持主要消息简短,或者如果你觉得需要提及实现细节,例如失败的特定系统调用。主要消息和详细消息都必须真实。对于如何解决问题提出建议,请使用提示消息,尤其是此建议可能并不总是适用的情况下。

The primary message should be short, factual, and avoid reference to implementation details such as specific function names. “Short” means “should fit on one line under normal conditions”. Use a detail message if needed to keep the primary message short, or if you feel a need to mention implementation details such as the particular system call that failed. Both primary and detail messages should be factual. Use a hint message for suggestions about what to do to fix the problem, especially if the suggestion might not always be applicable.

例如,不要以下面的方式编写:

For example, instead of:

IpcMemoryCreate: shmget(key=%d, size=%u, 0%o) failed: %m
(plus a long addendum that is basically a hint)

应如下编写:

write:

Primary:    could not create shared memory segment: %m
Detail:     Failed syscall was shmget(key=%d, size=%u, 0%o).
Hint:       the addendum

基本原理:保持主要消息简短有助于切中要点,并让客户端在假定一行足以容纳错误消息的情况下布局屏幕空间。可以将详细消息和提示消息降级为冗余模式,或者可能是弹出错误详细信息窗口。此外,通常会从服务器日志中取消显示详细信息和提示,以节省空间。最好避免提及实现细节,因为用户不需要了解这些细节。

Rationale: keeping the primary message short helps keep it to the point, and lets clients lay out screen space on the assumption that one line is enough for error messages. Detail and hint messages can be relegated to a verbose mode, or perhaps a pop-up error-details window. Also, details and hints would normally be suppressed from the server log to save space. Reference to implementation details is best avoided since users aren’t expected to know the details.

Formatting #

不要在消息文本中放入任何有关格式化的特定假设。预计客户端和服务器日志将换行以满足它们自己的需要。在长消息中,换行符 (\n) 可用于指示建议的段落断行。不要以换行符结束消息。不要使用制表符或其他格式化字符。(在错误上下文中显示时,将自动换行来区分上下文的层次,例如函数调用。)

Don’t put any specific assumptions about formatting into the message texts. Expect clients and the server log to wrap lines to fit their own needs. In long messages, newline characters (\n) can be used to indicate suggested paragraph breaks. Don’t end a message with a newline. Don’t use tabs or other formatting characters. (In error context displays, newlines are automatically added to separate levels of context such as function calls.)

基本原理:消息不一定显示在终端类型显示设备上。在 GUI 显示设备或浏览器中,这些格式化说明充其量会被忽略。

Rationale: Messages are not necessarily displayed on terminal-type displays. In GUI displays or browsers these formatting instructions are at best ignored.

Quotation Marks #

当引用适合时,英文文本应使用双引号。其他语言中的文本应始终使用一种引用,该引用与出版习惯和计算机中其他程序的文本输出一致。

English text should use double quotes when quoting is appropriate. Text in other languages should consistently use one kind of quotes that is consistent with publishing customs and computer output of other programs.

基本原理:选择双引号而非单引号在一定程度上是任意的,但往往更偏好使用双引号。有人建议根据 SQL 约定(即,单引号引用的字符串、双引号引用的标识符)选择引号类型,具体取决于对象类型。但这是一种语言内部技术问题,许多用户甚至不了解,它不能扩展到其他类型的带引号术语,也不能转换为其他语言,而且也没有什么意义。

Rationale: The choice of double quotes over single quotes is somewhat arbitrary, but tends to be the preferred use. Some have suggested choosing the kind of quotes depending on the type of object according to SQL conventions (namely, strings single quoted, identifiers double quoted). But this is a language-internal technical issue that many users aren’t even familiar with, it won’t scale to other kinds of quoted terms, it doesn’t translate to other languages, and it’s pretty pointless, too.

Use of Quotes #

始终使用引号来分隔文件名、用户提供的标识符和其他可能包含单词的变量。不要使用它们来标记不会包含单词的变量(例如,运算符名称)。

Always use quotes to delimit file names, user-supplied identifiers, and other variables that might contain words. Do not use them to mark up variables that will not contain words (for example, operator names).

后端有函数会根据需要对其自己的输出加上双引号(例如 format_type_be())。不要在这些函数的输出周围加上其他引号。

There are functions in the backend that will double-quote their own output as needed (for example, format_type_be()). Do not put additional quotes around the output of such functions.

基本原理:对象可以具有在嵌入到消息中时会产生歧义的名称。始终一致地表示插入名称的开始和结束位置。但不要用不必要或重复的引号使消息变得杂乱。

Rationale: Objects can have names that create ambiguity when embedded in a message. Be consistent about denoting where a plugged-in name starts and ends. But don’t clutter messages with unnecessary or duplicate quote marks.

Grammar and Punctuation #

主要错误消息和详细/提示消息的规则不同:

The rules are different for primary error messages and for detail/hint messages:

主要错误消息:不要大写第一个字母。不要以句号结束消息。甚至不要考虑以感叹号结束消息。

Primary error messages: Do not capitalize the first letter. Do not end a message with a period. Do not even think about ending a message with an exclamation point.

详细消息和提示消息:使用完整的句子,并以句号结束每个句子。大写句子的第一个单词。如果后面还有另一个句子,则在句号后加两个空格(对于英文;在其他语言中可能不合适)。

Detail and hint messages: Use complete sentences, and end each with a period. Capitalize the first word of sentences. Put two spaces after the period if another sentence follows (for English text; might be inappropriate in other languages).

错误上下文字符串:不要对第一个字母大写,也不要以句号结束字符串。上下文字符串通常不应是完整句子。

Error context strings: Do not capitalize the first letter and do not end the string with a period. Context strings should normally not be complete sentences.

基本原理:避免标点符号可以让客户端应用程序更容易将消息嵌入到各种语法环境中。通常,主要消息本身并不是语法完整的句子。(并且如果它们足够长以超过一个句子,则应将它们拆分为主要部分和详细部分。)但是,详情和提示消息更长,可能需要包括多个句子。为了保持一致性,即使只有一句话,也应遵循完整的句子样式。

Rationale: Avoiding punctuation makes it easier for client applications to embed the message into a variety of grammatical contexts. Often, primary messages are not grammatically complete sentences anyway. (And if they’re long enough to be more than one sentence, they should be split into primary and detail parts.) However, detail and hint messages are longer and might need to include multiple sentences. For consistency, they should follow complete-sentence style even when there’s only one sentence.

Upper Case vs. Lower Case #

对于消息措辞使用小写,包括主要错误消息的第一个字母。如果消息中出现 SQL 命令和关键字,则使用大写。

Use lower case for message wording, including the first letter of a primary error message. Use upper case for SQL commands and key words if they appear in the message.

基本原理:这样可以更容易地使所有内容看起来更加一致,因为有些消息是完整的句子,而有些不是。

Rationale: It’s easier to make everything look more consistent this way, since some messages are complete sentences and some not.

Avoid Passive Voice #

使用主动语态。如果有作用主语,则使用完整句子(“A 无法执行 B”)。如果主语是程序本身,则使用不带主语的电报样式;不要为程序使用“I”。

Use the active voice. Use complete sentences when there is an acting subject (“A could not do B”). Use telegram style without subject if the subject would be the program itself; do not use “I” for the program.

基本原理:该程序不是人类。不要假装它不是。

Rationale: The program is not human. Don’t pretend otherwise.

Present vs. Past Tense #

如果尝试做某事失败,但可能在下次成功(也许在修复某些问题后),则使用过去时。如果失败是肯定永久性的,则使用现在时。

Use past tense if an attempt to do something failed, but could perhaps succeed next time (perhaps after fixing some problem). Use present tense if the failure is certainly permanent.

以下形式的句子之间有非平凡的语义差异:

There is a nontrivial semantic difference between sentences of the form:

could not open file "%s": %m

及:

and:

cannot open file "%s"

第一个句子表示打开文件失败。消息应给出原因,例如“磁盘已满”或“文件不存在”。过去时是合适的,因为下次磁盘可能不再满了或可能存在该文件。

The first one means that the attempt to open the file failed. The message should give a reason, such as “disk full” or “file doesn’t exist”. The past tense is appropriate because next time the disk might not be full anymore or the file in question might exist.

第二种形式表示在程序中根本不存在打开指定文件的功能,或者在概念上这是不可能的。现在时是合适的,因为该条件会无限期地持续下去。

The second form indicates that the functionality of opening the named file does not exist at all in the program, or that it’s conceptually impossible. The present tense is appropriate because the condition will persist indefinitely.

基本原理:确实,普通用户将无法仅从消息的时态中得出确定的结论,但既然语言向我们提供了语法,我们就应该正确使用它。

Rationale: Granted, the average user will not be able to draw great conclusions merely from the tense of the message, but since the language provides us with a grammar we should use it correctly.

Type of the Object #

在引用对象名称时,请说明它是什么类型的对象。

When citing the name of an object, state what kind of object it is.

基本原理:否则,没有人知道“foo.bar.baz”指的是什么。

Rationale: Otherwise no one will know what “foo.bar.baz” refers to.

Brackets #

方括号仅用于 (1) 在命令概要中表示可选参数,或 (2) 表示数组下标。

Square brackets are only to be used (1) in command synopses to denote optional arguments, or (2) to denote an array subscript.

基本原理:其他任何内容都不符合广为人知的惯例用法,只会让人困惑。

Rationale: Anything else does not correspond to widely-known customary usage and will confuse people.

Assembling Error Messages #

当消息包含在其他地方生成文本时,请使用以下样式嵌入它:

When a message includes text that is generated elsewhere, embed it in this style:

could not open file %s: %m

基本原理:很难考虑所有可能的错误代码才能将此粘贴到一个平滑的句子中,因此需要某种标点符号。也有人建议将嵌入文本放在括号中,但如果嵌入文本很可能是消息中最重要的一部分,就像通常的情况一样,那就显得不自然。

Rationale: It would be difficult to account for all possible error codes to paste this into a single smooth sentence, so some sort of punctuation is needed. Putting the embedded text in parentheses has also been suggested, but it’s unnatural if the embedded text is likely to be the most important part of the message, as is often the case.

Reasons for Errors #

消息应始终说明错误发生的原因。例如:

Messages should always state the reason why an error occurred. For example:

BAD:    could not open file %s
BETTER: could not open file %s (I/O failure)

如果没有已知原因,则您最好修复该代码。

If no reason is known you better fix the code.

Function Names #

在错误文本中不要包含报告例程的名称。我们有其他机制可以在需要时找出该名称,对于大多数用户来说,这不是有用的信息。如果在没有函数名称的情况下错误文本没有多大意义,请重新表述。

Don’t include the name of the reporting routine in the error text. We have other mechanisms for finding that out when needed, and for most users it’s not helpful information. If the error text doesn’t make as much sense without the function name, reword it.

BAD:    pg_strtoint32: error in "z": cannot parse "z"
BETTER: invalid input syntax for type integer: "z"

同样,避免提及已调用的函数名称;相反,说明代码试图做什么:

Avoid mentioning called function names, either; instead say what the code was trying to do:

BAD:    open() failed: %m
BETTER: could not open file %s: %m

如果真的有必要,请在详细信息中提及系统调用。(在某些情况下,向详细信息中提供传递给系统调用的实际值可能是适当的信息。)

If it really seems necessary, mention the system call in the detail message. (In some cases, providing the actual values passed to the system call might be appropriate information for the detail message.)

理由:用户不知道所有这些函数的作用。

Rationale: Users don’t know what all those functions do.

Tricky Words to Avoid #

*Unable. * “Unable” 近似于被动语态。在适当的情况下,更好使用 “cannot” 或 “could not”。

*Unable. * “Unable” is nearly the passive voice. Better use “cannot” or “could not”, as appropriate.

*Bad. * 像“bad result”这样的错误消息很难从语法上进行合理解释。最好写出为何结果“bad”,例如“invalid format”。

*Bad. * Error messages like “bad result” are really hard to interpret intelligently. It’s better to write why the result is “bad”, e.g., “invalid format”.

*Illegal. * “Illegal”代表违法,其他情况则是“invalid”。更好的做法是,说明为何无效。

*Illegal. * “Illegal” stands for a violation of the law, the rest is “invalid”. Better yet, say why it’s invalid.

*Unknown. * 尽量避免使用“unknown”。考虑“error: unknown response”。如果您不知道响应是什么,您怎么知道响应是错误的?“Unrecognized”通常是更好的选择。此外,务必包括引起抱怨的值。

*Unknown. * Try to avoid “unknown”. Consider “error: unknown response”. If you don’t know what the response is, how do you know it’s erroneous? “Unrecognized” is often a better choice. Also, be sure to include the value being complained of.

BAD:    unknown node type
BETTER: unrecognized node type: 42

*Find vs. Exists. * 如果程序使用非平凡的算法来查找资源(例如,路径搜索)并且该算法失败,则可以说程序无法“找到”该资源。另一方面,如果资源的预期位置已知,但程序无法在那里访问该资源,则可以说该资源“不存在”。在这种情况下,使用“find”听起来很无力,并且会导致混淆。

*Find vs. Exists. * If the program uses a nontrivial algorithm to locate a resource (e.g., a path search) and that algorithm fails, it is fair to say that the program couldn’t “find” the resource. If, on the other hand, the expected location of the resource is known but the program cannot access it there then say that the resource doesn’t “exist”. Using “find” in this case sounds weak and confuses the issue.

*May vs. Can vs. Might. * “May”表示许可(例如,“You may borrow my rake.”),在文档或错误消息中很少使用。“Can”表示能力(例如,“I can lift that log.”),而“might”表示可能性(例如,“It might rain today.”)。使用正确的单词可以阐明含义并协助翻译。

*May vs. Can vs. Might. * “May” suggests permission (e.g., "You may borrow my rake."), and has little use in documentation or error messages. “Can” suggests ability (e.g., "I can lift that log."), and “might” suggests possibility (e.g., "It might rain today."). Using the proper word clarifies meaning and assists translation.

*Contractions. * 避免使用缩写,例如“can’t”;而应改为使用“cannot”。

*Contractions. * Avoid contractions, like “can’t”; use “cannot” instead.

*Non-negative. * 避免使用“non-negative”,因为对于它是否接受零,它不够明确。最好使用“greater than zero”或“greater than or equal to zero”。

*Non-negative. * Avoid “non-negative” as it is ambiguous about whether it accepts zero. It’s better to use “greater than zero” or “greater than or equal to zero”.

Proper Spelling #

将单词完整地拼写出来。例如,避免:

Spell out words in full. For instance, avoid:

理由:这将提高一致性。

Rationale: This will improve consistency.

Localization #

请记住,错误消息文本需要翻译成其他语言。按照 Section 57.2.2中的指南进行操作,以免给翻译人员带来困难。

Keep in mind that error message texts need to be translated into other languages. Follow the guidelines in Section 57.2.2 to avoid making life difficult for translators.