diff options
-rw-r--r-- | src/backend/nodes/outfuncs.c | 3 | ||||
-rw-r--r-- | src/backend/nodes/readfuncs.c | 4 | ||||
-rw-r--r-- | src/backend/pgxc/pool/execRemote.c | 38 | ||||
-rw-r--r-- | src/include/pgxc/execRemote.h | 1 | ||||
-rw-r--r-- | src/test/regress/expected/plpgsql_1.out | 23 | ||||
-rw-r--r-- | src/test/regress/sql/plpgsql.sql | 22 |
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; |