summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/backend/nodes/outfuncs.c3
-rw-r--r--src/backend/nodes/readfuncs.c4
-rw-r--r--src/backend/pgxc/pool/execRemote.c38
-rw-r--r--src/include/pgxc/execRemote.h1
-rw-r--r--src/test/regress/expected/plpgsql_1.out23
-rw-r--r--src/test/regress/sql/plpgsql.sql22
6 files changed, 83 insertions, 8 deletions
diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c
index e3eaf18eda..ee35e3f510 100644
--- a/src/backend/nodes/outfuncs.c
+++ b/src/backend/nodes/outfuncs.c
@@ -1462,6 +1462,9 @@ _outRemoteStmt(StringInfo str, const RemoteStmt *node)
appendStringInfo(str, " :paramid");
appendStringInfo(str, " %d", rparam->paramid);
+ appendStringInfo(str, " :paramused");
+ appendStringInfo(str, " %d", rparam->paramused);
+
appendStringInfo(str, " :paramtype");
if (portable_output)
{
diff --git a/src/backend/nodes/readfuncs.c b/src/backend/nodes/readfuncs.c
index 060ce5a2ec..e8f25b08dd 100644
--- a/src/backend/nodes/readfuncs.c
+++ b/src/backend/nodes/readfuncs.c
@@ -3262,6 +3262,10 @@ _readRemoteStmt(void)
token = pg_strtok(&length);
rparam->paramid = atoi(token);
+ token = pg_strtok(&length); /* skip :paramused */
+ token = pg_strtok(&length);
+ rparam->paramused = atoi(token);
+
token = pg_strtok(&length); /* skip :paramtype */
if (portable_input)
{
diff --git a/src/backend/pgxc/pool/execRemote.c b/src/backend/pgxc/pool/execRemote.c
index 4656176591..bce09736eb 100644
--- a/src/backend/pgxc/pool/execRemote.c
+++ b/src/backend/pgxc/pool/execRemote.c
@@ -5382,16 +5382,32 @@ ExecInitRemoteSubplan(RemoteSubplan *node, EState *estate, int eflags)
*/
if (!OidIsValid(param->ptype) && ext_params->paramFetch)
(*ext_params->paramFetch) (ext_params, i + 1);
+
/*
- * If parameter type is still not defined assume it is
- * unused
+ * If the parameter type is still not defined, assume that
+ * it is unused. But we put a default INT4OID type for such
+ * unused parameters to keep the parameter pushdown code
+ * happy.
+ *
+ * These unused parameters are never accessed during
+ * execution and we will just a null value for these
+ * "dummy" parameters. But including them here ensures that
+ * we send down the parameters in the correct order and at
+ * the position that the datanode needs
*/
- if (!OidIsValid(param->ptype))
- continue;
+ if (OidIsValid(param->ptype))
+ {
+ rstmt.remoteparams[paramno].paramused = 1;
+ rstmt.remoteparams[paramno].paramtype = param->ptype;
+ }
+ else
+ {
+ rstmt.remoteparams[paramno].paramused = 0;
+ rstmt.remoteparams[paramno].paramtype = INT4OID;
+ }
rstmt.remoteparams[paramno].paramkind = PARAM_EXTERN;
rstmt.remoteparams[paramno].paramid = i + 1;
- rstmt.remoteparams[paramno].paramtype = param->ptype;
paramno++;
}
/* store actual number of parameters */
@@ -5410,6 +5426,7 @@ ExecInitRemoteSubplan(RemoteSubplan *node, EState *estate, int eflags)
rstmt.remoteparams[paramno].paramkind = PARAM_EXEC;
rstmt.remoteparams[paramno].paramid = i;
rstmt.remoteparams[paramno].paramtype = prmdata->ptype;
+ rstmt.remoteparams[paramno].paramused = 1;
/* Will scan plan tree to find out data type of the param */
if (prmdata->ptype == InvalidOid)
defineParams = bms_add_member(defineParams, i);
@@ -5623,10 +5640,14 @@ ExecFinishInitRemoteSubplan(RemoteSubplanState *node)
static void
-append_param_data(StringInfo buf, Oid ptype, Datum value, bool isnull)
+append_param_data(StringInfo buf, Oid ptype, int pused, Datum value, bool isnull)
{
uint32 n32;
+ /* Assume unused parameters to have null values */
+ if (!pused)
+ ptype = INT4OID;
+
if (isnull)
{
n32 = htonl(-1);
@@ -5692,11 +5713,12 @@ static int encode_parameters(int nparams, RemoteParam *remoteparams,
{
RemoteParam *rparam = &remoteparams[i];
int ptype = rparam->paramtype;
+ int pused = rparam->paramused;
if (rparam->paramkind == PARAM_EXTERN)
{
ParamExternData *param;
param = &(estate->es_param_list_info->params[rparam->paramid - 1]);
- append_param_data(&buf, ptype, param->value, param->isnull);
+ append_param_data(&buf, ptype, pused, param->value, param->isnull);
}
else
{
@@ -5712,7 +5734,7 @@ static int encode_parameters(int nparams, RemoteParam *remoteparams,
}
if (!param->done)
param->isnull = true;
- append_param_data(&buf, ptype, param->value, param->isnull);
+ append_param_data(&buf, ptype, pused, param->value, param->isnull);
}
}
diff --git a/src/include/pgxc/execRemote.h b/src/include/pgxc/execRemote.h
index 4cbcbec4ad..eda1ac4e99 100644
--- a/src/include/pgxc/execRemote.h
+++ b/src/include/pgxc/execRemote.h
@@ -160,6 +160,7 @@ typedef struct RemoteParam
ParamKind paramkind; /* kind of parameter */
int paramid; /* numeric ID for parameter */
Oid paramtype; /* pg_type OID of parameter's datatype */
+ int paramused; /* is param used */
} RemoteParam;
diff --git a/src/test/regress/expected/plpgsql_1.out b/src/test/regress/expected/plpgsql_1.out
index 4f9dea9c25..45936927e3 100644
--- a/src/test/regress/expected/plpgsql_1.out
+++ b/src/test/regress/expected/plpgsql_1.out
@@ -5529,3 +5529,26 @@ end;
$$;
ERROR: Internal subtransactions not supported in Postgres-XL
CONTEXT: PL/pgSQL function inline_code_block line 2 during statement block entry
+-- Check parameter handling
+BEGIN;
+DROP TABLE IF EXISTS testcase_13;
+NOTICE: table "testcase_13" does not exist, skipping
+CREATE TABLE testcase_13 (patient_id integer);
+INSERT INTO testcase_13 VALUES (1);
+DO $$
+DECLARE
+ r RECORD;
+BEGIN
+FOR r IN SELECT * FROM testcase_13 LOOP
+ RAISE INFO 'r.patient_id=%', r.patient_id;
+ IF (SELECT EXISTS (
+ SELECT FROM testcase_13 WHERE patient_id = r.patient_id
+ ))
+ THEN
+ RAISE INFO 'condition true';
+ END IF;
+ END LOOP;
+END $$;
+INFO: r.patient_id=1
+INFO: condition true
+ROLLBACK;
diff --git a/src/test/regress/sql/plpgsql.sql b/src/test/regress/sql/plpgsql.sql
index b86524e026..750f80c8bc 100644
--- a/src/test/regress/sql/plpgsql.sql
+++ b/src/test/regress/sql/plpgsql.sql
@@ -4386,3 +4386,25 @@ exception when others then
null; -- do nothing
end;
$$;
+
+
+-- Check parameter handling
+BEGIN;
+DROP TABLE IF EXISTS testcase_13;
+CREATE TABLE testcase_13 (patient_id integer);
+INSERT INTO testcase_13 VALUES (1);
+DO $$
+DECLARE
+ r RECORD;
+BEGIN
+FOR r IN SELECT * FROM testcase_13 LOOP
+ RAISE INFO 'r.patient_id=%', r.patient_id;
+ IF (SELECT EXISTS (
+ SELECT FROM testcase_13 WHERE patient_id = r.patient_id
+ ))
+ THEN
+ RAISE INFO 'condition true';
+ END IF;
+ END LOOP;
+END $$;
+ROLLBACK;