Use boolean array for nulls parameters

Started by japinalmost 5 years ago4 messages
#1japin
japinli@hotmail.com
1 attachment(s)

Hi,

When I review the [1]/messages/by-id/CA+HiwqGkfJfYdeq5vHPh6eqPKjSbfpDDY+j-kXYFePQedtSLeg@mail.gmail.com, I find that the tuple's nulls array use char type.
However there are many places use boolean array to repsent the nulls array,
so I think we can replace the char type nulls array to boolean type. This
change will break the SPI_xxx API, I'm not sure whether this chagnges cause
other problems or not. Any thought?

[1]: /messages/by-id/CA+HiwqGkfJfYdeq5vHPh6eqPKjSbfpDDY+j-kXYFePQedtSLeg@mail.gmail.com

--
Regrads,
Japin Li.
ChengDu WenWu Information Technology Co.,Ltd.

Attachments:

v1-0001-Replace-the-char-to-bool-array-for-null-parameter.patchtext/x-patchDownload
From 7496f20ccfda7687333db9e5c43227ee30e4eda9 Mon Sep 17 00:00:00 2001
From: Japin Li <japinli@hotmail.com>
Date: Tue, 19 Jan 2021 15:51:44 +0800
Subject: [PATCH v1] Replace the char to bool array for null parameters

---
 doc/src/sgml/spi.sgml               | 60 ++++++++++++-----------------
 src/backend/executor/spi.c          | 18 ++++-----
 src/backend/utils/adt/ri_triggers.c |  8 ++--
 src/backend/utils/adt/ruleutils.c   | 10 ++---
 src/include/executor/spi.h          | 12 +++---
 src/pl/plperl/plperl.c              |  6 +--
 src/pl/plpython/plpy_cursorobject.c |  6 +--
 src/test/regress/regress.c          | 12 +++---
 8 files changed, 61 insertions(+), 71 deletions(-)

diff --git a/doc/src/sgml/spi.sgml b/doc/src/sgml/spi.sgml
index f5e0a35da0..d3cc405c42 100644
--- a/doc/src/sgml/spi.sgml
+++ b/doc/src/sgml/spi.sgml
@@ -649,7 +649,7 @@ int SPI_exec(const char * <parameter>command</parameter>, long <parameter>count<
 <synopsis>
 int SPI_execute_with_args(const char *<parameter>command</parameter>,
                           int <parameter>nargs</parameter>, Oid *<parameter>argtypes</parameter>,
-                          Datum *<parameter>values</parameter>, const char *<parameter>nulls</parameter>,
+                          Datum *<parameter>values</parameter>, const bool *<parameter>nulls</parameter>,
                           bool <parameter>read_only</parameter>, long <parameter>count</parameter>)
 </synopsis>
  </refsynopsisdiv>
@@ -728,7 +728,7 @@ int SPI_execute_with_args(const char *<parameter>command</parameter>,
    </varlistentry>
 
    <varlistentry>
-    <term><literal>const char * <parameter>nulls</parameter></literal></term>
+    <term><literal>const bool * <parameter>nulls</parameter></literal></term>
     <listitem>
      <para>
       an array of length <parameter>nargs</parameter>, describing which
@@ -739,12 +739,10 @@ int SPI_execute_with_args(const char *<parameter>command</parameter>,
       If <parameter>nulls</parameter> is <symbol>NULL</symbol> then
       <function>SPI_execute_with_args</function> assumes that no parameters
       are null.  Otherwise, each entry of the <parameter>nulls</parameter>
-      array should be <literal>'&nbsp;'</literal> if the corresponding parameter
-      value is non-null, or <literal>'n'</literal> if the corresponding parameter
+      array should be <literal>false</literal> if the corresponding parameter
+      value is non-null, or <literal>true</literal> if the corresponding parameter
       value is null.  (In the latter case, the actual value in the
-      corresponding <parameter>values</parameter> entry doesn't matter.)  Note
-      that <parameter>nulls</parameter> is not a text string, just an array:
-      it does not need a <literal>'\0'</literal> terminator.
+      corresponding <parameter>values</parameter> entry doesn't matter.)
      </para>
     </listitem>
    </varlistentry>
@@ -1601,7 +1599,7 @@ bool SPI_is_cursor_plan(SPIPlanPtr <parameter>plan</parameter>)
 
  <refsynopsisdiv>
 <synopsis>
-int SPI_execute_plan(SPIPlanPtr <parameter>plan</parameter>, Datum * <parameter>values</parameter>, const char * <parameter>nulls</parameter>,
+int SPI_execute_plan(SPIPlanPtr <parameter>plan</parameter>, Datum * <parameter>values</parameter>, const bool * <parameter>nulls</parameter>,
                      bool <parameter>read_only</parameter>, long <parameter>count</parameter>)
 </synopsis>
  </refsynopsisdiv>
@@ -1642,7 +1640,7 @@ int SPI_execute_plan(SPIPlanPtr <parameter>plan</parameter>, Datum * <parameter>
    </varlistentry>
 
    <varlistentry>
-    <term><literal>const char * <parameter>nulls</parameter></literal></term>
+    <term><literal>const bool * <parameter>nulls</parameter></literal></term>
     <listitem>
      <para>
       An array describing which parameters are null.  Must have same length as
@@ -1653,12 +1651,10 @@ int SPI_execute_plan(SPIPlanPtr <parameter>plan</parameter>, Datum * <parameter>
       If <parameter>nulls</parameter> is <symbol>NULL</symbol> then
       <function>SPI_execute_plan</function> assumes that no parameters
       are null.  Otherwise, each entry of the <parameter>nulls</parameter>
-      array should be <literal>'&nbsp;'</literal> if the corresponding parameter
-      value is non-null, or <literal>'n'</literal> if the corresponding parameter
+      array should be <literal>false</literal> if the corresponding parameter
+      value is non-null, or <literal>true</literal> if the corresponding parameter
       value is null.  (In the latter case, the actual value in the
-      corresponding <parameter>values</parameter> entry doesn't matter.)  Note
-      that <parameter>nulls</parameter> is not a text string, just an array:
-      it does not need a <literal>'\0'</literal> terminator.
+      corresponding <parameter>values</parameter> entry doesn't matter.)
      </para>
     </listitem>
    </varlistentry>
@@ -1946,7 +1942,7 @@ int SPI_execute_plan_with_receiver(SPIPlanPtr <parameter>plan</parameter>,
 
  <refsynopsisdiv>
 <synopsis>
-int SPI_execp(SPIPlanPtr <parameter>plan</parameter>, Datum * <parameter>values</parameter>, const char * <parameter>nulls</parameter>, long <parameter>count</parameter>)
+int SPI_execp(SPIPlanPtr <parameter>plan</parameter>, Datum * <parameter>values</parameter>, const bool * <parameter>nulls</parameter>, long <parameter>count</parameter>)
 </synopsis>
  </refsynopsisdiv>
 
@@ -1985,7 +1981,7 @@ int SPI_execp(SPIPlanPtr <parameter>plan</parameter>, Datum * <parameter>values<
    </varlistentry>
 
    <varlistentry>
-    <term><literal>const char * <parameter>nulls</parameter></literal></term>
+    <term><literal>const bool * <parameter>nulls</parameter></literal></term>
     <listitem>
      <para>
       An array describing which parameters are null.  Must have same length as
@@ -1996,12 +1992,10 @@ int SPI_execp(SPIPlanPtr <parameter>plan</parameter>, Datum * <parameter>values<
       If <parameter>nulls</parameter> is <symbol>NULL</symbol> then
       <function>SPI_execp</function> assumes that no parameters
       are null.  Otherwise, each entry of the <parameter>nulls</parameter>
-      array should be <literal>'&nbsp;'</literal> if the corresponding parameter
-      value is non-null, or <literal>'n'</literal> if the corresponding parameter
+      array should be <literal>false</literal> if the corresponding parameter
+      value is non-null, or <literal>true</literal> if the corresponding parameter
       value is null.  (In the latter case, the actual value in the
-      corresponding <parameter>values</parameter> entry doesn't matter.)  Note
-      that <parameter>nulls</parameter> is not a text string, just an array:
-      it does not need a <literal>'\0'</literal> terminator.
+      corresponding <parameter>values</parameter> entry doesn't matter.)
      </para>
     </listitem>
    </varlistentry>
@@ -2051,7 +2045,7 @@ int SPI_execp(SPIPlanPtr <parameter>plan</parameter>, Datum * <parameter>values<
  <refsynopsisdiv>
 <synopsis>
 Portal SPI_cursor_open(const char * <parameter>name</parameter>, SPIPlanPtr <parameter>plan</parameter>,
-                       Datum * <parameter>values</parameter>, const char * <parameter>nulls</parameter>,
+                       Datum * <parameter>values</parameter>, const bool * <parameter>nulls</parameter>,
                        bool <parameter>read_only</parameter>)
 </synopsis>
  </refsynopsisdiv>
@@ -2117,7 +2111,7 @@ Portal SPI_cursor_open(const char * <parameter>name</parameter>, SPIPlanPtr <par
    </varlistentry>
 
    <varlistentry>
-    <term><literal>const char * <parameter>nulls</parameter></literal></term>
+    <term><literal>const bool * <parameter>nulls</parameter></literal></term>
     <listitem>
      <para>
       An array describing which parameters are null.  Must have same length as
@@ -2128,12 +2122,10 @@ Portal SPI_cursor_open(const char * <parameter>name</parameter>, SPIPlanPtr <par
       If <parameter>nulls</parameter> is <symbol>NULL</symbol> then
       <function>SPI_cursor_open</function> assumes that no parameters
       are null.  Otherwise, each entry of the <parameter>nulls</parameter>
-      array should be <literal>'&nbsp;'</literal> if the corresponding parameter
-      value is non-null, or <literal>'n'</literal> if the corresponding parameter
+      array should be <literal>false</literal> if the corresponding parameter
+      value is non-null, or <literal>true</literal> if the corresponding parameter
       value is null.  (In the latter case, the actual value in the
-      corresponding <parameter>values</parameter> entry doesn't matter.)  Note
-      that <parameter>nulls</parameter> is not a text string, just an array:
-      it does not need a <literal>'\0'</literal> terminator.
+      corresponding <parameter>values</parameter> entry doesn't matter.)
      </para>
     </listitem>
    </varlistentry>
@@ -2177,7 +2169,7 @@ Portal SPI_cursor_open(const char * <parameter>name</parameter>, SPIPlanPtr <par
 Portal SPI_cursor_open_with_args(const char *<parameter>name</parameter>,
                                  const char *<parameter>command</parameter>,
                                  int <parameter>nargs</parameter>, Oid *<parameter>argtypes</parameter>,
-                                 Datum *<parameter>values</parameter>, const char *<parameter>nulls</parameter>,
+                                 Datum *<parameter>values</parameter>, const bool *<parameter>nulls</parameter>,
                                  bool <parameter>read_only</parameter>, int <parameter>cursorOptions</parameter>)
 </synopsis>
  </refsynopsisdiv>
@@ -2261,7 +2253,7 @@ Portal SPI_cursor_open_with_args(const char *<parameter>name</parameter>,
    </varlistentry>
 
    <varlistentry>
-    <term><literal>const char * <parameter>nulls</parameter></literal></term>
+    <term><literal>const bool * <parameter>nulls</parameter></literal></term>
     <listitem>
      <para>
       an array of length <parameter>nargs</parameter>, describing which
@@ -2272,12 +2264,10 @@ Portal SPI_cursor_open_with_args(const char *<parameter>name</parameter>,
       If <parameter>nulls</parameter> is <symbol>NULL</symbol> then
       <function>SPI_cursor_open_with_args</function> assumes that no parameters
       are null.  Otherwise, each entry of the <parameter>nulls</parameter>
-      array should be <literal>'&nbsp;'</literal> if the corresponding parameter
-      value is non-null, or <literal>'n'</literal> if the corresponding parameter
+      array should be <literal>false</literal> if the corresponding parameter
+      value is non-null, or <literal>true</literal> if the corresponding parameter
       value is null.  (In the latter case, the actual value in the
-      corresponding <parameter>values</parameter> entry doesn't matter.)  Note
-      that <parameter>nulls</parameter> is not a text string, just an array:
-      it does not need a <literal>'\0'</literal> terminator.
+      corresponding <parameter>values</parameter> entry doesn't matter.)
      </para>
     </listitem>
    </varlistentry>
diff --git a/src/backend/executor/spi.c b/src/backend/executor/spi.c
index e28d242922..631ab2167a 100644
--- a/src/backend/executor/spi.c
+++ b/src/backend/executor/spi.c
@@ -70,7 +70,7 @@ static int	_SPI_execute_plan(SPIPlanPtr plan, ParamListInfo paramLI,
 							  DestReceiver *caller_dest);
 
 static ParamListInfo _SPI_convert_params(int nargs, Oid *argtypes,
-										 Datum *Values, const char *Nulls);
+										 Datum *Values, const bool *Nulls);
 
 static int	_SPI_pquery(QueryDesc *queryDesc, bool fire_triggers, uint64 tcount);
 
@@ -536,7 +536,7 @@ SPI_exec(const char *src, long tcount)
 
 /* Execute a previously prepared plan */
 int
-SPI_execute_plan(SPIPlanPtr plan, Datum *Values, const char *Nulls,
+SPI_execute_plan(SPIPlanPtr plan, Datum *Values, const bool *Nulls,
 				 bool read_only, long tcount)
 {
 	int			res;
@@ -563,7 +563,7 @@ SPI_execute_plan(SPIPlanPtr plan, Datum *Values, const char *Nulls,
 
 /* Obsolete version of SPI_execute_plan */
 int
-SPI_execp(SPIPlanPtr plan, Datum *Values, const char *Nulls, long tcount)
+SPI_execp(SPIPlanPtr plan, Datum *Values, const bool *Nulls, long tcount)
 {
 	return SPI_execute_plan(plan, Values, Nulls, false, tcount);
 }
@@ -634,7 +634,7 @@ SPI_execute_plan_with_receiver(SPIPlanPtr plan,
  */
 int
 SPI_execute_snapshot(SPIPlanPtr plan,
-					 Datum *Values, const char *Nulls,
+					 Datum *Values, const bool *Nulls,
 					 Snapshot snapshot, Snapshot crosscheck_snapshot,
 					 bool read_only, bool fire_triggers, long tcount)
 {
@@ -669,7 +669,7 @@ SPI_execute_snapshot(SPIPlanPtr plan,
 int
 SPI_execute_with_args(const char *src,
 					  int nargs, Oid *argtypes,
-					  Datum *Values, const char *Nulls,
+					  Datum *Values, const bool *Nulls,
 					  bool read_only, long tcount)
 {
 	int			res;
@@ -1339,7 +1339,7 @@ SPI_freetuptable(SPITupleTable *tuptable)
  */
 Portal
 SPI_cursor_open(const char *name, SPIPlanPtr plan,
-				Datum *Values, const char *Nulls,
+				Datum *Values, const bool *Nulls,
 				bool read_only)
 {
 	Portal		portal;
@@ -1368,7 +1368,7 @@ Portal
 SPI_cursor_open_with_args(const char *name,
 						  const char *src,
 						  int nargs, Oid *argtypes,
-						  Datum *Values, const char *Nulls,
+						  Datum *Values, const bool *Nulls,
 						  bool read_only, int cursorOptions)
 {
 	Portal		result;
@@ -2636,7 +2636,7 @@ fail:
  */
 static ParamListInfo
 _SPI_convert_params(int nargs, Oid *argtypes,
-					Datum *Values, const char *Nulls)
+					Datum *Values, const bool *Nulls)
 {
 	ParamListInfo paramLI;
 
@@ -2649,7 +2649,7 @@ _SPI_convert_params(int nargs, Oid *argtypes,
 			ParamExternData *prm = &paramLI->params[i];
 
 			prm->value = Values[i];
-			prm->isnull = (Nulls && Nulls[i] == 'n');
+			prm->isnull = Nulls && Nulls[i];
 			prm->pflags = PARAM_FLAG_CONST;
 			prm->ptype = argtypes[i];
 		}
diff --git a/src/backend/utils/adt/ri_triggers.c b/src/backend/utils/adt/ri_triggers.c
index 6e3a41062f..793766570d 100644
--- a/src/backend/utils/adt/ri_triggers.c
+++ b/src/backend/utils/adt/ri_triggers.c
@@ -216,7 +216,7 @@ static bool ri_PerformCheck(const RI_ConstraintInfo *riinfo,
 							bool detectNewRows, int expect_OK);
 static void ri_ExtractValues(Relation rel, TupleTableSlot *slot,
 							 const RI_ConstraintInfo *riinfo, bool rel_is_pk,
-							 Datum *vals, char *nulls);
+							 Datum *vals, bool *nulls);
 static void ri_ReportViolation(const RI_ConstraintInfo *riinfo,
 							   Relation pk_rel, Relation fk_rel,
 							   TupleTableSlot *violatorslot, TupleDesc tupdesc,
@@ -2191,7 +2191,7 @@ ri_PerformCheck(const RI_ConstraintInfo *riinfo,
 	Oid			save_userid;
 	int			save_sec_context;
 	Datum		vals[RI_MAX_NUMKEYS * 2];
-	char		nulls[RI_MAX_NUMKEYS * 2];
+	bool		nulls[RI_MAX_NUMKEYS * 2];
 
 	/*
 	 * Use the query type code to determine whether the query is run against
@@ -2314,7 +2314,7 @@ ri_PerformCheck(const RI_ConstraintInfo *riinfo,
 static void
 ri_ExtractValues(Relation rel, TupleTableSlot *slot,
 				 const RI_ConstraintInfo *riinfo, bool rel_is_pk,
-				 Datum *vals, char *nulls)
+				 Datum *vals, bool *nulls)
 {
 	const int16 *attnums;
 	bool		isnull;
@@ -2327,7 +2327,7 @@ ri_ExtractValues(Relation rel, TupleTableSlot *slot,
 	for (int i = 0; i < riinfo->nkeys; i++)
 	{
 		vals[i] = slot_getattr(slot, attnums[i], &isnull);
-		nulls[i] = isnull ? 'n' : ' ';
+		nulls[i] = isnull;
 	}
 }
 
diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c
index 8a1fbda572..3c8fa2c95d 100644
--- a/src/backend/utils/adt/ruleutils.c
+++ b/src/backend/utils/adt/ruleutils.c
@@ -531,7 +531,7 @@ static char *
 pg_get_ruledef_worker(Oid ruleoid, int prettyFlags)
 {
 	Datum		args[1];
-	char		nulls[1];
+	bool		nulls[1];
 	int			spirc;
 	HeapTuple	ruletup;
 	TupleDesc	rulettc;
@@ -570,7 +570,7 @@ pg_get_ruledef_worker(Oid ruleoid, int prettyFlags)
 	 * Get the pg_rewrite tuple for this rule
 	 */
 	args[0] = ObjectIdGetDatum(ruleoid);
-	nulls[0] = ' ';
+	nulls[0] = false;
 	spirc = SPI_execute_plan(plan_getrulebyoid, args, nulls, true, 0);
 	if (spirc != SPI_OK_SELECT)
 		elog(ERROR, "failed to get pg_rewrite tuple for rule %u", ruleoid);
@@ -724,7 +724,7 @@ static char *
 pg_get_viewdef_worker(Oid viewoid, int prettyFlags, int wrapColumn)
 {
 	Datum		args[2];
-	char		nulls[2];
+	bool		nulls[2];
 	int			spirc;
 	HeapTuple	ruletup;
 	TupleDesc	rulettc;
@@ -765,8 +765,8 @@ pg_get_viewdef_worker(Oid viewoid, int prettyFlags, int wrapColumn)
 	 */
 	args[0] = ObjectIdGetDatum(viewoid);
 	args[1] = DirectFunctionCall1(namein, CStringGetDatum(ViewSelectRuleName));
-	nulls[0] = ' ';
-	nulls[1] = ' ';
+	nulls[0] = false;
+	nulls[1] = false;
 	spirc = SPI_execute_plan(plan_getviewrule, args, nulls, true, 0);
 	if (spirc != SPI_OK_SELECT)
 		elog(ERROR, "failed to get pg_rewrite tuple for view %u", viewoid);
diff --git a/src/include/executor/spi.h b/src/include/executor/spi.h
index 9c70603434..8e4bd34ff7 100644
--- a/src/include/executor/spi.h
+++ b/src/include/executor/spi.h
@@ -94,7 +94,7 @@ extern int	SPI_connect(void);
 extern int	SPI_connect_ext(int options);
 extern int	SPI_finish(void);
 extern int	SPI_execute(const char *src, bool read_only, long tcount);
-extern int	SPI_execute_plan(SPIPlanPtr plan, Datum *Values, const char *Nulls,
+extern int	SPI_execute_plan(SPIPlanPtr plan, Datum *Values, const bool *Nulls,
 							 bool read_only, long tcount);
 extern int	SPI_execute_plan_with_paramlist(SPIPlanPtr plan,
 											ParamListInfo params,
@@ -104,16 +104,16 @@ extern int	SPI_execute_plan_with_receiver(SPIPlanPtr plan,
 										   bool read_only, long tcount,
 										   DestReceiver *dest);
 extern int	SPI_exec(const char *src, long tcount);
-extern int	SPI_execp(SPIPlanPtr plan, Datum *Values, const char *Nulls,
+extern int	SPI_execp(SPIPlanPtr plan, Datum *Values, const bool *Nulls,
 					  long tcount);
 extern int	SPI_execute_snapshot(SPIPlanPtr plan,
-								 Datum *Values, const char *Nulls,
+								 Datum *Values, const bool *Nulls,
 								 Snapshot snapshot,
 								 Snapshot crosscheck_snapshot,
 								 bool read_only, bool fire_triggers, long tcount);
 extern int	SPI_execute_with_args(const char *src,
 								  int nargs, Oid *argtypes,
-								  Datum *Values, const char *Nulls,
+								  Datum *Values, const bool *Nulls,
 								  bool read_only, long tcount);
 extern int	SPI_execute_with_receiver(const char *src,
 									  ParamListInfo params,
@@ -161,11 +161,11 @@ extern void SPI_freetuple(HeapTuple pointer);
 extern void SPI_freetuptable(SPITupleTable *tuptable);
 
 extern Portal SPI_cursor_open(const char *name, SPIPlanPtr plan,
-							  Datum *Values, const char *Nulls, bool read_only);
+							  Datum *Values, const bool *Nulls, bool read_only);
 extern Portal SPI_cursor_open_with_args(const char *name,
 										const char *src,
 										int nargs, Oid *argtypes,
-										Datum *Values, const char *Nulls,
+										Datum *Values, const bool *Nulls,
 										bool read_only, int cursorOptions);
 extern Portal SPI_cursor_open_with_paramlist(const char *name, SPIPlanPtr plan,
 											 ParamListInfo params, bool read_only);
diff --git a/src/pl/plperl/plperl.c b/src/pl/plperl/plperl.c
index 6299adf71a..1b8946d9fb 100644
--- a/src/pl/plperl/plperl.c
+++ b/src/pl/plperl/plperl.c
@@ -3806,7 +3806,7 @@ SV *
 plperl_spi_query_prepared(char *query, int argc, SV **argv)
 {
 	int			i;
-	char	   *nulls;
+	bool	   *nulls;
 	Datum	   *argvalues;
 	plperl_query_desc *qdesc;
 	plperl_query_entry *hash_entry;
@@ -3849,7 +3849,7 @@ plperl_spi_query_prepared(char *query, int argc, SV **argv)
 		 ************************************************************/
 		if (argc > 0)
 		{
-			nulls = (char *) palloc(argc);
+			nulls = (bool *) palloc(argc);
 			argvalues = (Datum *) palloc(argc * sizeof(Datum));
 		}
 		else
@@ -3869,7 +3869,7 @@ plperl_spi_query_prepared(char *query, int argc, SV **argv)
 											  &qdesc->arginfuncs[i],
 											  qdesc->argtypioparams[i],
 											  &isnull);
-			nulls[i] = isnull ? 'n' : ' ';
+			nulls[i] = isnull;
 		}
 
 		/************************************************************
diff --git a/src/pl/plpython/plpy_cursorobject.c b/src/pl/plpython/plpy_cursorobject.c
index 08d8b607e3..0918fe0f1f 100644
--- a/src/pl/plpython/plpy_cursorobject.c
+++ b/src/pl/plpython/plpy_cursorobject.c
@@ -201,11 +201,11 @@ PLy_cursor_plan(PyObject *ob, PyObject *args)
 	PG_TRY();
 	{
 		Portal		portal;
-		char	   *volatile nulls;
+		bool	   *volatile nulls;
 		volatile int j;
 
 		if (nargs > 0)
-			nulls = palloc(nargs * sizeof(char));
+			nulls = palloc(nargs * sizeof(bool));
 		else
 			nulls = NULL;
 
@@ -220,7 +220,7 @@ PLy_cursor_plan(PyObject *ob, PyObject *args)
 				bool		isnull;
 
 				plan->values[j] = PLy_output_convert(arg, elem, &isnull);
-				nulls[j] = isnull ? 'n' : ' ';
+				nulls[j] = isnull;
 			}
 			PG_FINALLY();
 			{
diff --git a/src/test/regress/regress.c b/src/test/regress/regress.c
index 32ab9ed6b5..b31202d500 100644
--- a/src/test/regress/regress.c
+++ b/src/test/regress/regress.c
@@ -273,7 +273,7 @@ ttdummy(PG_FUNCTION_ARGS)
 	Datum		newon,
 				newoff;
 	Datum	   *cvals;			/* column values */
-	char	   *cnulls;			/* column nulls */
+	bool	   *cnulls;			/* column nulls */
 	char	   *relname;		/* triggered relation name */
 	Relation	rel;			/* triggered relation */
 	HeapTuple	trigtuple;
@@ -374,27 +374,27 @@ ttdummy(PG_FUNCTION_ARGS)
 
 	/* Fetch tuple values and nulls */
 	cvals = (Datum *) palloc(natts * sizeof(Datum));
-	cnulls = (char *) palloc(natts * sizeof(char));
+	cnulls = (bool *) palloc(natts * sizeof(bool));
 	for (i = 0; i < natts; i++)
 	{
 		cvals[i] = SPI_getbinval((newtuple != NULL) ? newtuple : trigtuple,
 								 tupdesc, i + 1, &isnull);
-		cnulls[i] = (isnull) ? 'n' : ' ';
+		cnulls[i] = isnull;
 	}
 
 	/* change date column(s) */
 	if (newtuple)				/* UPDATE */
 	{
 		cvals[attnum[0] - 1] = newoff;	/* start_date eq current date */
-		cnulls[attnum[0] - 1] = ' ';
+		cnulls[attnum[0] - 1] = false;
 		cvals[attnum[1] - 1] = TTDUMMY_INFINITY;	/* stop_date eq INFINITY */
-		cnulls[attnum[1] - 1] = ' ';
+		cnulls[attnum[1] - 1] = false;
 	}
 	else
 		/* DELETE */
 	{
 		cvals[attnum[1] - 1] = newoff;	/* stop_date eq current date */
-		cnulls[attnum[1] - 1] = ' ';
+		cnulls[attnum[1] - 1] = false;
 	}
 
 	/* if there is no plan ... */
-- 
2.30.0

#2Hamid Akhtar
hamid.akhtar@gmail.com
In reply to: japin (#1)
Re: Use boolean array for nulls parameters

I personally don't see any benefit in this change. The focus shouldn't be
on fixing things that aren't broken. Perhaps, there is more value in using
bitmap data type to keep track of NULL values, which is typical storage vs
performance debate, and IMHO, it's better to err on using slightly more
storage for much better performance. IIRC, the bitmap idea has previously
discussed been rejected too.

On Tue, Jan 19, 2021 at 7:07 PM japin <japinli@hotmail.com> wrote:

Hi,

When I review the [1], I find that the tuple's nulls array use char type.
However there are many places use boolean array to repsent the nulls array,
so I think we can replace the char type nulls array to boolean type. This
change will break the SPI_xxx API, I'm not sure whether this chagnges cause
other problems or not. Any thought?

[1] -
/messages/by-id/CA+HiwqGkfJfYdeq5vHPh6eqPKjSbfpDDY+j-kXYFePQedtSLeg@mail.gmail.com

--
Regrads,
Japin Li.
ChengDu WenWu Information Technology Co.,Ltd.

--
Highgo Software (Canada/China/Pakistan)
URL : www.highgo.ca
ADDR: 10318 WHALLEY BLVD, Surrey, BC
CELL:+923335449950 EMAIL: mailto:hamid.akhtar@highgo.ca
SKYPE: engineeredvirus

#3Tom Lane
tgl@sss.pgh.pa.us
In reply to: japin (#1)
Re: Use boolean array for nulls parameters

japin <japinli@hotmail.com> writes:

When I review the [1], I find that the tuple's nulls array use char type.
However there are many places use boolean array to repsent the nulls array,
so I think we can replace the char type nulls array to boolean type. This
change will break the SPI_xxx API, I'm not sure whether this chagnges cause
other problems or not. Any thought?

We have always considered that changing the APIs of published SPI
interfaces is a non-starter. The entire reason those calls still
exist at all is for the benefit of third-party extensions.

regards, tom lane

#4japin
japinli@hotmail.com
In reply to: Tom Lane (#3)
Re: Use boolean array for nulls parameters

On Tue, 19 Jan 2021 at 23:45, Tom Lane <tgl@sss.pgh.pa.us> wrote:

japin <japinli@hotmail.com> writes:

When I review the [1], I find that the tuple's nulls array use char type.
However there are many places use boolean array to repsent the nulls array,
so I think we can replace the char type nulls array to boolean type. This
change will break the SPI_xxx API, I'm not sure whether this chagnges cause
other problems or not. Any thought?

We have always considered that changing the APIs of published SPI
interfaces is a non-starter. The entire reason those calls still
exist at all is for the benefit of third-party extensions.

Thanks for your clarify. I agree that we should keep the APIs stable, maybe we
can modify this in someday when the APIs must be changed.

--
Regrads,
Japin Li.
ChengDu WenWu Information Technology Co.,Ltd.