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
}