11
11
#include "common/base64.h"
12
12
#include "executor/executor.h"
13
13
#include "nodes/nodes.h"
14
+ #include "nodes/params.h"
14
15
#include "nodes/plannodes.h"
15
16
#include "tcop/pquery.h"
16
17
#include "tcop/utility.h"
@@ -42,10 +43,13 @@ _PG_init(void)
42
43
Datum
43
44
pg_store_query_plan (PG_FUNCTION_ARGS )
44
45
{
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 ;
49
53
FILE * fout ;
50
54
MemoryContext oldcontext ;
51
55
List * parsetree_list ;
@@ -56,21 +60,21 @@ pg_store_query_plan(PG_FUNCTION_ARGS)
56
60
size_t string_len ;
57
61
58
62
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 );
60
64
61
65
oldcontext = MemoryContextSwitchTo (MessageContext );
62
66
63
- parsetree_list = pg_parse_query (query_string );
67
+ parsetree_list = pg_parse_query (squery );
64
68
nstmts = list_length (parsetree_list );
65
69
if (nstmts != 1 )
66
70
elog (ERROR , "Query contains %d elements, but must contain only one." , nstmts );
67
71
68
72
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 );
70
74
plantree_list = pg_plan_queries (querytree_list , CURSOR_OPT_PARALLEL_OK , NULL );
71
75
72
76
queryDesc = CreateQueryDesc ((PlannedStmt * ) linitial (plantree_list ),
73
- query_string ,
77
+ squery ,
74
78
InvalidSnapshot ,
75
79
InvalidSnapshot ,
76
80
None_Receiver ,
@@ -82,24 +86,35 @@ pg_store_query_plan(PG_FUNCTION_ARGS)
82
86
83
87
fout = fopen (filename , "wb" );
84
88
Assert (fout != NULL );
85
- string_len = strlen (query_string );
89
+ string_len = strlen (squery );
86
90
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 );
88
92
89
93
set_portable_output (true);
90
- plan_string = nodeToString (queryDesc -> plannedstmt );
94
+ splan = nodeToString (queryDesc -> plannedstmt );
91
95
set_portable_output (false);
92
- string_len = strlen (plan_string );
96
+ string_len = strlen (splan );
93
97
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 );
96
111
fclose (fout );
97
112
MemoryContextSwitchTo (oldcontext );
98
113
PG_RETURN_VOID ();
99
114
}
100
115
101
116
static void
102
- exec_plan (char * query_string , char * plan_string )
117
+ exec_plan (char * squery , char * splan , char * sparams )
103
118
{
104
119
PlannedStmt * pstmt ;
105
120
ParamListInfo paramLI = NULL ;
@@ -108,28 +123,42 @@ exec_plan(char *query_string, char *plan_string)
108
123
QueryDesc * queryDesc ;
109
124
DestReceiver * receiver ;
110
125
int eflags = 0 ;
126
+ Oid * param_types = NULL ;
127
+ char * start_address = sparams ;
128
+
129
+ Assert (squery && splan && sparams );
111
130
112
131
PG_TRY ();
113
132
{
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 );
117
137
}
118
138
PG_CATCH ();
119
139
{
120
- elog (INFO , "BAD PLAN: %s. Query: %s" , plan_string , query_string );
140
+ elog (INFO , "BAD PLAN: %s. Query: %s" , splan , squery );
121
141
PG_RE_THROW ();
122
142
}
123
143
PG_END_TRY ();
124
144
125
145
if (EXPLAN_DEBUG_LEVEL > 0 )
126
- elog (INFO , "query: %s\n" , query_string );
146
+ elog (INFO , "query: %s\n" , squery );
127
147
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 ;
129
155
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);
133
162
134
163
SetRemoteSubplan (psrc , pstmt );
135
164
cplan = GetCachedPlan (psrc , paramLI , false, NULL );
@@ -139,7 +168,7 @@ exec_plan(char *query_string, char *plan_string)
139
168
PG_TRY ();
140
169
{
141
170
queryDesc = CreateQueryDesc (pstmt ,
142
- query_string ,
171
+ squery ,
143
172
GetActiveSnapshot (),
144
173
InvalidSnapshot ,
145
174
receiver ,
@@ -155,7 +184,7 @@ exec_plan(char *query_string, char *plan_string)
155
184
}
156
185
PG_CATCH ();
157
186
{
158
- elog (INFO , "BAD QUERY: '%s'." , query_string );
187
+ elog (INFO , "BAD QUERY: '%s'." , squery );
159
188
ReleaseCachedPlan (cplan , false);
160
189
PG_RE_THROW ();
161
190
}
@@ -171,37 +200,49 @@ exec_plan(char *query_string, char *plan_string)
171
200
Datum
172
201
pg_exec_plan (PG_FUNCTION_ARGS )
173
202
{
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 ));
176
206
177
207
char * dec_query ,
178
- * dec_plan ;
208
+ * dec_plan ,
209
+ * dec_params ;
179
210
int dec_query_len ,
180
211
dec_query_len1 ,
181
212
dec_plan_len ,
182
- dec_plan_len1 ;
213
+ dec_plan_len1 ,
214
+ dec_params_len ,
215
+ dec_params_len1 ;
183
216
184
- Assert (query_string != NULL );
185
- Assert (plan_string != NULL );
217
+ Assert (squery != NULL );
218
+ Assert (splan != NULL );
219
+ Assert (sparams != NULL );
186
220
187
- dec_query_len = pg_b64_dec_len (strlen (query_string ) + 1 ) + 1 ;
221
+ dec_query_len = pg_b64_dec_len (strlen (squery )) ;
188
222
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 );
191
225
192
- dec_plan_len = pg_b64_dec_len (strlen (plan_string ) + 1 );
226
+ dec_plan_len = pg_b64_dec_len (strlen (splan ) );
193
227
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 );
196
235
197
- exec_plan (dec_query , dec_plan );
236
+ exec_plan (dec_query , dec_plan , dec_params );
198
237
pfree (dec_query );
199
238
pfree (dec_plan );
239
+ pfree (dec_params );
200
240
PG_RETURN_BOOL (true);
201
241
}
202
242
203
243
static void
204
- LoadPlanFromFile (const char * filename , char * * query_string , char * * plan_string )
244
+ LoadPlanFromFile (const char * filename , char * * squery , char * * splan ,
245
+ char * * sparams )
205
246
{
206
247
FILE * fin ;
207
248
size_t string_len ;
@@ -210,16 +251,28 @@ LoadPlanFromFile(const char *filename, char **query_string, char **plan_string)
210
251
fin = fopen (filename , "rb" );
211
252
Assert (fin != NULL );
212
253
254
+ /* Read query string size, allocate memory and read query from the file. */
213
255
nelems = fread (& string_len , sizeof (size_t ), 1 , fin );
214
256
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 );
217
259
Assert (nelems == string_len );
218
260
261
+ /* Read plan size, allocate memory and read plan from the file. */
219
262
nelems = fread (& string_len , sizeof (size_t ), 1 , fin );
220
263
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 );
223
276
Assert (nelems == string_len );
224
277
225
278
fclose (fin );
@@ -229,11 +282,17 @@ LoadPlanFromFile(const char *filename, char **query_string, char **plan_string)
229
282
Datum
230
283
pg_exec_stored_plan (PG_FUNCTION_ARGS )
231
284
{
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 );
238
297
PG_RETURN_BOOL (true);
239
298
}
0 commit comments