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