|
8 | 8 | *
|
9 | 9 | *
|
10 | 10 | * 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 $ |
12 | 12 | *
|
13 | 13 | *-------------------------------------------------------------------------
|
14 | 14 | */
|
@@ -36,6 +36,10 @@ static int _SPI_stack_depth = 0; /* allocated size of _SPI_stack */
|
36 | 36 | static int _SPI_connected = -1;
|
37 | 37 | static int _SPI_curid = -1;
|
38 | 38 |
|
| 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 | + |
39 | 43 | static void _SPI_prepare_plan(const char *src, SPIPlanPtr plan,
|
40 | 44 | ParamListInfo boundParams);
|
41 | 45 |
|
@@ -916,6 +920,80 @@ Portal
|
916 | 920 | SPI_cursor_open(const char *name, SPIPlanPtr plan,
|
917 | 921 | Datum *Values, const char *Nulls,
|
918 | 922 | 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) |
919 | 997 | {
|
920 | 998 | CachedPlanSource *plansource;
|
921 | 999 | CachedPlan *cplan;
|
@@ -997,7 +1075,7 @@ SPI_cursor_open(const char *name, SPIPlanPtr plan,
|
997 | 1075 | ParamExternData *prm = ¶mLI->params[k];
|
998 | 1076 |
|
999 | 1077 | prm->ptype = plan->argtypes[k];
|
1000 |
| - prm->pflags = 0; |
| 1078 | + prm->pflags = pflags; |
1001 | 1079 | prm->isnull = (Nulls && Nulls[k] == 'n');
|
1002 | 1080 | if (prm->isnull)
|
1003 | 1081 | {
|
@@ -1129,64 +1207,6 @@ SPI_cursor_open(const char *name, SPIPlanPtr plan,
|
1129 | 1207 | }
|
1130 | 1208 |
|
1131 | 1209 |
|
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 |
| - |
1190 | 1210 | /*
|
1191 | 1211 | * SPI_cursor_find()
|
1192 | 1212 | *
|
|
0 commit comments