|
8 | 8 | *
|
9 | 9 | *
|
10 | 10 | * IDENTIFICATION
|
11 |
| - * $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.210 2008/04/17 21:37:28 alvherre Exp $ |
| 11 | + * $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.211 2008/05/03 00:11:36 tgl Exp $ |
12 | 12 | *
|
13 | 13 | *-------------------------------------------------------------------------
|
14 | 14 | */
|
@@ -197,6 +197,8 @@ static void assign_text_var(PLpgSQL_var *var, const char *str);
|
197 | 197 | static PreparedParamsData *exec_eval_using_params(PLpgSQL_execstate *estate,
|
198 | 198 | List *params);
|
199 | 199 | static void free_params_data(PreparedParamsData *ppd);
|
| 200 | +static Portal exec_dynquery_with_params(PLpgSQL_execstate *estate, |
| 201 | + PLpgSQL_expr *query, List *params); |
200 | 202 |
|
201 | 203 |
|
202 | 204 | /* ----------
|
@@ -1968,7 +1970,7 @@ exec_stmt_return(PLpgSQL_execstate *estate, PLpgSQL_stmt_return *stmt)
|
1968 | 1970 | PLpgSQL_row *row = (PLpgSQL_row *) retvar;
|
1969 | 1971 |
|
1970 | 1972 | Assert(row->rowtupdesc);
|
1971 |
| - estate->retval = |
| 1973 | + estate->retval = |
1972 | 1974 | PointerGetDatum(make_tuple_from_row(estate, row,
|
1973 | 1975 | row->rowtupdesc));
|
1974 | 1976 | if (DatumGetPointer(estate->retval) == NULL) /* should not happen */
|
@@ -2189,7 +2191,18 @@ exec_stmt_return_query(PLpgSQL_execstate *estate,
|
2189 | 2191 | if (estate->tuple_store == NULL)
|
2190 | 2192 | exec_init_tuple_store(estate);
|
2191 | 2193 |
|
2192 |
| - exec_run_select(estate, stmt->query, 0, &portal); |
| 2194 | + if (stmt->query != NULL) |
| 2195 | + { |
| 2196 | + /* static query */ |
| 2197 | + exec_run_select(estate, stmt->query, 0, &portal); |
| 2198 | + } |
| 2199 | + else |
| 2200 | + { |
| 2201 | + /* RETURN QUERY EXECUTE */ |
| 2202 | + Assert(stmt->dynquery != NULL); |
| 2203 | + portal = exec_dynquery_with_params(estate, stmt->dynquery, |
| 2204 | + stmt->params); |
| 2205 | + } |
2193 | 2206 |
|
2194 | 2207 | if (!compatible_tupdesc(estate->rettupdesc, portal->tupDesc))
|
2195 | 2208 | ereport(ERROR,
|
@@ -2841,58 +2854,10 @@ exec_stmt_dynexecute(PLpgSQL_execstate *estate,
|
2841 | 2854 | static int
|
2842 | 2855 | exec_stmt_dynfors(PLpgSQL_execstate *estate, PLpgSQL_stmt_dynfors *stmt)
|
2843 | 2856 | {
|
2844 |
| - Datum query; |
2845 |
| - bool isnull; |
2846 |
| - Oid restype; |
2847 |
| - char *querystr; |
2848 | 2857 | Portal portal;
|
2849 | 2858 | int rc;
|
2850 | 2859 |
|
2851 |
| - /* |
2852 |
| - * Evaluate the string expression after the EXECUTE keyword. It's result |
2853 |
| - * is the querystring we have to execute. |
2854 |
| - */ |
2855 |
| - query = exec_eval_expr(estate, stmt->query, &isnull, &restype); |
2856 |
| - if (isnull) |
2857 |
| - ereport(ERROR, |
2858 |
| - (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), |
2859 |
| - errmsg("cannot EXECUTE a null querystring"))); |
2860 |
| - |
2861 |
| - /* Get the C-String representation */ |
2862 |
| - querystr = convert_value_to_string(query, restype); |
2863 |
| - |
2864 |
| - exec_eval_cleanup(estate); |
2865 |
| - |
2866 |
| - /* |
2867 |
| - * Open an implicit cursor for the query. We use SPI_cursor_open_with_args |
2868 |
| - * even when there are no params, because this avoids making and freeing |
2869 |
| - * one copy of the plan. |
2870 |
| - */ |
2871 |
| - if (stmt->params) |
2872 |
| - { |
2873 |
| - PreparedParamsData *ppd; |
2874 |
| - |
2875 |
| - ppd = exec_eval_using_params(estate, stmt->params); |
2876 |
| - portal = SPI_cursor_open_with_args(NULL, |
2877 |
| - querystr, |
2878 |
| - ppd->nargs, ppd->types, |
2879 |
| - ppd->values, ppd->nulls, |
2880 |
| - estate->readonly_func, 0); |
2881 |
| - free_params_data(ppd); |
2882 |
| - } |
2883 |
| - else |
2884 |
| - { |
2885 |
| - portal = SPI_cursor_open_with_args(NULL, |
2886 |
| - querystr, |
2887 |
| - 0, NULL, |
2888 |
| - NULL, NULL, |
2889 |
| - estate->readonly_func, 0); |
2890 |
| - } |
2891 |
| - |
2892 |
| - if (portal == NULL) |
2893 |
| - elog(ERROR, "could not open implicit cursor for query \"%s\": %s", |
2894 |
| - querystr, SPI_result_code_string(SPI_result)); |
2895 |
| - pfree(querystr); |
| 2860 | + portal = exec_dynquery_with_params(estate, stmt->query, stmt->params); |
2896 | 2861 |
|
2897 | 2862 | /*
|
2898 | 2863 | * Execute the loop
|
@@ -5208,3 +5173,65 @@ free_params_data(PreparedParamsData *ppd)
|
5208 | 5173 |
|
5209 | 5174 | pfree(ppd);
|
5210 | 5175 | }
|
| 5176 | + |
| 5177 | +/* |
| 5178 | + * Open portal for dynamic query |
| 5179 | + */ |
| 5180 | +static Portal |
| 5181 | +exec_dynquery_with_params(PLpgSQL_execstate *estate, PLpgSQL_expr *dynquery, |
| 5182 | + List *params) |
| 5183 | +{ |
| 5184 | + Portal portal; |
| 5185 | + Datum query; |
| 5186 | + bool isnull; |
| 5187 | + Oid restype; |
| 5188 | + char *querystr; |
| 5189 | + |
| 5190 | + /* |
| 5191 | + * Evaluate the string expression after the EXECUTE keyword. Its result |
| 5192 | + * is the querystring we have to execute. |
| 5193 | + */ |
| 5194 | + query = exec_eval_expr(estate, dynquery, &isnull, &restype); |
| 5195 | + if (isnull) |
| 5196 | + ereport(ERROR, |
| 5197 | + (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), |
| 5198 | + errmsg("cannot EXECUTE a null querystring"))); |
| 5199 | + |
| 5200 | + /* Get the C-String representation */ |
| 5201 | + querystr = convert_value_to_string(query, restype); |
| 5202 | + |
| 5203 | + exec_eval_cleanup(estate); |
| 5204 | + |
| 5205 | + /* |
| 5206 | + * Open an implicit cursor for the query. We use SPI_cursor_open_with_args |
| 5207 | + * even when there are no params, because this avoids making and freeing |
| 5208 | + * one copy of the plan. |
| 5209 | + */ |
| 5210 | + if (params) |
| 5211 | + { |
| 5212 | + PreparedParamsData *ppd; |
| 5213 | + |
| 5214 | + ppd = exec_eval_using_params(estate, params); |
| 5215 | + portal = SPI_cursor_open_with_args(NULL, |
| 5216 | + querystr, |
| 5217 | + ppd->nargs, ppd->types, |
| 5218 | + ppd->values, ppd->nulls, |
| 5219 | + estate->readonly_func, 0); |
| 5220 | + free_params_data(ppd); |
| 5221 | + } |
| 5222 | + else |
| 5223 | + { |
| 5224 | + portal = SPI_cursor_open_with_args(NULL, |
| 5225 | + querystr, |
| 5226 | + 0, NULL, |
| 5227 | + NULL, NULL, |
| 5228 | + estate->readonly_func, 0); |
| 5229 | + } |
| 5230 | + |
| 5231 | + if (portal == NULL) |
| 5232 | + elog(ERROR, "could not open implicit cursor for query \"%s\": %s", |
| 5233 | + querystr, SPI_result_code_string(SPI_result)); |
| 5234 | + pfree(querystr); |
| 5235 | + |
| 5236 | + return portal; |
| 5237 | +} |
0 commit comments