public inbox for [email protected]  
help / color / mirror / Atom feed
Add missing period to DETAIL messages
12+ messages / 5 participants
[nested] [flat]

* Add missing period to DETAIL messages
@ 2026-04-09 04:27  Peter Smith <[email protected]>
  0 siblings, 1 reply; 12+ messages in thread

From: Peter Smith @ 2026-04-09 04:27 UTC (permalink / raw)
  To: PostgreSQL Hackers <[email protected]>

Hi,

According to the error message style guide [1] "Detail and hint
messages: Use complete sentences, and end each with a period."

I found some DETAIL messages not following that period rule.

PSA a patch that fixes the missing period. In passing, I also fixed
some capitalization.

======
[1] https://www.postgresql.org/docs/devel/error-style-guide.html#ERROR-STYLE-GUIDE-GRAMMAR-PUNCTUATION

Kind Regards,
Peter Smith.
Fujitsu Australia


Attachments:

  [application/octet-stream] v1-0001-Add-missing-period-to-DETAIL-messages.patch (28.8K, 2-v1-0001-Add-missing-period-to-DETAIL-messages.patch)
  download | inline diff:
From 2df76239d028340359a073741c0924deaed4c40e Mon Sep 17 00:00:00 2001
From: Peter Smith <[email protected]>
Date: Thu, 9 Apr 2026 14:21:40 +1000
Subject: [PATCH v1] Add missing period to DETAIL messages

---
 contrib/cube/cubescan.l                       |  4 +-
 contrib/cube/expected/cube.out                | 46 +++++++++----------
 contrib/dblink/dblink.c                       |  2 +-
 .../passwordcheck/expected/passwordcheck.out  |  2 +-
 contrib/passwordcheck/passwordcheck.c         |  2 +-
 .../postgres_fdw/expected/postgres_fdw.out    |  2 +-
 contrib/seg/expected/seg.out                  | 32 ++++++-------
 contrib/seg/segscan.l                         |  4 +-
 src/backend/commands/copyto.c                 |  2 +-
 src/backend/commands/extension.c              |  2 +-
 src/backend/commands/tablecmds.c              | 10 ++--
 src/backend/libpq/be-secure-openssl.c         |  2 +-
 src/backend/partitioning/partbounds.c         |  4 +-
 .../expected/test_extensions.out              |  2 +-
 src/test/regress/expected/create_view.out     |  2 +-
 src/test/regress/expected/partition_merge.out |  4 +-
 src/test/regress/expected/partition_split.out | 10 ++--
 src/test/regress/expected/rangefuncs.out      |  2 +-
 18 files changed, 67 insertions(+), 67 deletions(-)

diff --git a/contrib/cube/cubescan.l b/contrib/cube/cubescan.l
index e2806dc288f..286efce23aa 100644
--- a/contrib/cube/cubescan.l
+++ b/contrib/cube/cubescan.l
@@ -82,7 +82,7 @@ cube_yyerror(NDBOX **result, Size scanbuflen,
 				(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 				 errmsg("invalid input syntax for cube"),
 		/* translator: %s is typically "syntax error" */
-				 errdetail("%s at end of input", message)));
+				 errdetail("%s at end of input.", message)));
 	}
 	else
 	{
@@ -90,7 +90,7 @@ cube_yyerror(NDBOX **result, Size scanbuflen,
 				(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 				 errmsg("invalid input syntax for cube"),
 		/* translator: first %s is typically "syntax error" */
-				 errdetail("%s at or near \"%s\"", message, yytext)));
+				 errdetail("%s at or near \"%s\".", message, yytext)));
 	}
 }
 
diff --git a/contrib/cube/expected/cube.out b/contrib/cube/expected/cube.out
index 47787c50bd9..f685e0acce5 100644
--- a/contrib/cube/expected/cube.out
+++ b/contrib/cube/expected/cube.out
@@ -189,78 +189,78 @@ SELECT ''::cube AS cube;
 ERROR:  invalid input syntax for cube
 LINE 1: SELECT ''::cube AS cube;
                ^
-DETAIL:  syntax error at end of input
+DETAIL:  syntax error at end of input.
 SELECT 'ABC'::cube AS cube;
 ERROR:  invalid input syntax for cube
 LINE 1: SELECT 'ABC'::cube AS cube;
                ^
-DETAIL:  syntax error at or near "A"
+DETAIL:  syntax error at or near "A".
 SELECT '[]'::cube AS cube;
 ERROR:  invalid input syntax for cube
 LINE 1: SELECT '[]'::cube AS cube;
                ^
-DETAIL:  syntax error at or near "]"
+DETAIL:  syntax error at or near "]".
 SELECT '[()]'::cube AS cube;
 ERROR:  invalid input syntax for cube
 LINE 1: SELECT '[()]'::cube AS cube;
                ^
-DETAIL:  syntax error at or near "]"
+DETAIL:  syntax error at or near "]".
 SELECT '[(1)]'::cube AS cube;
 ERROR:  invalid input syntax for cube
 LINE 1: SELECT '[(1)]'::cube AS cube;
                ^
-DETAIL:  syntax error at or near "]"
+DETAIL:  syntax error at or near "]".
 SELECT '[(1),]'::cube AS cube;
 ERROR:  invalid input syntax for cube
 LINE 1: SELECT '[(1),]'::cube AS cube;
                ^
-DETAIL:  syntax error at or near "]"
+DETAIL:  syntax error at or near "]".
 SELECT '[(1),2]'::cube AS cube;
 ERROR:  invalid input syntax for cube
 LINE 1: SELECT '[(1),2]'::cube AS cube;
                ^
-DETAIL:  syntax error at or near "2"
+DETAIL:  syntax error at or near "2".
 SELECT '[(1),(2),(3)]'::cube AS cube;
 ERROR:  invalid input syntax for cube
 LINE 1: SELECT '[(1),(2),(3)]'::cube AS cube;
                ^
-DETAIL:  syntax error at or near ","
+DETAIL:  syntax error at or near ",".
 SELECT '1,'::cube AS cube;
 ERROR:  invalid input syntax for cube
 LINE 1: SELECT '1,'::cube AS cube;
                ^
-DETAIL:  syntax error at end of input
+DETAIL:  syntax error at end of input.
 SELECT '1,2,'::cube AS cube;
 ERROR:  invalid input syntax for cube
 LINE 1: SELECT '1,2,'::cube AS cube;
                ^
-DETAIL:  syntax error at end of input
+DETAIL:  syntax error at end of input.
 SELECT '1,,2'::cube AS cube;
 ERROR:  invalid input syntax for cube
 LINE 1: SELECT '1,,2'::cube AS cube;
                ^
-DETAIL:  syntax error at or near ","
+DETAIL:  syntax error at or near ",".
 SELECT '(1,)'::cube AS cube;
 ERROR:  invalid input syntax for cube
 LINE 1: SELECT '(1,)'::cube AS cube;
                ^
-DETAIL:  syntax error at or near ")"
+DETAIL:  syntax error at or near ")".
 SELECT '(1,2,)'::cube AS cube;
 ERROR:  invalid input syntax for cube
 LINE 1: SELECT '(1,2,)'::cube AS cube;
                ^
-DETAIL:  syntax error at or near ")"
+DETAIL:  syntax error at or near ")".
 SELECT '(1,,2)'::cube AS cube;
 ERROR:  invalid input syntax for cube
 LINE 1: SELECT '(1,,2)'::cube AS cube;
                ^
-DETAIL:  syntax error at or near ","
+DETAIL:  syntax error at or near ",".
 -- invalid input: semantic errors and trailing garbage
 SELECT '[(1),(2)],'::cube AS cube; -- 0
 ERROR:  invalid input syntax for cube
 LINE 1: SELECT '[(1),(2)],'::cube AS cube;
                ^
-DETAIL:  syntax error at or near ","
+DETAIL:  syntax error at or near ",".
 SELECT '[(1,2,3),(2,3)]'::cube AS cube; -- 1
 ERROR:  invalid input syntax for cube
 LINE 1: SELECT '[(1,2,3),(2,3)]'::cube AS cube;
@@ -275,7 +275,7 @@ SELECT '(1),(2),'::cube AS cube; -- 2
 ERROR:  invalid input syntax for cube
 LINE 1: SELECT '(1),(2),'::cube AS cube;
                ^
-DETAIL:  syntax error at or near ","
+DETAIL:  syntax error at or near ",".
 SELECT '(1,2,3),(2,3)'::cube AS cube; -- 3
 ERROR:  invalid input syntax for cube
 LINE 1: SELECT '(1,2,3),(2,3)'::cube AS cube;
@@ -290,37 +290,37 @@ SELECT '(1,2,3)ab'::cube AS cube; -- 4
 ERROR:  invalid input syntax for cube
 LINE 1: SELECT '(1,2,3)ab'::cube AS cube;
                ^
-DETAIL:  syntax error at or near "a"
+DETAIL:  syntax error at or near "a".
 SELECT '(1,2,3)a'::cube AS cube; -- 5
 ERROR:  invalid input syntax for cube
 LINE 1: SELECT '(1,2,3)a'::cube AS cube;
                ^
-DETAIL:  syntax error at or near "a"
+DETAIL:  syntax error at or near "a".
 SELECT '(1,2)('::cube AS cube; -- 5
 ERROR:  invalid input syntax for cube
 LINE 1: SELECT '(1,2)('::cube AS cube;
                ^
-DETAIL:  syntax error at or near "("
+DETAIL:  syntax error at or near "(".
 SELECT '1,2ab'::cube AS cube; -- 6
 ERROR:  invalid input syntax for cube
 LINE 1: SELECT '1,2ab'::cube AS cube;
                ^
-DETAIL:  syntax error at or near "a"
+DETAIL:  syntax error at or near "a".
 SELECT '1 e7'::cube AS cube; -- 6
 ERROR:  invalid input syntax for cube
 LINE 1: SELECT '1 e7'::cube AS cube;
                ^
-DETAIL:  syntax error at or near "e"
+DETAIL:  syntax error at or near "e".
 SELECT '1,2a'::cube AS cube; -- 7
 ERROR:  invalid input syntax for cube
 LINE 1: SELECT '1,2a'::cube AS cube;
                ^
-DETAIL:  syntax error at or near "a"
+DETAIL:  syntax error at or near "a".
 SELECT '1..2'::cube AS cube; -- 7
 ERROR:  invalid input syntax for cube
 LINE 1: SELECT '1..2'::cube AS cube;
                ^
-DETAIL:  syntax error at or near ".2"
+DETAIL:  syntax error at or near ".2".
 SELECT '-1e-700'::cube AS cube; -- out of range
 ERROR:  "-1e-700" is out of range for type double precision
 LINE 1: SELECT '-1e-700'::cube AS cube;
diff --git a/contrib/dblink/dblink.c b/contrib/dblink/dblink.c
index 9798cb535bc..2113aa41333 100644
--- a/contrib/dblink/dblink.c
+++ b/contrib/dblink/dblink.c
@@ -2710,7 +2710,7 @@ dblink_security_check(PGconn *conn, const char *connname, const char *connstr)
 	ereport(ERROR,
 			(errcode(ERRCODE_S_R_E_PROHIBITED_SQL_STATEMENT_ATTEMPTED),
 			 errmsg("password or GSSAPI delegated credentials required"),
-			 errdetail("Non-superusers may only connect using credentials they provide, eg: password in connection string or delegated GSSAPI credentials"),
+			 errdetail("Non-superusers may only connect using credentials they provide, eg: password in connection string or delegated GSSAPI credentials."),
 			 errhint("Ensure provided credentials match target server's authentication method.")));
 }
 
diff --git a/contrib/passwordcheck/expected/passwordcheck.out b/contrib/passwordcheck/expected/passwordcheck.out
index 83472c76d27..ef524837ca9 100644
--- a/contrib/passwordcheck/expected/passwordcheck.out
+++ b/contrib/passwordcheck/expected/passwordcheck.out
@@ -6,7 +6,7 @@ ALTER USER regress_passwordcheck_user1 PASSWORD 'a_nice_long_password';
 -- error: too short
 ALTER USER regress_passwordcheck_user1 PASSWORD 'tooshrt';
 ERROR:  password is too short
-DETAIL:  password must be at least "passwordcheck.min_password_length" (8) bytes long
+DETAIL:  password must be at least "passwordcheck.min_password_length" (8) bytes long.
 -- ok
 SET passwordcheck.min_password_length = 6;
 ALTER USER regress_passwordcheck_user1 PASSWORD 'v_shrt';
diff --git a/contrib/passwordcheck/passwordcheck.c b/contrib/passwordcheck/passwordcheck.c
index 13fd5c976a0..94f4d535539 100644
--- a/contrib/passwordcheck/passwordcheck.c
+++ b/contrib/passwordcheck/passwordcheck.c
@@ -101,7 +101,7 @@ check_password(const char *username,
 			ereport(ERROR,
 					(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
 					 errmsg("password is too short"),
-					 errdetail("password must be at least \"passwordcheck.min_password_length\" (%d) bytes long",
+					 errdetail("password must be at least \"passwordcheck.min_password_length\" (%d) bytes long.",
 							   min_password_length)));
 
 		/* check if the password contains the username */
diff --git a/contrib/postgres_fdw/expected/postgres_fdw.out b/contrib/postgres_fdw/expected/postgres_fdw.out
index cd22553236f..09340988dab 100644
--- a/contrib/postgres_fdw/expected/postgres_fdw.out
+++ b/contrib/postgres_fdw/expected/postgres_fdw.out
@@ -11664,7 +11664,7 @@ DELETE FROM result_tbl;
 -- Test COPY TO when foreign table is partition
 COPY async_pt TO stdout; --error
 ERROR:  cannot copy from foreign table "async_p1"
-DETAIL:  Partition "async_p1" is a foreign table in partitioned table "async_pt"
+DETAIL:  Partition "async_p1" is a foreign table in partitioned table "async_pt".
 HINT:  Try the COPY (SELECT ...) TO variant.
 DROP FOREIGN TABLE async_p3;
 DROP TABLE base_tbl3;
diff --git a/contrib/seg/expected/seg.out b/contrib/seg/expected/seg.out
index cd21139b5a7..b9fbf23c0f1 100644
--- a/contrib/seg/expected/seg.out
+++ b/contrib/seg/expected/seg.out
@@ -405,42 +405,42 @@ SELECT ''::seg AS seg;
 ERROR:  bad seg representation
 LINE 1: SELECT ''::seg AS seg;
                ^
-DETAIL:  syntax error at end of input
+DETAIL:  syntax error at end of input.
 SELECT 'ABC'::seg AS seg;
 ERROR:  bad seg representation
 LINE 1: SELECT 'ABC'::seg AS seg;
                ^
-DETAIL:  syntax error at or near "A"
+DETAIL:  syntax error at or near "A".
 SELECT '1ABC'::seg AS seg;
 ERROR:  bad seg representation
 LINE 1: SELECT '1ABC'::seg AS seg;
                ^
-DETAIL:  syntax error at or near "A"
+DETAIL:  syntax error at or near "A".
 SELECT '1.'::seg AS seg;
 ERROR:  bad seg representation
 LINE 1: SELECT '1.'::seg AS seg;
                ^
-DETAIL:  syntax error at or near "."
+DETAIL:  syntax error at or near ".".
 SELECT '1.....'::seg AS seg;
 ERROR:  bad seg representation
 LINE 1: SELECT '1.....'::seg AS seg;
                ^
-DETAIL:  syntax error at or near ".."
+DETAIL:  syntax error at or near "..".
 SELECT '.1'::seg AS seg;
 ERROR:  bad seg representation
 LINE 1: SELECT '.1'::seg AS seg;
                ^
-DETAIL:  syntax error at or near "."
+DETAIL:  syntax error at or near ".".
 SELECT '1..2.'::seg AS seg;
 ERROR:  bad seg representation
 LINE 1: SELECT '1..2.'::seg AS seg;
                ^
-DETAIL:  syntax error at or near "."
+DETAIL:  syntax error at or near ".".
 SELECT '1 e7'::seg AS seg;
 ERROR:  bad seg representation
 LINE 1: SELECT '1 e7'::seg AS seg;
                ^
-DETAIL:  syntax error at or near "e"
+DETAIL:  syntax error at or near "e".
 SELECT '1e700'::seg AS seg;
 ERROR:  "1e700" is out of range for type real
 LINE 1: SELECT '1e700'::seg AS seg;
@@ -1287,13 +1287,13 @@ FROM unnest(ARRAY['-1 .. 1'::text,
                   '1 e7',
                   '1e700']) str,
      LATERAL pg_input_error_info(str, 'seg') as errinfo;
-   seg    | ok | sql_error_code |                message                |            detail            | hint 
-----------+----+----------------+---------------------------------------+------------------------------+------
- -1 .. 1  | t  |                |                                       |                              | 
- 100(+-)1 | t  |                |                                       |                              | 
-          | f  | 42601          | bad seg representation                | syntax error at end of input | 
- ABC      | f  | 42601          | bad seg representation                | syntax error at or near "A"  | 
- 1 e7     | f  | 42601          | bad seg representation                | syntax error at or near "e"  | 
- 1e700    | f  | 22003          | "1e700" is out of range for type real |                              | 
+   seg    | ok | sql_error_code |                message                |            detail             | hint 
+----------+----+----------------+---------------------------------------+-------------------------------+------
+ -1 .. 1  | t  |                |                                       |                               | 
+ 100(+-)1 | t  |                |                                       |                               | 
+          | f  | 42601          | bad seg representation                | syntax error at end of input. | 
+ ABC      | f  | 42601          | bad seg representation                | syntax error at or near "A".  | 
+ 1 e7     | f  | 42601          | bad seg representation                | syntax error at or near "e".  | 
+ 1e700    | f  | 22003          | "1e700" is out of range for type real |                               | 
 (6 rows)
 
diff --git a/contrib/seg/segscan.l b/contrib/seg/segscan.l
index 3a0cd7ed506..18558688765 100644
--- a/contrib/seg/segscan.l
+++ b/contrib/seg/segscan.l
@@ -79,7 +79,7 @@ seg_yyerror(SEG *result, struct Node *escontext, yyscan_t yyscanner, const char
 				(errcode(ERRCODE_SYNTAX_ERROR),
 				 errmsg("bad seg representation"),
 		/* translator: %s is typically "syntax error" */
-				 errdetail("%s at end of input", message)));
+				 errdetail("%s at end of input.", message)));
 	}
 	else
 	{
@@ -87,7 +87,7 @@ seg_yyerror(SEG *result, struct Node *escontext, yyscan_t yyscanner, const char
 				(errcode(ERRCODE_SYNTAX_ERROR),
 				 errmsg("bad seg representation"),
 		/* translator: first %s is typically "syntax error" */
-				 errdetail("%s at or near \"%s\"", message, yytext)));
+				 errdetail("%s at or near \"%s\".", message, yytext)));
 	}
 }
 
diff --git a/src/backend/commands/copyto.c b/src/backend/commands/copyto.c
index f0e0147c665..2d2a2e84952 100644
--- a/src/backend/commands/copyto.c
+++ b/src/backend/commands/copyto.c
@@ -838,7 +838,7 @@ BeginCopyTo(ParseState *pstate,
 					ereport(ERROR,
 							errcode(ERRCODE_WRONG_OBJECT_TYPE),
 							errmsg("cannot copy from foreign table \"%s\"", relation_name),
-							errdetail("Partition \"%s\" is a foreign table in partitioned table \"%s\"",
+							errdetail("Partition \"%s\" is a foreign table in partitioned table \"%s\".",
 									  relation_name, RelationGetRelationName(rel)),
 							errhint("Try the COPY (SELECT ...) TO variant."));
 				}
diff --git a/src/backend/commands/extension.c b/src/backend/commands/extension.c
index a330b5fd6ce..cd8810e7dbd 100644
--- a/src/backend/commands/extension.c
+++ b/src/backend/commands/extension.c
@@ -3431,7 +3431,7 @@ AlterExtensionNamespace(const char *extensionName, const char *newschema, Oid *o
 					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 					 errmsg("extension \"%s\" does not support SET SCHEMA",
 							NameStr(extForm->extname)),
-					 errdetail("%s is not in the extension's schema \"%s\"",
+					 errdetail("%s is not in the extension's schema \"%s\".",
 							   getObjectDescription(&dep, false),
 							   get_namespace_name(oldNspOid))));
 	}
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 803a0e47567..d9d5622aa46 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -15377,7 +15377,7 @@ RememberAllDependentForRebuilding(AlteredTableInfo *tab, AlterTableType subtype,
 					ereport(ERROR,
 							(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 							 errmsg("cannot alter type of a column used by a function or procedure"),
-							 errdetail("%s depends on column \"%s\"",
+							 errdetail("%s depends on column \"%s\".",
 									   getObjectDescription(&foundObject, false),
 									   colName)));
 				break;
@@ -15392,7 +15392,7 @@ RememberAllDependentForRebuilding(AlteredTableInfo *tab, AlterTableType subtype,
 					ereport(ERROR,
 							(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 							 errmsg("cannot alter type of a column used by a view or rule"),
-							 errdetail("%s depends on column \"%s\"",
+							 errdetail("%s depends on column \"%s\".",
 									   getObjectDescription(&foundObject, false),
 									   colName)));
 				break;
@@ -15412,7 +15412,7 @@ RememberAllDependentForRebuilding(AlteredTableInfo *tab, AlterTableType subtype,
 					ereport(ERROR,
 							(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 							 errmsg("cannot alter type of a column used in a trigger definition"),
-							 errdetail("%s depends on column \"%s\"",
+							 errdetail("%s depends on column \"%s\".",
 									   getObjectDescription(&foundObject, false),
 									   colName)));
 				break;
@@ -15431,7 +15431,7 @@ RememberAllDependentForRebuilding(AlteredTableInfo *tab, AlterTableType subtype,
 					ereport(ERROR,
 							(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 							 errmsg("cannot alter type of a column used in a policy definition"),
-							 errdetail("%s depends on column \"%s\"",
+							 errdetail("%s depends on column \"%s\".",
 									   getObjectDescription(&foundObject, false),
 									   colName)));
 				break;
@@ -15490,7 +15490,7 @@ RememberAllDependentForRebuilding(AlteredTableInfo *tab, AlterTableType subtype,
 					ereport(ERROR,
 							(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 							 errmsg("cannot alter type of a column used by a publication WHERE clause"),
-							 errdetail("%s depends on column \"%s\"",
+							 errdetail("%s depends on column \"%s\".",
 									   getObjectDescription(&foundObject, false),
 									   colName)));
 				break;
diff --git a/src/backend/libpq/be-secure-openssl.c b/src/backend/libpq/be-secure-openssl.c
index a3e222f3a3d..c7fe2dc7b99 100644
--- a/src/backend/libpq/be-secure-openssl.c
+++ b/src/backend/libpq/be-secure-openssl.c
@@ -473,7 +473,7 @@ be_tls_init(bool isServerStart)
 			ereport(isServerStart ? FATAL : LOG,
 					(errcode(ERRCODE_CONFIG_FILE_ERROR),
 					 errmsg("could not set SSL protocol version range"),
-					 errdetail("\"%s\" cannot be higher than \"%s\"",
+					 errdetail("\"%s\" cannot be higher than \"%s\".",
 							   "ssl_min_protocol_version",
 							   "ssl_max_protocol_version")));
 			goto error;
diff --git a/src/backend/partitioning/partbounds.c b/src/backend/partitioning/partbounds.c
index 5afa781f086..8b1ac2a90a9 100644
--- a/src/backend/partitioning/partbounds.c
+++ b/src/backend/partitioning/partbounds.c
@@ -5032,7 +5032,7 @@ check_two_partitions_bounds_range(Relation parent,
 					errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
 					errmsg("can not merge partition \"%s\" together with partition \"%s\"",
 						   second_name->relname, first_name->relname),
-					errdetail("lower bound of partition \"%s\" is not equal to the upper bound of partition \"%s\"",
+					errdetail("Lower bound of partition \"%s\" is not equal to the upper bound of partition \"%s\".",
 							  second_name->relname, first_name->relname),
 					errhint("ALTER TABLE ... MERGE PARTITIONS requires the partition bounds to be adjacent."),
 					parser_errposition(pstate, datum->location));
@@ -5041,7 +5041,7 @@ check_two_partitions_bounds_range(Relation parent,
 					errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
 					errmsg("can not split to partition \"%s\" together with partition \"%s\"",
 						   second_name->relname, first_name->relname),
-					errdetail("lower bound of partition \"%s\" is not equal to the upper bound of partition \"%s\"",
+					errdetail("Lower bound of partition \"%s\" is not equal to the upper bound of partition \"%s\".",
 							  second_name->relname, first_name->relname),
 					errhint("ALTER TABLE ... SPLIT PARTITION requires the partition bounds to be adjacent."),
 					parser_errposition(pstate, datum->location));
diff --git a/src/test/modules/test_extensions/expected/test_extensions.out b/src/test/modules/test_extensions/expected/test_extensions.out
index fdae52d6ab2..1b5debdeeb1 100644
--- a/src/test/modules/test_extensions/expected/test_extensions.out
+++ b/src/test/modules/test_extensions/expected/test_extensions.out
@@ -566,7 +566,7 @@ SELECT pg_describe_object(classid, objid, objsubid) as obj,
 -- fails, as function dep_req1 is not in the same schema as the extension.
 ALTER EXTENSION test_ext_req_schema1 SET SCHEMA test_func_dep3;
 ERROR:  extension "test_ext_req_schema1" does not support SET SCHEMA
-DETAIL:  function test_func_dep2.dep_req1() is not in the extension's schema "test_func_dep1"
+DETAIL:  function test_func_dep2.dep_req1() is not in the extension's schema "test_func_dep1".
 -- Move back the function, and the extension can be moved.
 ALTER FUNCTION test_func_dep2.dep_req1() SET SCHEMA test_func_dep1;
 ALTER EXTENSION test_ext_req_schema1 SET SCHEMA test_func_dep3;
diff --git a/src/test/regress/expected/create_view.out b/src/test/regress/expected/create_view.out
index 63cf4b4371d..053fa56573f 100644
--- a/src/test/regress/expected/create_view.out
+++ b/src/test/regress/expected/create_view.out
@@ -1720,7 +1720,7 @@ rollback;
 -- likewise, altering a referenced column's type is prohibited ...
 alter table tt14t alter column f4 type integer using f4::integer;  -- fail
 ERROR:  cannot alter type of a column used by a view or rule
-DETAIL:  rule _RETURN on view tt14v depends on column "f4"
+DETAIL:  rule _RETURN on view tt14v depends on column "f4".
 -- ... but some bug might let it happen, so check defenses
 begin;
 -- destroy the dependency entry that prevents the ALTER:
diff --git a/src/test/regress/expected/partition_merge.out b/src/test/regress/expected/partition_merge.out
index 883110e25d9..9b8f5ee137c 100644
--- a/src/test/regress/expected/partition_merge.out
+++ b/src/test/regress/expected/partition_merge.out
@@ -35,14 +35,14 @@ HINT:  ALTER TABLE ... MERGE PARTITIONS can only merge partitions don't have sub
 -- (space between sections sales_jan2022 and sales_mar2022)
 ALTER TABLE sales_range MERGE PARTITIONS (sales_jan2022, sales_mar2022) INTO sales_jan_mar2022;
 ERROR:  can not merge partition "sales_mar2022" together with partition "sales_jan2022"
-DETAIL:  lower bound of partition "sales_mar2022" is not equal to the upper bound of partition "sales_jan2022"
+DETAIL:  Lower bound of partition "sales_mar2022" is not equal to the upper bound of partition "sales_jan2022".
 HINT:  ALTER TABLE ... MERGE PARTITIONS requires the partition bounds to be adjacent.
 -- ERROR:  can not merge partition "sales_jan2022" together with partition "sales_dec2021"
 -- DETAIL:  lower bound of partition "sales_jan2022" is not equal to the upper bound of partition "sales_dec2021"
 -- (space between sections sales_dec2021 and sales_jan2022)
 ALTER TABLE sales_range MERGE PARTITIONS (sales_dec2021, sales_jan2022, sales_feb2022) INTO sales_dec_jan_feb2022;
 ERROR:  can not merge partition "sales_jan2022" together with partition "sales_dec2021"
-DETAIL:  lower bound of partition "sales_jan2022" is not equal to the upper bound of partition "sales_dec2021"
+DETAIL:  Lower bound of partition "sales_jan2022" is not equal to the upper bound of partition "sales_dec2021".
 HINT:  ALTER TABLE ... MERGE PARTITIONS requires the partition bounds to be adjacent.
 -- ERROR:  partition with name "sales_feb2022" is already used
 ALTER TABLE sales_range MERGE PARTITIONS (sales_feb2022, sales_mar2022, partitions_merge_schema.sales_feb2022) INTO sales_feb_mar_apr2022;
diff --git a/src/test/regress/expected/partition_split.out b/src/test/regress/expected/partition_split.out
index dbcb9a4f6b7..a3f52117944 100644
--- a/src/test/regress/expected/partition_split.out
+++ b/src/test/regress/expected/partition_split.out
@@ -109,7 +109,7 @@ ALTER TABLE sales_range SPLIT PARTITION sales_feb_mar_apr2022 INTO
 ERROR:  can not split to partition "sales_mar2022" together with partition "sales_feb2022"
 LINE 3:    PARTITION sales_mar2022 FOR VALUES FROM ('2022-02-01') TO...
                                                     ^
-DETAIL:  lower bound of partition "sales_mar2022" is not equal to the upper bound of partition "sales_feb2022"
+DETAIL:  Lower bound of partition "sales_mar2022" is not equal to the upper bound of partition "sales_feb2022".
 HINT:  ALTER TABLE ... SPLIT PARTITION requires the partition bounds to be adjacent.
 -- Tests for spaces between partitions, them should be executed without DEFAULT partition
 ALTER TABLE sales_range DETACH PARTITION sales_others;
@@ -470,7 +470,7 @@ ALTER TABLE sales_range SPLIT PARTITION sales_others INTO
 ERROR:  can not split to partition "sales_error" together with partition "sales_dec2021"
 LINE 3:    PARTITION sales_error FOR VALUES FROM ('2021-12-30') TO (...
                                                   ^
-DETAIL:  lower bound of partition "sales_error" is not equal to the upper bound of partition "sales_dec2021"
+DETAIL:  Lower bound of partition "sales_error" is not equal to the upper bound of partition "sales_dec2021".
 HINT:  ALTER TABLE ... SPLIT PARTITION requires the partition bounds to be adjacent.
 -- sales_error intersects with sales_feb2022 (upper bound)
 -- ERROR:  can not split to partition "sales_feb2022" together with partition "sales_error"
@@ -482,7 +482,7 @@ ALTER TABLE sales_range SPLIT PARTITION sales_others INTO
 ERROR:  can not split to partition "sales_feb2022" together with partition "sales_error"
 LINE 4:    PARTITION sales_feb2022 FOR VALUES FROM ('2022-02-01') TO...
                                                     ^
-DETAIL:  lower bound of partition "sales_feb2022" is not equal to the upper bound of partition "sales_error"
+DETAIL:  Lower bound of partition "sales_feb2022" is not equal to the upper bound of partition "sales_error".
 HINT:  ALTER TABLE ... SPLIT PARTITION requires the partition bounds to be adjacent.
 -- sales_error intersects with sales_dec2021 (inside bound)
 -- ERROR:  can not split to partition "sales_error" together with partition "sales_dec2021"
@@ -494,7 +494,7 @@ ALTER TABLE sales_range SPLIT PARTITION sales_others INTO
 ERROR:  can not split to partition "sales_error" together with partition "sales_dec2021"
 LINE 3:    PARTITION sales_error FOR VALUES FROM ('2021-12-10') TO (...
                                                   ^
-DETAIL:  lower bound of partition "sales_error" is not equal to the upper bound of partition "sales_dec2021"
+DETAIL:  Lower bound of partition "sales_error" is not equal to the upper bound of partition "sales_dec2021".
 HINT:  ALTER TABLE ... SPLIT PARTITION requires the partition bounds to be adjacent.
 -- sales_error intersects with sales_dec2021 (exactly the same bounds)
 -- ERROR:  can not split to partition "sales_error" together with partition "sales_dec2021"
@@ -506,7 +506,7 @@ ALTER TABLE sales_range SPLIT PARTITION sales_others INTO
 ERROR:  can not split to partition "sales_error" together with partition "sales_dec2021"
 LINE 3:    PARTITION sales_error FOR VALUES FROM ('2021-12-01') TO (...
                                                   ^
-DETAIL:  lower bound of partition "sales_error" is not equal to the upper bound of partition "sales_dec2021"
+DETAIL:  Lower bound of partition "sales_error" is not equal to the upper bound of partition "sales_dec2021".
 HINT:  ALTER TABLE ... SPLIT PARTITION requires the partition bounds to be adjacent.
 -- ERROR:  can not split DEFAULT partition "sales_others"
 -- HINT:  To split DEFAULT partition one of the new partition must be DEFAULT.
diff --git a/src/test/regress/expected/rangefuncs.out b/src/test/regress/expected/rangefuncs.out
index 5cc94011e97..a7cb1b5611d 100644
--- a/src/test/regress/expected/rangefuncs.out
+++ b/src/test/regress/expected/rangefuncs.out
@@ -2279,7 +2279,7 @@ ERROR:  attribute 5 of type record has been dropped
 rollback;
 alter table users alter column seq type numeric;  -- fail, view has reference
 ERROR:  cannot alter type of a column used by a view or rule
-DETAIL:  rule _RETURN on view usersview depends on column "seq"
+DETAIL:  rule _RETURN on view usersview depends on column "seq".
 -- likewise, check we don't crash if the dependency goes wrong
 begin;
 -- destroy the dependency entry that prevents the ALTER:
-- 
2.47.3



^ permalink  raw  reply  [nested|flat] 12+ messages in thread

* Re: Add missing period to DETAIL messages
@ 2026-04-09 08:00  Chao Li <[email protected]>
  parent: Peter Smith <[email protected]>
  0 siblings, 1 reply; 12+ messages in thread

From: Chao Li @ 2026-04-09 08:00 UTC (permalink / raw)
  To: Peter Smith <[email protected]>; +Cc: PostgreSQL Hackers <[email protected]>



> On Apr 9, 2026, at 12:27, Peter Smith <[email protected]> wrote:
> 
> Hi,
> 
> According to the error message style guide [1] "Detail and hint
> messages: Use complete sentences, and end each with a period."
> 
> I found some DETAIL messages not following that period rule.
> 
> PSA a patch that fixes the missing period. In passing, I also fixed
> some capitalization.
> 
> ======
> [1] https://www.postgresql.org/docs/devel/error-style-guide.html#ERROR-STYLE-GUIDE-GRAMMAR-PUNCTUATION
> 
> Kind Regards,
> Peter Smith.
> Fujitsu Australia
> <v1-0001-Add-missing-period-to-DETAIL-messages.patch>


```
-					 errdetail("password must be at least \"passwordcheck.min_password_length\" (%d) bytes long",
+					 errdetail("password must be at least \"passwordcheck.min_password_length\" (%d) bytes long.”,
```

First “p” should be capital.

Best regards,
--
Chao Li (Evan)
HighGo Software Co., Ltd.
https://www.highgo.com/









^ permalink  raw  reply  [nested|flat] 12+ messages in thread

* Re: Add missing period to DETAIL messages
@ 2026-04-10 01:02  Peter Smith <[email protected]>
  parent: Chao Li <[email protected]>
  0 siblings, 1 reply; 12+ messages in thread

From: Peter Smith @ 2026-04-10 01:02 UTC (permalink / raw)
  To: Chao Li <[email protected]>; +Cc: PostgreSQL Hackers <[email protected]>

On Thu, Apr 9, 2026 at 6:00 PM Chao Li <[email protected]> wrote:
...
> > <v1-0001-Add-missing-period-to-DETAIL-messages.patch>
>
>
> ```
> -                                        errdetail("password must be at least \"passwordcheck.min_password_length\" (%d) bytes long",
> +                                        errdetail("password must be at least \"passwordcheck.min_password_length\" (%d) bytes long.”,
> ```
>
> First “p” should be capital.
>

Thanks for your review.

I have fixed that capitalisation, plus a couple more.

PSA v2.

======
KInd Regards,
Peter Smith.
Fujitsu Australia


Attachments:

  [application/octet-stream] v2-0001-Add-missing-period-to-DETAIL-messages.patch (32.3K, 2-v2-0001-Add-missing-period-to-DETAIL-messages.patch)
  download | inline diff:
From 17d4c8478b489bc70eabbfcdf7498a12f1b8fa7c Mon Sep 17 00:00:00 2001
From: Peter Smith <[email protected]>
Date: Fri, 10 Apr 2026 09:37:17 +1000
Subject: [PATCH v2] Add missing period to DETAIL messages

---
 contrib/cube/cubescan.l                       |  4 +-
 contrib/cube/expected/cube.out                | 46 +++++++++----------
 contrib/dblink/dblink.c                       |  2 +-
 .../passwordcheck/expected/passwordcheck.out  |  2 +-
 contrib/passwordcheck/passwordcheck.c         |  2 +-
 .../expected/pg_stash_advice.out              |  2 +-
 .../expected/pg_stash_advice_utf8.out         |  2 +-
 contrib/pg_stash_advice/pg_stash_advice.c     |  8 ++--
 .../postgres_fdw/expected/postgres_fdw.out    |  2 +-
 contrib/seg/expected/seg.out                  | 32 ++++++-------
 contrib/seg/segscan.l                         |  4 +-
 src/backend/commands/copyto.c                 |  2 +-
 src/backend/commands/extension.c              |  2 +-
 src/backend/commands/tablecmds.c              | 10 ++--
 src/backend/libpq/be-secure-openssl.c         |  2 +-
 src/backend/partitioning/partbounds.c         |  4 +-
 .../expected/test_extensions.out              |  2 +-
 src/test/regress/expected/create_view.out     |  2 +-
 src/test/regress/expected/partition_merge.out |  4 +-
 src/test/regress/expected/partition_split.out | 10 ++--
 src/test/regress/expected/rangefuncs.out      |  2 +-
 21 files changed, 73 insertions(+), 73 deletions(-)

diff --git a/contrib/cube/cubescan.l b/contrib/cube/cubescan.l
index e2806dc288f..286efce23aa 100644
--- a/contrib/cube/cubescan.l
+++ b/contrib/cube/cubescan.l
@@ -82,7 +82,7 @@ cube_yyerror(NDBOX **result, Size scanbuflen,
 				(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 				 errmsg("invalid input syntax for cube"),
 		/* translator: %s is typically "syntax error" */
-				 errdetail("%s at end of input", message)));
+				 errdetail("%s at end of input.", message)));
 	}
 	else
 	{
@@ -90,7 +90,7 @@ cube_yyerror(NDBOX **result, Size scanbuflen,
 				(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 				 errmsg("invalid input syntax for cube"),
 		/* translator: first %s is typically "syntax error" */
-				 errdetail("%s at or near \"%s\"", message, yytext)));
+				 errdetail("%s at or near \"%s\".", message, yytext)));
 	}
 }
 
diff --git a/contrib/cube/expected/cube.out b/contrib/cube/expected/cube.out
index 47787c50bd9..f685e0acce5 100644
--- a/contrib/cube/expected/cube.out
+++ b/contrib/cube/expected/cube.out
@@ -189,78 +189,78 @@ SELECT ''::cube AS cube;
 ERROR:  invalid input syntax for cube
 LINE 1: SELECT ''::cube AS cube;
                ^
-DETAIL:  syntax error at end of input
+DETAIL:  syntax error at end of input.
 SELECT 'ABC'::cube AS cube;
 ERROR:  invalid input syntax for cube
 LINE 1: SELECT 'ABC'::cube AS cube;
                ^
-DETAIL:  syntax error at or near "A"
+DETAIL:  syntax error at or near "A".
 SELECT '[]'::cube AS cube;
 ERROR:  invalid input syntax for cube
 LINE 1: SELECT '[]'::cube AS cube;
                ^
-DETAIL:  syntax error at or near "]"
+DETAIL:  syntax error at or near "]".
 SELECT '[()]'::cube AS cube;
 ERROR:  invalid input syntax for cube
 LINE 1: SELECT '[()]'::cube AS cube;
                ^
-DETAIL:  syntax error at or near "]"
+DETAIL:  syntax error at or near "]".
 SELECT '[(1)]'::cube AS cube;
 ERROR:  invalid input syntax for cube
 LINE 1: SELECT '[(1)]'::cube AS cube;
                ^
-DETAIL:  syntax error at or near "]"
+DETAIL:  syntax error at or near "]".
 SELECT '[(1),]'::cube AS cube;
 ERROR:  invalid input syntax for cube
 LINE 1: SELECT '[(1),]'::cube AS cube;
                ^
-DETAIL:  syntax error at or near "]"
+DETAIL:  syntax error at or near "]".
 SELECT '[(1),2]'::cube AS cube;
 ERROR:  invalid input syntax for cube
 LINE 1: SELECT '[(1),2]'::cube AS cube;
                ^
-DETAIL:  syntax error at or near "2"
+DETAIL:  syntax error at or near "2".
 SELECT '[(1),(2),(3)]'::cube AS cube;
 ERROR:  invalid input syntax for cube
 LINE 1: SELECT '[(1),(2),(3)]'::cube AS cube;
                ^
-DETAIL:  syntax error at or near ","
+DETAIL:  syntax error at or near ",".
 SELECT '1,'::cube AS cube;
 ERROR:  invalid input syntax for cube
 LINE 1: SELECT '1,'::cube AS cube;
                ^
-DETAIL:  syntax error at end of input
+DETAIL:  syntax error at end of input.
 SELECT '1,2,'::cube AS cube;
 ERROR:  invalid input syntax for cube
 LINE 1: SELECT '1,2,'::cube AS cube;
                ^
-DETAIL:  syntax error at end of input
+DETAIL:  syntax error at end of input.
 SELECT '1,,2'::cube AS cube;
 ERROR:  invalid input syntax for cube
 LINE 1: SELECT '1,,2'::cube AS cube;
                ^
-DETAIL:  syntax error at or near ","
+DETAIL:  syntax error at or near ",".
 SELECT '(1,)'::cube AS cube;
 ERROR:  invalid input syntax for cube
 LINE 1: SELECT '(1,)'::cube AS cube;
                ^
-DETAIL:  syntax error at or near ")"
+DETAIL:  syntax error at or near ")".
 SELECT '(1,2,)'::cube AS cube;
 ERROR:  invalid input syntax for cube
 LINE 1: SELECT '(1,2,)'::cube AS cube;
                ^
-DETAIL:  syntax error at or near ")"
+DETAIL:  syntax error at or near ")".
 SELECT '(1,,2)'::cube AS cube;
 ERROR:  invalid input syntax for cube
 LINE 1: SELECT '(1,,2)'::cube AS cube;
                ^
-DETAIL:  syntax error at or near ","
+DETAIL:  syntax error at or near ",".
 -- invalid input: semantic errors and trailing garbage
 SELECT '[(1),(2)],'::cube AS cube; -- 0
 ERROR:  invalid input syntax for cube
 LINE 1: SELECT '[(1),(2)],'::cube AS cube;
                ^
-DETAIL:  syntax error at or near ","
+DETAIL:  syntax error at or near ",".
 SELECT '[(1,2,3),(2,3)]'::cube AS cube; -- 1
 ERROR:  invalid input syntax for cube
 LINE 1: SELECT '[(1,2,3),(2,3)]'::cube AS cube;
@@ -275,7 +275,7 @@ SELECT '(1),(2),'::cube AS cube; -- 2
 ERROR:  invalid input syntax for cube
 LINE 1: SELECT '(1),(2),'::cube AS cube;
                ^
-DETAIL:  syntax error at or near ","
+DETAIL:  syntax error at or near ",".
 SELECT '(1,2,3),(2,3)'::cube AS cube; -- 3
 ERROR:  invalid input syntax for cube
 LINE 1: SELECT '(1,2,3),(2,3)'::cube AS cube;
@@ -290,37 +290,37 @@ SELECT '(1,2,3)ab'::cube AS cube; -- 4
 ERROR:  invalid input syntax for cube
 LINE 1: SELECT '(1,2,3)ab'::cube AS cube;
                ^
-DETAIL:  syntax error at or near "a"
+DETAIL:  syntax error at or near "a".
 SELECT '(1,2,3)a'::cube AS cube; -- 5
 ERROR:  invalid input syntax for cube
 LINE 1: SELECT '(1,2,3)a'::cube AS cube;
                ^
-DETAIL:  syntax error at or near "a"
+DETAIL:  syntax error at or near "a".
 SELECT '(1,2)('::cube AS cube; -- 5
 ERROR:  invalid input syntax for cube
 LINE 1: SELECT '(1,2)('::cube AS cube;
                ^
-DETAIL:  syntax error at or near "("
+DETAIL:  syntax error at or near "(".
 SELECT '1,2ab'::cube AS cube; -- 6
 ERROR:  invalid input syntax for cube
 LINE 1: SELECT '1,2ab'::cube AS cube;
                ^
-DETAIL:  syntax error at or near "a"
+DETAIL:  syntax error at or near "a".
 SELECT '1 e7'::cube AS cube; -- 6
 ERROR:  invalid input syntax for cube
 LINE 1: SELECT '1 e7'::cube AS cube;
                ^
-DETAIL:  syntax error at or near "e"
+DETAIL:  syntax error at or near "e".
 SELECT '1,2a'::cube AS cube; -- 7
 ERROR:  invalid input syntax for cube
 LINE 1: SELECT '1,2a'::cube AS cube;
                ^
-DETAIL:  syntax error at or near "a"
+DETAIL:  syntax error at or near "a".
 SELECT '1..2'::cube AS cube; -- 7
 ERROR:  invalid input syntax for cube
 LINE 1: SELECT '1..2'::cube AS cube;
                ^
-DETAIL:  syntax error at or near ".2"
+DETAIL:  syntax error at or near ".2".
 SELECT '-1e-700'::cube AS cube; -- out of range
 ERROR:  "-1e-700" is out of range for type double precision
 LINE 1: SELECT '-1e-700'::cube AS cube;
diff --git a/contrib/dblink/dblink.c b/contrib/dblink/dblink.c
index 9798cb535bc..2113aa41333 100644
--- a/contrib/dblink/dblink.c
+++ b/contrib/dblink/dblink.c
@@ -2710,7 +2710,7 @@ dblink_security_check(PGconn *conn, const char *connname, const char *connstr)
 	ereport(ERROR,
 			(errcode(ERRCODE_S_R_E_PROHIBITED_SQL_STATEMENT_ATTEMPTED),
 			 errmsg("password or GSSAPI delegated credentials required"),
-			 errdetail("Non-superusers may only connect using credentials they provide, eg: password in connection string or delegated GSSAPI credentials"),
+			 errdetail("Non-superusers may only connect using credentials they provide, eg: password in connection string or delegated GSSAPI credentials."),
 			 errhint("Ensure provided credentials match target server's authentication method.")));
 }
 
diff --git a/contrib/passwordcheck/expected/passwordcheck.out b/contrib/passwordcheck/expected/passwordcheck.out
index 83472c76d27..9d02129e936 100644
--- a/contrib/passwordcheck/expected/passwordcheck.out
+++ b/contrib/passwordcheck/expected/passwordcheck.out
@@ -6,7 +6,7 @@ ALTER USER regress_passwordcheck_user1 PASSWORD 'a_nice_long_password';
 -- error: too short
 ALTER USER regress_passwordcheck_user1 PASSWORD 'tooshrt';
 ERROR:  password is too short
-DETAIL:  password must be at least "passwordcheck.min_password_length" (8) bytes long
+DETAIL:  Password must be at least "passwordcheck.min_password_length" (8) bytes long.
 -- ok
 SET passwordcheck.min_password_length = 6;
 ALTER USER regress_passwordcheck_user1 PASSWORD 'v_shrt';
diff --git a/contrib/passwordcheck/passwordcheck.c b/contrib/passwordcheck/passwordcheck.c
index 13fd5c976a0..b45187cce9e 100644
--- a/contrib/passwordcheck/passwordcheck.c
+++ b/contrib/passwordcheck/passwordcheck.c
@@ -101,7 +101,7 @@ check_password(const char *username,
 			ereport(ERROR,
 					(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
 					 errmsg("password is too short"),
-					 errdetail("password must be at least \"passwordcheck.min_password_length\" (%d) bytes long",
+					 errdetail("Password must be at least \"passwordcheck.min_password_length\" (%d) bytes long.",
 							   min_password_length)));
 
 		/* check if the password contains the username */
diff --git a/contrib/pg_stash_advice/expected/pg_stash_advice.out b/contrib/pg_stash_advice/expected/pg_stash_advice.out
index 788da854aa7..8c24a21295e 100644
--- a/contrib/pg_stash_advice/expected/pg_stash_advice.out
+++ b/contrib/pg_stash_advice/expected/pg_stash_advice.out
@@ -315,7 +315,7 @@ SELECT pg_create_advice_stash('   ');
 ERROR:  advice stash name must begin with a letter or underscore and contain only letters, digits, and underscores
 SET pg_stash_advice.stash_name = '99bottles';
 ERROR:  invalid value for parameter "pg_stash_advice.stash_name": "99bottles"
-DETAIL:  advice stash name must begin with a letter or underscore and contain only letters, digits, and underscores
+DETAIL:  Advice stash name must begin with a letter or underscore and contain only letters, digits, and underscores.
 -- Clean up state in dynamic shared memory.
 SELECT pg_drop_advice_stash('regress_stash');
  pg_drop_advice_stash 
diff --git a/contrib/pg_stash_advice/expected/pg_stash_advice_utf8.out b/contrib/pg_stash_advice/expected/pg_stash_advice_utf8.out
index 7c532571ed5..c4bc93c8efb 100644
--- a/contrib/pg_stash_advice/expected/pg_stash_advice_utf8.out
+++ b/contrib/pg_stash_advice/expected/pg_stash_advice_utf8.out
@@ -13,4 +13,4 @@ SELECT pg_create_advice_stash('café');
 ERROR:  advice stash name must not contain non-ASCII characters
 SET pg_stash_advice.stash_name = 'café';
 ERROR:  invalid value for parameter "pg_stash_advice.stash_name": "café"
-DETAIL:  advice stash name must not contain non-ASCII characters
+DETAIL:  Advice stash name must not contain non-ASCII characters.
diff --git a/contrib/pg_stash_advice/pg_stash_advice.c b/contrib/pg_stash_advice/pg_stash_advice.c
index 1858c6a135a..343258c88b1 100644
--- a/contrib/pg_stash_advice/pg_stash_advice.c
+++ b/contrib/pg_stash_advice/pg_stash_advice.c
@@ -385,7 +385,7 @@ pgsa_check_stash_name_guc(char **newval, void **extra, GucSource source)
 	if (strlen(stash_name) + 1 > NAMEDATALEN)
 	{
 		GUC_check_errcode(ERRCODE_INVALID_PARAMETER_VALUE);
-		GUC_check_errdetail("advice stash names may not be longer than %d bytes",
+		GUC_check_errdetail("Advice stash names may not be longer than %d bytes.",
 							NAMEDATALEN - 1);
 		return false;
 	}
@@ -397,7 +397,7 @@ pgsa_check_stash_name_guc(char **newval, void **extra, GucSource source)
 	if (!pg_is_ascii(stash_name))
 	{
 		GUC_check_errcode(ERRCODE_INVALID_PARAMETER_VALUE);
-		GUC_check_errdetail("advice stash name must not contain non-ASCII characters");
+		GUC_check_errdetail("Advice stash name must not contain non-ASCII characters.");
 		return false;
 	}
 
@@ -409,7 +409,7 @@ pgsa_check_stash_name_guc(char **newval, void **extra, GucSource source)
 	if (!pgsa_is_identifier(stash_name))
 	{
 		GUC_check_errcode(ERRCODE_INVALID_PARAMETER_VALUE);
-		GUC_check_errdetail("advice stash name must begin with a letter or underscore and contain only letters, digits, and underscores");
+		GUC_check_errdetail("Advice stash name must begin with a letter or underscore and contain only letters, digits, and underscores.");
 		return false;
 	}
 
@@ -698,7 +698,7 @@ pgsa_set_advice_string(char *stash_name, int64 queryId, char *advice_string)
 		ereport(ERROR,
 				errcode(ERRCODE_OUT_OF_MEMORY),
 				errmsg("out of memory"),
-				errdetail("could not insert advice string into shared hash table"));
+				errdetail("Could not insert advice string into shared hash table."));
 	}
 
 	/* Update the entry and release the lock. */
diff --git a/contrib/postgres_fdw/expected/postgres_fdw.out b/contrib/postgres_fdw/expected/postgres_fdw.out
index cd22553236f..09340988dab 100644
--- a/contrib/postgres_fdw/expected/postgres_fdw.out
+++ b/contrib/postgres_fdw/expected/postgres_fdw.out
@@ -11664,7 +11664,7 @@ DELETE FROM result_tbl;
 -- Test COPY TO when foreign table is partition
 COPY async_pt TO stdout; --error
 ERROR:  cannot copy from foreign table "async_p1"
-DETAIL:  Partition "async_p1" is a foreign table in partitioned table "async_pt"
+DETAIL:  Partition "async_p1" is a foreign table in partitioned table "async_pt".
 HINT:  Try the COPY (SELECT ...) TO variant.
 DROP FOREIGN TABLE async_p3;
 DROP TABLE base_tbl3;
diff --git a/contrib/seg/expected/seg.out b/contrib/seg/expected/seg.out
index cd21139b5a7..b9fbf23c0f1 100644
--- a/contrib/seg/expected/seg.out
+++ b/contrib/seg/expected/seg.out
@@ -405,42 +405,42 @@ SELECT ''::seg AS seg;
 ERROR:  bad seg representation
 LINE 1: SELECT ''::seg AS seg;
                ^
-DETAIL:  syntax error at end of input
+DETAIL:  syntax error at end of input.
 SELECT 'ABC'::seg AS seg;
 ERROR:  bad seg representation
 LINE 1: SELECT 'ABC'::seg AS seg;
                ^
-DETAIL:  syntax error at or near "A"
+DETAIL:  syntax error at or near "A".
 SELECT '1ABC'::seg AS seg;
 ERROR:  bad seg representation
 LINE 1: SELECT '1ABC'::seg AS seg;
                ^
-DETAIL:  syntax error at or near "A"
+DETAIL:  syntax error at or near "A".
 SELECT '1.'::seg AS seg;
 ERROR:  bad seg representation
 LINE 1: SELECT '1.'::seg AS seg;
                ^
-DETAIL:  syntax error at or near "."
+DETAIL:  syntax error at or near ".".
 SELECT '1.....'::seg AS seg;
 ERROR:  bad seg representation
 LINE 1: SELECT '1.....'::seg AS seg;
                ^
-DETAIL:  syntax error at or near ".."
+DETAIL:  syntax error at or near "..".
 SELECT '.1'::seg AS seg;
 ERROR:  bad seg representation
 LINE 1: SELECT '.1'::seg AS seg;
                ^
-DETAIL:  syntax error at or near "."
+DETAIL:  syntax error at or near ".".
 SELECT '1..2.'::seg AS seg;
 ERROR:  bad seg representation
 LINE 1: SELECT '1..2.'::seg AS seg;
                ^
-DETAIL:  syntax error at or near "."
+DETAIL:  syntax error at or near ".".
 SELECT '1 e7'::seg AS seg;
 ERROR:  bad seg representation
 LINE 1: SELECT '1 e7'::seg AS seg;
                ^
-DETAIL:  syntax error at or near "e"
+DETAIL:  syntax error at or near "e".
 SELECT '1e700'::seg AS seg;
 ERROR:  "1e700" is out of range for type real
 LINE 1: SELECT '1e700'::seg AS seg;
@@ -1287,13 +1287,13 @@ FROM unnest(ARRAY['-1 .. 1'::text,
                   '1 e7',
                   '1e700']) str,
      LATERAL pg_input_error_info(str, 'seg') as errinfo;
-   seg    | ok | sql_error_code |                message                |            detail            | hint 
-----------+----+----------------+---------------------------------------+------------------------------+------
- -1 .. 1  | t  |                |                                       |                              | 
- 100(+-)1 | t  |                |                                       |                              | 
-          | f  | 42601          | bad seg representation                | syntax error at end of input | 
- ABC      | f  | 42601          | bad seg representation                | syntax error at or near "A"  | 
- 1 e7     | f  | 42601          | bad seg representation                | syntax error at or near "e"  | 
- 1e700    | f  | 22003          | "1e700" is out of range for type real |                              | 
+   seg    | ok | sql_error_code |                message                |            detail             | hint 
+----------+----+----------------+---------------------------------------+-------------------------------+------
+ -1 .. 1  | t  |                |                                       |                               | 
+ 100(+-)1 | t  |                |                                       |                               | 
+          | f  | 42601          | bad seg representation                | syntax error at end of input. | 
+ ABC      | f  | 42601          | bad seg representation                | syntax error at or near "A".  | 
+ 1 e7     | f  | 42601          | bad seg representation                | syntax error at or near "e".  | 
+ 1e700    | f  | 22003          | "1e700" is out of range for type real |                               | 
 (6 rows)
 
diff --git a/contrib/seg/segscan.l b/contrib/seg/segscan.l
index 3a0cd7ed506..18558688765 100644
--- a/contrib/seg/segscan.l
+++ b/contrib/seg/segscan.l
@@ -79,7 +79,7 @@ seg_yyerror(SEG *result, struct Node *escontext, yyscan_t yyscanner, const char
 				(errcode(ERRCODE_SYNTAX_ERROR),
 				 errmsg("bad seg representation"),
 		/* translator: %s is typically "syntax error" */
-				 errdetail("%s at end of input", message)));
+				 errdetail("%s at end of input.", message)));
 	}
 	else
 	{
@@ -87,7 +87,7 @@ seg_yyerror(SEG *result, struct Node *escontext, yyscan_t yyscanner, const char
 				(errcode(ERRCODE_SYNTAX_ERROR),
 				 errmsg("bad seg representation"),
 		/* translator: first %s is typically "syntax error" */
-				 errdetail("%s at or near \"%s\"", message, yytext)));
+				 errdetail("%s at or near \"%s\".", message, yytext)));
 	}
 }
 
diff --git a/src/backend/commands/copyto.c b/src/backend/commands/copyto.c
index f0e0147c665..2d2a2e84952 100644
--- a/src/backend/commands/copyto.c
+++ b/src/backend/commands/copyto.c
@@ -838,7 +838,7 @@ BeginCopyTo(ParseState *pstate,
 					ereport(ERROR,
 							errcode(ERRCODE_WRONG_OBJECT_TYPE),
 							errmsg("cannot copy from foreign table \"%s\"", relation_name),
-							errdetail("Partition \"%s\" is a foreign table in partitioned table \"%s\"",
+							errdetail("Partition \"%s\" is a foreign table in partitioned table \"%s\".",
 									  relation_name, RelationGetRelationName(rel)),
 							errhint("Try the COPY (SELECT ...) TO variant."));
 				}
diff --git a/src/backend/commands/extension.c b/src/backend/commands/extension.c
index a330b5fd6ce..cd8810e7dbd 100644
--- a/src/backend/commands/extension.c
+++ b/src/backend/commands/extension.c
@@ -3431,7 +3431,7 @@ AlterExtensionNamespace(const char *extensionName, const char *newschema, Oid *o
 					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 					 errmsg("extension \"%s\" does not support SET SCHEMA",
 							NameStr(extForm->extname)),
-					 errdetail("%s is not in the extension's schema \"%s\"",
+					 errdetail("%s is not in the extension's schema \"%s\".",
 							   getObjectDescription(&dep, false),
 							   get_namespace_name(oldNspOid))));
 	}
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 803a0e47567..d9d5622aa46 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -15377,7 +15377,7 @@ RememberAllDependentForRebuilding(AlteredTableInfo *tab, AlterTableType subtype,
 					ereport(ERROR,
 							(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 							 errmsg("cannot alter type of a column used by a function or procedure"),
-							 errdetail("%s depends on column \"%s\"",
+							 errdetail("%s depends on column \"%s\".",
 									   getObjectDescription(&foundObject, false),
 									   colName)));
 				break;
@@ -15392,7 +15392,7 @@ RememberAllDependentForRebuilding(AlteredTableInfo *tab, AlterTableType subtype,
 					ereport(ERROR,
 							(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 							 errmsg("cannot alter type of a column used by a view or rule"),
-							 errdetail("%s depends on column \"%s\"",
+							 errdetail("%s depends on column \"%s\".",
 									   getObjectDescription(&foundObject, false),
 									   colName)));
 				break;
@@ -15412,7 +15412,7 @@ RememberAllDependentForRebuilding(AlteredTableInfo *tab, AlterTableType subtype,
 					ereport(ERROR,
 							(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 							 errmsg("cannot alter type of a column used in a trigger definition"),
-							 errdetail("%s depends on column \"%s\"",
+							 errdetail("%s depends on column \"%s\".",
 									   getObjectDescription(&foundObject, false),
 									   colName)));
 				break;
@@ -15431,7 +15431,7 @@ RememberAllDependentForRebuilding(AlteredTableInfo *tab, AlterTableType subtype,
 					ereport(ERROR,
 							(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 							 errmsg("cannot alter type of a column used in a policy definition"),
-							 errdetail("%s depends on column \"%s\"",
+							 errdetail("%s depends on column \"%s\".",
 									   getObjectDescription(&foundObject, false),
 									   colName)));
 				break;
@@ -15490,7 +15490,7 @@ RememberAllDependentForRebuilding(AlteredTableInfo *tab, AlterTableType subtype,
 					ereport(ERROR,
 							(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 							 errmsg("cannot alter type of a column used by a publication WHERE clause"),
-							 errdetail("%s depends on column \"%s\"",
+							 errdetail("%s depends on column \"%s\".",
 									   getObjectDescription(&foundObject, false),
 									   colName)));
 				break;
diff --git a/src/backend/libpq/be-secure-openssl.c b/src/backend/libpq/be-secure-openssl.c
index a3e222f3a3d..c7fe2dc7b99 100644
--- a/src/backend/libpq/be-secure-openssl.c
+++ b/src/backend/libpq/be-secure-openssl.c
@@ -473,7 +473,7 @@ be_tls_init(bool isServerStart)
 			ereport(isServerStart ? FATAL : LOG,
 					(errcode(ERRCODE_CONFIG_FILE_ERROR),
 					 errmsg("could not set SSL protocol version range"),
-					 errdetail("\"%s\" cannot be higher than \"%s\"",
+					 errdetail("\"%s\" cannot be higher than \"%s\".",
 							   "ssl_min_protocol_version",
 							   "ssl_max_protocol_version")));
 			goto error;
diff --git a/src/backend/partitioning/partbounds.c b/src/backend/partitioning/partbounds.c
index 5afa781f086..8b1ac2a90a9 100644
--- a/src/backend/partitioning/partbounds.c
+++ b/src/backend/partitioning/partbounds.c
@@ -5032,7 +5032,7 @@ check_two_partitions_bounds_range(Relation parent,
 					errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
 					errmsg("can not merge partition \"%s\" together with partition \"%s\"",
 						   second_name->relname, first_name->relname),
-					errdetail("lower bound of partition \"%s\" is not equal to the upper bound of partition \"%s\"",
+					errdetail("Lower bound of partition \"%s\" is not equal to the upper bound of partition \"%s\".",
 							  second_name->relname, first_name->relname),
 					errhint("ALTER TABLE ... MERGE PARTITIONS requires the partition bounds to be adjacent."),
 					parser_errposition(pstate, datum->location));
@@ -5041,7 +5041,7 @@ check_two_partitions_bounds_range(Relation parent,
 					errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
 					errmsg("can not split to partition \"%s\" together with partition \"%s\"",
 						   second_name->relname, first_name->relname),
-					errdetail("lower bound of partition \"%s\" is not equal to the upper bound of partition \"%s\"",
+					errdetail("Lower bound of partition \"%s\" is not equal to the upper bound of partition \"%s\".",
 							  second_name->relname, first_name->relname),
 					errhint("ALTER TABLE ... SPLIT PARTITION requires the partition bounds to be adjacent."),
 					parser_errposition(pstate, datum->location));
diff --git a/src/test/modules/test_extensions/expected/test_extensions.out b/src/test/modules/test_extensions/expected/test_extensions.out
index fdae52d6ab2..1b5debdeeb1 100644
--- a/src/test/modules/test_extensions/expected/test_extensions.out
+++ b/src/test/modules/test_extensions/expected/test_extensions.out
@@ -566,7 +566,7 @@ SELECT pg_describe_object(classid, objid, objsubid) as obj,
 -- fails, as function dep_req1 is not in the same schema as the extension.
 ALTER EXTENSION test_ext_req_schema1 SET SCHEMA test_func_dep3;
 ERROR:  extension "test_ext_req_schema1" does not support SET SCHEMA
-DETAIL:  function test_func_dep2.dep_req1() is not in the extension's schema "test_func_dep1"
+DETAIL:  function test_func_dep2.dep_req1() is not in the extension's schema "test_func_dep1".
 -- Move back the function, and the extension can be moved.
 ALTER FUNCTION test_func_dep2.dep_req1() SET SCHEMA test_func_dep1;
 ALTER EXTENSION test_ext_req_schema1 SET SCHEMA test_func_dep3;
diff --git a/src/test/regress/expected/create_view.out b/src/test/regress/expected/create_view.out
index 63cf4b4371d..053fa56573f 100644
--- a/src/test/regress/expected/create_view.out
+++ b/src/test/regress/expected/create_view.out
@@ -1720,7 +1720,7 @@ rollback;
 -- likewise, altering a referenced column's type is prohibited ...
 alter table tt14t alter column f4 type integer using f4::integer;  -- fail
 ERROR:  cannot alter type of a column used by a view or rule
-DETAIL:  rule _RETURN on view tt14v depends on column "f4"
+DETAIL:  rule _RETURN on view tt14v depends on column "f4".
 -- ... but some bug might let it happen, so check defenses
 begin;
 -- destroy the dependency entry that prevents the ALTER:
diff --git a/src/test/regress/expected/partition_merge.out b/src/test/regress/expected/partition_merge.out
index 883110e25d9..9b8f5ee137c 100644
--- a/src/test/regress/expected/partition_merge.out
+++ b/src/test/regress/expected/partition_merge.out
@@ -35,14 +35,14 @@ HINT:  ALTER TABLE ... MERGE PARTITIONS can only merge partitions don't have sub
 -- (space between sections sales_jan2022 and sales_mar2022)
 ALTER TABLE sales_range MERGE PARTITIONS (sales_jan2022, sales_mar2022) INTO sales_jan_mar2022;
 ERROR:  can not merge partition "sales_mar2022" together with partition "sales_jan2022"
-DETAIL:  lower bound of partition "sales_mar2022" is not equal to the upper bound of partition "sales_jan2022"
+DETAIL:  Lower bound of partition "sales_mar2022" is not equal to the upper bound of partition "sales_jan2022".
 HINT:  ALTER TABLE ... MERGE PARTITIONS requires the partition bounds to be adjacent.
 -- ERROR:  can not merge partition "sales_jan2022" together with partition "sales_dec2021"
 -- DETAIL:  lower bound of partition "sales_jan2022" is not equal to the upper bound of partition "sales_dec2021"
 -- (space between sections sales_dec2021 and sales_jan2022)
 ALTER TABLE sales_range MERGE PARTITIONS (sales_dec2021, sales_jan2022, sales_feb2022) INTO sales_dec_jan_feb2022;
 ERROR:  can not merge partition "sales_jan2022" together with partition "sales_dec2021"
-DETAIL:  lower bound of partition "sales_jan2022" is not equal to the upper bound of partition "sales_dec2021"
+DETAIL:  Lower bound of partition "sales_jan2022" is not equal to the upper bound of partition "sales_dec2021".
 HINT:  ALTER TABLE ... MERGE PARTITIONS requires the partition bounds to be adjacent.
 -- ERROR:  partition with name "sales_feb2022" is already used
 ALTER TABLE sales_range MERGE PARTITIONS (sales_feb2022, sales_mar2022, partitions_merge_schema.sales_feb2022) INTO sales_feb_mar_apr2022;
diff --git a/src/test/regress/expected/partition_split.out b/src/test/regress/expected/partition_split.out
index dbcb9a4f6b7..a3f52117944 100644
--- a/src/test/regress/expected/partition_split.out
+++ b/src/test/regress/expected/partition_split.out
@@ -109,7 +109,7 @@ ALTER TABLE sales_range SPLIT PARTITION sales_feb_mar_apr2022 INTO
 ERROR:  can not split to partition "sales_mar2022" together with partition "sales_feb2022"
 LINE 3:    PARTITION sales_mar2022 FOR VALUES FROM ('2022-02-01') TO...
                                                     ^
-DETAIL:  lower bound of partition "sales_mar2022" is not equal to the upper bound of partition "sales_feb2022"
+DETAIL:  Lower bound of partition "sales_mar2022" is not equal to the upper bound of partition "sales_feb2022".
 HINT:  ALTER TABLE ... SPLIT PARTITION requires the partition bounds to be adjacent.
 -- Tests for spaces between partitions, them should be executed without DEFAULT partition
 ALTER TABLE sales_range DETACH PARTITION sales_others;
@@ -470,7 +470,7 @@ ALTER TABLE sales_range SPLIT PARTITION sales_others INTO
 ERROR:  can not split to partition "sales_error" together with partition "sales_dec2021"
 LINE 3:    PARTITION sales_error FOR VALUES FROM ('2021-12-30') TO (...
                                                   ^
-DETAIL:  lower bound of partition "sales_error" is not equal to the upper bound of partition "sales_dec2021"
+DETAIL:  Lower bound of partition "sales_error" is not equal to the upper bound of partition "sales_dec2021".
 HINT:  ALTER TABLE ... SPLIT PARTITION requires the partition bounds to be adjacent.
 -- sales_error intersects with sales_feb2022 (upper bound)
 -- ERROR:  can not split to partition "sales_feb2022" together with partition "sales_error"
@@ -482,7 +482,7 @@ ALTER TABLE sales_range SPLIT PARTITION sales_others INTO
 ERROR:  can not split to partition "sales_feb2022" together with partition "sales_error"
 LINE 4:    PARTITION sales_feb2022 FOR VALUES FROM ('2022-02-01') TO...
                                                     ^
-DETAIL:  lower bound of partition "sales_feb2022" is not equal to the upper bound of partition "sales_error"
+DETAIL:  Lower bound of partition "sales_feb2022" is not equal to the upper bound of partition "sales_error".
 HINT:  ALTER TABLE ... SPLIT PARTITION requires the partition bounds to be adjacent.
 -- sales_error intersects with sales_dec2021 (inside bound)
 -- ERROR:  can not split to partition "sales_error" together with partition "sales_dec2021"
@@ -494,7 +494,7 @@ ALTER TABLE sales_range SPLIT PARTITION sales_others INTO
 ERROR:  can not split to partition "sales_error" together with partition "sales_dec2021"
 LINE 3:    PARTITION sales_error FOR VALUES FROM ('2021-12-10') TO (...
                                                   ^
-DETAIL:  lower bound of partition "sales_error" is not equal to the upper bound of partition "sales_dec2021"
+DETAIL:  Lower bound of partition "sales_error" is not equal to the upper bound of partition "sales_dec2021".
 HINT:  ALTER TABLE ... SPLIT PARTITION requires the partition bounds to be adjacent.
 -- sales_error intersects with sales_dec2021 (exactly the same bounds)
 -- ERROR:  can not split to partition "sales_error" together with partition "sales_dec2021"
@@ -506,7 +506,7 @@ ALTER TABLE sales_range SPLIT PARTITION sales_others INTO
 ERROR:  can not split to partition "sales_error" together with partition "sales_dec2021"
 LINE 3:    PARTITION sales_error FOR VALUES FROM ('2021-12-01') TO (...
                                                   ^
-DETAIL:  lower bound of partition "sales_error" is not equal to the upper bound of partition "sales_dec2021"
+DETAIL:  Lower bound of partition "sales_error" is not equal to the upper bound of partition "sales_dec2021".
 HINT:  ALTER TABLE ... SPLIT PARTITION requires the partition bounds to be adjacent.
 -- ERROR:  can not split DEFAULT partition "sales_others"
 -- HINT:  To split DEFAULT partition one of the new partition must be DEFAULT.
diff --git a/src/test/regress/expected/rangefuncs.out b/src/test/regress/expected/rangefuncs.out
index 5cc94011e97..a7cb1b5611d 100644
--- a/src/test/regress/expected/rangefuncs.out
+++ b/src/test/regress/expected/rangefuncs.out
@@ -2279,7 +2279,7 @@ ERROR:  attribute 5 of type record has been dropped
 rollback;
 alter table users alter column seq type numeric;  -- fail, view has reference
 ERROR:  cannot alter type of a column used by a view or rule
-DETAIL:  rule _RETURN on view usersview depends on column "seq"
+DETAIL:  rule _RETURN on view usersview depends on column "seq".
 -- likewise, check we don't crash if the dependency goes wrong
 begin;
 -- destroy the dependency entry that prevents the ALTER:
-- 
2.47.3



^ permalink  raw  reply  [nested|flat] 12+ messages in thread

* Re: Add missing period to DETAIL messages
@ 2026-04-13 01:04  Peter Smith <[email protected]>
  parent: Peter Smith <[email protected]>
  0 siblings, 1 reply; 12+ messages in thread

From: Peter Smith @ 2026-04-13 01:04 UTC (permalink / raw)
  To: Chao Li <[email protected]>; +Cc: PostgreSQL Hackers <[email protected]>

Found one more oversight.

PSA v3.

======
Kind Regards,
Peter Smith.
Fujitsu Australia





^ permalink  raw  reply  [nested|flat] 12+ messages in thread

* Re: Add missing period to DETAIL messages
@ 2026-04-13 01:05  Peter Smith <[email protected]>
  parent: Peter Smith <[email protected]>
  0 siblings, 2 replies; 12+ messages in thread

From: Peter Smith @ 2026-04-13 01:05 UTC (permalink / raw)
  To: Chao Li <[email protected]>; +Cc: PostgreSQL Hackers <[email protected]>

(here's the missing attachment)

On Mon, Apr 13, 2026 at 11:04 AM Peter Smith <[email protected]> wrote:
>
> Found one more oversight.
>
> PSA v3.
>
> ======
> Kind Regards,
> Peter Smith.
> Fujitsu Australia


Attachments:

  [application/octet-stream] v3-0001-Add-missing-period-to-DETAIL-messages.patch (33.1K, 2-v3-0001-Add-missing-period-to-DETAIL-messages.patch)
  download | inline diff:
From 0a98edb0d4b0e5d8e1d94524200019c7f6e371ab Mon Sep 17 00:00:00 2001
From: Peter Smith <[email protected]>
Date: Mon, 13 Apr 2026 09:31:45 +1000
Subject: [PATCH v3] Add missing period to DETAIL messages

---
 contrib/cube/cubescan.l                       |  4 +-
 contrib/cube/expected/cube.out                | 46 +++++++++----------
 contrib/dblink/dblink.c                       |  2 +-
 .../passwordcheck/expected/passwordcheck.out  |  2 +-
 .../expected/passwordcheck_1.out              |  2 +-
 contrib/passwordcheck/passwordcheck.c         |  2 +-
 .../expected/pg_stash_advice.out              |  2 +-
 .../expected/pg_stash_advice_utf8.out         |  2 +-
 contrib/pg_stash_advice/pg_stash_advice.c     |  8 ++--
 .../postgres_fdw/expected/postgres_fdw.out    |  2 +-
 contrib/seg/expected/seg.out                  | 32 ++++++-------
 contrib/seg/segscan.l                         |  4 +-
 src/backend/commands/copyto.c                 |  2 +-
 src/backend/commands/extension.c              |  2 +-
 src/backend/commands/tablecmds.c              | 10 ++--
 src/backend/libpq/be-secure-openssl.c         |  2 +-
 src/backend/partitioning/partbounds.c         |  4 +-
 .../expected/test_extensions.out              |  2 +-
 src/test/regress/expected/create_view.out     |  2 +-
 src/test/regress/expected/partition_merge.out |  4 +-
 src/test/regress/expected/partition_split.out | 10 ++--
 src/test/regress/expected/rangefuncs.out      |  2 +-
 22 files changed, 74 insertions(+), 74 deletions(-)

diff --git a/contrib/cube/cubescan.l b/contrib/cube/cubescan.l
index e2806dc288f..286efce23aa 100644
--- a/contrib/cube/cubescan.l
+++ b/contrib/cube/cubescan.l
@@ -82,7 +82,7 @@ cube_yyerror(NDBOX **result, Size scanbuflen,
 				(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 				 errmsg("invalid input syntax for cube"),
 		/* translator: %s is typically "syntax error" */
-				 errdetail("%s at end of input", message)));
+				 errdetail("%s at end of input.", message)));
 	}
 	else
 	{
@@ -90,7 +90,7 @@ cube_yyerror(NDBOX **result, Size scanbuflen,
 				(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 				 errmsg("invalid input syntax for cube"),
 		/* translator: first %s is typically "syntax error" */
-				 errdetail("%s at or near \"%s\"", message, yytext)));
+				 errdetail("%s at or near \"%s\".", message, yytext)));
 	}
 }
 
diff --git a/contrib/cube/expected/cube.out b/contrib/cube/expected/cube.out
index 47787c50bd9..f685e0acce5 100644
--- a/contrib/cube/expected/cube.out
+++ b/contrib/cube/expected/cube.out
@@ -189,78 +189,78 @@ SELECT ''::cube AS cube;
 ERROR:  invalid input syntax for cube
 LINE 1: SELECT ''::cube AS cube;
                ^
-DETAIL:  syntax error at end of input
+DETAIL:  syntax error at end of input.
 SELECT 'ABC'::cube AS cube;
 ERROR:  invalid input syntax for cube
 LINE 1: SELECT 'ABC'::cube AS cube;
                ^
-DETAIL:  syntax error at or near "A"
+DETAIL:  syntax error at or near "A".
 SELECT '[]'::cube AS cube;
 ERROR:  invalid input syntax for cube
 LINE 1: SELECT '[]'::cube AS cube;
                ^
-DETAIL:  syntax error at or near "]"
+DETAIL:  syntax error at or near "]".
 SELECT '[()]'::cube AS cube;
 ERROR:  invalid input syntax for cube
 LINE 1: SELECT '[()]'::cube AS cube;
                ^
-DETAIL:  syntax error at or near "]"
+DETAIL:  syntax error at or near "]".
 SELECT '[(1)]'::cube AS cube;
 ERROR:  invalid input syntax for cube
 LINE 1: SELECT '[(1)]'::cube AS cube;
                ^
-DETAIL:  syntax error at or near "]"
+DETAIL:  syntax error at or near "]".
 SELECT '[(1),]'::cube AS cube;
 ERROR:  invalid input syntax for cube
 LINE 1: SELECT '[(1),]'::cube AS cube;
                ^
-DETAIL:  syntax error at or near "]"
+DETAIL:  syntax error at or near "]".
 SELECT '[(1),2]'::cube AS cube;
 ERROR:  invalid input syntax for cube
 LINE 1: SELECT '[(1),2]'::cube AS cube;
                ^
-DETAIL:  syntax error at or near "2"
+DETAIL:  syntax error at or near "2".
 SELECT '[(1),(2),(3)]'::cube AS cube;
 ERROR:  invalid input syntax for cube
 LINE 1: SELECT '[(1),(2),(3)]'::cube AS cube;
                ^
-DETAIL:  syntax error at or near ","
+DETAIL:  syntax error at or near ",".
 SELECT '1,'::cube AS cube;
 ERROR:  invalid input syntax for cube
 LINE 1: SELECT '1,'::cube AS cube;
                ^
-DETAIL:  syntax error at end of input
+DETAIL:  syntax error at end of input.
 SELECT '1,2,'::cube AS cube;
 ERROR:  invalid input syntax for cube
 LINE 1: SELECT '1,2,'::cube AS cube;
                ^
-DETAIL:  syntax error at end of input
+DETAIL:  syntax error at end of input.
 SELECT '1,,2'::cube AS cube;
 ERROR:  invalid input syntax for cube
 LINE 1: SELECT '1,,2'::cube AS cube;
                ^
-DETAIL:  syntax error at or near ","
+DETAIL:  syntax error at or near ",".
 SELECT '(1,)'::cube AS cube;
 ERROR:  invalid input syntax for cube
 LINE 1: SELECT '(1,)'::cube AS cube;
                ^
-DETAIL:  syntax error at or near ")"
+DETAIL:  syntax error at or near ")".
 SELECT '(1,2,)'::cube AS cube;
 ERROR:  invalid input syntax for cube
 LINE 1: SELECT '(1,2,)'::cube AS cube;
                ^
-DETAIL:  syntax error at or near ")"
+DETAIL:  syntax error at or near ")".
 SELECT '(1,,2)'::cube AS cube;
 ERROR:  invalid input syntax for cube
 LINE 1: SELECT '(1,,2)'::cube AS cube;
                ^
-DETAIL:  syntax error at or near ","
+DETAIL:  syntax error at or near ",".
 -- invalid input: semantic errors and trailing garbage
 SELECT '[(1),(2)],'::cube AS cube; -- 0
 ERROR:  invalid input syntax for cube
 LINE 1: SELECT '[(1),(2)],'::cube AS cube;
                ^
-DETAIL:  syntax error at or near ","
+DETAIL:  syntax error at or near ",".
 SELECT '[(1,2,3),(2,3)]'::cube AS cube; -- 1
 ERROR:  invalid input syntax for cube
 LINE 1: SELECT '[(1,2,3),(2,3)]'::cube AS cube;
@@ -275,7 +275,7 @@ SELECT '(1),(2),'::cube AS cube; -- 2
 ERROR:  invalid input syntax for cube
 LINE 1: SELECT '(1),(2),'::cube AS cube;
                ^
-DETAIL:  syntax error at or near ","
+DETAIL:  syntax error at or near ",".
 SELECT '(1,2,3),(2,3)'::cube AS cube; -- 3
 ERROR:  invalid input syntax for cube
 LINE 1: SELECT '(1,2,3),(2,3)'::cube AS cube;
@@ -290,37 +290,37 @@ SELECT '(1,2,3)ab'::cube AS cube; -- 4
 ERROR:  invalid input syntax for cube
 LINE 1: SELECT '(1,2,3)ab'::cube AS cube;
                ^
-DETAIL:  syntax error at or near "a"
+DETAIL:  syntax error at or near "a".
 SELECT '(1,2,3)a'::cube AS cube; -- 5
 ERROR:  invalid input syntax for cube
 LINE 1: SELECT '(1,2,3)a'::cube AS cube;
                ^
-DETAIL:  syntax error at or near "a"
+DETAIL:  syntax error at or near "a".
 SELECT '(1,2)('::cube AS cube; -- 5
 ERROR:  invalid input syntax for cube
 LINE 1: SELECT '(1,2)('::cube AS cube;
                ^
-DETAIL:  syntax error at or near "("
+DETAIL:  syntax error at or near "(".
 SELECT '1,2ab'::cube AS cube; -- 6
 ERROR:  invalid input syntax for cube
 LINE 1: SELECT '1,2ab'::cube AS cube;
                ^
-DETAIL:  syntax error at or near "a"
+DETAIL:  syntax error at or near "a".
 SELECT '1 e7'::cube AS cube; -- 6
 ERROR:  invalid input syntax for cube
 LINE 1: SELECT '1 e7'::cube AS cube;
                ^
-DETAIL:  syntax error at or near "e"
+DETAIL:  syntax error at or near "e".
 SELECT '1,2a'::cube AS cube; -- 7
 ERROR:  invalid input syntax for cube
 LINE 1: SELECT '1,2a'::cube AS cube;
                ^
-DETAIL:  syntax error at or near "a"
+DETAIL:  syntax error at or near "a".
 SELECT '1..2'::cube AS cube; -- 7
 ERROR:  invalid input syntax for cube
 LINE 1: SELECT '1..2'::cube AS cube;
                ^
-DETAIL:  syntax error at or near ".2"
+DETAIL:  syntax error at or near ".2".
 SELECT '-1e-700'::cube AS cube; -- out of range
 ERROR:  "-1e-700" is out of range for type double precision
 LINE 1: SELECT '-1e-700'::cube AS cube;
diff --git a/contrib/dblink/dblink.c b/contrib/dblink/dblink.c
index 9798cb535bc..2113aa41333 100644
--- a/contrib/dblink/dblink.c
+++ b/contrib/dblink/dblink.c
@@ -2710,7 +2710,7 @@ dblink_security_check(PGconn *conn, const char *connname, const char *connstr)
 	ereport(ERROR,
 			(errcode(ERRCODE_S_R_E_PROHIBITED_SQL_STATEMENT_ATTEMPTED),
 			 errmsg("password or GSSAPI delegated credentials required"),
-			 errdetail("Non-superusers may only connect using credentials they provide, eg: password in connection string or delegated GSSAPI credentials"),
+			 errdetail("Non-superusers may only connect using credentials they provide, eg: password in connection string or delegated GSSAPI credentials."),
 			 errhint("Ensure provided credentials match target server's authentication method.")));
 }
 
diff --git a/contrib/passwordcheck/expected/passwordcheck.out b/contrib/passwordcheck/expected/passwordcheck.out
index 83472c76d27..9d02129e936 100644
--- a/contrib/passwordcheck/expected/passwordcheck.out
+++ b/contrib/passwordcheck/expected/passwordcheck.out
@@ -6,7 +6,7 @@ ALTER USER regress_passwordcheck_user1 PASSWORD 'a_nice_long_password';
 -- error: too short
 ALTER USER regress_passwordcheck_user1 PASSWORD 'tooshrt';
 ERROR:  password is too short
-DETAIL:  password must be at least "passwordcheck.min_password_length" (8) bytes long
+DETAIL:  Password must be at least "passwordcheck.min_password_length" (8) bytes long.
 -- ok
 SET passwordcheck.min_password_length = 6;
 ALTER USER regress_passwordcheck_user1 PASSWORD 'v_shrt';
diff --git a/contrib/passwordcheck/expected/passwordcheck_1.out b/contrib/passwordcheck/expected/passwordcheck_1.out
index fb12ec45cc4..a334720431d 100644
--- a/contrib/passwordcheck/expected/passwordcheck_1.out
+++ b/contrib/passwordcheck/expected/passwordcheck_1.out
@@ -6,7 +6,7 @@ ALTER USER regress_passwordcheck_user1 PASSWORD 'a_nice_long_password';
 -- error: too short
 ALTER USER regress_passwordcheck_user1 PASSWORD 'tooshrt';
 ERROR:  password is too short
-DETAIL:  password must be at least "passwordcheck.min_password_length" (8) bytes long
+DETAIL:  Password must be at least "passwordcheck.min_password_length" (8) bytes long.
 -- ok
 SET passwordcheck.min_password_length = 6;
 ALTER USER regress_passwordcheck_user1 PASSWORD 'v_shrt';
diff --git a/contrib/passwordcheck/passwordcheck.c b/contrib/passwordcheck/passwordcheck.c
index 13fd5c976a0..b45187cce9e 100644
--- a/contrib/passwordcheck/passwordcheck.c
+++ b/contrib/passwordcheck/passwordcheck.c
@@ -101,7 +101,7 @@ check_password(const char *username,
 			ereport(ERROR,
 					(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
 					 errmsg("password is too short"),
-					 errdetail("password must be at least \"passwordcheck.min_password_length\" (%d) bytes long",
+					 errdetail("Password must be at least \"passwordcheck.min_password_length\" (%d) bytes long.",
 							   min_password_length)));
 
 		/* check if the password contains the username */
diff --git a/contrib/pg_stash_advice/expected/pg_stash_advice.out b/contrib/pg_stash_advice/expected/pg_stash_advice.out
index 788da854aa7..8c24a21295e 100644
--- a/contrib/pg_stash_advice/expected/pg_stash_advice.out
+++ b/contrib/pg_stash_advice/expected/pg_stash_advice.out
@@ -315,7 +315,7 @@ SELECT pg_create_advice_stash('   ');
 ERROR:  advice stash name must begin with a letter or underscore and contain only letters, digits, and underscores
 SET pg_stash_advice.stash_name = '99bottles';
 ERROR:  invalid value for parameter "pg_stash_advice.stash_name": "99bottles"
-DETAIL:  advice stash name must begin with a letter or underscore and contain only letters, digits, and underscores
+DETAIL:  Advice stash name must begin with a letter or underscore and contain only letters, digits, and underscores.
 -- Clean up state in dynamic shared memory.
 SELECT pg_drop_advice_stash('regress_stash');
  pg_drop_advice_stash 
diff --git a/contrib/pg_stash_advice/expected/pg_stash_advice_utf8.out b/contrib/pg_stash_advice/expected/pg_stash_advice_utf8.out
index 7c532571ed5..c4bc93c8efb 100644
--- a/contrib/pg_stash_advice/expected/pg_stash_advice_utf8.out
+++ b/contrib/pg_stash_advice/expected/pg_stash_advice_utf8.out
@@ -13,4 +13,4 @@ SELECT pg_create_advice_stash('café');
 ERROR:  advice stash name must not contain non-ASCII characters
 SET pg_stash_advice.stash_name = 'café';
 ERROR:  invalid value for parameter "pg_stash_advice.stash_name": "café"
-DETAIL:  advice stash name must not contain non-ASCII characters
+DETAIL:  Advice stash name must not contain non-ASCII characters.
diff --git a/contrib/pg_stash_advice/pg_stash_advice.c b/contrib/pg_stash_advice/pg_stash_advice.c
index 1858c6a135a..343258c88b1 100644
--- a/contrib/pg_stash_advice/pg_stash_advice.c
+++ b/contrib/pg_stash_advice/pg_stash_advice.c
@@ -385,7 +385,7 @@ pgsa_check_stash_name_guc(char **newval, void **extra, GucSource source)
 	if (strlen(stash_name) + 1 > NAMEDATALEN)
 	{
 		GUC_check_errcode(ERRCODE_INVALID_PARAMETER_VALUE);
-		GUC_check_errdetail("advice stash names may not be longer than %d bytes",
+		GUC_check_errdetail("Advice stash names may not be longer than %d bytes.",
 							NAMEDATALEN - 1);
 		return false;
 	}
@@ -397,7 +397,7 @@ pgsa_check_stash_name_guc(char **newval, void **extra, GucSource source)
 	if (!pg_is_ascii(stash_name))
 	{
 		GUC_check_errcode(ERRCODE_INVALID_PARAMETER_VALUE);
-		GUC_check_errdetail("advice stash name must not contain non-ASCII characters");
+		GUC_check_errdetail("Advice stash name must not contain non-ASCII characters.");
 		return false;
 	}
 
@@ -409,7 +409,7 @@ pgsa_check_stash_name_guc(char **newval, void **extra, GucSource source)
 	if (!pgsa_is_identifier(stash_name))
 	{
 		GUC_check_errcode(ERRCODE_INVALID_PARAMETER_VALUE);
-		GUC_check_errdetail("advice stash name must begin with a letter or underscore and contain only letters, digits, and underscores");
+		GUC_check_errdetail("Advice stash name must begin with a letter or underscore and contain only letters, digits, and underscores.");
 		return false;
 	}
 
@@ -698,7 +698,7 @@ pgsa_set_advice_string(char *stash_name, int64 queryId, char *advice_string)
 		ereport(ERROR,
 				errcode(ERRCODE_OUT_OF_MEMORY),
 				errmsg("out of memory"),
-				errdetail("could not insert advice string into shared hash table"));
+				errdetail("Could not insert advice string into shared hash table."));
 	}
 
 	/* Update the entry and release the lock. */
diff --git a/contrib/postgres_fdw/expected/postgres_fdw.out b/contrib/postgres_fdw/expected/postgres_fdw.out
index 10e87acabef..f0bf16b3bd5 100644
--- a/contrib/postgres_fdw/expected/postgres_fdw.out
+++ b/contrib/postgres_fdw/expected/postgres_fdw.out
@@ -11664,7 +11664,7 @@ DELETE FROM result_tbl;
 -- Test COPY TO when foreign table is partition
 COPY async_pt TO stdout; --error
 ERROR:  cannot copy from foreign table "async_p1"
-DETAIL:  Partition "async_p1" is a foreign table in partitioned table "async_pt"
+DETAIL:  Partition "async_p1" is a foreign table in partitioned table "async_pt".
 HINT:  Try the COPY (SELECT ...) TO variant.
 DROP FOREIGN TABLE async_p3;
 DROP TABLE base_tbl3;
diff --git a/contrib/seg/expected/seg.out b/contrib/seg/expected/seg.out
index cd21139b5a7..b9fbf23c0f1 100644
--- a/contrib/seg/expected/seg.out
+++ b/contrib/seg/expected/seg.out
@@ -405,42 +405,42 @@ SELECT ''::seg AS seg;
 ERROR:  bad seg representation
 LINE 1: SELECT ''::seg AS seg;
                ^
-DETAIL:  syntax error at end of input
+DETAIL:  syntax error at end of input.
 SELECT 'ABC'::seg AS seg;
 ERROR:  bad seg representation
 LINE 1: SELECT 'ABC'::seg AS seg;
                ^
-DETAIL:  syntax error at or near "A"
+DETAIL:  syntax error at or near "A".
 SELECT '1ABC'::seg AS seg;
 ERROR:  bad seg representation
 LINE 1: SELECT '1ABC'::seg AS seg;
                ^
-DETAIL:  syntax error at or near "A"
+DETAIL:  syntax error at or near "A".
 SELECT '1.'::seg AS seg;
 ERROR:  bad seg representation
 LINE 1: SELECT '1.'::seg AS seg;
                ^
-DETAIL:  syntax error at or near "."
+DETAIL:  syntax error at or near ".".
 SELECT '1.....'::seg AS seg;
 ERROR:  bad seg representation
 LINE 1: SELECT '1.....'::seg AS seg;
                ^
-DETAIL:  syntax error at or near ".."
+DETAIL:  syntax error at or near "..".
 SELECT '.1'::seg AS seg;
 ERROR:  bad seg representation
 LINE 1: SELECT '.1'::seg AS seg;
                ^
-DETAIL:  syntax error at or near "."
+DETAIL:  syntax error at or near ".".
 SELECT '1..2.'::seg AS seg;
 ERROR:  bad seg representation
 LINE 1: SELECT '1..2.'::seg AS seg;
                ^
-DETAIL:  syntax error at or near "."
+DETAIL:  syntax error at or near ".".
 SELECT '1 e7'::seg AS seg;
 ERROR:  bad seg representation
 LINE 1: SELECT '1 e7'::seg AS seg;
                ^
-DETAIL:  syntax error at or near "e"
+DETAIL:  syntax error at or near "e".
 SELECT '1e700'::seg AS seg;
 ERROR:  "1e700" is out of range for type real
 LINE 1: SELECT '1e700'::seg AS seg;
@@ -1287,13 +1287,13 @@ FROM unnest(ARRAY['-1 .. 1'::text,
                   '1 e7',
                   '1e700']) str,
      LATERAL pg_input_error_info(str, 'seg') as errinfo;
-   seg    | ok | sql_error_code |                message                |            detail            | hint 
-----------+----+----------------+---------------------------------------+------------------------------+------
- -1 .. 1  | t  |                |                                       |                              | 
- 100(+-)1 | t  |                |                                       |                              | 
-          | f  | 42601          | bad seg representation                | syntax error at end of input | 
- ABC      | f  | 42601          | bad seg representation                | syntax error at or near "A"  | 
- 1 e7     | f  | 42601          | bad seg representation                | syntax error at or near "e"  | 
- 1e700    | f  | 22003          | "1e700" is out of range for type real |                              | 
+   seg    | ok | sql_error_code |                message                |            detail             | hint 
+----------+----+----------------+---------------------------------------+-------------------------------+------
+ -1 .. 1  | t  |                |                                       |                               | 
+ 100(+-)1 | t  |                |                                       |                               | 
+          | f  | 42601          | bad seg representation                | syntax error at end of input. | 
+ ABC      | f  | 42601          | bad seg representation                | syntax error at or near "A".  | 
+ 1 e7     | f  | 42601          | bad seg representation                | syntax error at or near "e".  | 
+ 1e700    | f  | 22003          | "1e700" is out of range for type real |                               | 
 (6 rows)
 
diff --git a/contrib/seg/segscan.l b/contrib/seg/segscan.l
index 3a0cd7ed506..18558688765 100644
--- a/contrib/seg/segscan.l
+++ b/contrib/seg/segscan.l
@@ -79,7 +79,7 @@ seg_yyerror(SEG *result, struct Node *escontext, yyscan_t yyscanner, const char
 				(errcode(ERRCODE_SYNTAX_ERROR),
 				 errmsg("bad seg representation"),
 		/* translator: %s is typically "syntax error" */
-				 errdetail("%s at end of input", message)));
+				 errdetail("%s at end of input.", message)));
 	}
 	else
 	{
@@ -87,7 +87,7 @@ seg_yyerror(SEG *result, struct Node *escontext, yyscan_t yyscanner, const char
 				(errcode(ERRCODE_SYNTAX_ERROR),
 				 errmsg("bad seg representation"),
 		/* translator: first %s is typically "syntax error" */
-				 errdetail("%s at or near \"%s\"", message, yytext)));
+				 errdetail("%s at or near \"%s\".", message, yytext)));
 	}
 }
 
diff --git a/src/backend/commands/copyto.c b/src/backend/commands/copyto.c
index f0e0147c665..2d2a2e84952 100644
--- a/src/backend/commands/copyto.c
+++ b/src/backend/commands/copyto.c
@@ -838,7 +838,7 @@ BeginCopyTo(ParseState *pstate,
 					ereport(ERROR,
 							errcode(ERRCODE_WRONG_OBJECT_TYPE),
 							errmsg("cannot copy from foreign table \"%s\"", relation_name),
-							errdetail("Partition \"%s\" is a foreign table in partitioned table \"%s\"",
+							errdetail("Partition \"%s\" is a foreign table in partitioned table \"%s\".",
 									  relation_name, RelationGetRelationName(rel)),
 							errhint("Try the COPY (SELECT ...) TO variant."));
 				}
diff --git a/src/backend/commands/extension.c b/src/backend/commands/extension.c
index a330b5fd6ce..cd8810e7dbd 100644
--- a/src/backend/commands/extension.c
+++ b/src/backend/commands/extension.c
@@ -3431,7 +3431,7 @@ AlterExtensionNamespace(const char *extensionName, const char *newschema, Oid *o
 					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 					 errmsg("extension \"%s\" does not support SET SCHEMA",
 							NameStr(extForm->extname)),
-					 errdetail("%s is not in the extension's schema \"%s\"",
+					 errdetail("%s is not in the extension's schema \"%s\".",
 							   getObjectDescription(&dep, false),
 							   get_namespace_name(oldNspOid))));
 	}
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 803a0e47567..d9d5622aa46 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -15377,7 +15377,7 @@ RememberAllDependentForRebuilding(AlteredTableInfo *tab, AlterTableType subtype,
 					ereport(ERROR,
 							(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 							 errmsg("cannot alter type of a column used by a function or procedure"),
-							 errdetail("%s depends on column \"%s\"",
+							 errdetail("%s depends on column \"%s\".",
 									   getObjectDescription(&foundObject, false),
 									   colName)));
 				break;
@@ -15392,7 +15392,7 @@ RememberAllDependentForRebuilding(AlteredTableInfo *tab, AlterTableType subtype,
 					ereport(ERROR,
 							(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 							 errmsg("cannot alter type of a column used by a view or rule"),
-							 errdetail("%s depends on column \"%s\"",
+							 errdetail("%s depends on column \"%s\".",
 									   getObjectDescription(&foundObject, false),
 									   colName)));
 				break;
@@ -15412,7 +15412,7 @@ RememberAllDependentForRebuilding(AlteredTableInfo *tab, AlterTableType subtype,
 					ereport(ERROR,
 							(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 							 errmsg("cannot alter type of a column used in a trigger definition"),
-							 errdetail("%s depends on column \"%s\"",
+							 errdetail("%s depends on column \"%s\".",
 									   getObjectDescription(&foundObject, false),
 									   colName)));
 				break;
@@ -15431,7 +15431,7 @@ RememberAllDependentForRebuilding(AlteredTableInfo *tab, AlterTableType subtype,
 					ereport(ERROR,
 							(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 							 errmsg("cannot alter type of a column used in a policy definition"),
-							 errdetail("%s depends on column \"%s\"",
+							 errdetail("%s depends on column \"%s\".",
 									   getObjectDescription(&foundObject, false),
 									   colName)));
 				break;
@@ -15490,7 +15490,7 @@ RememberAllDependentForRebuilding(AlteredTableInfo *tab, AlterTableType subtype,
 					ereport(ERROR,
 							(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 							 errmsg("cannot alter type of a column used by a publication WHERE clause"),
-							 errdetail("%s depends on column \"%s\"",
+							 errdetail("%s depends on column \"%s\".",
 									   getObjectDescription(&foundObject, false),
 									   colName)));
 				break;
diff --git a/src/backend/libpq/be-secure-openssl.c b/src/backend/libpq/be-secure-openssl.c
index a3e222f3a3d..c7fe2dc7b99 100644
--- a/src/backend/libpq/be-secure-openssl.c
+++ b/src/backend/libpq/be-secure-openssl.c
@@ -473,7 +473,7 @@ be_tls_init(bool isServerStart)
 			ereport(isServerStart ? FATAL : LOG,
 					(errcode(ERRCODE_CONFIG_FILE_ERROR),
 					 errmsg("could not set SSL protocol version range"),
-					 errdetail("\"%s\" cannot be higher than \"%s\"",
+					 errdetail("\"%s\" cannot be higher than \"%s\".",
 							   "ssl_min_protocol_version",
 							   "ssl_max_protocol_version")));
 			goto error;
diff --git a/src/backend/partitioning/partbounds.c b/src/backend/partitioning/partbounds.c
index 5afa781f086..8b1ac2a90a9 100644
--- a/src/backend/partitioning/partbounds.c
+++ b/src/backend/partitioning/partbounds.c
@@ -5032,7 +5032,7 @@ check_two_partitions_bounds_range(Relation parent,
 					errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
 					errmsg("can not merge partition \"%s\" together with partition \"%s\"",
 						   second_name->relname, first_name->relname),
-					errdetail("lower bound of partition \"%s\" is not equal to the upper bound of partition \"%s\"",
+					errdetail("Lower bound of partition \"%s\" is not equal to the upper bound of partition \"%s\".",
 							  second_name->relname, first_name->relname),
 					errhint("ALTER TABLE ... MERGE PARTITIONS requires the partition bounds to be adjacent."),
 					parser_errposition(pstate, datum->location));
@@ -5041,7 +5041,7 @@ check_two_partitions_bounds_range(Relation parent,
 					errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
 					errmsg("can not split to partition \"%s\" together with partition \"%s\"",
 						   second_name->relname, first_name->relname),
-					errdetail("lower bound of partition \"%s\" is not equal to the upper bound of partition \"%s\"",
+					errdetail("Lower bound of partition \"%s\" is not equal to the upper bound of partition \"%s\".",
 							  second_name->relname, first_name->relname),
 					errhint("ALTER TABLE ... SPLIT PARTITION requires the partition bounds to be adjacent."),
 					parser_errposition(pstate, datum->location));
diff --git a/src/test/modules/test_extensions/expected/test_extensions.out b/src/test/modules/test_extensions/expected/test_extensions.out
index fdae52d6ab2..1b5debdeeb1 100644
--- a/src/test/modules/test_extensions/expected/test_extensions.out
+++ b/src/test/modules/test_extensions/expected/test_extensions.out
@@ -566,7 +566,7 @@ SELECT pg_describe_object(classid, objid, objsubid) as obj,
 -- fails, as function dep_req1 is not in the same schema as the extension.
 ALTER EXTENSION test_ext_req_schema1 SET SCHEMA test_func_dep3;
 ERROR:  extension "test_ext_req_schema1" does not support SET SCHEMA
-DETAIL:  function test_func_dep2.dep_req1() is not in the extension's schema "test_func_dep1"
+DETAIL:  function test_func_dep2.dep_req1() is not in the extension's schema "test_func_dep1".
 -- Move back the function, and the extension can be moved.
 ALTER FUNCTION test_func_dep2.dep_req1() SET SCHEMA test_func_dep1;
 ALTER EXTENSION test_ext_req_schema1 SET SCHEMA test_func_dep3;
diff --git a/src/test/regress/expected/create_view.out b/src/test/regress/expected/create_view.out
index 63cf4b4371d..053fa56573f 100644
--- a/src/test/regress/expected/create_view.out
+++ b/src/test/regress/expected/create_view.out
@@ -1720,7 +1720,7 @@ rollback;
 -- likewise, altering a referenced column's type is prohibited ...
 alter table tt14t alter column f4 type integer using f4::integer;  -- fail
 ERROR:  cannot alter type of a column used by a view or rule
-DETAIL:  rule _RETURN on view tt14v depends on column "f4"
+DETAIL:  rule _RETURN on view tt14v depends on column "f4".
 -- ... but some bug might let it happen, so check defenses
 begin;
 -- destroy the dependency entry that prevents the ALTER:
diff --git a/src/test/regress/expected/partition_merge.out b/src/test/regress/expected/partition_merge.out
index 883110e25d9..9b8f5ee137c 100644
--- a/src/test/regress/expected/partition_merge.out
+++ b/src/test/regress/expected/partition_merge.out
@@ -35,14 +35,14 @@ HINT:  ALTER TABLE ... MERGE PARTITIONS can only merge partitions don't have sub
 -- (space between sections sales_jan2022 and sales_mar2022)
 ALTER TABLE sales_range MERGE PARTITIONS (sales_jan2022, sales_mar2022) INTO sales_jan_mar2022;
 ERROR:  can not merge partition "sales_mar2022" together with partition "sales_jan2022"
-DETAIL:  lower bound of partition "sales_mar2022" is not equal to the upper bound of partition "sales_jan2022"
+DETAIL:  Lower bound of partition "sales_mar2022" is not equal to the upper bound of partition "sales_jan2022".
 HINT:  ALTER TABLE ... MERGE PARTITIONS requires the partition bounds to be adjacent.
 -- ERROR:  can not merge partition "sales_jan2022" together with partition "sales_dec2021"
 -- DETAIL:  lower bound of partition "sales_jan2022" is not equal to the upper bound of partition "sales_dec2021"
 -- (space between sections sales_dec2021 and sales_jan2022)
 ALTER TABLE sales_range MERGE PARTITIONS (sales_dec2021, sales_jan2022, sales_feb2022) INTO sales_dec_jan_feb2022;
 ERROR:  can not merge partition "sales_jan2022" together with partition "sales_dec2021"
-DETAIL:  lower bound of partition "sales_jan2022" is not equal to the upper bound of partition "sales_dec2021"
+DETAIL:  Lower bound of partition "sales_jan2022" is not equal to the upper bound of partition "sales_dec2021".
 HINT:  ALTER TABLE ... MERGE PARTITIONS requires the partition bounds to be adjacent.
 -- ERROR:  partition with name "sales_feb2022" is already used
 ALTER TABLE sales_range MERGE PARTITIONS (sales_feb2022, sales_mar2022, partitions_merge_schema.sales_feb2022) INTO sales_feb_mar_apr2022;
diff --git a/src/test/regress/expected/partition_split.out b/src/test/regress/expected/partition_split.out
index b4053685af0..4cf04ea4f5b 100644
--- a/src/test/regress/expected/partition_split.out
+++ b/src/test/regress/expected/partition_split.out
@@ -109,7 +109,7 @@ ALTER TABLE sales_range SPLIT PARTITION sales_feb_mar_apr2022 INTO
 ERROR:  can not split to partition "sales_mar2022" together with partition "sales_feb2022"
 LINE 3:    PARTITION sales_mar2022 FOR VALUES FROM ('2022-02-01') TO...
                                                     ^
-DETAIL:  lower bound of partition "sales_mar2022" is not equal to the upper bound of partition "sales_feb2022"
+DETAIL:  Lower bound of partition "sales_mar2022" is not equal to the upper bound of partition "sales_feb2022".
 HINT:  ALTER TABLE ... SPLIT PARTITION requires the partition bounds to be adjacent.
 -- Tests for spaces between partitions, them should be executed without DEFAULT partition
 ALTER TABLE sales_range DETACH PARTITION sales_others;
@@ -470,7 +470,7 @@ ALTER TABLE sales_range SPLIT PARTITION sales_others INTO
 ERROR:  can not split to partition "sales_error" together with partition "sales_dec2021"
 LINE 3:    PARTITION sales_error FOR VALUES FROM ('2021-12-30') TO (...
                                                   ^
-DETAIL:  lower bound of partition "sales_error" is not equal to the upper bound of partition "sales_dec2021"
+DETAIL:  Lower bound of partition "sales_error" is not equal to the upper bound of partition "sales_dec2021".
 HINT:  ALTER TABLE ... SPLIT PARTITION requires the partition bounds to be adjacent.
 -- sales_error intersects with sales_feb2022 (upper bound)
 -- ERROR:  can not split to partition "sales_feb2022" together with partition "sales_error"
@@ -482,7 +482,7 @@ ALTER TABLE sales_range SPLIT PARTITION sales_others INTO
 ERROR:  can not split to partition "sales_feb2022" together with partition "sales_error"
 LINE 4:    PARTITION sales_feb2022 FOR VALUES FROM ('2022-02-01') TO...
                                                     ^
-DETAIL:  lower bound of partition "sales_feb2022" is not equal to the upper bound of partition "sales_error"
+DETAIL:  Lower bound of partition "sales_feb2022" is not equal to the upper bound of partition "sales_error".
 HINT:  ALTER TABLE ... SPLIT PARTITION requires the partition bounds to be adjacent.
 -- sales_error intersects with sales_dec2021 (inside bound)
 -- ERROR:  can not split to partition "sales_error" together with partition "sales_dec2021"
@@ -494,7 +494,7 @@ ALTER TABLE sales_range SPLIT PARTITION sales_others INTO
 ERROR:  can not split to partition "sales_error" together with partition "sales_dec2021"
 LINE 3:    PARTITION sales_error FOR VALUES FROM ('2021-12-10') TO (...
                                                   ^
-DETAIL:  lower bound of partition "sales_error" is not equal to the upper bound of partition "sales_dec2021"
+DETAIL:  Lower bound of partition "sales_error" is not equal to the upper bound of partition "sales_dec2021".
 HINT:  ALTER TABLE ... SPLIT PARTITION requires the partition bounds to be adjacent.
 -- sales_error intersects with sales_dec2021 (exactly the same bounds)
 -- ERROR:  can not split to partition "sales_error" together with partition "sales_dec2021"
@@ -506,7 +506,7 @@ ALTER TABLE sales_range SPLIT PARTITION sales_others INTO
 ERROR:  can not split to partition "sales_error" together with partition "sales_dec2021"
 LINE 3:    PARTITION sales_error FOR VALUES FROM ('2021-12-01') TO (...
                                                   ^
-DETAIL:  lower bound of partition "sales_error" is not equal to the upper bound of partition "sales_dec2021"
+DETAIL:  Lower bound of partition "sales_error" is not equal to the upper bound of partition "sales_dec2021".
 HINT:  ALTER TABLE ... SPLIT PARTITION requires the partition bounds to be adjacent.
 -- ERROR:  can not split DEFAULT partition "sales_others"
 -- HINT:  To split DEFAULT partition one of the new partition must be DEFAULT.
diff --git a/src/test/regress/expected/rangefuncs.out b/src/test/regress/expected/rangefuncs.out
index 5cc94011e97..a7cb1b5611d 100644
--- a/src/test/regress/expected/rangefuncs.out
+++ b/src/test/regress/expected/rangefuncs.out
@@ -2279,7 +2279,7 @@ ERROR:  attribute 5 of type record has been dropped
 rollback;
 alter table users alter column seq type numeric;  -- fail, view has reference
 ERROR:  cannot alter type of a column used by a view or rule
-DETAIL:  rule _RETURN on view usersview depends on column "seq"
+DETAIL:  rule _RETURN on view usersview depends on column "seq".
 -- likewise, check we don't crash if the dependency goes wrong
 begin;
 -- destroy the dependency entry that prevents the ALTER:
-- 
2.47.3



^ permalink  raw  reply  [nested|flat] 12+ messages in thread

* Re: Add missing period to DETAIL messages
@ 2026-04-14 05:51  vignesh C <[email protected]>
  parent: Peter Smith <[email protected]>
  1 sibling, 1 reply; 12+ messages in thread

From: vignesh C @ 2026-04-14 05:51 UTC (permalink / raw)
  To: Peter Smith <[email protected]>; +Cc: Chao Li <[email protected]>; PostgreSQL Hackers <[email protected]>

On Mon, 13 Apr 2026 at 06:36, Peter Smith <[email protected]> wrote:
>
> (here's the missing attachment)
>
> On Mon, Apr 13, 2026 at 11:04 AM Peter Smith <[email protected]> wrote:
> >
> > Found one more oversight.
> >
> > PSA v3.

Should these also be updated:
1) ginfuncs.c
if (opaq->flags != (GIN_DATA | GIN_LEAF | GIN_COMPRESSED))
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("input page is not a compressed GIN data leaf page"),
errdetail("Flags %04X, expected %04X",
   opaq->flags,
   (GIN_DATA | GIN_LEAF | GIN_COMPRESSED))));

2) shell_archive.c
ereport(lev,
(errmsg("archive command failed with exit code %d",
WEXITSTATUS(rc)),
errdetail("The failed archive command was: %s",
   xlogarchcmd)));

3) shell_archive.c
ereport(lev,
(errmsg("archive command was terminated by exception 0x%X",
WTERMSIG(rc)),
errhint("See C include file \"ntstatus.h\" for a description of the
hexadecimal value."),
errdetail("The failed archive command was: %s",
   xlogarchcmd)));

4) shell_archive.c
ereport(lev,
(errmsg("archive command was terminated by signal %d: %s",
WTERMSIG(rc), pg_strsignal(WTERMSIG(rc))),
errdetail("The failed archive command was: %s",
   xlogarchcmd)));

5) shell_archive.c
ereport(lev,
(errmsg("archive command exited with unrecognized status %d",
rc),
errdetail("The failed archive command was: %s",
   xlogarchcmd)));

6) matview.c
ereport(ERROR,
(errcode(ERRCODE_CARDINALITY_VIOLATION),
errmsg("new data for materialized view \"%s\" contains duplicate rows
without any null columns",
RelationGetRelationName(matviewRel)),
errdetail("Row: %s",
   SPI_getvalue(SPI_tuptable->vals[0], SPI_tuptable->tupdesc, 1))));

Regards,
Vignesh





^ permalink  raw  reply  [nested|flat] 12+ messages in thread

* Re: Add missing period to DETAIL messages
@ 2026-04-14 06:28  Peter Smith <[email protected]>
  parent: vignesh C <[email protected]>
  0 siblings, 0 replies; 12+ messages in thread

From: Peter Smith @ 2026-04-14 06:28 UTC (permalink / raw)
  To: vignesh C <[email protected]>; +Cc: Chao Li <[email protected]>; PostgreSQL Hackers <[email protected]>

On Tue, Apr 14, 2026 at 3:51 PM vignesh C <[email protected]> wrote:
>
> On Mon, 13 Apr 2026 at 06:36, Peter Smith <[email protected]> wrote:
> >
> > (here's the missing attachment)
> >
> > On Mon, Apr 13, 2026 at 11:04 AM Peter Smith <[email protected]> wrote:
> > >
> > > Found one more oversight.
> > >
> > > PSA v3.
>

Hi Vignesh.

Thanks for your review!

I deliberately avoided any potentially controversial or troublesome
modifications.

So I have already seen all those you questioned and chose to avoid
them for various reasons.

In general, I did not put a period on any message that ended with a
":" followed by some substitution, for fear that the period (.) might
ambiguously appear to be part of the substituted value. Below are some
other reasons...

> Should these also be updated:
> 1) ginfuncs.c
> if (opaq->flags != (GIN_DATA | GIN_LEAF | GIN_COMPRESSED))
> ereport(ERROR,
> (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
> errmsg("input page is not a compressed GIN data leaf page"),
> errdetail("Flags %04X, expected %04X",
>    opaq->flags,
>    (GIN_DATA | GIN_LEAF | GIN_COMPRESSED))));
>

Yeah. This was one I was wavering about. I didn't want to be worried
that the '.' might somehow mess with the last format specifier. And
escaping the period using "\." just seemed overkill. I concluded there
seemed to be more reasons to avoid changing it than to change it.

> 2) shell_archive.c
> ereport(lev,
> (errmsg("archive command failed with exit code %d",
> WEXITSTATUS(rc)),
> errdetail("The failed archive command was: %s",
>    xlogarchcmd)));

Not done because I didn't want it to appear that the '.' might be part
of the substituted command.

>
> 3) shell_archive.c
> ereport(lev,
> (errmsg("archive command was terminated by exception 0x%X",
> WTERMSIG(rc)),
> errhint("See C include file \"ntstatus.h\" for a description of the
> hexadecimal value."),
> errdetail("The failed archive command was: %s",
>    xlogarchcmd)));

Not done because I didn't want it to appear that the '.' might be part
of the substituted command.

>
> 4) shell_archive.c
> ereport(lev,
> (errmsg("archive command was terminated by signal %d: %s",
> WTERMSIG(rc), pg_strsignal(WTERMSIG(rc))),
> errdetail("The failed archive command was: %s",
>    xlogarchcmd)));
>

Not done because I didn't want it to appear that the '.' might be part
of the substituted command.

> 5) shell_archive.c
> ereport(lev,
> (errmsg("archive command exited with unrecognized status %d",
> rc),
> errdetail("The failed archive command was: %s",
>    xlogarchcmd)));
>

Not done because I didn't want it to appear that the '.' might be part
of the substituted command.

> 6) matview.c
> ereport(ERROR,
> (errcode(ERRCODE_CARDINALITY_VIOLATION),
> errmsg("new data for materialized view \"%s\" contains duplicate rows
> without any null columns",
> RelationGetRelationName(matviewRel)),
> errdetail("Row: %s",
>    SPI_getvalue(SPI_tuptable->vals[0], SPI_tuptable->tupdesc, 1))));
>

Not done because I didn't want it to appear that the '.' might be part
of the substituted row value.

======
Kind Regards,
Peter Smith.
Fujitsu Australia





^ permalink  raw  reply  [nested|flat] 12+ messages in thread

* Re: Add missing period to DETAIL messages
@ 2026-04-15 05:47  Xiaopeng Wang <[email protected]>
  parent: Peter Smith <[email protected]>
  1 sibling, 1 reply; 12+ messages in thread

From: Xiaopeng Wang @ 2026-04-15 05:47 UTC (permalink / raw)
  To: Peter Smith <[email protected]>; Chao Li <[email protected]>; +Cc: PostgreSQL Hackers <[email protected]>

在 2026/4/13 9:05, Peter Smith 写道:
> (here's the missing attachment)
>
> On Mon, Apr 13, 2026 at 11:04 AM Peter Smith<[email protected]> wrote:
>> Found one more oversight.
>>
>> PSA v3.
>>
>> ======
>> Kind Regards,
>> Peter Smith.
>> Fujitsu Australia

Looks good to me.

A small comment is that, the commit message claims only “add missing period to DETAIL messages”, but apparently the patch also changes capitalization in many places, so the commit message should be updated.

Regards,
Xiaopeng Wang


^ permalink  raw  reply  [nested|flat] 12+ messages in thread

* Re: Add missing period to DETAIL messages
@ 2026-04-15 07:41  Peter Smith <[email protected]>
  parent: Xiaopeng Wang <[email protected]>
  0 siblings, 1 reply; 12+ messages in thread

From: Peter Smith @ 2026-04-15 07:41 UTC (permalink / raw)
  To: Xiaopeng Wang <[email protected]>; +Cc: Chao Li <[email protected]>; PostgreSQL Hackers <[email protected]>

On Wed, Apr 15, 2026 at 3:48 PM Xiaopeng Wang <[email protected]> wrote:
>
...
>
> Looks good to me.
>
> A small comment is that, the commit message claims only “add missing period to DETAIL messages”, but apparently the patch also changes capitalization in many places, so the commit message should be updated.
>

Fair point. Thanks for your review!

PSA v4 which has an improved commit message.

======
Kind Regards,
Peter Smith.
Fujitsu Australia


Attachments:

  [application/octet-stream] v4-0001-DETAIL-messages-fix-capitalization-and-add-missin.patch (33.6K, 2-v4-0001-DETAIL-messages-fix-capitalization-and-add-missin.patch)
  download | inline diff:
From e2e40fcbb474891e01c1259cb0d769371c739688 Mon Sep 17 00:00:00 2001
From: Peter Smith <[email protected]>
Date: Wed, 15 Apr 2026 16:25:37 +1000
Subject: [PATCH v4] DETAIL messages - fix capitalization and add missing
 periods.

Change DETAIL messages to conform to the style guide by capitalizing the first
word of sentences and ending sentences with a period.

Author: Peter Smith <[email protected]>
Reviewed-by: Chao Li <[email protected]>
Reviewed-by: vignesh C <vignesh21.gmail.com>
Reviewed-by: Xiaopeng Wang <wxp_728.163.com>

Discussion: https://www.postgresql.org/message-id/flat/CAHut%2BPszSntkUgN%2BQa9matGY6MLEoFGSuVbuKDgnnTdZ7YPRwg%40mail.gmail.com
---
 contrib/cube/cubescan.l                       |  4 +-
 contrib/cube/expected/cube.out                | 46 +++++++++----------
 contrib/dblink/dblink.c                       |  2 +-
 .../passwordcheck/expected/passwordcheck.out  |  2 +-
 .../expected/passwordcheck_1.out              |  2 +-
 contrib/passwordcheck/passwordcheck.c         |  2 +-
 .../expected/pg_stash_advice.out              |  2 +-
 .../expected/pg_stash_advice_utf8.out         |  2 +-
 contrib/pg_stash_advice/pg_stash_advice.c     |  8 ++--
 .../postgres_fdw/expected/postgres_fdw.out    |  2 +-
 contrib/seg/expected/seg.out                  | 32 ++++++-------
 contrib/seg/segscan.l                         |  4 +-
 src/backend/commands/copyto.c                 |  2 +-
 src/backend/commands/extension.c              |  2 +-
 src/backend/commands/tablecmds.c              | 10 ++--
 src/backend/libpq/be-secure-openssl.c         |  2 +-
 src/backend/partitioning/partbounds.c         |  4 +-
 .../expected/test_extensions.out              |  2 +-
 src/test/regress/expected/create_view.out     |  2 +-
 src/test/regress/expected/partition_merge.out |  4 +-
 src/test/regress/expected/partition_split.out | 10 ++--
 src/test/regress/expected/rangefuncs.out      |  2 +-
 22 files changed, 74 insertions(+), 74 deletions(-)

diff --git a/contrib/cube/cubescan.l b/contrib/cube/cubescan.l
index e2806dc288f..286efce23aa 100644
--- a/contrib/cube/cubescan.l
+++ b/contrib/cube/cubescan.l
@@ -82,7 +82,7 @@ cube_yyerror(NDBOX **result, Size scanbuflen,
 				(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 				 errmsg("invalid input syntax for cube"),
 		/* translator: %s is typically "syntax error" */
-				 errdetail("%s at end of input", message)));
+				 errdetail("%s at end of input.", message)));
 	}
 	else
 	{
@@ -90,7 +90,7 @@ cube_yyerror(NDBOX **result, Size scanbuflen,
 				(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 				 errmsg("invalid input syntax for cube"),
 		/* translator: first %s is typically "syntax error" */
-				 errdetail("%s at or near \"%s\"", message, yytext)));
+				 errdetail("%s at or near \"%s\".", message, yytext)));
 	}
 }
 
diff --git a/contrib/cube/expected/cube.out b/contrib/cube/expected/cube.out
index 47787c50bd9..f685e0acce5 100644
--- a/contrib/cube/expected/cube.out
+++ b/contrib/cube/expected/cube.out
@@ -189,78 +189,78 @@ SELECT ''::cube AS cube;
 ERROR:  invalid input syntax for cube
 LINE 1: SELECT ''::cube AS cube;
                ^
-DETAIL:  syntax error at end of input
+DETAIL:  syntax error at end of input.
 SELECT 'ABC'::cube AS cube;
 ERROR:  invalid input syntax for cube
 LINE 1: SELECT 'ABC'::cube AS cube;
                ^
-DETAIL:  syntax error at or near "A"
+DETAIL:  syntax error at or near "A".
 SELECT '[]'::cube AS cube;
 ERROR:  invalid input syntax for cube
 LINE 1: SELECT '[]'::cube AS cube;
                ^
-DETAIL:  syntax error at or near "]"
+DETAIL:  syntax error at or near "]".
 SELECT '[()]'::cube AS cube;
 ERROR:  invalid input syntax for cube
 LINE 1: SELECT '[()]'::cube AS cube;
                ^
-DETAIL:  syntax error at or near "]"
+DETAIL:  syntax error at or near "]".
 SELECT '[(1)]'::cube AS cube;
 ERROR:  invalid input syntax for cube
 LINE 1: SELECT '[(1)]'::cube AS cube;
                ^
-DETAIL:  syntax error at or near "]"
+DETAIL:  syntax error at or near "]".
 SELECT '[(1),]'::cube AS cube;
 ERROR:  invalid input syntax for cube
 LINE 1: SELECT '[(1),]'::cube AS cube;
                ^
-DETAIL:  syntax error at or near "]"
+DETAIL:  syntax error at or near "]".
 SELECT '[(1),2]'::cube AS cube;
 ERROR:  invalid input syntax for cube
 LINE 1: SELECT '[(1),2]'::cube AS cube;
                ^
-DETAIL:  syntax error at or near "2"
+DETAIL:  syntax error at or near "2".
 SELECT '[(1),(2),(3)]'::cube AS cube;
 ERROR:  invalid input syntax for cube
 LINE 1: SELECT '[(1),(2),(3)]'::cube AS cube;
                ^
-DETAIL:  syntax error at or near ","
+DETAIL:  syntax error at or near ",".
 SELECT '1,'::cube AS cube;
 ERROR:  invalid input syntax for cube
 LINE 1: SELECT '1,'::cube AS cube;
                ^
-DETAIL:  syntax error at end of input
+DETAIL:  syntax error at end of input.
 SELECT '1,2,'::cube AS cube;
 ERROR:  invalid input syntax for cube
 LINE 1: SELECT '1,2,'::cube AS cube;
                ^
-DETAIL:  syntax error at end of input
+DETAIL:  syntax error at end of input.
 SELECT '1,,2'::cube AS cube;
 ERROR:  invalid input syntax for cube
 LINE 1: SELECT '1,,2'::cube AS cube;
                ^
-DETAIL:  syntax error at or near ","
+DETAIL:  syntax error at or near ",".
 SELECT '(1,)'::cube AS cube;
 ERROR:  invalid input syntax for cube
 LINE 1: SELECT '(1,)'::cube AS cube;
                ^
-DETAIL:  syntax error at or near ")"
+DETAIL:  syntax error at or near ")".
 SELECT '(1,2,)'::cube AS cube;
 ERROR:  invalid input syntax for cube
 LINE 1: SELECT '(1,2,)'::cube AS cube;
                ^
-DETAIL:  syntax error at or near ")"
+DETAIL:  syntax error at or near ")".
 SELECT '(1,,2)'::cube AS cube;
 ERROR:  invalid input syntax for cube
 LINE 1: SELECT '(1,,2)'::cube AS cube;
                ^
-DETAIL:  syntax error at or near ","
+DETAIL:  syntax error at or near ",".
 -- invalid input: semantic errors and trailing garbage
 SELECT '[(1),(2)],'::cube AS cube; -- 0
 ERROR:  invalid input syntax for cube
 LINE 1: SELECT '[(1),(2)],'::cube AS cube;
                ^
-DETAIL:  syntax error at or near ","
+DETAIL:  syntax error at or near ",".
 SELECT '[(1,2,3),(2,3)]'::cube AS cube; -- 1
 ERROR:  invalid input syntax for cube
 LINE 1: SELECT '[(1,2,3),(2,3)]'::cube AS cube;
@@ -275,7 +275,7 @@ SELECT '(1),(2),'::cube AS cube; -- 2
 ERROR:  invalid input syntax for cube
 LINE 1: SELECT '(1),(2),'::cube AS cube;
                ^
-DETAIL:  syntax error at or near ","
+DETAIL:  syntax error at or near ",".
 SELECT '(1,2,3),(2,3)'::cube AS cube; -- 3
 ERROR:  invalid input syntax for cube
 LINE 1: SELECT '(1,2,3),(2,3)'::cube AS cube;
@@ -290,37 +290,37 @@ SELECT '(1,2,3)ab'::cube AS cube; -- 4
 ERROR:  invalid input syntax for cube
 LINE 1: SELECT '(1,2,3)ab'::cube AS cube;
                ^
-DETAIL:  syntax error at or near "a"
+DETAIL:  syntax error at or near "a".
 SELECT '(1,2,3)a'::cube AS cube; -- 5
 ERROR:  invalid input syntax for cube
 LINE 1: SELECT '(1,2,3)a'::cube AS cube;
                ^
-DETAIL:  syntax error at or near "a"
+DETAIL:  syntax error at or near "a".
 SELECT '(1,2)('::cube AS cube; -- 5
 ERROR:  invalid input syntax for cube
 LINE 1: SELECT '(1,2)('::cube AS cube;
                ^
-DETAIL:  syntax error at or near "("
+DETAIL:  syntax error at or near "(".
 SELECT '1,2ab'::cube AS cube; -- 6
 ERROR:  invalid input syntax for cube
 LINE 1: SELECT '1,2ab'::cube AS cube;
                ^
-DETAIL:  syntax error at or near "a"
+DETAIL:  syntax error at or near "a".
 SELECT '1 e7'::cube AS cube; -- 6
 ERROR:  invalid input syntax for cube
 LINE 1: SELECT '1 e7'::cube AS cube;
                ^
-DETAIL:  syntax error at or near "e"
+DETAIL:  syntax error at or near "e".
 SELECT '1,2a'::cube AS cube; -- 7
 ERROR:  invalid input syntax for cube
 LINE 1: SELECT '1,2a'::cube AS cube;
                ^
-DETAIL:  syntax error at or near "a"
+DETAIL:  syntax error at or near "a".
 SELECT '1..2'::cube AS cube; -- 7
 ERROR:  invalid input syntax for cube
 LINE 1: SELECT '1..2'::cube AS cube;
                ^
-DETAIL:  syntax error at or near ".2"
+DETAIL:  syntax error at or near ".2".
 SELECT '-1e-700'::cube AS cube; -- out of range
 ERROR:  "-1e-700" is out of range for type double precision
 LINE 1: SELECT '-1e-700'::cube AS cube;
diff --git a/contrib/dblink/dblink.c b/contrib/dblink/dblink.c
index 9798cb535bc..2113aa41333 100644
--- a/contrib/dblink/dblink.c
+++ b/contrib/dblink/dblink.c
@@ -2710,7 +2710,7 @@ dblink_security_check(PGconn *conn, const char *connname, const char *connstr)
 	ereport(ERROR,
 			(errcode(ERRCODE_S_R_E_PROHIBITED_SQL_STATEMENT_ATTEMPTED),
 			 errmsg("password or GSSAPI delegated credentials required"),
-			 errdetail("Non-superusers may only connect using credentials they provide, eg: password in connection string or delegated GSSAPI credentials"),
+			 errdetail("Non-superusers may only connect using credentials they provide, eg: password in connection string or delegated GSSAPI credentials."),
 			 errhint("Ensure provided credentials match target server's authentication method.")));
 }
 
diff --git a/contrib/passwordcheck/expected/passwordcheck.out b/contrib/passwordcheck/expected/passwordcheck.out
index 83472c76d27..9d02129e936 100644
--- a/contrib/passwordcheck/expected/passwordcheck.out
+++ b/contrib/passwordcheck/expected/passwordcheck.out
@@ -6,7 +6,7 @@ ALTER USER regress_passwordcheck_user1 PASSWORD 'a_nice_long_password';
 -- error: too short
 ALTER USER regress_passwordcheck_user1 PASSWORD 'tooshrt';
 ERROR:  password is too short
-DETAIL:  password must be at least "passwordcheck.min_password_length" (8) bytes long
+DETAIL:  Password must be at least "passwordcheck.min_password_length" (8) bytes long.
 -- ok
 SET passwordcheck.min_password_length = 6;
 ALTER USER regress_passwordcheck_user1 PASSWORD 'v_shrt';
diff --git a/contrib/passwordcheck/expected/passwordcheck_1.out b/contrib/passwordcheck/expected/passwordcheck_1.out
index fb12ec45cc4..a334720431d 100644
--- a/contrib/passwordcheck/expected/passwordcheck_1.out
+++ b/contrib/passwordcheck/expected/passwordcheck_1.out
@@ -6,7 +6,7 @@ ALTER USER regress_passwordcheck_user1 PASSWORD 'a_nice_long_password';
 -- error: too short
 ALTER USER regress_passwordcheck_user1 PASSWORD 'tooshrt';
 ERROR:  password is too short
-DETAIL:  password must be at least "passwordcheck.min_password_length" (8) bytes long
+DETAIL:  Password must be at least "passwordcheck.min_password_length" (8) bytes long.
 -- ok
 SET passwordcheck.min_password_length = 6;
 ALTER USER regress_passwordcheck_user1 PASSWORD 'v_shrt';
diff --git a/contrib/passwordcheck/passwordcheck.c b/contrib/passwordcheck/passwordcheck.c
index 13fd5c976a0..b45187cce9e 100644
--- a/contrib/passwordcheck/passwordcheck.c
+++ b/contrib/passwordcheck/passwordcheck.c
@@ -101,7 +101,7 @@ check_password(const char *username,
 			ereport(ERROR,
 					(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
 					 errmsg("password is too short"),
-					 errdetail("password must be at least \"passwordcheck.min_password_length\" (%d) bytes long",
+					 errdetail("Password must be at least \"passwordcheck.min_password_length\" (%d) bytes long.",
 							   min_password_length)));
 
 		/* check if the password contains the username */
diff --git a/contrib/pg_stash_advice/expected/pg_stash_advice.out b/contrib/pg_stash_advice/expected/pg_stash_advice.out
index 788da854aa7..8c24a21295e 100644
--- a/contrib/pg_stash_advice/expected/pg_stash_advice.out
+++ b/contrib/pg_stash_advice/expected/pg_stash_advice.out
@@ -315,7 +315,7 @@ SELECT pg_create_advice_stash('   ');
 ERROR:  advice stash name must begin with a letter or underscore and contain only letters, digits, and underscores
 SET pg_stash_advice.stash_name = '99bottles';
 ERROR:  invalid value for parameter "pg_stash_advice.stash_name": "99bottles"
-DETAIL:  advice stash name must begin with a letter or underscore and contain only letters, digits, and underscores
+DETAIL:  Advice stash name must begin with a letter or underscore and contain only letters, digits, and underscores.
 -- Clean up state in dynamic shared memory.
 SELECT pg_drop_advice_stash('regress_stash');
  pg_drop_advice_stash 
diff --git a/contrib/pg_stash_advice/expected/pg_stash_advice_utf8.out b/contrib/pg_stash_advice/expected/pg_stash_advice_utf8.out
index 7c532571ed5..c4bc93c8efb 100644
--- a/contrib/pg_stash_advice/expected/pg_stash_advice_utf8.out
+++ b/contrib/pg_stash_advice/expected/pg_stash_advice_utf8.out
@@ -13,4 +13,4 @@ SELECT pg_create_advice_stash('café');
 ERROR:  advice stash name must not contain non-ASCII characters
 SET pg_stash_advice.stash_name = 'café';
 ERROR:  invalid value for parameter "pg_stash_advice.stash_name": "café"
-DETAIL:  advice stash name must not contain non-ASCII characters
+DETAIL:  Advice stash name must not contain non-ASCII characters.
diff --git a/contrib/pg_stash_advice/pg_stash_advice.c b/contrib/pg_stash_advice/pg_stash_advice.c
index 1858c6a135a..343258c88b1 100644
--- a/contrib/pg_stash_advice/pg_stash_advice.c
+++ b/contrib/pg_stash_advice/pg_stash_advice.c
@@ -385,7 +385,7 @@ pgsa_check_stash_name_guc(char **newval, void **extra, GucSource source)
 	if (strlen(stash_name) + 1 > NAMEDATALEN)
 	{
 		GUC_check_errcode(ERRCODE_INVALID_PARAMETER_VALUE);
-		GUC_check_errdetail("advice stash names may not be longer than %d bytes",
+		GUC_check_errdetail("Advice stash names may not be longer than %d bytes.",
 							NAMEDATALEN - 1);
 		return false;
 	}
@@ -397,7 +397,7 @@ pgsa_check_stash_name_guc(char **newval, void **extra, GucSource source)
 	if (!pg_is_ascii(stash_name))
 	{
 		GUC_check_errcode(ERRCODE_INVALID_PARAMETER_VALUE);
-		GUC_check_errdetail("advice stash name must not contain non-ASCII characters");
+		GUC_check_errdetail("Advice stash name must not contain non-ASCII characters.");
 		return false;
 	}
 
@@ -409,7 +409,7 @@ pgsa_check_stash_name_guc(char **newval, void **extra, GucSource source)
 	if (!pgsa_is_identifier(stash_name))
 	{
 		GUC_check_errcode(ERRCODE_INVALID_PARAMETER_VALUE);
-		GUC_check_errdetail("advice stash name must begin with a letter or underscore and contain only letters, digits, and underscores");
+		GUC_check_errdetail("Advice stash name must begin with a letter or underscore and contain only letters, digits, and underscores.");
 		return false;
 	}
 
@@ -698,7 +698,7 @@ pgsa_set_advice_string(char *stash_name, int64 queryId, char *advice_string)
 		ereport(ERROR,
 				errcode(ERRCODE_OUT_OF_MEMORY),
 				errmsg("out of memory"),
-				errdetail("could not insert advice string into shared hash table"));
+				errdetail("Could not insert advice string into shared hash table."));
 	}
 
 	/* Update the entry and release the lock. */
diff --git a/contrib/postgres_fdw/expected/postgres_fdw.out b/contrib/postgres_fdw/expected/postgres_fdw.out
index 10e87acabef..f0bf16b3bd5 100644
--- a/contrib/postgres_fdw/expected/postgres_fdw.out
+++ b/contrib/postgres_fdw/expected/postgres_fdw.out
@@ -11664,7 +11664,7 @@ DELETE FROM result_tbl;
 -- Test COPY TO when foreign table is partition
 COPY async_pt TO stdout; --error
 ERROR:  cannot copy from foreign table "async_p1"
-DETAIL:  Partition "async_p1" is a foreign table in partitioned table "async_pt"
+DETAIL:  Partition "async_p1" is a foreign table in partitioned table "async_pt".
 HINT:  Try the COPY (SELECT ...) TO variant.
 DROP FOREIGN TABLE async_p3;
 DROP TABLE base_tbl3;
diff --git a/contrib/seg/expected/seg.out b/contrib/seg/expected/seg.out
index cd21139b5a7..b9fbf23c0f1 100644
--- a/contrib/seg/expected/seg.out
+++ b/contrib/seg/expected/seg.out
@@ -405,42 +405,42 @@ SELECT ''::seg AS seg;
 ERROR:  bad seg representation
 LINE 1: SELECT ''::seg AS seg;
                ^
-DETAIL:  syntax error at end of input
+DETAIL:  syntax error at end of input.
 SELECT 'ABC'::seg AS seg;
 ERROR:  bad seg representation
 LINE 1: SELECT 'ABC'::seg AS seg;
                ^
-DETAIL:  syntax error at or near "A"
+DETAIL:  syntax error at or near "A".
 SELECT '1ABC'::seg AS seg;
 ERROR:  bad seg representation
 LINE 1: SELECT '1ABC'::seg AS seg;
                ^
-DETAIL:  syntax error at or near "A"
+DETAIL:  syntax error at or near "A".
 SELECT '1.'::seg AS seg;
 ERROR:  bad seg representation
 LINE 1: SELECT '1.'::seg AS seg;
                ^
-DETAIL:  syntax error at or near "."
+DETAIL:  syntax error at or near ".".
 SELECT '1.....'::seg AS seg;
 ERROR:  bad seg representation
 LINE 1: SELECT '1.....'::seg AS seg;
                ^
-DETAIL:  syntax error at or near ".."
+DETAIL:  syntax error at or near "..".
 SELECT '.1'::seg AS seg;
 ERROR:  bad seg representation
 LINE 1: SELECT '.1'::seg AS seg;
                ^
-DETAIL:  syntax error at or near "."
+DETAIL:  syntax error at or near ".".
 SELECT '1..2.'::seg AS seg;
 ERROR:  bad seg representation
 LINE 1: SELECT '1..2.'::seg AS seg;
                ^
-DETAIL:  syntax error at or near "."
+DETAIL:  syntax error at or near ".".
 SELECT '1 e7'::seg AS seg;
 ERROR:  bad seg representation
 LINE 1: SELECT '1 e7'::seg AS seg;
                ^
-DETAIL:  syntax error at or near "e"
+DETAIL:  syntax error at or near "e".
 SELECT '1e700'::seg AS seg;
 ERROR:  "1e700" is out of range for type real
 LINE 1: SELECT '1e700'::seg AS seg;
@@ -1287,13 +1287,13 @@ FROM unnest(ARRAY['-1 .. 1'::text,
                   '1 e7',
                   '1e700']) str,
      LATERAL pg_input_error_info(str, 'seg') as errinfo;
-   seg    | ok | sql_error_code |                message                |            detail            | hint 
-----------+----+----------------+---------------------------------------+------------------------------+------
- -1 .. 1  | t  |                |                                       |                              | 
- 100(+-)1 | t  |                |                                       |                              | 
-          | f  | 42601          | bad seg representation                | syntax error at end of input | 
- ABC      | f  | 42601          | bad seg representation                | syntax error at or near "A"  | 
- 1 e7     | f  | 42601          | bad seg representation                | syntax error at or near "e"  | 
- 1e700    | f  | 22003          | "1e700" is out of range for type real |                              | 
+   seg    | ok | sql_error_code |                message                |            detail             | hint 
+----------+----+----------------+---------------------------------------+-------------------------------+------
+ -1 .. 1  | t  |                |                                       |                               | 
+ 100(+-)1 | t  |                |                                       |                               | 
+          | f  | 42601          | bad seg representation                | syntax error at end of input. | 
+ ABC      | f  | 42601          | bad seg representation                | syntax error at or near "A".  | 
+ 1 e7     | f  | 42601          | bad seg representation                | syntax error at or near "e".  | 
+ 1e700    | f  | 22003          | "1e700" is out of range for type real |                               | 
 (6 rows)
 
diff --git a/contrib/seg/segscan.l b/contrib/seg/segscan.l
index 3a0cd7ed506..18558688765 100644
--- a/contrib/seg/segscan.l
+++ b/contrib/seg/segscan.l
@@ -79,7 +79,7 @@ seg_yyerror(SEG *result, struct Node *escontext, yyscan_t yyscanner, const char
 				(errcode(ERRCODE_SYNTAX_ERROR),
 				 errmsg("bad seg representation"),
 		/* translator: %s is typically "syntax error" */
-				 errdetail("%s at end of input", message)));
+				 errdetail("%s at end of input.", message)));
 	}
 	else
 	{
@@ -87,7 +87,7 @@ seg_yyerror(SEG *result, struct Node *escontext, yyscan_t yyscanner, const char
 				(errcode(ERRCODE_SYNTAX_ERROR),
 				 errmsg("bad seg representation"),
 		/* translator: first %s is typically "syntax error" */
-				 errdetail("%s at or near \"%s\"", message, yytext)));
+				 errdetail("%s at or near \"%s\".", message, yytext)));
 	}
 }
 
diff --git a/src/backend/commands/copyto.c b/src/backend/commands/copyto.c
index f0e0147c665..2d2a2e84952 100644
--- a/src/backend/commands/copyto.c
+++ b/src/backend/commands/copyto.c
@@ -838,7 +838,7 @@ BeginCopyTo(ParseState *pstate,
 					ereport(ERROR,
 							errcode(ERRCODE_WRONG_OBJECT_TYPE),
 							errmsg("cannot copy from foreign table \"%s\"", relation_name),
-							errdetail("Partition \"%s\" is a foreign table in partitioned table \"%s\"",
+							errdetail("Partition \"%s\" is a foreign table in partitioned table \"%s\".",
 									  relation_name, RelationGetRelationName(rel)),
 							errhint("Try the COPY (SELECT ...) TO variant."));
 				}
diff --git a/src/backend/commands/extension.c b/src/backend/commands/extension.c
index a330b5fd6ce..cd8810e7dbd 100644
--- a/src/backend/commands/extension.c
+++ b/src/backend/commands/extension.c
@@ -3431,7 +3431,7 @@ AlterExtensionNamespace(const char *extensionName, const char *newschema, Oid *o
 					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 					 errmsg("extension \"%s\" does not support SET SCHEMA",
 							NameStr(extForm->extname)),
-					 errdetail("%s is not in the extension's schema \"%s\"",
+					 errdetail("%s is not in the extension's schema \"%s\".",
 							   getObjectDescription(&dep, false),
 							   get_namespace_name(oldNspOid))));
 	}
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 803a0e47567..d9d5622aa46 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -15377,7 +15377,7 @@ RememberAllDependentForRebuilding(AlteredTableInfo *tab, AlterTableType subtype,
 					ereport(ERROR,
 							(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 							 errmsg("cannot alter type of a column used by a function or procedure"),
-							 errdetail("%s depends on column \"%s\"",
+							 errdetail("%s depends on column \"%s\".",
 									   getObjectDescription(&foundObject, false),
 									   colName)));
 				break;
@@ -15392,7 +15392,7 @@ RememberAllDependentForRebuilding(AlteredTableInfo *tab, AlterTableType subtype,
 					ereport(ERROR,
 							(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 							 errmsg("cannot alter type of a column used by a view or rule"),
-							 errdetail("%s depends on column \"%s\"",
+							 errdetail("%s depends on column \"%s\".",
 									   getObjectDescription(&foundObject, false),
 									   colName)));
 				break;
@@ -15412,7 +15412,7 @@ RememberAllDependentForRebuilding(AlteredTableInfo *tab, AlterTableType subtype,
 					ereport(ERROR,
 							(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 							 errmsg("cannot alter type of a column used in a trigger definition"),
-							 errdetail("%s depends on column \"%s\"",
+							 errdetail("%s depends on column \"%s\".",
 									   getObjectDescription(&foundObject, false),
 									   colName)));
 				break;
@@ -15431,7 +15431,7 @@ RememberAllDependentForRebuilding(AlteredTableInfo *tab, AlterTableType subtype,
 					ereport(ERROR,
 							(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 							 errmsg("cannot alter type of a column used in a policy definition"),
-							 errdetail("%s depends on column \"%s\"",
+							 errdetail("%s depends on column \"%s\".",
 									   getObjectDescription(&foundObject, false),
 									   colName)));
 				break;
@@ -15490,7 +15490,7 @@ RememberAllDependentForRebuilding(AlteredTableInfo *tab, AlterTableType subtype,
 					ereport(ERROR,
 							(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 							 errmsg("cannot alter type of a column used by a publication WHERE clause"),
-							 errdetail("%s depends on column \"%s\"",
+							 errdetail("%s depends on column \"%s\".",
 									   getObjectDescription(&foundObject, false),
 									   colName)));
 				break;
diff --git a/src/backend/libpq/be-secure-openssl.c b/src/backend/libpq/be-secure-openssl.c
index a3e222f3a3d..c7fe2dc7b99 100644
--- a/src/backend/libpq/be-secure-openssl.c
+++ b/src/backend/libpq/be-secure-openssl.c
@@ -473,7 +473,7 @@ be_tls_init(bool isServerStart)
 			ereport(isServerStart ? FATAL : LOG,
 					(errcode(ERRCODE_CONFIG_FILE_ERROR),
 					 errmsg("could not set SSL protocol version range"),
-					 errdetail("\"%s\" cannot be higher than \"%s\"",
+					 errdetail("\"%s\" cannot be higher than \"%s\".",
 							   "ssl_min_protocol_version",
 							   "ssl_max_protocol_version")));
 			goto error;
diff --git a/src/backend/partitioning/partbounds.c b/src/backend/partitioning/partbounds.c
index 5afa781f086..8b1ac2a90a9 100644
--- a/src/backend/partitioning/partbounds.c
+++ b/src/backend/partitioning/partbounds.c
@@ -5032,7 +5032,7 @@ check_two_partitions_bounds_range(Relation parent,
 					errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
 					errmsg("can not merge partition \"%s\" together with partition \"%s\"",
 						   second_name->relname, first_name->relname),
-					errdetail("lower bound of partition \"%s\" is not equal to the upper bound of partition \"%s\"",
+					errdetail("Lower bound of partition \"%s\" is not equal to the upper bound of partition \"%s\".",
 							  second_name->relname, first_name->relname),
 					errhint("ALTER TABLE ... MERGE PARTITIONS requires the partition bounds to be adjacent."),
 					parser_errposition(pstate, datum->location));
@@ -5041,7 +5041,7 @@ check_two_partitions_bounds_range(Relation parent,
 					errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
 					errmsg("can not split to partition \"%s\" together with partition \"%s\"",
 						   second_name->relname, first_name->relname),
-					errdetail("lower bound of partition \"%s\" is not equal to the upper bound of partition \"%s\"",
+					errdetail("Lower bound of partition \"%s\" is not equal to the upper bound of partition \"%s\".",
 							  second_name->relname, first_name->relname),
 					errhint("ALTER TABLE ... SPLIT PARTITION requires the partition bounds to be adjacent."),
 					parser_errposition(pstate, datum->location));
diff --git a/src/test/modules/test_extensions/expected/test_extensions.out b/src/test/modules/test_extensions/expected/test_extensions.out
index fdae52d6ab2..1b5debdeeb1 100644
--- a/src/test/modules/test_extensions/expected/test_extensions.out
+++ b/src/test/modules/test_extensions/expected/test_extensions.out
@@ -566,7 +566,7 @@ SELECT pg_describe_object(classid, objid, objsubid) as obj,
 -- fails, as function dep_req1 is not in the same schema as the extension.
 ALTER EXTENSION test_ext_req_schema1 SET SCHEMA test_func_dep3;
 ERROR:  extension "test_ext_req_schema1" does not support SET SCHEMA
-DETAIL:  function test_func_dep2.dep_req1() is not in the extension's schema "test_func_dep1"
+DETAIL:  function test_func_dep2.dep_req1() is not in the extension's schema "test_func_dep1".
 -- Move back the function, and the extension can be moved.
 ALTER FUNCTION test_func_dep2.dep_req1() SET SCHEMA test_func_dep1;
 ALTER EXTENSION test_ext_req_schema1 SET SCHEMA test_func_dep3;
diff --git a/src/test/regress/expected/create_view.out b/src/test/regress/expected/create_view.out
index 63cf4b4371d..053fa56573f 100644
--- a/src/test/regress/expected/create_view.out
+++ b/src/test/regress/expected/create_view.out
@@ -1720,7 +1720,7 @@ rollback;
 -- likewise, altering a referenced column's type is prohibited ...
 alter table tt14t alter column f4 type integer using f4::integer;  -- fail
 ERROR:  cannot alter type of a column used by a view or rule
-DETAIL:  rule _RETURN on view tt14v depends on column "f4"
+DETAIL:  rule _RETURN on view tt14v depends on column "f4".
 -- ... but some bug might let it happen, so check defenses
 begin;
 -- destroy the dependency entry that prevents the ALTER:
diff --git a/src/test/regress/expected/partition_merge.out b/src/test/regress/expected/partition_merge.out
index 883110e25d9..9b8f5ee137c 100644
--- a/src/test/regress/expected/partition_merge.out
+++ b/src/test/regress/expected/partition_merge.out
@@ -35,14 +35,14 @@ HINT:  ALTER TABLE ... MERGE PARTITIONS can only merge partitions don't have sub
 -- (space between sections sales_jan2022 and sales_mar2022)
 ALTER TABLE sales_range MERGE PARTITIONS (sales_jan2022, sales_mar2022) INTO sales_jan_mar2022;
 ERROR:  can not merge partition "sales_mar2022" together with partition "sales_jan2022"
-DETAIL:  lower bound of partition "sales_mar2022" is not equal to the upper bound of partition "sales_jan2022"
+DETAIL:  Lower bound of partition "sales_mar2022" is not equal to the upper bound of partition "sales_jan2022".
 HINT:  ALTER TABLE ... MERGE PARTITIONS requires the partition bounds to be adjacent.
 -- ERROR:  can not merge partition "sales_jan2022" together with partition "sales_dec2021"
 -- DETAIL:  lower bound of partition "sales_jan2022" is not equal to the upper bound of partition "sales_dec2021"
 -- (space between sections sales_dec2021 and sales_jan2022)
 ALTER TABLE sales_range MERGE PARTITIONS (sales_dec2021, sales_jan2022, sales_feb2022) INTO sales_dec_jan_feb2022;
 ERROR:  can not merge partition "sales_jan2022" together with partition "sales_dec2021"
-DETAIL:  lower bound of partition "sales_jan2022" is not equal to the upper bound of partition "sales_dec2021"
+DETAIL:  Lower bound of partition "sales_jan2022" is not equal to the upper bound of partition "sales_dec2021".
 HINT:  ALTER TABLE ... MERGE PARTITIONS requires the partition bounds to be adjacent.
 -- ERROR:  partition with name "sales_feb2022" is already used
 ALTER TABLE sales_range MERGE PARTITIONS (sales_feb2022, sales_mar2022, partitions_merge_schema.sales_feb2022) INTO sales_feb_mar_apr2022;
diff --git a/src/test/regress/expected/partition_split.out b/src/test/regress/expected/partition_split.out
index 43ca299648e..e35e859cc13 100644
--- a/src/test/regress/expected/partition_split.out
+++ b/src/test/regress/expected/partition_split.out
@@ -109,7 +109,7 @@ ALTER TABLE sales_range SPLIT PARTITION sales_feb_mar_apr2022 INTO
 ERROR:  can not split to partition "sales_mar2022" together with partition "sales_feb2022"
 LINE 3:    PARTITION sales_mar2022 FOR VALUES FROM ('2022-02-01') TO...
                                                     ^
-DETAIL:  lower bound of partition "sales_mar2022" is not equal to the upper bound of partition "sales_feb2022"
+DETAIL:  Lower bound of partition "sales_mar2022" is not equal to the upper bound of partition "sales_feb2022".
 HINT:  ALTER TABLE ... SPLIT PARTITION requires the partition bounds to be adjacent.
 -- Tests for spaces between partitions, them should be executed without DEFAULT partition
 ALTER TABLE sales_range DETACH PARTITION sales_others;
@@ -470,7 +470,7 @@ ALTER TABLE sales_range SPLIT PARTITION sales_others INTO
 ERROR:  can not split to partition "sales_error" together with partition "sales_dec2021"
 LINE 3:    PARTITION sales_error FOR VALUES FROM ('2021-12-30') TO (...
                                                   ^
-DETAIL:  lower bound of partition "sales_error" is not equal to the upper bound of partition "sales_dec2021"
+DETAIL:  Lower bound of partition "sales_error" is not equal to the upper bound of partition "sales_dec2021".
 HINT:  ALTER TABLE ... SPLIT PARTITION requires the partition bounds to be adjacent.
 -- sales_error intersects with sales_feb2022 (upper bound)
 -- ERROR:  can not split to partition "sales_feb2022" together with partition "sales_error"
@@ -482,7 +482,7 @@ ALTER TABLE sales_range SPLIT PARTITION sales_others INTO
 ERROR:  can not split to partition "sales_feb2022" together with partition "sales_error"
 LINE 4:    PARTITION sales_feb2022 FOR VALUES FROM ('2022-02-01') TO...
                                                     ^
-DETAIL:  lower bound of partition "sales_feb2022" is not equal to the upper bound of partition "sales_error"
+DETAIL:  Lower bound of partition "sales_feb2022" is not equal to the upper bound of partition "sales_error".
 HINT:  ALTER TABLE ... SPLIT PARTITION requires the partition bounds to be adjacent.
 -- sales_error intersects with sales_dec2021 (inside bound)
 -- ERROR:  can not split to partition "sales_error" together with partition "sales_dec2021"
@@ -494,7 +494,7 @@ ALTER TABLE sales_range SPLIT PARTITION sales_others INTO
 ERROR:  can not split to partition "sales_error" together with partition "sales_dec2021"
 LINE 3:    PARTITION sales_error FOR VALUES FROM ('2021-12-10') TO (...
                                                   ^
-DETAIL:  lower bound of partition "sales_error" is not equal to the upper bound of partition "sales_dec2021"
+DETAIL:  Lower bound of partition "sales_error" is not equal to the upper bound of partition "sales_dec2021".
 HINT:  ALTER TABLE ... SPLIT PARTITION requires the partition bounds to be adjacent.
 -- sales_error intersects with sales_dec2021 (exactly the same bounds)
 -- ERROR:  can not split to partition "sales_error" together with partition "sales_dec2021"
@@ -506,7 +506,7 @@ ALTER TABLE sales_range SPLIT PARTITION sales_others INTO
 ERROR:  can not split to partition "sales_error" together with partition "sales_dec2021"
 LINE 3:    PARTITION sales_error FOR VALUES FROM ('2021-12-01') TO (...
                                                   ^
-DETAIL:  lower bound of partition "sales_error" is not equal to the upper bound of partition "sales_dec2021"
+DETAIL:  Lower bound of partition "sales_error" is not equal to the upper bound of partition "sales_dec2021".
 HINT:  ALTER TABLE ... SPLIT PARTITION requires the partition bounds to be adjacent.
 -- ERROR:  can not split DEFAULT partition "sales_others"
 -- HINT:  To split DEFAULT partition one of the new partition must be DEFAULT.
diff --git a/src/test/regress/expected/rangefuncs.out b/src/test/regress/expected/rangefuncs.out
index 5cc94011e97..a7cb1b5611d 100644
--- a/src/test/regress/expected/rangefuncs.out
+++ b/src/test/regress/expected/rangefuncs.out
@@ -2279,7 +2279,7 @@ ERROR:  attribute 5 of type record has been dropped
 rollback;
 alter table users alter column seq type numeric;  -- fail, view has reference
 ERROR:  cannot alter type of a column used by a view or rule
-DETAIL:  rule _RETURN on view usersview depends on column "seq"
+DETAIL:  rule _RETURN on view usersview depends on column "seq".
 -- likewise, check we don't crash if the dependency goes wrong
 begin;
 -- destroy the dependency entry that prevents the ALTER:
-- 
2.47.3



^ permalink  raw  reply  [nested|flat] 12+ messages in thread

* Re: Add missing period to DETAIL messages
@ 2026-04-15 18:26  Peter Eisentraut <[email protected]>
  parent: Peter Smith <[email protected]>
  0 siblings, 1 reply; 12+ messages in thread

From: Peter Eisentraut @ 2026-04-15 18:26 UTC (permalink / raw)
  To: Peter Smith <[email protected]>; Xiaopeng Wang <[email protected]>; +Cc: Chao Li <[email protected]>; PostgreSQL Hackers <[email protected]>

On 15.04.26 09:41, Peter Smith wrote:
> On Wed, Apr 15, 2026 at 3:48 PM Xiaopeng Wang <[email protected]> wrote:
>>
> ...
>>
>> Looks good to me.
>>
>> A small comment is that, the commit message claims only “add missing period to DETAIL messages”, but apparently the patch also changes capitalization in many places, so the commit message should be updated.
>>
> 
> Fair point. Thanks for your review!
> 
> PSA v4 which has an improved commit message.

Most of these look good, but I don't think this is an improvement:

-DETAIL:  syntax error at end of input
+DETAIL:  syntax error at end of input.

The guidelines say that the detail message should be a sentence.  But 
this is not a sentence.  Just adding a period doesn't make it a 
sentence.  IMO, having a period at the end of a thing that is not a 
sentence is worse than not having it be a sentence.  The latter just 
violates our quality standards, the former is confusing for a user who 
sees that particular output.






^ permalink  raw  reply  [nested|flat] 12+ messages in thread

* Re: Add missing period to DETAIL messages
@ 2026-04-16 00:22  Peter Smith <[email protected]>
  parent: Peter Eisentraut <[email protected]>
  0 siblings, 1 reply; 12+ messages in thread

From: Peter Smith @ 2026-04-16 00:22 UTC (permalink / raw)
  To: Peter Eisentraut <[email protected]>; +Cc: Xiaopeng Wang <[email protected]>; Chao Li <[email protected]>; PostgreSQL Hackers <[email protected]>

On Thu, Apr 16, 2026 at 4:26 AM Peter Eisentraut <[email protected]> wrote:
>
> On 15.04.26 09:41, Peter Smith wrote:
> > On Wed, Apr 15, 2026 at 3:48 PM Xiaopeng Wang <[email protected]> wrote:
> >>
> > ...
> >>
> >> Looks good to me.
> >>
> >> A small comment is that, the commit message claims only “add missing period to DETAIL messages”, but apparently the patch also changes capitalization in many places, so the commit message should be updated.
> >>
> >
> > Fair point. Thanks for your review!
> >
> > PSA v4 which has an improved commit message.
>
> Most of these look good, but I don't think this is an improvement:
>
> -DETAIL:  syntax error at end of input
> +DETAIL:  syntax error at end of input.
>
> The guidelines say that the detail message should be a sentence.  But
> this is not a sentence.  Just adding a period doesn't make it a
> sentence.  IMO, having a period at the end of a thing that is not a
> sentence is worse than not having it be a sentence.  The latter just
> violates our quality standards, the former is confusing for a user who
> sees that particular output.

Thanks for your review.

OK, I've removed that "syntax error at end of input." change from the patch.

IIUC, the identical (non-sentence) issue also applies to other ones
like 'syntax error at or near \"%s\".'
So I  removed those from the patch, too.

PSA v5, which makes the above changes.

~~

Now I am having doubts about those '%s depends on column \"%s\".' changes.

Despite looking like sentences, I have no control over the first word
capitalisation, so the results are like:
-DETAIL:  rule _RETURN on view usersview depends on column "seq"
+DETAIL:  rule _RETURN on view usersview depends on column "seq".

In hindsight, maybe just adding periods for these was also not
warranted? What do you think about those?

======
Kind Regards,
Peter Smith.
Fujitsu Australia


Attachments:

  [application/octet-stream] v5-0001-Change-DETAIL-messages-to-conform-to-the-style-gu.patch (22.8K, 2-v5-0001-Change-DETAIL-messages-to-conform-to-the-style-gu.patch)
  download | inline diff:
From 05bfe46802b6bbff220b59cb123bf02a3a83ed90 Mon Sep 17 00:00:00 2001
From: Peter Smith <[email protected]>
Date: Thu, 16 Apr 2026 10:13:56 +1000
Subject: [PATCH v5] Change DETAIL messages to conform to the style guide by
 capitalizing the first word of sentences and ending sentences with a period.

Author: Peter Smith <[email protected]>
Reviewed-by: Chao Li <[email protected]>
Reviewed-by: vignesh C <vignesh21.gmail.com>
Reviewed-by: Xiaopeng Wang <wxp_728.163.com>
Reviewed-by: Peter Eisentraut <[email protected]>

Discussion: https://www.postgresql.org/message-id/flat/CAHut%2BPszSntkUgN%2BQa9matGY6MLEoFGSuVbuKDgnnTdZ7YPRwg%40mail.gmail.com
---
 contrib/dblink/dblink.c                                |  2 +-
 contrib/passwordcheck/expected/passwordcheck.out       |  2 +-
 contrib/passwordcheck/expected/passwordcheck_1.out     |  2 +-
 contrib/passwordcheck/passwordcheck.c                  |  2 +-
 contrib/pg_stash_advice/expected/pg_stash_advice.out   |  2 +-
 .../pg_stash_advice/expected/pg_stash_advice_utf8.out  |  2 +-
 contrib/pg_stash_advice/pg_stash_advice.c              |  8 ++++----
 contrib/postgres_fdw/expected/postgres_fdw.out         |  2 +-
 src/backend/commands/copyto.c                          |  2 +-
 src/backend/commands/extension.c                       |  2 +-
 src/backend/commands/tablecmds.c                       | 10 +++++-----
 src/backend/libpq/be-secure-openssl.c                  |  2 +-
 src/backend/partitioning/partbounds.c                  |  4 ++--
 .../test_extensions/expected/test_extensions.out       |  2 +-
 src/test/regress/expected/create_view.out              |  2 +-
 src/test/regress/expected/partition_merge.out          |  4 ++--
 src/test/regress/expected/partition_split.out          | 10 +++++-----
 src/test/regress/expected/rangefuncs.out               |  2 +-
 18 files changed, 31 insertions(+), 31 deletions(-)

diff --git a/contrib/dblink/dblink.c b/contrib/dblink/dblink.c
index 9798cb535bc..2113aa41333 100644
--- a/contrib/dblink/dblink.c
+++ b/contrib/dblink/dblink.c
@@ -2710,7 +2710,7 @@ dblink_security_check(PGconn *conn, const char *connname, const char *connstr)
 	ereport(ERROR,
 			(errcode(ERRCODE_S_R_E_PROHIBITED_SQL_STATEMENT_ATTEMPTED),
 			 errmsg("password or GSSAPI delegated credentials required"),
-			 errdetail("Non-superusers may only connect using credentials they provide, eg: password in connection string or delegated GSSAPI credentials"),
+			 errdetail("Non-superusers may only connect using credentials they provide, eg: password in connection string or delegated GSSAPI credentials."),
 			 errhint("Ensure provided credentials match target server's authentication method.")));
 }
 
diff --git a/contrib/passwordcheck/expected/passwordcheck.out b/contrib/passwordcheck/expected/passwordcheck.out
index 83472c76d27..9d02129e936 100644
--- a/contrib/passwordcheck/expected/passwordcheck.out
+++ b/contrib/passwordcheck/expected/passwordcheck.out
@@ -6,7 +6,7 @@ ALTER USER regress_passwordcheck_user1 PASSWORD 'a_nice_long_password';
 -- error: too short
 ALTER USER regress_passwordcheck_user1 PASSWORD 'tooshrt';
 ERROR:  password is too short
-DETAIL:  password must be at least "passwordcheck.min_password_length" (8) bytes long
+DETAIL:  Password must be at least "passwordcheck.min_password_length" (8) bytes long.
 -- ok
 SET passwordcheck.min_password_length = 6;
 ALTER USER regress_passwordcheck_user1 PASSWORD 'v_shrt';
diff --git a/contrib/passwordcheck/expected/passwordcheck_1.out b/contrib/passwordcheck/expected/passwordcheck_1.out
index fb12ec45cc4..a334720431d 100644
--- a/contrib/passwordcheck/expected/passwordcheck_1.out
+++ b/contrib/passwordcheck/expected/passwordcheck_1.out
@@ -6,7 +6,7 @@ ALTER USER regress_passwordcheck_user1 PASSWORD 'a_nice_long_password';
 -- error: too short
 ALTER USER regress_passwordcheck_user1 PASSWORD 'tooshrt';
 ERROR:  password is too short
-DETAIL:  password must be at least "passwordcheck.min_password_length" (8) bytes long
+DETAIL:  Password must be at least "passwordcheck.min_password_length" (8) bytes long.
 -- ok
 SET passwordcheck.min_password_length = 6;
 ALTER USER regress_passwordcheck_user1 PASSWORD 'v_shrt';
diff --git a/contrib/passwordcheck/passwordcheck.c b/contrib/passwordcheck/passwordcheck.c
index 13fd5c976a0..b45187cce9e 100644
--- a/contrib/passwordcheck/passwordcheck.c
+++ b/contrib/passwordcheck/passwordcheck.c
@@ -101,7 +101,7 @@ check_password(const char *username,
 			ereport(ERROR,
 					(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
 					 errmsg("password is too short"),
-					 errdetail("password must be at least \"passwordcheck.min_password_length\" (%d) bytes long",
+					 errdetail("Password must be at least \"passwordcheck.min_password_length\" (%d) bytes long.",
 							   min_password_length)));
 
 		/* check if the password contains the username */
diff --git a/contrib/pg_stash_advice/expected/pg_stash_advice.out b/contrib/pg_stash_advice/expected/pg_stash_advice.out
index 788da854aa7..8c24a21295e 100644
--- a/contrib/pg_stash_advice/expected/pg_stash_advice.out
+++ b/contrib/pg_stash_advice/expected/pg_stash_advice.out
@@ -315,7 +315,7 @@ SELECT pg_create_advice_stash('   ');
 ERROR:  advice stash name must begin with a letter or underscore and contain only letters, digits, and underscores
 SET pg_stash_advice.stash_name = '99bottles';
 ERROR:  invalid value for parameter "pg_stash_advice.stash_name": "99bottles"
-DETAIL:  advice stash name must begin with a letter or underscore and contain only letters, digits, and underscores
+DETAIL:  Advice stash name must begin with a letter or underscore and contain only letters, digits, and underscores.
 -- Clean up state in dynamic shared memory.
 SELECT pg_drop_advice_stash('regress_stash');
  pg_drop_advice_stash 
diff --git a/contrib/pg_stash_advice/expected/pg_stash_advice_utf8.out b/contrib/pg_stash_advice/expected/pg_stash_advice_utf8.out
index 7c532571ed5..c4bc93c8efb 100644
--- a/contrib/pg_stash_advice/expected/pg_stash_advice_utf8.out
+++ b/contrib/pg_stash_advice/expected/pg_stash_advice_utf8.out
@@ -13,4 +13,4 @@ SELECT pg_create_advice_stash('café');
 ERROR:  advice stash name must not contain non-ASCII characters
 SET pg_stash_advice.stash_name = 'café';
 ERROR:  invalid value for parameter "pg_stash_advice.stash_name": "café"
-DETAIL:  advice stash name must not contain non-ASCII characters
+DETAIL:  Advice stash name must not contain non-ASCII characters.
diff --git a/contrib/pg_stash_advice/pg_stash_advice.c b/contrib/pg_stash_advice/pg_stash_advice.c
index 1858c6a135a..343258c88b1 100644
--- a/contrib/pg_stash_advice/pg_stash_advice.c
+++ b/contrib/pg_stash_advice/pg_stash_advice.c
@@ -385,7 +385,7 @@ pgsa_check_stash_name_guc(char **newval, void **extra, GucSource source)
 	if (strlen(stash_name) + 1 > NAMEDATALEN)
 	{
 		GUC_check_errcode(ERRCODE_INVALID_PARAMETER_VALUE);
-		GUC_check_errdetail("advice stash names may not be longer than %d bytes",
+		GUC_check_errdetail("Advice stash names may not be longer than %d bytes.",
 							NAMEDATALEN - 1);
 		return false;
 	}
@@ -397,7 +397,7 @@ pgsa_check_stash_name_guc(char **newval, void **extra, GucSource source)
 	if (!pg_is_ascii(stash_name))
 	{
 		GUC_check_errcode(ERRCODE_INVALID_PARAMETER_VALUE);
-		GUC_check_errdetail("advice stash name must not contain non-ASCII characters");
+		GUC_check_errdetail("Advice stash name must not contain non-ASCII characters.");
 		return false;
 	}
 
@@ -409,7 +409,7 @@ pgsa_check_stash_name_guc(char **newval, void **extra, GucSource source)
 	if (!pgsa_is_identifier(stash_name))
 	{
 		GUC_check_errcode(ERRCODE_INVALID_PARAMETER_VALUE);
-		GUC_check_errdetail("advice stash name must begin with a letter or underscore and contain only letters, digits, and underscores");
+		GUC_check_errdetail("Advice stash name must begin with a letter or underscore and contain only letters, digits, and underscores.");
 		return false;
 	}
 
@@ -698,7 +698,7 @@ pgsa_set_advice_string(char *stash_name, int64 queryId, char *advice_string)
 		ereport(ERROR,
 				errcode(ERRCODE_OUT_OF_MEMORY),
 				errmsg("out of memory"),
-				errdetail("could not insert advice string into shared hash table"));
+				errdetail("Could not insert advice string into shared hash table."));
 	}
 
 	/* Update the entry and release the lock. */
diff --git a/contrib/postgres_fdw/expected/postgres_fdw.out b/contrib/postgres_fdw/expected/postgres_fdw.out
index 10e87acabef..f0bf16b3bd5 100644
--- a/contrib/postgres_fdw/expected/postgres_fdw.out
+++ b/contrib/postgres_fdw/expected/postgres_fdw.out
@@ -11664,7 +11664,7 @@ DELETE FROM result_tbl;
 -- Test COPY TO when foreign table is partition
 COPY async_pt TO stdout; --error
 ERROR:  cannot copy from foreign table "async_p1"
-DETAIL:  Partition "async_p1" is a foreign table in partitioned table "async_pt"
+DETAIL:  Partition "async_p1" is a foreign table in partitioned table "async_pt".
 HINT:  Try the COPY (SELECT ...) TO variant.
 DROP FOREIGN TABLE async_p3;
 DROP TABLE base_tbl3;
diff --git a/src/backend/commands/copyto.c b/src/backend/commands/copyto.c
index 85d15353647..5fa3bba8b56 100644
--- a/src/backend/commands/copyto.c
+++ b/src/backend/commands/copyto.c
@@ -838,7 +838,7 @@ BeginCopyTo(ParseState *pstate,
 					ereport(ERROR,
 							errcode(ERRCODE_WRONG_OBJECT_TYPE),
 							errmsg("cannot copy from foreign table \"%s\"", relation_name),
-							errdetail("Partition \"%s\" is a foreign table in partitioned table \"%s\"",
+							errdetail("Partition \"%s\" is a foreign table in partitioned table \"%s\".",
 									  relation_name, RelationGetRelationName(rel)),
 							errhint("Try the COPY (SELECT ...) TO variant."));
 				}
diff --git a/src/backend/commands/extension.c b/src/backend/commands/extension.c
index a330b5fd6ce..cd8810e7dbd 100644
--- a/src/backend/commands/extension.c
+++ b/src/backend/commands/extension.c
@@ -3431,7 +3431,7 @@ AlterExtensionNamespace(const char *extensionName, const char *newschema, Oid *o
 					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 					 errmsg("extension \"%s\" does not support SET SCHEMA",
 							NameStr(extForm->extname)),
-					 errdetail("%s is not in the extension's schema \"%s\"",
+					 errdetail("%s is not in the extension's schema \"%s\".",
 							   getObjectDescription(&dep, false),
 							   get_namespace_name(oldNspOid))));
 	}
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 803a0e47567..d9d5622aa46 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -15377,7 +15377,7 @@ RememberAllDependentForRebuilding(AlteredTableInfo *tab, AlterTableType subtype,
 					ereport(ERROR,
 							(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 							 errmsg("cannot alter type of a column used by a function or procedure"),
-							 errdetail("%s depends on column \"%s\"",
+							 errdetail("%s depends on column \"%s\".",
 									   getObjectDescription(&foundObject, false),
 									   colName)));
 				break;
@@ -15392,7 +15392,7 @@ RememberAllDependentForRebuilding(AlteredTableInfo *tab, AlterTableType subtype,
 					ereport(ERROR,
 							(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 							 errmsg("cannot alter type of a column used by a view or rule"),
-							 errdetail("%s depends on column \"%s\"",
+							 errdetail("%s depends on column \"%s\".",
 									   getObjectDescription(&foundObject, false),
 									   colName)));
 				break;
@@ -15412,7 +15412,7 @@ RememberAllDependentForRebuilding(AlteredTableInfo *tab, AlterTableType subtype,
 					ereport(ERROR,
 							(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 							 errmsg("cannot alter type of a column used in a trigger definition"),
-							 errdetail("%s depends on column \"%s\"",
+							 errdetail("%s depends on column \"%s\".",
 									   getObjectDescription(&foundObject, false),
 									   colName)));
 				break;
@@ -15431,7 +15431,7 @@ RememberAllDependentForRebuilding(AlteredTableInfo *tab, AlterTableType subtype,
 					ereport(ERROR,
 							(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 							 errmsg("cannot alter type of a column used in a policy definition"),
-							 errdetail("%s depends on column \"%s\"",
+							 errdetail("%s depends on column \"%s\".",
 									   getObjectDescription(&foundObject, false),
 									   colName)));
 				break;
@@ -15490,7 +15490,7 @@ RememberAllDependentForRebuilding(AlteredTableInfo *tab, AlterTableType subtype,
 					ereport(ERROR,
 							(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 							 errmsg("cannot alter type of a column used by a publication WHERE clause"),
-							 errdetail("%s depends on column \"%s\"",
+							 errdetail("%s depends on column \"%s\".",
 									   getObjectDescription(&foundObject, false),
 									   colName)));
 				break;
diff --git a/src/backend/libpq/be-secure-openssl.c b/src/backend/libpq/be-secure-openssl.c
index a3e222f3a3d..c7fe2dc7b99 100644
--- a/src/backend/libpq/be-secure-openssl.c
+++ b/src/backend/libpq/be-secure-openssl.c
@@ -473,7 +473,7 @@ be_tls_init(bool isServerStart)
 			ereport(isServerStart ? FATAL : LOG,
 					(errcode(ERRCODE_CONFIG_FILE_ERROR),
 					 errmsg("could not set SSL protocol version range"),
-					 errdetail("\"%s\" cannot be higher than \"%s\"",
+					 errdetail("\"%s\" cannot be higher than \"%s\".",
 							   "ssl_min_protocol_version",
 							   "ssl_max_protocol_version")));
 			goto error;
diff --git a/src/backend/partitioning/partbounds.c b/src/backend/partitioning/partbounds.c
index 5afa781f086..8b1ac2a90a9 100644
--- a/src/backend/partitioning/partbounds.c
+++ b/src/backend/partitioning/partbounds.c
@@ -5032,7 +5032,7 @@ check_two_partitions_bounds_range(Relation parent,
 					errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
 					errmsg("can not merge partition \"%s\" together with partition \"%s\"",
 						   second_name->relname, first_name->relname),
-					errdetail("lower bound of partition \"%s\" is not equal to the upper bound of partition \"%s\"",
+					errdetail("Lower bound of partition \"%s\" is not equal to the upper bound of partition \"%s\".",
 							  second_name->relname, first_name->relname),
 					errhint("ALTER TABLE ... MERGE PARTITIONS requires the partition bounds to be adjacent."),
 					parser_errposition(pstate, datum->location));
@@ -5041,7 +5041,7 @@ check_two_partitions_bounds_range(Relation parent,
 					errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
 					errmsg("can not split to partition \"%s\" together with partition \"%s\"",
 						   second_name->relname, first_name->relname),
-					errdetail("lower bound of partition \"%s\" is not equal to the upper bound of partition \"%s\"",
+					errdetail("Lower bound of partition \"%s\" is not equal to the upper bound of partition \"%s\".",
 							  second_name->relname, first_name->relname),
 					errhint("ALTER TABLE ... SPLIT PARTITION requires the partition bounds to be adjacent."),
 					parser_errposition(pstate, datum->location));
diff --git a/src/test/modules/test_extensions/expected/test_extensions.out b/src/test/modules/test_extensions/expected/test_extensions.out
index fdae52d6ab2..1b5debdeeb1 100644
--- a/src/test/modules/test_extensions/expected/test_extensions.out
+++ b/src/test/modules/test_extensions/expected/test_extensions.out
@@ -566,7 +566,7 @@ SELECT pg_describe_object(classid, objid, objsubid) as obj,
 -- fails, as function dep_req1 is not in the same schema as the extension.
 ALTER EXTENSION test_ext_req_schema1 SET SCHEMA test_func_dep3;
 ERROR:  extension "test_ext_req_schema1" does not support SET SCHEMA
-DETAIL:  function test_func_dep2.dep_req1() is not in the extension's schema "test_func_dep1"
+DETAIL:  function test_func_dep2.dep_req1() is not in the extension's schema "test_func_dep1".
 -- Move back the function, and the extension can be moved.
 ALTER FUNCTION test_func_dep2.dep_req1() SET SCHEMA test_func_dep1;
 ALTER EXTENSION test_ext_req_schema1 SET SCHEMA test_func_dep3;
diff --git a/src/test/regress/expected/create_view.out b/src/test/regress/expected/create_view.out
index 63cf4b4371d..053fa56573f 100644
--- a/src/test/regress/expected/create_view.out
+++ b/src/test/regress/expected/create_view.out
@@ -1720,7 +1720,7 @@ rollback;
 -- likewise, altering a referenced column's type is prohibited ...
 alter table tt14t alter column f4 type integer using f4::integer;  -- fail
 ERROR:  cannot alter type of a column used by a view or rule
-DETAIL:  rule _RETURN on view tt14v depends on column "f4"
+DETAIL:  rule _RETURN on view tt14v depends on column "f4".
 -- ... but some bug might let it happen, so check defenses
 begin;
 -- destroy the dependency entry that prevents the ALTER:
diff --git a/src/test/regress/expected/partition_merge.out b/src/test/regress/expected/partition_merge.out
index 883110e25d9..9b8f5ee137c 100644
--- a/src/test/regress/expected/partition_merge.out
+++ b/src/test/regress/expected/partition_merge.out
@@ -35,14 +35,14 @@ HINT:  ALTER TABLE ... MERGE PARTITIONS can only merge partitions don't have sub
 -- (space between sections sales_jan2022 and sales_mar2022)
 ALTER TABLE sales_range MERGE PARTITIONS (sales_jan2022, sales_mar2022) INTO sales_jan_mar2022;
 ERROR:  can not merge partition "sales_mar2022" together with partition "sales_jan2022"
-DETAIL:  lower bound of partition "sales_mar2022" is not equal to the upper bound of partition "sales_jan2022"
+DETAIL:  Lower bound of partition "sales_mar2022" is not equal to the upper bound of partition "sales_jan2022".
 HINT:  ALTER TABLE ... MERGE PARTITIONS requires the partition bounds to be adjacent.
 -- ERROR:  can not merge partition "sales_jan2022" together with partition "sales_dec2021"
 -- DETAIL:  lower bound of partition "sales_jan2022" is not equal to the upper bound of partition "sales_dec2021"
 -- (space between sections sales_dec2021 and sales_jan2022)
 ALTER TABLE sales_range MERGE PARTITIONS (sales_dec2021, sales_jan2022, sales_feb2022) INTO sales_dec_jan_feb2022;
 ERROR:  can not merge partition "sales_jan2022" together with partition "sales_dec2021"
-DETAIL:  lower bound of partition "sales_jan2022" is not equal to the upper bound of partition "sales_dec2021"
+DETAIL:  Lower bound of partition "sales_jan2022" is not equal to the upper bound of partition "sales_dec2021".
 HINT:  ALTER TABLE ... MERGE PARTITIONS requires the partition bounds to be adjacent.
 -- ERROR:  partition with name "sales_feb2022" is already used
 ALTER TABLE sales_range MERGE PARTITIONS (sales_feb2022, sales_mar2022, partitions_merge_schema.sales_feb2022) INTO sales_feb_mar_apr2022;
diff --git a/src/test/regress/expected/partition_split.out b/src/test/regress/expected/partition_split.out
index 43ca299648e..e35e859cc13 100644
--- a/src/test/regress/expected/partition_split.out
+++ b/src/test/regress/expected/partition_split.out
@@ -109,7 +109,7 @@ ALTER TABLE sales_range SPLIT PARTITION sales_feb_mar_apr2022 INTO
 ERROR:  can not split to partition "sales_mar2022" together with partition "sales_feb2022"
 LINE 3:    PARTITION sales_mar2022 FOR VALUES FROM ('2022-02-01') TO...
                                                     ^
-DETAIL:  lower bound of partition "sales_mar2022" is not equal to the upper bound of partition "sales_feb2022"
+DETAIL:  Lower bound of partition "sales_mar2022" is not equal to the upper bound of partition "sales_feb2022".
 HINT:  ALTER TABLE ... SPLIT PARTITION requires the partition bounds to be adjacent.
 -- Tests for spaces between partitions, them should be executed without DEFAULT partition
 ALTER TABLE sales_range DETACH PARTITION sales_others;
@@ -470,7 +470,7 @@ ALTER TABLE sales_range SPLIT PARTITION sales_others INTO
 ERROR:  can not split to partition "sales_error" together with partition "sales_dec2021"
 LINE 3:    PARTITION sales_error FOR VALUES FROM ('2021-12-30') TO (...
                                                   ^
-DETAIL:  lower bound of partition "sales_error" is not equal to the upper bound of partition "sales_dec2021"
+DETAIL:  Lower bound of partition "sales_error" is not equal to the upper bound of partition "sales_dec2021".
 HINT:  ALTER TABLE ... SPLIT PARTITION requires the partition bounds to be adjacent.
 -- sales_error intersects with sales_feb2022 (upper bound)
 -- ERROR:  can not split to partition "sales_feb2022" together with partition "sales_error"
@@ -482,7 +482,7 @@ ALTER TABLE sales_range SPLIT PARTITION sales_others INTO
 ERROR:  can not split to partition "sales_feb2022" together with partition "sales_error"
 LINE 4:    PARTITION sales_feb2022 FOR VALUES FROM ('2022-02-01') TO...
                                                     ^
-DETAIL:  lower bound of partition "sales_feb2022" is not equal to the upper bound of partition "sales_error"
+DETAIL:  Lower bound of partition "sales_feb2022" is not equal to the upper bound of partition "sales_error".
 HINT:  ALTER TABLE ... SPLIT PARTITION requires the partition bounds to be adjacent.
 -- sales_error intersects with sales_dec2021 (inside bound)
 -- ERROR:  can not split to partition "sales_error" together with partition "sales_dec2021"
@@ -494,7 +494,7 @@ ALTER TABLE sales_range SPLIT PARTITION sales_others INTO
 ERROR:  can not split to partition "sales_error" together with partition "sales_dec2021"
 LINE 3:    PARTITION sales_error FOR VALUES FROM ('2021-12-10') TO (...
                                                   ^
-DETAIL:  lower bound of partition "sales_error" is not equal to the upper bound of partition "sales_dec2021"
+DETAIL:  Lower bound of partition "sales_error" is not equal to the upper bound of partition "sales_dec2021".
 HINT:  ALTER TABLE ... SPLIT PARTITION requires the partition bounds to be adjacent.
 -- sales_error intersects with sales_dec2021 (exactly the same bounds)
 -- ERROR:  can not split to partition "sales_error" together with partition "sales_dec2021"
@@ -506,7 +506,7 @@ ALTER TABLE sales_range SPLIT PARTITION sales_others INTO
 ERROR:  can not split to partition "sales_error" together with partition "sales_dec2021"
 LINE 3:    PARTITION sales_error FOR VALUES FROM ('2021-12-01') TO (...
                                                   ^
-DETAIL:  lower bound of partition "sales_error" is not equal to the upper bound of partition "sales_dec2021"
+DETAIL:  Lower bound of partition "sales_error" is not equal to the upper bound of partition "sales_dec2021".
 HINT:  ALTER TABLE ... SPLIT PARTITION requires the partition bounds to be adjacent.
 -- ERROR:  can not split DEFAULT partition "sales_others"
 -- HINT:  To split DEFAULT partition one of the new partition must be DEFAULT.
diff --git a/src/test/regress/expected/rangefuncs.out b/src/test/regress/expected/rangefuncs.out
index 5cc94011e97..a7cb1b5611d 100644
--- a/src/test/regress/expected/rangefuncs.out
+++ b/src/test/regress/expected/rangefuncs.out
@@ -2279,7 +2279,7 @@ ERROR:  attribute 5 of type record has been dropped
 rollback;
 alter table users alter column seq type numeric;  -- fail, view has reference
 ERROR:  cannot alter type of a column used by a view or rule
-DETAIL:  rule _RETURN on view usersview depends on column "seq"
+DETAIL:  rule _RETURN on view usersview depends on column "seq".
 -- likewise, check we don't crash if the dependency goes wrong
 begin;
 -- destroy the dependency entry that prevents the ALTER:
-- 
2.47.3



^ permalink  raw  reply  [nested|flat] 12+ messages in thread

* Re: Add missing period to DETAIL messages
@ 2026-05-18 05:52  Peter Smith <[email protected]>
  parent: Peter Smith <[email protected]>
  0 siblings, 0 replies; 12+ messages in thread

From: Peter Smith @ 2026-05-18 05:52 UTC (permalink / raw)
  To: Peter Eisentraut <[email protected]>; +Cc: Xiaopeng Wang <[email protected]>; Chao Li <[email protected]>; PostgreSQL Hackers <[email protected]>

This patch seemed to be nearing completion, but then the thread went
quiet for 4 weeks.Is there more I can do to help this patch proceed to
be pushed?

======
Kind Regards,
Peter Smith.
Fujitsu Australia






^ permalink  raw  reply  [nested|flat] 12+ messages in thread


end of thread, other threads:[~2026-05-18 05:52 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz follow: Atom feed)
-- links below jump to the message on this page --
2026-04-09 04:27 Add missing period to DETAIL messages Peter Smith <[email protected]>
2026-04-09 08:00 ` Chao Li <[email protected]>
2026-04-10 01:02   ` Peter Smith <[email protected]>
2026-04-13 01:04     ` Peter Smith <[email protected]>
2026-04-13 01:05       ` Peter Smith <[email protected]>
2026-04-14 05:51         ` vignesh C <[email protected]>
2026-04-14 06:28           ` Peter Smith <[email protected]>
2026-04-15 05:47         ` Xiaopeng Wang <[email protected]>
2026-04-15 07:41           ` Peter Smith <[email protected]>
2026-04-15 18:26             ` Peter Eisentraut <[email protected]>
2026-04-16 00:22               ` Peter Smith <[email protected]>
2026-05-18 05:52                 ` Peter Smith <[email protected]>

This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox