pg_proc.dat "proargmodes is not a 1-D char array"

Started by Craig Ringerover 5 years ago8 messages
#1Craig Ringer
craig@2ndquadrant.com

Hi all

Random tip for future searchers. If you've modified pg_proc.dat and initdb
fails with "proargmodes is not a 1-D char array" - it could well actually
be that the length of proargmodes does not match the length of
proallargtypes given the test

ARR_DIMS(arr)[0] != numargs ||

in funcapi.c.

--
Craig Ringer http://www.2ndQuadrant.com/
2ndQuadrant - PostgreSQL Solutions for the Enterprise

#2Alvaro Herrera
alvherre@alvh.no-ip.org
In reply to: Craig Ringer (#1)
Re: pg_proc.dat "proargmodes is not a 1-D char array"

On 2020-Sep-30, Craig Ringer wrote:

Hi all

Random tip for future searchers. If you've modified pg_proc.dat and initdb
fails with "proargmodes is not a 1-D char array" - it could well actually
be that the length of proargmodes does not match the length of
proallargtypes given the test

ARR_DIMS(arr)[0] != numargs ||

in funcapi.c.

Perhaps we can improve these error messages like below. (Or maybe just
keep it one message "proargmodes is not a 1-D char array of %d
elements"?) There are about 5 places to change I think.

diff --git a/src/backend/utils/fmgr/funcapi.c b/src/backend/utils/fmgr/funcapi.c
index b9efa77291..c76c16f799 100644
--- a/src/backend/utils/fmgr/funcapi.c
+++ b/src/backend/utils/fmgr/funcapi.c
@@ -1167,10 +1167,11 @@ get_func_arg_info(HeapTuple procTup,
 	{
 		arr = DatumGetArrayTypeP(proargmodes);	/* ensure not toasted */
 		if (ARR_NDIM(arr) != 1 ||
-			ARR_DIMS(arr)[0] != numargs ||
 			ARR_HASNULL(arr) ||
 			ARR_ELEMTYPE(arr) != CHAROID)
 			elog(ERROR, "proargmodes is not a 1-D char array");
+		if (ARR_DIMS(arr)[0] != numargs)
+			elog(ERROR, "proargmodes is not %d elements long", numargs);
 		*p_argmodes = (char *) palloc(numargs * sizeof(char));
 		memcpy(*p_argmodes, ARR_DATA_PTR(arr),
 			   numargs * sizeof(char));
#3Tom Lane
tgl@sss.pgh.pa.us
In reply to: Alvaro Herrera (#2)
Re: pg_proc.dat "proargmodes is not a 1-D char array"

Alvaro Herrera <alvherre@alvh.no-ip.org> writes:

Perhaps we can improve these error messages like below. (Or maybe just
keep it one message "proargmodes is not a 1-D char array of %d
elements"?) There are about 5 places to change I think.

I doubt that it's really worth expending more code on this.
Certainly I see no reason why that particular test is more likely
to fail than the others, in the presence of corrupt data --- and
I don't want to add individual elog's for each one.

Adding the expected length to the error message might be OK though.

regards, tom lane

#4Robert Haas
robertmhaas@gmail.com
In reply to: Tom Lane (#3)
Re: pg_proc.dat "proargmodes is not a 1-D char array"

On Tue, Nov 17, 2020 at 10:32 AM Tom Lane <tgl@sss.pgh.pa.us> wrote:

Adding the expected length to the error message might be OK though.

Certainly seems like we should do at least that much. The current
message is just wrong, right?

--
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

#5Tom Lane
tgl@sss.pgh.pa.us
In reply to: Robert Haas (#4)
Re: pg_proc.dat "proargmodes is not a 1-D char array"

Robert Haas <robertmhaas@gmail.com> writes:

On Tue, Nov 17, 2020 at 10:32 AM Tom Lane <tgl@sss.pgh.pa.us> wrote:

Adding the expected length to the error message might be OK though.

Certainly seems like we should do at least that much. The current
message is just wrong, right?

It's incomplete, for sure. Doesn't mention nulls either.

regards, tom lane

#6Alvaro Herrera
alvherre@alvh.no-ip.org
In reply to: Tom Lane (#5)
1 attachment(s)
Re: pg_proc.dat "proargmodes is not a 1-D char array"

On 2020-Nov-17, Tom Lane wrote:

Robert Haas <robertmhaas@gmail.com> writes:

On Tue, Nov 17, 2020 at 10:32 AM Tom Lane <tgl@sss.pgh.pa.us> wrote:

Adding the expected length to the error message might be OK though.

Certainly seems like we should do at least that much. The current
message is just wrong, right?

It's incomplete, for sure. Doesn't mention nulls either.

So let's go with this one.

Attachments:

arraylen.patchtext/x-diff; charset=us-asciiDownload
diff --git a/src/backend/utils/fmgr/funcapi.c b/src/backend/utils/fmgr/funcapi.c
index b9efa77291..9696c88f24 100644
--- a/src/backend/utils/fmgr/funcapi.c
+++ b/src/backend/utils/fmgr/funcapi.c
@@ -1123,7 +1123,7 @@ get_func_arg_info(HeapTuple procTup,
 			numargs < 0 ||
 			ARR_HASNULL(arr) ||
 			ARR_ELEMTYPE(arr) != OIDOID)
-			elog(ERROR, "proallargtypes is not a 1-D Oid array");
+			elog(ERROR, "proallargtypes is not a 1-D Oid array or it contains nulls");
 		Assert(numargs >= procStruct->pronargs);
 		*p_argtypes = (Oid *) palloc(numargs * sizeof(Oid));
 		memcpy(*p_argtypes, ARR_DATA_PTR(arr),
@@ -1170,7 +1170,8 @@ get_func_arg_info(HeapTuple procTup,
 			ARR_DIMS(arr)[0] != numargs ||
 			ARR_HASNULL(arr) ||
 			ARR_ELEMTYPE(arr) != CHAROID)
-			elog(ERROR, "proargmodes is not a 1-D char array");
+			elog(ERROR, "proargmodes is not a 1-D char array of length %d or it contains nulls",
+				 numargs);
 		*p_argmodes = (char *) palloc(numargs * sizeof(char));
 		memcpy(*p_argmodes, ARR_DATA_PTR(arr),
 			   numargs * sizeof(char));
@@ -1210,7 +1211,7 @@ get_func_trftypes(HeapTuple procTup,
 			nelems < 0 ||
 			ARR_HASNULL(arr) ||
 			ARR_ELEMTYPE(arr) != OIDOID)
-			elog(ERROR, "protrftypes is not a 1-D Oid array");
+			elog(ERROR, "protrftypes is not a 1-D Oid array or it contains nulls");
 		Assert(nelems >= ((Form_pg_proc) GETSTRUCT(procTup))->pronargs);
 		*p_trftypes = (Oid *) palloc(nelems * sizeof(Oid));
 		memcpy(*p_trftypes, ARR_DATA_PTR(arr),
@@ -1261,7 +1262,7 @@ get_func_input_arg_names(char prokind,
 	if (ARR_NDIM(arr) != 1 ||
 		ARR_HASNULL(arr) ||
 		ARR_ELEMTYPE(arr) != TEXTOID)
-		elog(ERROR, "proargnames is not a 1-D text array");
+		elog(ERROR, "proargnames is not a 1-D text array or it contains nulls");
 	deconstruct_array(arr, TEXTOID, -1, false, TYPALIGN_INT,
 					  &argnames, NULL, &numargs);
 	if (proargmodes != PointerGetDatum(NULL))
@@ -1271,7 +1272,8 @@ get_func_input_arg_names(char prokind,
 			ARR_DIMS(arr)[0] != numargs ||
 			ARR_HASNULL(arr) ||
 			ARR_ELEMTYPE(arr) != CHAROID)
-			elog(ERROR, "proargmodes is not a 1-D char array");
+			elog(ERROR, "proargmodes is not a 1-D char array of length %d or it contains nulls",
+				 numargs);
 		argmodes = (char *) ARR_DATA_PTR(arr);
 	}
 	else
@@ -1368,14 +1370,15 @@ get_func_result_name(Oid functionId)
 			numargs < 0 ||
 			ARR_HASNULL(arr) ||
 			ARR_ELEMTYPE(arr) != CHAROID)
-			elog(ERROR, "proargmodes is not a 1-D char array");
+			elog(ERROR, "proargmodes is not a 1-D char array or it contains nulls");
 		argmodes = (char *) ARR_DATA_PTR(arr);
 		arr = DatumGetArrayTypeP(proargnames);	/* ensure not toasted */
 		if (ARR_NDIM(arr) != 1 ||
 			ARR_DIMS(arr)[0] != numargs ||
 			ARR_HASNULL(arr) ||
 			ARR_ELEMTYPE(arr) != TEXTOID)
-			elog(ERROR, "proargnames is not a 1-D text array");
+			elog(ERROR, "proargnames is not a 1-D text array of length %d or it contains nulls",
+				 numargs);
 		deconstruct_array(arr, TEXTOID, -1, false, TYPALIGN_INT,
 						  &argnames, NULL, &nargnames);
 		Assert(nargnames == numargs);
@@ -1506,14 +1509,15 @@ build_function_result_tupdesc_d(char prokind,
 		numargs < 0 ||
 		ARR_HASNULL(arr) ||
 		ARR_ELEMTYPE(arr) != OIDOID)
-		elog(ERROR, "proallargtypes is not a 1-D Oid array");
+		elog(ERROR, "proallargtypes is not a 1-D Oid array or it contains nulls");
 	argtypes = (Oid *) ARR_DATA_PTR(arr);
 	arr = DatumGetArrayTypeP(proargmodes);	/* ensure not toasted */
 	if (ARR_NDIM(arr) != 1 ||
 		ARR_DIMS(arr)[0] != numargs ||
 		ARR_HASNULL(arr) ||
 		ARR_ELEMTYPE(arr) != CHAROID)
-		elog(ERROR, "proargmodes is not a 1-D char array");
+		elog(ERROR, "proargmodes is not a 1-D char array of length %d or it contains nulls",
+			 numargs);
 	argmodes = (char *) ARR_DATA_PTR(arr);
 	if (proargnames != PointerGetDatum(NULL))
 	{
@@ -1522,7 +1526,8 @@ build_function_result_tupdesc_d(char prokind,
 			ARR_DIMS(arr)[0] != numargs ||
 			ARR_HASNULL(arr) ||
 			ARR_ELEMTYPE(arr) != TEXTOID)
-			elog(ERROR, "proargnames is not a 1-D text array");
+			elog(ERROR, "proargnames is not a 1-D text array of length %d or it contains nulls",
+				 numargs);
 		deconstruct_array(arr, TEXTOID, -1, false, TYPALIGN_INT,
 						  &argnames, NULL, &nargnames);
 		Assert(nargnames == numargs);
#7Tom Lane
tgl@sss.pgh.pa.us
In reply to: Alvaro Herrera (#6)
Re: pg_proc.dat "proargmodes is not a 1-D char array"

Alvaro Herrera <alvherre@alvh.no-ip.org> writes:

So let's go with this one.

WFM.

regards, tom lane

#8Alvaro Herrera
alvherre@alvh.no-ip.org
In reply to: Tom Lane (#7)
Re: pg_proc.dat "proargmodes is not a 1-D char array"

On 2020-Nov-23, Tom Lane wrote:

Alvaro Herrera <alvherre@alvh.no-ip.org> writes:

So let's go with this one.

WFM.

Thanks, pushed.