1 /* Generated by re2c 0.13.5 */
2 #line 1 "ext/pdo/pdo_sql_parser.re"
3 /*
4 +----------------------------------------------------------------------+
5 | PHP Version 5 |
6 +----------------------------------------------------------------------+
7 | Copyright (c) 1997-2015 The PHP Group |
8 +----------------------------------------------------------------------+
9 | This source file is subject to version 3.01 of the PHP license, |
10 | that is bundled with this package in the file LICENSE, and is |
11 | available through the world-wide-web at the following url: |
12 | http://www.php.net/license/3_01.txt |
13 | If you did not receive a copy of the PHP license and are unable to |
14 | obtain it through the world-wide-web, please send a note to |
15 | license@php.net so we can mail you a copy immediately. |
16 +----------------------------------------------------------------------+
17 | Author: George Schlossnagle <george@omniti.com> |
18 +----------------------------------------------------------------------+
19 */
20
21 /* $Id$ */
22
23 #include "php.h"
24 #include "php_pdo_driver.h"
25 #include "php_pdo_int.h"
26
27 #define PDO_PARSER_TEXT 1
28 #define PDO_PARSER_BIND 2
29 #define PDO_PARSER_BIND_POS 3
30 #define PDO_PARSER_EOI 4
31
32 #define RET(i) {s->cur = cursor; return i; }
33 #define SKIP_ONE(i) {s->cur = s->tok + 1; return i; }
34
35 #define YYCTYPE unsigned char
36 #define YYCURSOR cursor
37 #define YYLIMIT s->end
38 #define YYMARKER s->ptr
39 #define YYFILL(n) { RET(PDO_PARSER_EOI); }
40
41 typedef struct Scanner {
42 char *ptr, *cur, *tok, *end;
43 } Scanner;
44
scan(Scanner * s)45 static int scan(Scanner *s)
46 {
47 char *cursor = s->cur;
48
49 s->tok = cursor;
50 #line 55 "ext/pdo/pdo_sql_parser.re"
51
52
53
54 #line 55 "ext/pdo/pdo_sql_parser.c"
55 {
56 YYCTYPE yych;
57 unsigned int yyaccept = 0;
58
59 if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
60 yych = *YYCURSOR;
61 switch (yych) {
62 case 0x00: goto yy2;
63 case '"': goto yy3;
64 case '\'': goto yy5;
65 case '-': goto yy11;
66 case '/': goto yy9;
67 case ':': goto yy6;
68 case '?': goto yy7;
69 default: goto yy12;
70 }
71 yy2:
72 YYCURSOR = YYMARKER;
73 switch (yyaccept) {
74 case 0: goto yy4;
75 case 1: goto yy10;
76 }
77 yy3:
78 yyaccept = 0;
79 yych = *(YYMARKER = ++YYCURSOR);
80 if (yych >= 0x01) goto yy43;
81 yy4:
82 #line 63 "ext/pdo/pdo_sql_parser.re"
83 { SKIP_ONE(PDO_PARSER_TEXT); }
84 #line 85 "ext/pdo/pdo_sql_parser.c"
85 yy5:
86 yyaccept = 0;
87 yych = *(YYMARKER = ++YYCURSOR);
88 if (yych <= 0x00) goto yy4;
89 goto yy38;
90 yy6:
91 yych = *++YYCURSOR;
92 switch (yych) {
93 case '0':
94 case '1':
95 case '2':
96 case '3':
97 case '4':
98 case '5':
99 case '6':
100 case '7':
101 case '8':
102 case '9':
103 case 'A':
104 case 'B':
105 case 'C':
106 case 'D':
107 case 'E':
108 case 'F':
109 case 'G':
110 case 'H':
111 case 'I':
112 case 'J':
113 case 'K':
114 case 'L':
115 case 'M':
116 case 'N':
117 case 'O':
118 case 'P':
119 case 'Q':
120 case 'R':
121 case 'S':
122 case 'T':
123 case 'U':
124 case 'V':
125 case 'W':
126 case 'X':
127 case 'Y':
128 case 'Z':
129 case '_':
130 case 'a':
131 case 'b':
132 case 'c':
133 case 'd':
134 case 'e':
135 case 'f':
136 case 'g':
137 case 'h':
138 case 'i':
139 case 'j':
140 case 'k':
141 case 'l':
142 case 'm':
143 case 'n':
144 case 'o':
145 case 'p':
146 case 'q':
147 case 'r':
148 case 's':
149 case 't':
150 case 'u':
151 case 'v':
152 case 'w':
153 case 'x':
154 case 'y':
155 case 'z': goto yy32;
156 case ':': goto yy35;
157 default: goto yy4;
158 }
159 yy7:
160 ++YYCURSOR;
161 switch ((yych = *YYCURSOR)) {
162 case '?': goto yy29;
163 default: goto yy8;
164 }
165 yy8:
166 #line 62 "ext/pdo/pdo_sql_parser.re"
167 { RET(PDO_PARSER_BIND_POS); }
168 #line 169 "ext/pdo/pdo_sql_parser.c"
169 yy9:
170 ++YYCURSOR;
171 switch ((yych = *YYCURSOR)) {
172 case '*': goto yy19;
173 default: goto yy13;
174 }
175 yy10:
176 #line 65 "ext/pdo/pdo_sql_parser.re"
177 { RET(PDO_PARSER_TEXT); }
178 #line 179 "ext/pdo/pdo_sql_parser.c"
179 yy11:
180 yych = *++YYCURSOR;
181 switch (yych) {
182 case '-': goto yy14;
183 default: goto yy13;
184 }
185 yy12:
186 ++YYCURSOR;
187 if (YYLIMIT <= YYCURSOR) YYFILL(1);
188 yych = *YYCURSOR;
189 yy13:
190 switch (yych) {
191 case 0x00:
192 case '"':
193 case '\'':
194 case ':':
195 case '?': goto yy10;
196 default: goto yy12;
197 }
198 yy14:
199 ++YYCURSOR;
200 if (YYLIMIT <= YYCURSOR) YYFILL(1);
201 yych = *YYCURSOR;
202 switch (yych) {
203 case 0x00:
204 case '"':
205 case '\'':
206 case ':':
207 case '?': goto yy17;
208 case '\n':
209 case '\r': goto yy12;
210 default: goto yy14;
211 }
212 yy16:
213 #line 64 "ext/pdo/pdo_sql_parser.re"
214 { RET(PDO_PARSER_TEXT); }
215 #line 216 "ext/pdo/pdo_sql_parser.c"
216 yy17:
217 ++YYCURSOR;
218 if (YYLIMIT <= YYCURSOR) YYFILL(1);
219 yych = *YYCURSOR;
220 switch (yych) {
221 case '\n':
222 case '\r': goto yy16;
223 default: goto yy17;
224 }
225 yy19:
226 yyaccept = 1;
227 YYMARKER = ++YYCURSOR;
228 if (YYLIMIT <= YYCURSOR) YYFILL(1);
229 yych = *YYCURSOR;
230 switch (yych) {
231 case 0x00:
232 case '"':
233 case '\'':
234 case ':':
235 case '?': goto yy21;
236 case '*': goto yy23;
237 default: goto yy19;
238 }
239 yy21:
240 ++YYCURSOR;
241 if (YYLIMIT <= YYCURSOR) YYFILL(1);
242 yych = *YYCURSOR;
243 switch (yych) {
244 case '*': goto yy26;
245 default: goto yy21;
246 }
247 yy23:
248 yyaccept = 1;
249 YYMARKER = ++YYCURSOR;
250 if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
251 yych = *YYCURSOR;
252 switch (yych) {
253 case 0x00:
254 case '"':
255 case '\'':
256 case ':':
257 case '?': goto yy21;
258 case '*': goto yy23;
259 case '/': goto yy25;
260 default: goto yy19;
261 }
262 yy25:
263 yych = *++YYCURSOR;
264 switch (yych) {
265 case 0x00:
266 case '"':
267 case '\'':
268 case ':':
269 case '?': goto yy16;
270 default: goto yy12;
271 }
272 yy26:
273 ++YYCURSOR;
274 if (YYLIMIT <= YYCURSOR) YYFILL(1);
275 yych = *YYCURSOR;
276 switch (yych) {
277 case '*': goto yy26;
278 case '/': goto yy28;
279 default: goto yy21;
280 }
281 yy28:
282 yych = *++YYCURSOR;
283 goto yy16;
284 yy29:
285 ++YYCURSOR;
286 if (YYLIMIT <= YYCURSOR) YYFILL(1);
287 yych = *YYCURSOR;
288 switch (yych) {
289 case '?': goto yy29;
290 default: goto yy31;
291 }
292 yy31:
293 #line 60 "ext/pdo/pdo_sql_parser.re"
294 { RET(PDO_PARSER_TEXT); }
295 #line 296 "ext/pdo/pdo_sql_parser.c"
296 yy32:
297 ++YYCURSOR;
298 if (YYLIMIT <= YYCURSOR) YYFILL(1);
299 yych = *YYCURSOR;
300 switch (yych) {
301 case '0':
302 case '1':
303 case '2':
304 case '3':
305 case '4':
306 case '5':
307 case '6':
308 case '7':
309 case '8':
310 case '9':
311 case 'A':
312 case 'B':
313 case 'C':
314 case 'D':
315 case 'E':
316 case 'F':
317 case 'G':
318 case 'H':
319 case 'I':
320 case 'J':
321 case 'K':
322 case 'L':
323 case 'M':
324 case 'N':
325 case 'O':
326 case 'P':
327 case 'Q':
328 case 'R':
329 case 'S':
330 case 'T':
331 case 'U':
332 case 'V':
333 case 'W':
334 case 'X':
335 case 'Y':
336 case 'Z':
337 case '_':
338 case 'a':
339 case 'b':
340 case 'c':
341 case 'd':
342 case 'e':
343 case 'f':
344 case 'g':
345 case 'h':
346 case 'i':
347 case 'j':
348 case 'k':
349 case 'l':
350 case 'm':
351 case 'n':
352 case 'o':
353 case 'p':
354 case 'q':
355 case 'r':
356 case 's':
357 case 't':
358 case 'u':
359 case 'v':
360 case 'w':
361 case 'x':
362 case 'y':
363 case 'z': goto yy32;
364 default: goto yy34;
365 }
366 yy34:
367 #line 61 "ext/pdo/pdo_sql_parser.re"
368 { RET(PDO_PARSER_BIND); }
369 #line 370 "ext/pdo/pdo_sql_parser.c"
370 yy35:
371 ++YYCURSOR;
372 if (YYLIMIT <= YYCURSOR) YYFILL(1);
373 yych = *YYCURSOR;
374 switch (yych) {
375 case ':': goto yy35;
376 default: goto yy31;
377 }
378 yy37:
379 ++YYCURSOR;
380 if (YYLIMIT <= YYCURSOR) YYFILL(1);
381 yych = *YYCURSOR;
382 yy38:
383 switch (yych) {
384 case 0x00: goto yy2;
385 case '\'': goto yy40;
386 case '\\': goto yy39;
387 default: goto yy37;
388 }
389 yy39:
390 ++YYCURSOR;
391 if (YYLIMIT <= YYCURSOR) YYFILL(1);
392 yych = *YYCURSOR;
393 if (yych <= 0x00) goto yy2;
394 goto yy37;
395 yy40:
396 ++YYCURSOR;
397 #line 59 "ext/pdo/pdo_sql_parser.re"
398 { RET(PDO_PARSER_TEXT); }
399 #line 400 "ext/pdo/pdo_sql_parser.c"
400 yy42:
401 ++YYCURSOR;
402 if (YYLIMIT <= YYCURSOR) YYFILL(1);
403 yych = *YYCURSOR;
404 yy43:
405 switch (yych) {
406 case 0x00: goto yy2;
407 case '"': goto yy45;
408 case '\\': goto yy44;
409 default: goto yy42;
410 }
411 yy44:
412 ++YYCURSOR;
413 if (YYLIMIT <= YYCURSOR) YYFILL(1);
414 yych = *YYCURSOR;
415 if (yych <= 0x00) goto yy2;
416 goto yy42;
417 yy45:
418 ++YYCURSOR;
419 #line 58 "ext/pdo/pdo_sql_parser.re"
420 { RET(PDO_PARSER_TEXT); }
421 #line 422 "ext/pdo/pdo_sql_parser.c"
422 }
423 #line 66 "ext/pdo/pdo_sql_parser.re"
424
425 }
426
427 struct placeholder {
428 char *pos;
429 int len;
430 int bindno;
431 int qlen; /* quoted length of value */
432 char *quoted; /* quoted value */
433 int freeq;
434 struct placeholder *next;
435 };
436
pdo_parse_params(pdo_stmt_t * stmt,char * inquery,int inquery_len,char ** outquery,int * outquery_len TSRMLS_DC)437 PDO_API int pdo_parse_params(pdo_stmt_t *stmt, char *inquery, int inquery_len,
438 char **outquery, int *outquery_len TSRMLS_DC)
439 {
440 Scanner s;
441 char *ptr, *newbuffer;
442 int t;
443 int bindno = 0;
444 int ret = 0;
445 int newbuffer_len;
446 HashTable *params;
447 struct pdo_bound_param_data *param;
448 int query_type = PDO_PLACEHOLDER_NONE;
449 struct placeholder *placeholders = NULL, *placetail = NULL, *plc = NULL;
450
451 ptr = *outquery;
452 s.cur = inquery;
453 s.end = inquery + inquery_len + 1;
454
455 /* phase 1: look for args */
456 while((t = scan(&s)) != PDO_PARSER_EOI) {
457 if (t == PDO_PARSER_BIND || t == PDO_PARSER_BIND_POS) {
458 if (t == PDO_PARSER_BIND) {
459 int len = s.cur - s.tok;
460 if ((inquery < (s.cur - len)) && isalnum(*(s.cur - len - 1))) {
461 continue;
462 }
463 query_type |= PDO_PLACEHOLDER_NAMED;
464 } else {
465 query_type |= PDO_PLACEHOLDER_POSITIONAL;
466 }
467
468 plc = emalloc(sizeof(*plc));
469 memset(plc, 0, sizeof(*plc));
470 plc->next = NULL;
471 plc->pos = s.tok;
472 plc->len = s.cur - s.tok;
473 plc->bindno = bindno++;
474
475 if (placetail) {
476 placetail->next = plc;
477 } else {
478 placeholders = plc;
479 }
480 placetail = plc;
481 }
482 }
483
484 if (bindno == 0) {
485 /* nothing to do; good! */
486 return 0;
487 }
488
489 /* did the query make sense to me? */
490 if (query_type == (PDO_PLACEHOLDER_NAMED|PDO_PLACEHOLDER_POSITIONAL)) {
491 /* they mixed both types; punt */
492 pdo_raise_impl_error(stmt->dbh, stmt, "HY093", "mixed named and positional parameters" TSRMLS_CC);
493 ret = -1;
494 goto clean_up;
495 }
496
497 if (stmt->supports_placeholders == query_type && !stmt->named_rewrite_template) {
498 /* query matches native syntax */
499 ret = 0;
500 goto clean_up;
501 }
502
503 if (stmt->named_rewrite_template) {
504 /* magic/hack.
505 * We we pretend that the query was positional even if
506 * it was named so that we fall into the
507 * named rewrite case below. Not too pretty,
508 * but it works. */
509 query_type = PDO_PLACEHOLDER_POSITIONAL;
510 }
511
512 params = stmt->bound_params;
513
514 /* Do we have placeholders but no bound params */
515 if (bindno && !params && stmt->supports_placeholders == PDO_PLACEHOLDER_NONE) {
516 pdo_raise_impl_error(stmt->dbh, stmt, "HY093", "no parameters were bound" TSRMLS_CC);
517 ret = -1;
518 goto clean_up;
519 }
520
521 if (params && bindno != zend_hash_num_elements(params) && stmt->supports_placeholders == PDO_PLACEHOLDER_NONE) {
522 /* extra bit of validation for instances when same params are bound more then once */
523 if (query_type != PDO_PLACEHOLDER_POSITIONAL && bindno > zend_hash_num_elements(params)) {
524 int ok = 1;
525 for (plc = placeholders; plc; plc = plc->next) {
526 if (zend_hash_find(params, plc->pos, plc->len, (void**) ¶m) == FAILURE) {
527 ok = 0;
528 break;
529 }
530 }
531 if (ok) {
532 goto safe;
533 }
534 }
535 pdo_raise_impl_error(stmt->dbh, stmt, "HY093", "number of bound variables does not match number of tokens" TSRMLS_CC);
536 ret = -1;
537 goto clean_up;
538 }
539 safe:
540 /* what are we going to do ? */
541 if (stmt->supports_placeholders == PDO_PLACEHOLDER_NONE) {
542 /* query generation */
543
544 newbuffer_len = inquery_len;
545
546 /* let's quote all the values */
547 for (plc = placeholders; plc; plc = plc->next) {
548 if (query_type == PDO_PLACEHOLDER_POSITIONAL) {
549 ret = zend_hash_index_find(params, plc->bindno, (void**) ¶m);
550 } else {
551 ret = zend_hash_find(params, plc->pos, plc->len, (void**) ¶m);
552 }
553 if (ret == FAILURE) {
554 /* parameter was not defined */
555 ret = -1;
556 pdo_raise_impl_error(stmt->dbh, stmt, "HY093", "parameter was not defined" TSRMLS_CC);
557 goto clean_up;
558 }
559 if (stmt->dbh->methods->quoter) {
560 if (param->param_type == PDO_PARAM_LOB && Z_TYPE_P(param->parameter) == IS_RESOURCE) {
561 php_stream *stm;
562
563 php_stream_from_zval_no_verify(stm, ¶m->parameter);
564 if (stm) {
565 size_t len;
566 char *buf = NULL;
567
568 len = php_stream_copy_to_mem(stm, &buf, PHP_STREAM_COPY_ALL, 0);
569 if (!stmt->dbh->methods->quoter(stmt->dbh, buf, len, &plc->quoted, &plc->qlen,
570 param->param_type TSRMLS_CC)) {
571 /* bork */
572 ret = -1;
573 strncpy(stmt->error_code, stmt->dbh->error_code, 6);
574 if (buf) {
575 efree(buf);
576 }
577 goto clean_up;
578 }
579 if (buf) {
580 efree(buf);
581 }
582 } else {
583 pdo_raise_impl_error(stmt->dbh, stmt, "HY105", "Expected a stream resource" TSRMLS_CC);
584 ret = -1;
585 goto clean_up;
586 }
587 plc->freeq = 1;
588 } else {
589 zval tmp_param = *param->parameter;
590 zval_copy_ctor(&tmp_param);
591 switch (Z_TYPE(tmp_param)) {
592 case IS_NULL:
593 plc->quoted = "NULL";
594 plc->qlen = sizeof("NULL")-1;
595 plc->freeq = 0;
596 break;
597
598 case IS_BOOL:
599 convert_to_long(&tmp_param);
600 /* fall through */
601 case IS_LONG:
602 case IS_DOUBLE:
603 convert_to_string(&tmp_param);
604 plc->qlen = Z_STRLEN(tmp_param);
605 plc->quoted = estrdup(Z_STRVAL(tmp_param));
606 plc->freeq = 1;
607 break;
608
609 default:
610 convert_to_string(&tmp_param);
611 if (!stmt->dbh->methods->quoter(stmt->dbh, Z_STRVAL(tmp_param),
612 Z_STRLEN(tmp_param), &plc->quoted, &plc->qlen,
613 param->param_type TSRMLS_CC)) {
614 /* bork */
615 ret = -1;
616 strncpy(stmt->error_code, stmt->dbh->error_code, 6);
617 goto clean_up;
618 }
619 plc->freeq = 1;
620 }
621 zval_dtor(&tmp_param);
622 }
623 } else {
624 plc->quoted = Z_STRVAL_P(param->parameter);
625 plc->qlen = Z_STRLEN_P(param->parameter);
626 }
627 newbuffer_len += plc->qlen;
628 }
629
630 rewrite:
631 /* allocate output buffer */
632 newbuffer = emalloc(newbuffer_len + 1);
633 *outquery = newbuffer;
634
635 /* and build the query */
636 plc = placeholders;
637 ptr = inquery;
638
639 do {
640 t = plc->pos - ptr;
641 if (t) {
642 memcpy(newbuffer, ptr, t);
643 newbuffer += t;
644 }
645 memcpy(newbuffer, plc->quoted, plc->qlen);
646 newbuffer += plc->qlen;
647 ptr = plc->pos + plc->len;
648
649 plc = plc->next;
650 } while (plc);
651
652 t = (inquery + inquery_len) - ptr;
653 if (t) {
654 memcpy(newbuffer, ptr, t);
655 newbuffer += t;
656 }
657 *newbuffer = '\0';
658 *outquery_len = newbuffer - *outquery;
659
660 ret = 1;
661 goto clean_up;
662
663 } else if (query_type == PDO_PLACEHOLDER_POSITIONAL) {
664 /* rewrite ? to :pdoX */
665 char *name, *idxbuf;
666 const char *tmpl = stmt->named_rewrite_template ? stmt->named_rewrite_template : ":pdo%d";
667 int bind_no = 1;
668
669 newbuffer_len = inquery_len;
670
671 if (stmt->bound_param_map == NULL) {
672 ALLOC_HASHTABLE(stmt->bound_param_map);
673 zend_hash_init(stmt->bound_param_map, 13, NULL, NULL, 0);
674 }
675
676 for (plc = placeholders; plc; plc = plc->next) {
677 int skip_map = 0;
678 char *p;
679 name = estrndup(plc->pos, plc->len);
680
681 /* check if bound parameter is already available */
682 if (!strcmp(name, "?") || zend_hash_find(stmt->bound_param_map, name, plc->len + 1, (void**) &p) == FAILURE) {
683 spprintf(&idxbuf, 0, tmpl, bind_no++);
684 } else {
685 idxbuf = estrdup(p);
686 skip_map = 1;
687 }
688
689 plc->quoted = idxbuf;
690 plc->qlen = strlen(plc->quoted);
691 plc->freeq = 1;
692 newbuffer_len += plc->qlen;
693
694 if (!skip_map && stmt->named_rewrite_template) {
695 /* create a mapping */
696 zend_hash_update(stmt->bound_param_map, name, plc->len + 1, idxbuf, plc->qlen + 1, NULL);
697 }
698
699 /* map number to name */
700 zend_hash_index_update(stmt->bound_param_map, plc->bindno, idxbuf, plc->qlen + 1, NULL);
701
702 efree(name);
703 }
704
705 goto rewrite;
706
707 } else {
708 /* rewrite :name to ? */
709
710 newbuffer_len = inquery_len;
711
712 if (stmt->bound_param_map == NULL) {
713 ALLOC_HASHTABLE(stmt->bound_param_map);
714 zend_hash_init(stmt->bound_param_map, 13, NULL, NULL, 0);
715 }
716
717 for (plc = placeholders; plc; plc = plc->next) {
718 char *name;
719
720 name = estrndup(plc->pos, plc->len);
721 zend_hash_index_update(stmt->bound_param_map, plc->bindno, name, plc->len + 1, NULL);
722 efree(name);
723 plc->quoted = "?";
724 plc->qlen = 1;
725 }
726
727 goto rewrite;
728 }
729
730 clean_up:
731
732 while (placeholders) {
733 plc = placeholders;
734 placeholders = plc->next;
735
736 if (plc->freeq) {
737 efree(plc->quoted);
738 }
739
740 efree(plc);
741 }
742
743 return ret;
744 }
745
746 #if 0
747 int old_pdo_parse_params(pdo_stmt_t *stmt, char *inquery, int inquery_len, char **outquery,
748 int *outquery_len TSRMLS_DC)
749 {
750 Scanner s;
751 char *ptr;
752 int t;
753 int bindno = 0;
754 int newbuffer_len;
755 int padding;
756 HashTable *params = stmt->bound_params;
757 struct pdo_bound_param_data *param;
758 /* allocate buffer for query with expanded binds, ptr is our writing pointer */
759 newbuffer_len = inquery_len;
760
761 /* calculate the possible padding factor due to quoting */
762 if(stmt->dbh->max_escaped_char_length) {
763 padding = stmt->dbh->max_escaped_char_length;
764 } else {
765 padding = 3;
766 }
767 if(params) {
768 zend_hash_internal_pointer_reset(params);
769 while (SUCCESS == zend_hash_get_current_data(params, (void**)¶m)) {
770 if(param->parameter) {
771 convert_to_string(param->parameter);
772 /* accommodate a string that needs to be fully quoted
773 bind placeholders are at least 2 characters, so
774 the accommodate their own "'s
775 */
776 newbuffer_len += padding * Z_STRLEN_P(param->parameter);
777 }
778 zend_hash_move_forward(params);
779 }
780 }
781 *outquery = (char *) emalloc(newbuffer_len + 1);
782 *outquery_len = 0;
783
784 ptr = *outquery;
785 s.cur = inquery;
786 while((t = scan(&s)) != PDO_PARSER_EOI) {
787 if(t == PDO_PARSER_TEXT) {
788 memcpy(ptr, s.tok, s.cur - s.tok);
789 ptr += (s.cur - s.tok);
790 *outquery_len += (s.cur - s.tok);
791 }
792 else if(t == PDO_PARSER_BIND) {
793 if(!params) {
794 /* error */
795 efree(*outquery);
796 *outquery = NULL;
797 return (int) (s.cur - inquery);
798 }
799 /* lookup bind first via hash and then index */
800 /* stupid keys need to be null-terminated, even though we know their length */
801 if((SUCCESS == zend_hash_find(params, s.tok, s.cur-s.tok,(void **)¶m))
802 ||
803 (SUCCESS == zend_hash_index_find(params, bindno, (void **)¶m)))
804 {
805 char *quotedstr;
806 int quotedstrlen;
807 /* restore the in-string key, doesn't need null-termination here */
808 /* currently everything is a string here */
809
810 /* quote the bind value if necessary */
811 if(stmt->dbh->methods->quoter(stmt->dbh, Z_STRVAL_P(param->parameter),
812 Z_STRLEN_P(param->parameter), "edstr, "edstrlen TSRMLS_CC))
813 {
814 memcpy(ptr, quotedstr, quotedstrlen);
815 ptr += quotedstrlen;
816 *outquery_len += quotedstrlen;
817 efree(quotedstr);
818 } else {
819 memcpy(ptr, Z_STRVAL_P(param->parameter), Z_STRLEN_P(param->parameter));
820 ptr += Z_STRLEN_P(param->parameter);
821 *outquery_len += (Z_STRLEN_P(param->parameter));
822 }
823 }
824 else {
825 /* error and cleanup */
826 efree(*outquery);
827 *outquery = NULL;
828 return (int) (s.cur - inquery);
829 }
830 bindno++;
831 }
832 else if(t == PDO_PARSER_BIND_POS) {
833 if(!params) {
834 /* error */
835 efree(*outquery);
836 *outquery = NULL;
837 return (int) (s.cur - inquery);
838 }
839 /* lookup bind by index */
840 if(SUCCESS == zend_hash_index_find(params, bindno, (void **)¶m))
841 {
842 char *quotedstr;
843 int quotedstrlen;
844 /* currently everything is a string here */
845
846 /* quote the bind value if necessary */
847 if(stmt->dbh->methods->quoter(stmt->dbh, Z_STRVAL_P(param->parameter),
848 Z_STRLEN_P(param->parameter), "edstr, "edstrlen TSRMLS_CC))
849 {
850 memcpy(ptr, quotedstr, quotedstrlen);
851 ptr += quotedstrlen;
852 *outquery_len += quotedstrlen;
853 efree(quotedstr);
854 } else {
855 memcpy(ptr, Z_STRVAL_P(param->parameter), Z_STRLEN_P(param->parameter));
856 ptr += Z_STRLEN_P(param->parameter);
857 *outquery_len += (Z_STRLEN_P(param->parameter));
858 }
859 }
860 else {
861 /* error and cleanup */
862 efree(*outquery);
863 *outquery = NULL;
864 return (int) (s.cur - inquery);
865 }
866 bindno++;
867 }
868 }
869 *ptr = '\0';
870 return 0;
871 }
872 #endif
873
874 /*
875 * Local variables:
876 * tab-width: 4
877 * c-basic-offset: 4
878 * End:
879 * vim600: noet sw=4 ts=4 fdm=marker ft=c
880 * vim<600: noet sw=4 ts=4
881 */
882