Skip to content

Commit 6a9fffc

Browse files
committed
Refactor SPI_cursor_open/SPI_cursor_open_with_args so that the latter sets
the PARAM_FLAG_CONST flag on the parameters that are passed into the portal, while the former's behavior is unchanged. This should only affect the case where the portal is executing an EXPLAIN; it will cause the generated plan to look more like what would be generated if the portal were actually executing the command being explained. Per gripe from Pavel.
1 parent 6d19e9f commit 6a9fffc

File tree

1 file changed

+80
-60
lines changed
  • src/backend/executor

1 file changed

+80
-60
lines changed

src/backend/executor/spi.c

Lines changed: 80 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/executor/spi.c,v 1.195 2008/05/12 20:02:00 alvherre Exp $
11+
* $PostgreSQL: pgsql/src/backend/executor/spi.c,v 1.196 2008/06/01 17:32:48 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -36,6 +36,10 @@ static int _SPI_stack_depth = 0; /* allocated size of _SPI_stack */
3636
static int _SPI_connected = -1;
3737
static int _SPI_curid = -1;
3838

39+
static Portal SPI_cursor_open_internal(const char *name, SPIPlanPtr plan,
40+
Datum *Values, const char *Nulls,
41+
bool read_only, int pflags);
42+
3943
static void _SPI_prepare_plan(const char *src, SPIPlanPtr plan,
4044
ParamListInfo boundParams);
4145

@@ -916,6 +920,80 @@ Portal
916920
SPI_cursor_open(const char *name, SPIPlanPtr plan,
917921
Datum *Values, const char *Nulls,
918922
bool read_only)
923+
{
924+
return SPI_cursor_open_internal(name, plan, Values, Nulls,
925+
read_only, 0);
926+
}
927+
928+
929+
/*
930+
* SPI_cursor_open_with_args()
931+
*
932+
* Parse and plan a query and open it as a portal. Like SPI_execute_with_args,
933+
* we can tell the planner to rely on the parameter values as constants,
934+
* because the plan will only be used once.
935+
*/
936+
Portal
937+
SPI_cursor_open_with_args(const char *name,
938+
const char *src,
939+
int nargs, Oid *argtypes,
940+
Datum *Values, const char *Nulls,
941+
bool read_only, int cursorOptions)
942+
{
943+
Portal result;
944+
_SPI_plan plan;
945+
ParamListInfo paramLI;
946+
947+
if (src == NULL || nargs < 0)
948+
elog(ERROR, "SPI_cursor_open_with_args called with invalid arguments");
949+
950+
if (nargs > 0 && (argtypes == NULL || Values == NULL))
951+
elog(ERROR, "SPI_cursor_open_with_args called with missing parameters");
952+
953+
SPI_result = _SPI_begin_call(true);
954+
if (SPI_result < 0)
955+
elog(ERROR, "SPI_cursor_open_with_args called while not connected");
956+
957+
memset(&plan, 0, sizeof(_SPI_plan));
958+
plan.magic = _SPI_PLAN_MAGIC;
959+
plan.cursor_options = cursorOptions;
960+
plan.nargs = nargs;
961+
plan.argtypes = argtypes;
962+
963+
paramLI = _SPI_convert_params(nargs, argtypes,
964+
Values, Nulls,
965+
PARAM_FLAG_CONST);
966+
967+
_SPI_prepare_plan(src, &plan, paramLI);
968+
969+
/* We needn't copy the plan; SPI_cursor_open_internal will do so */
970+
971+
/* Adjust stack so that SPI_cursor_open_internal doesn't complain */
972+
_SPI_curid--;
973+
974+
/* SPI_cursor_open_internal must be called in procedure memory context */
975+
_SPI_procmem();
976+
977+
result = SPI_cursor_open_internal(name, &plan, Values, Nulls,
978+
read_only, PARAM_FLAG_CONST);
979+
980+
/* And clean up */
981+
_SPI_curid++;
982+
_SPI_end_call(true);
983+
984+
return result;
985+
}
986+
987+
988+
/*
989+
* SPI_cursor_open_internal()
990+
*
991+
* Common code for SPI_cursor_open and SPI_cursor_open_with_args
992+
*/
993+
static Portal
994+
SPI_cursor_open_internal(const char *name, SPIPlanPtr plan,
995+
Datum *Values, const char *Nulls,
996+
bool read_only, int pflags)
919997
{
920998
CachedPlanSource *plansource;
921999
CachedPlan *cplan;
@@ -997,7 +1075,7 @@ SPI_cursor_open(const char *name, SPIPlanPtr plan,
9971075
ParamExternData *prm = &paramLI->params[k];
9981076

9991077
prm->ptype = plan->argtypes[k];
1000-
prm->pflags = 0;
1078+
prm->pflags = pflags;
10011079
prm->isnull = (Nulls && Nulls[k] == 'n');
10021080
if (prm->isnull)
10031081
{
@@ -1129,64 +1207,6 @@ SPI_cursor_open(const char *name, SPIPlanPtr plan,
11291207
}
11301208

11311209

1132-
/*
1133-
* SPI_cursor_open_with_args()
1134-
*
1135-
* Parse and plan a query and open it as a portal. Like SPI_execute_with_args,
1136-
* we can tell the planner to rely on the parameter values as constants,
1137-
* because the plan will only be used once.
1138-
*/
1139-
Portal
1140-
SPI_cursor_open_with_args(const char *name,
1141-
const char *src,
1142-
int nargs, Oid *argtypes,
1143-
Datum *Values, const char *Nulls,
1144-
bool read_only, int cursorOptions)
1145-
{
1146-
Portal result;
1147-
_SPI_plan plan;
1148-
ParamListInfo paramLI;
1149-
1150-
if (src == NULL || nargs < 0)
1151-
elog(ERROR, "SPI_cursor_open_with_args called with invalid arguments");
1152-
1153-
if (nargs > 0 && (argtypes == NULL || Values == NULL))
1154-
elog(ERROR, "SPI_cursor_open_with_args called with missing parameters");
1155-
1156-
SPI_result = _SPI_begin_call(true);
1157-
if (SPI_result < 0)
1158-
elog(ERROR, "SPI_cursor_open_with_args called while not connected");
1159-
1160-
memset(&plan, 0, sizeof(_SPI_plan));
1161-
plan.magic = _SPI_PLAN_MAGIC;
1162-
plan.cursor_options = cursorOptions;
1163-
plan.nargs = nargs;
1164-
plan.argtypes = argtypes;
1165-
1166-
paramLI = _SPI_convert_params(nargs, argtypes,
1167-
Values, Nulls,
1168-
PARAM_FLAG_CONST);
1169-
1170-
_SPI_prepare_plan(src, &plan, paramLI);
1171-
1172-
/* We needn't copy the plan; SPI_cursor_open will do so */
1173-
1174-
/* Adjust stack so that SPI_cursor_open doesn't complain */
1175-
_SPI_curid--;
1176-
1177-
/* SPI_cursor_open expects to be called in procedure memory context */
1178-
_SPI_procmem();
1179-
1180-
result = SPI_cursor_open(name, &plan, Values, Nulls, read_only);
1181-
1182-
/* And clean up */
1183-
_SPI_curid++;
1184-
_SPI_end_call(true);
1185-
1186-
return result;
1187-
}
1188-
1189-
11901210
/*
11911211
* SPI_cursor_find()
11921212
*

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy