1111#include "common/base64.h"
1212#include "executor/executor.h"
1313#include "nodes/nodes.h"
14+ #include "nodes/params.h"
1415#include "nodes/plannodes.h"
1516#include "tcop/pquery.h"
1617#include "tcop/utility.h"
@@ -42,10 +43,13 @@ _PG_init(void)
4243Datum
4344pg_store_query_plan (PG_FUNCTION_ARGS )
4445{
45- char * query_string = TextDatumGetCString (PG_GETARG_DATUM (1 )),
46- * filename = TextDatumGetCString (PG_GETARG_DATUM (0 )),
47- * plan_string ;
48- int nstmts ;
46+ char * filename = TextDatumGetCString (PG_GETARG_DATUM (0 )),
47+ * squery = TextDatumGetCString (PG_GETARG_DATUM (1 )),
48+ * sparams = NULL ,
49+ * start_address ,
50+ * splan ;
51+ int nstmts ,
52+ sparams_len ;
4953 FILE * fout ;
5054 MemoryContext oldcontext ;
5155 List * parsetree_list ;
@@ -56,21 +60,21 @@ pg_store_query_plan(PG_FUNCTION_ARGS)
5660 size_t string_len ;
5761
5862 if (EXPLAN_DEBUG_LEVEL > 0 )
59- elog (LOG , "Store into %s plan of the query %s." , filename , query_string );
63+ elog (LOG , "Store into %s plan of the query %s." , filename , squery );
6064
6165 oldcontext = MemoryContextSwitchTo (MessageContext );
6266
63- parsetree_list = pg_parse_query (query_string );
67+ parsetree_list = pg_parse_query (squery );
6468 nstmts = list_length (parsetree_list );
6569 if (nstmts != 1 )
6670 elog (ERROR , "Query contains %d elements, but must contain only one." , nstmts );
6771
6872 parsetree = (RawStmt * ) linitial (parsetree_list );
69- querytree_list = pg_analyze_and_rewrite (parsetree , query_string , NULL , 0 , NULL );
73+ querytree_list = pg_analyze_and_rewrite (parsetree , squery , NULL , 0 , NULL );
7074 plantree_list = pg_plan_queries (querytree_list , CURSOR_OPT_PARALLEL_OK , NULL );
7175
7276 queryDesc = CreateQueryDesc ((PlannedStmt * ) linitial (plantree_list ),
73- query_string ,
77+ squery ,
7478 InvalidSnapshot ,
7579 InvalidSnapshot ,
7680 None_Receiver ,
@@ -82,24 +86,35 @@ pg_store_query_plan(PG_FUNCTION_ARGS)
8286
8387 fout = fopen (filename , "wb" );
8488 Assert (fout != NULL );
85- string_len = strlen (query_string );
89+ string_len = strlen (squery );
8690 fwrite (& string_len , sizeof (size_t ), 1 , fout );
87- fwrite (query_string , sizeof (char ), string_len , fout );
91+ fwrite (squery , sizeof (char ), string_len , fout );
8892
8993 set_portable_output (true);
90- plan_string = nodeToString (queryDesc -> plannedstmt );
94+ splan = nodeToString (queryDesc -> plannedstmt );
9195 set_portable_output (false);
92- string_len = strlen (plan_string );
96+ string_len = strlen (splan );
9397 fwrite (& string_len , sizeof (size_t ), 1 , fout );
94- fwrite (plan_string , sizeof (char ), string_len , fout );
95-
98+ fwrite (splan , sizeof (char ), string_len , fout );
99+
100+ /*
101+ * Serialize parameters list. In this case we have no parameters and will
102+ * serialize NULL list.
103+ */
104+ sparams_len = EstimateParamListSpace (NULL );
105+ sparams = palloc0 (sparams_len );
106+ start_address = sparams ;
107+ SerializeParamList (NULL , & start_address );
108+ string_len = sparams_len ;
109+ fwrite (& string_len , sizeof (size_t ), 1 , fout );
110+ fwrite (sparams , sizeof (char ), string_len , fout );
96111 fclose (fout );
97112 MemoryContextSwitchTo (oldcontext );
98113 PG_RETURN_VOID ();
99114}
100115
101116static void
102- exec_plan (char * query_string , char * plan_string )
117+ exec_plan (char * squery , char * splan , char * sparams )
103118{
104119 PlannedStmt * pstmt ;
105120 ParamListInfo paramLI = NULL ;
@@ -108,28 +123,42 @@ exec_plan(char *query_string, char *plan_string)
108123 QueryDesc * queryDesc ;
109124 DestReceiver * receiver ;
110125 int eflags = 0 ;
126+ Oid * param_types = NULL ;
127+ char * start_address = sparams ;
128+
129+ Assert (squery && splan && sparams );
111130
112131 PG_TRY ();
113132 {
114- set_portable_input (true);
115- pstmt = (PlannedStmt * ) stringToNode (plan_string );
116- set_portable_input (false);
133+ pstmt = (PlannedStmt * ) stringToNode (splan );
134+
135+ /* Deserialize parameters of the query */
136+ paramLI = RestoreParamList (& start_address );
117137 }
118138 PG_CATCH ();
119139 {
120- elog (INFO , "BAD PLAN: %s. Query: %s" , plan_string , query_string );
140+ elog (INFO , "BAD PLAN: %s. Query: %s" , splan , squery );
121141 PG_RE_THROW ();
122142 }
123143 PG_END_TRY ();
124144
125145 if (EXPLAN_DEBUG_LEVEL > 0 )
126- elog (INFO , "query: %s\n" , query_string );
146+ elog (INFO , "query: %s\n" , squery );
127147 if (EXPLAN_DEBUG_LEVEL > 1 )
128- elog (INFO , "\nplan: %s\n" , plan_string );
148+ elog (INFO , "\nplan: %s\n" , splan );
149+
150+ psrc = CreateCachedPlan (NULL , squery , NULL );
151+
152+ if (paramLI -> numParams > 0 )
153+ {
154+ int i ;
129155
130- psrc = CreateCachedPlan (NULL , query_string , NULL );
131- CompleteCachedPlan (psrc , NIL , NULL , NULL , 0 , NULL , NULL ,
132- CURSOR_OPT_GENERIC_PLAN , false);
156+ param_types = palloc (sizeof (Oid ) * paramLI -> numParams );
157+ for (i = 0 ; i < paramLI -> numParams ; i ++ )
158+ param_types [i ] = paramLI -> params [i ].ptype ;
159+ }
160+ CompleteCachedPlan (psrc , NIL , NULL , param_types , paramLI -> numParams , NULL ,
161+ NULL , CURSOR_OPT_GENERIC_PLAN , false);
133162
134163 SetRemoteSubplan (psrc , pstmt );
135164 cplan = GetCachedPlan (psrc , paramLI , false, NULL );
@@ -139,7 +168,7 @@ exec_plan(char *query_string, char *plan_string)
139168 PG_TRY ();
140169 {
141170 queryDesc = CreateQueryDesc (pstmt ,
142- query_string ,
171+ squery ,
143172 GetActiveSnapshot (),
144173 InvalidSnapshot ,
145174 receiver ,
@@ -155,7 +184,7 @@ exec_plan(char *query_string, char *plan_string)
155184 }
156185 PG_CATCH ();
157186 {
158- elog (INFO , "BAD QUERY: '%s'." , query_string );
187+ elog (INFO , "BAD QUERY: '%s'." , squery );
159188 ReleaseCachedPlan (cplan , false);
160189 PG_RE_THROW ();
161190 }
@@ -171,37 +200,49 @@ exec_plan(char *query_string, char *plan_string)
171200Datum
172201pg_exec_plan (PG_FUNCTION_ARGS )
173202{
174- char * query_string = TextDatumGetCString (PG_GETARG_DATUM (0 ));
175- char * plan_string = TextDatumGetCString (PG_GETARG_DATUM (1 ));
203+ char * squery = TextDatumGetCString (PG_GETARG_DATUM (0 ));
204+ char * splan = TextDatumGetCString (PG_GETARG_DATUM (1 ));
205+ char * sparams = TextDatumGetCString (PG_GETARG_DATUM (2 ));
176206
177207 char * dec_query ,
178- * dec_plan ;
208+ * dec_plan ,
209+ * dec_params ;
179210 int dec_query_len ,
180211 dec_query_len1 ,
181212 dec_plan_len ,
182- dec_plan_len1 ;
213+ dec_plan_len1 ,
214+ dec_params_len ,
215+ dec_params_len1 ;
183216
184- Assert (query_string != NULL );
185- Assert (plan_string != NULL );
217+ Assert (squery != NULL );
218+ Assert (splan != NULL );
219+ Assert (sparams != NULL );
186220
187- dec_query_len = pg_b64_dec_len (strlen (query_string ) + 1 ) + 1 ;
221+ dec_query_len = pg_b64_dec_len (strlen (squery )) ;
188222 dec_query = palloc0 (dec_query_len + 1 );
189- dec_query_len1 = pg_b64_decode (query_string , strlen (query_string ), dec_query );
190- Assert (dec_query_len > dec_query_len1 );
223+ dec_query_len1 = pg_b64_decode (squery , strlen (squery ), dec_query );
224+ Assert (dec_query_len >= dec_query_len1 );
191225
192- dec_plan_len = pg_b64_dec_len (strlen (plan_string ) + 1 );
226+ dec_plan_len = pg_b64_dec_len (strlen (splan ) );
193227 dec_plan = palloc0 (dec_plan_len + 1 );
194- dec_plan_len1 = pg_b64_decode (plan_string , strlen (plan_string ), dec_plan );
195- Assert (dec_plan_len > dec_plan_len1 );
228+ dec_plan_len1 = pg_b64_decode (splan , strlen (splan ), dec_plan );
229+ Assert (dec_plan_len >= dec_plan_len1 );
230+
231+ dec_params_len = pg_b64_dec_len (strlen (sparams ));
232+ dec_params = palloc0 (dec_params_len + 1 );
233+ dec_params_len1 = pg_b64_decode (sparams , strlen (sparams ), dec_params );
234+ Assert (dec_params_len >= dec_params_len1 );
196235
197- exec_plan (dec_query , dec_plan );
236+ exec_plan (dec_query , dec_plan , dec_params );
198237 pfree (dec_query );
199238 pfree (dec_plan );
239+ pfree (dec_params );
200240 PG_RETURN_BOOL (true);
201241}
202242
203243static void
204- LoadPlanFromFile (const char * filename , char * * query_string , char * * plan_string )
244+ LoadPlanFromFile (const char * filename , char * * squery , char * * splan ,
245+ char * * sparams )
205246{
206247 FILE * fin ;
207248 size_t string_len ;
@@ -210,16 +251,28 @@ LoadPlanFromFile(const char *filename, char **query_string, char **plan_string)
210251 fin = fopen (filename , "rb" );
211252 Assert (fin != NULL );
212253
254+ /* Read query string size, allocate memory and read query from the file. */
213255 nelems = fread (& string_len , sizeof (size_t ), 1 , fin );
214256 Assert (nelems == 1 );
215- * query_string = palloc0 (string_len + 1 );
216- nelems = fread (* query_string , sizeof (char ), string_len , fin );
257+ * squery = palloc0 (string_len + 1 );
258+ nelems = fread (* squery , sizeof (char ), string_len , fin );
217259 Assert (nelems == string_len );
218260
261+ /* Read plan size, allocate memory and read plan from the file. */
219262 nelems = fread (& string_len , sizeof (size_t ), 1 , fin );
220263 Assert (nelems == 1 );
221- * plan_string = palloc0 (string_len + 1 );
222- nelems = fread (* plan_string , sizeof (char ), string_len , fin );
264+ * splan = palloc0 (string_len + 1 );
265+ nelems = fread (* splan , sizeof (char ), string_len , fin );
266+ Assert (nelems == string_len );
267+
268+ /*
269+ * Read serialized query parameters string length, allocate memory and
270+ * read it from the file.
271+ */
272+ nelems = fread (& string_len , sizeof (size_t ), 1 , fin );
273+ Assert (nelems == 1 );
274+ * sparams = palloc0 (string_len + 1 );
275+ nelems = fread (* sparams , sizeof (char ), string_len , fin );
223276 Assert (nelems == string_len );
224277
225278 fclose (fin );
@@ -229,11 +282,17 @@ LoadPlanFromFile(const char *filename, char **query_string, char **plan_string)
229282Datum
230283pg_exec_stored_plan (PG_FUNCTION_ARGS )
231284{
232- char * filename = TextDatumGetCString (PG_GETARG_DATUM (0 )),
233- * query_string = NULL ,
234- * plan_string = NULL ;
235-
236- LoadPlanFromFile (filename , & query_string , & plan_string );
237- exec_plan (query_string , plan_string );
285+ char * filename = TextDatumGetCString (PG_GETARG_DATUM (0 )),
286+ * squery = NULL ,
287+ * splan = NULL ,
288+ * sparams = NULL ;
289+
290+ LoadPlanFromFile (filename , & squery , & splan , & sparams );
291+
292+ Assert (squery && splan && sparams );
293+ exec_plan (squery , splan , sparams );
294+ pfree (squery );
295+ pfree (splan );
296+ pfree (sparams );
238297 PG_RETURN_BOOL (true);
239298}
0 commit comments