|
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 | staticPreparedParamsData*exec_eval_using_params(PLpgSQL_execstate*estate, |
198 | 198 | List*params); |
199 | 199 | staticvoidfree_params_data(PreparedParamsData*ppd); |
| 200 | +staticPortalexec_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 | staticint |
2842 | 2855 | exec_stmt_dynfors(PLpgSQL_execstate*estate,PLpgSQL_stmt_dynfors*stmt) |
2843 | 2856 | { |
2844 | | -Datumquery; |
2845 | | -boolisnull; |
2846 | | -Oidrestype; |
2847 | | -char*querystr; |
2848 | 2857 | Portalportal; |
2849 | 2858 | intrc; |
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 | +staticPortal |
| 5181 | +exec_dynquery_with_params(PLpgSQL_execstate*estate,PLpgSQL_expr*dynquery, |
| 5182 | +List*params) |
| 5183 | +{ |
| 5184 | +Portalportal; |
| 5185 | +Datumquery; |
| 5186 | +boolisnull; |
| 5187 | +Oidrestype; |
| 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 | +returnportal; |
| 5237 | +} |