1 /*
2 * Copyright (c) 2017-2018 Tatsuo Ishii
3 * Copyright (c) 2018-2021 PgPool Global Development Group
4 *
5 * Permission to use, copy, modify, and distribute this software and
6 * its documentation for any purpose and without fee is hereby
7 * granted, provided that the above copyright notice appear in all
8 * copies and that both that copyright notice and this permission
9 * notice appear in supporting documentation, and that the name of the
10 * author not be used in advertising or publicity pertaining to
11 * distribution of the software without specific, written prior
12 * permission. The author makes no representations about the
13 * suitability of this software for any purpose. It is provided "as
14 * is" without express or implied warranty.
15 *
16 * Process Parse, Bind, Execute message.
17 */
18
19 #include "../../include/config.h"
20 #include "pgproto/pgproto.h"
21 #include <unistd.h>
22 #include <stdlib.h>
23 #include <stdio.h>
24 #include <getopt.h>
25 #include <string.h>
26 #include <errno.h>
27 #include <fcntl.h>
28 #include "pgproto/fe_memutils.h"
29 #include <libpq-fe.h>
30 #include "pgproto/read.h"
31 #include "pgproto/send.h"
32 #include "pgproto/extended_query.h"
33 #include "pgproto/buffer.h"
34
35 /*
36 * Send parse messae. "conn" should at the point right after the message kind
37 * was read.
38 */
39 void
process_parse(char * buf,PGconn * conn)40 process_parse(char *buf, PGconn *conn)
41 {
42 char *query;
43 int len;
44 char *stmt;
45 short noids;
46 int oids[MAXENTRIES];
47 int i;
48 char *bufp;
49
50 SKIP_TABS(buf);
51
52 len = sizeof(int);
53
54 stmt = buffer_read_string(buf, &bufp);
55 buf = bufp;
56 len += strlen(stmt) + 1;
57
58 SKIP_TABS(buf);
59
60 query = buffer_read_string(buf, &bufp);
61 buf = bufp;
62 len += strlen(query) + 1;
63
64 SKIP_TABS(buf);
65
66 fprintf(stderr, "FE=> Parse(stmt=\"%s\", query=\"%s\")", stmt, query);
67
68 noids = buffer_read_int(buf, &bufp);
69 buf = bufp;
70
71 if (noids > MAXENTRIES)
72 {
73 fprintf(stderr, "Too many oid params for parse message (%d)\n", noids);
74 exit(1);
75 }
76
77 len += sizeof(short) + noids * sizeof(int);
78
79 if (noids > 0)
80 {
81 fprintf(stderr, ", oids={");
82
83 for (i = 0; i < noids; i++)
84 {
85 oids[i] = buffer_read_int(buf, &bufp);
86 fprintf(stderr, "%d", oids[i]);
87 if ((i + 1) != noids)
88 fprintf(stderr, ",");
89 buf = bufp;
90 }
91 }
92 fprintf(stderr, "\n");
93
94 send_char('P', conn);
95 send_int(len, conn);
96 send_string(stmt, conn);
97 free(stmt);
98 send_string(query, conn);
99 free(query);
100 send_int16(noids, conn);
101 if (noids > 0)
102 {
103 for (i = 0; i < noids; i++)
104 {
105 send_int(oids[i], conn);
106 }
107 }
108 }
109
110 /*
111 * Send bind message. "conn" should be at the point right after the message kind
112 * was read.
113 */
114 void
process_bind(char * buf,PGconn * conn)115 process_bind(char *buf, PGconn *conn)
116 {
117 int len;
118 char *stmt;
119 char *portal;
120 short nparams;
121 short ncodes;
122 short codes[MAXENTRIES];
123 int paramlens[MAXENTRIES];
124 char *paramvals[MAXENTRIES];
125 short nresult_formatcodes;
126 short result_formatcodes[MAXENTRIES];
127 int i;
128 char *bufp;
129
130 SKIP_TABS(buf);
131
132 len = sizeof(int);
133
134 portal = buffer_read_string(buf, &bufp);
135 buf = bufp;
136 len += strlen(portal) + 1;
137
138 SKIP_TABS(buf);
139
140 stmt = buffer_read_string(buf, &bufp);
141 buf = bufp;
142 len += strlen(stmt) + 1;
143
144 fprintf(stderr, "FE=> Bind(stmt=\"%s\", portal=\"%s\")", stmt, portal);
145
146 SKIP_TABS(buf);
147
148 ncodes = buffer_read_int(buf, &bufp);
149 len += sizeof(short) + sizeof(short) * ncodes;
150 buf = bufp;
151
152 SKIP_TABS(buf);
153
154 if (ncodes > MAXENTRIES)
155 {
156 fprintf(stderr, "Too many codes for bind message (%d)\n", ncodes);
157 exit(1);
158 }
159
160 if (ncodes > 0)
161 {
162 for (i = 0; i < ncodes; i++)
163 {
164 codes[i] = buffer_read_int(buf, &bufp);
165 buf = bufp;
166 SKIP_TABS(buf);
167 }
168 }
169
170 nparams = buffer_read_int(buf, &bufp);
171 len += sizeof(short) + sizeof(short) * nparams;
172 buf = bufp;
173 SKIP_TABS(buf);
174
175 if (nparams > MAXENTRIES)
176 {
177 fprintf(stderr, "Too many params for bind message (%d)\n", nparams);
178 exit(1);
179 }
180
181 for (i = 0; i < nparams; i++)
182 {
183 paramlens[i] = buffer_read_int(buf, &bufp);
184 len += sizeof(int);
185
186 if (paramlens[i] > 0)
187 {
188 buf = bufp;
189 paramvals[i] = buffer_read_string(buf, &bufp);
190 buf = bufp;
191 SKIP_TABS(buf);
192 len += paramlens[i];
193 }
194 }
195
196 SKIP_TABS(buf);
197
198 nresult_formatcodes = buffer_read_int(buf, &bufp);
199 buf = bufp;
200 len += sizeof(short) + sizeof(short) * nresult_formatcodes;
201 SKIP_TABS(buf);
202
203 if (nresult_formatcodes >= 2)
204 {
205 for (i = 0; i < nresult_formatcodes; i++)
206 {
207 result_formatcodes[i] = buffer_read_int(buf, &bufp);
208 buf = bufp;
209 SKIP_TABS(buf);
210 }
211 }
212 fprintf(stderr, "\n");
213
214 send_char('B', conn);
215 send_int(len, conn);
216 send_string(portal, conn);
217 free(portal);
218 send_string(stmt, conn);
219 free(stmt);
220 send_int16(ncodes, conn);
221 for (i = 0; i < ncodes; i++)
222 {
223 send_int16(codes[i], conn);
224 }
225
226 send_int16(nparams, conn);
227 for (i = 0; i < nparams; i++)
228 {
229 if (paramlens[i] != -1)
230 {
231 if (ncodes == 0 || codes[i] == 0)
232 {
233 send_string(paramvals[i], conn);
234 }
235 else
236 {
237 send_int(atoi(paramvals[i]), conn);
238 }
239 }
240 }
241
242 send_int16(nresult_formatcodes, conn);
243 for (i = 0; i < nresult_formatcodes; i++)
244 {
245 send_int16(result_formatcodes[i], conn);
246 }
247 }
248
249 /*
250 * Send execute messae. "conn" should at the point right after the message
251 * kind was read.
252 */
253 void
process_execute(char * buf,PGconn * conn)254 process_execute(char *buf, PGconn *conn)
255 {
256 int len;
257 char *portal;
258 int maxrows;
259 char *bufp;
260
261 SKIP_TABS(buf);
262
263 len = sizeof(int);
264
265 portal = buffer_read_string(buf, &bufp);
266 buf = bufp;
267 len += strlen(portal) + 1;
268
269 SKIP_TABS(buf);
270
271 fprintf(stderr, "FE=> Execute(portal=\"%s\")\n", portal);
272
273 SKIP_TABS(buf);
274
275 maxrows = buffer_read_int(buf, &bufp);
276
277 len += sizeof(int);
278
279 send_char('E', conn);
280 send_int(len, conn);
281 send_string(portal, conn);
282 send_int(maxrows, conn);
283 free(portal);
284 }
285
286 /*
287 * Send describe messae. "conn" should at the point right after the message kind
288 * was read.
289 */
290 void
process_describe(char * buf,PGconn * conn)291 process_describe(char *buf, PGconn *conn)
292 {
293 char kind;
294 int len;
295 char *stmt;
296 char *bufp;
297
298 SKIP_TABS(buf);
299
300 len = sizeof(int);
301
302 kind = buffer_read_char(buf, &bufp);
303 buf = bufp;
304 len += 1;
305
306 SKIP_TABS(buf);
307
308 stmt = buffer_read_string(buf, &bufp);
309 buf = bufp;
310 len += strlen(stmt) + 1;
311
312 SKIP_TABS(buf);
313
314 if (kind == 'S')
315 {
316 fprintf(stderr, "FE=> Describe(stmt=\"%s\")\n", stmt);
317 }
318 else if (kind == 'P')
319 {
320 fprintf(stderr, "FE=> Describe(portal=\"%s\")\n", stmt);
321 }
322 else
323 {
324 fprintf(stderr, "Close: unknown kind:%c\n", kind);
325 exit(1);
326 }
327
328 send_char('D', conn);
329 send_int(len, conn);
330 send_char(kind, conn);
331 send_string(stmt, conn);
332 free(stmt);
333 }
334
335 /*
336 * Send close messae. "conn" should at the point right after the message kind
337 * was read.
338 */
339 void
process_close(char * buf,PGconn * conn)340 process_close(char *buf, PGconn *conn)
341 {
342 char kind;
343 int len;
344 char *stmt;
345 char *bufp;
346
347 SKIP_TABS(buf);
348
349 len = sizeof(int);
350
351 kind = buffer_read_char(buf, &bufp);
352 buf = bufp;
353 len += 1;
354
355 SKIP_TABS(buf);
356
357 stmt = buffer_read_string(buf, &bufp);
358 buf = bufp;
359 len += strlen(stmt) + 1;
360
361 SKIP_TABS(buf);
362
363 if (kind == 'S')
364 {
365 fprintf(stderr, "FE=> Close(stmt=\"%s\")\n", stmt);
366 }
367 else if (kind == 'P')
368 {
369 fprintf(stderr, "FE=> Close(portal=\"%s\")\n", stmt);
370 }
371 else
372 {
373 fprintf(stderr, "Close: unknown kind:%c\n", kind);
374 exit(1);
375 }
376
377 send_char('C', conn);
378 send_int(len, conn);
379 send_char(kind, conn);
380 send_string(stmt, conn);
381 free(stmt);
382 }
383