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] - https://www.postgresql.org/message-id/flat/ca+hiwqgkfjfydeq5vhph6eqpkjsbfpddy+j-kxyfepqedts...@mail.gmail.com -- Regrads, Japin Li. ChengDu WenWu Information Technology Co.,Ltd.
>From 7496f20ccfda7687333db9e5c43227ee30e4eda9 Mon Sep 17 00:00:00 2001 From: Japin Li <japi...@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>' '</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>' '</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>' '</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>' '</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>' '</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 = ¶mLI->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