File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / php / ext / pdo / pdo_sql_parser.c
Revision 1.1.1.4 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Mon Oct 14 08:02:24 2013 UTC (10 years, 8 months ago) by misho
Branches: php, MAIN
CVS tags: v5_4_29p0, v5_4_20p0, v5_4_20, HEAD
v 5.4.20

    1: /* Generated by re2c 0.13.5 on Tue Aug 20 18:02:48 2013 */
    2: /*
    3:   +----------------------------------------------------------------------+
    4:   | PHP Version 5                                                        |
    5:   +----------------------------------------------------------------------+
    6:   | Copyright (c) 1997-2013 The PHP Group                                |
    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: 
   20: /* $Id: pdo_sql_parser.c,v 1.1.1.4 2013/10/14 08:02:24 misho Exp $ */
   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
   36: #define YYLIMIT         s->end
   37: #define YYMARKER        s->ptr
   38: #define YYFILL(n)		{ RET(PDO_PARSER_EOI); }
   39: 
   40: typedef struct Scanner {
   41: 	char 	*ptr, *cur, *tok, *end;
   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) {
   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;
   67: 	}
   68: yy2:
   69: 	YYCURSOR = YYMARKER;
   70: 	switch (yyaccept) {
   71: 	case 0: 	goto yy4;
   72: 	case 1: 	goto yy10;
   73: 	}
   74: yy3:
   75: 	yyaccept = 0;
   76: 	yych = *(YYMARKER = ++YYCURSOR);
   77: 	if (yych >= 0x01) goto yy43;
   78: yy4:
   79: 	{ SKIP_ONE(PDO_PARSER_TEXT); }
   80: yy5:
   81: 	yyaccept = 0;
   82: 	yych = *(YYMARKER = ++YYCURSOR);
   83: 	if (yych <= 0x00) goto yy4;
   84: 	goto yy38;
   85: yy6:
   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':
  150: 	case 'z':	goto yy32;
  151: 	case ':':	goto yy35;
  152: 	default:	goto yy4;
  153: 	}
  154: yy7:
  155: 	++YYCURSOR;
  156: 	switch ((yych = *YYCURSOR)) {
  157: 	case '?':	goto yy29;
  158: 	default:	goto yy8;
  159: 	}
  160: yy8:
  161: 	{ RET(PDO_PARSER_BIND_POS); }
  162: yy9:
  163: 	++YYCURSOR;
  164: 	switch ((yych = *YYCURSOR)) {
  165: 	case '*':	goto yy19;
  166: 	default:	goto yy13;
  167: 	}
  168: yy10:
  169: 	{ RET(PDO_PARSER_TEXT); }
  170: yy11:
  171: 	yych = *++YYCURSOR;
  172: 	switch (yych) {
  173: 	case '-':	goto yy14;
  174: 	default:	goto yy13;
  175: 	}
  176: yy12:
  177: 	++YYCURSOR;
  178: 	if (YYLIMIT <= YYCURSOR) YYFILL(1);
  179: 	yych = *YYCURSOR;
  180: yy13:
  181: 	switch (yych) {
  182: 	case 0x00:
  183: 	case '"':
  184: 	case '\'':
  185: 	case ':':
  186: 	case '?':	goto yy10;
  187: 	default:	goto yy12;
  188: 	}
  189: yy14:
  190: 	++YYCURSOR;
  191: 	if (YYLIMIT <= YYCURSOR) YYFILL(1);
  192: 	yych = *YYCURSOR;
  193: 	switch (yych) {
  194: 	case 0x00:
  195: 	case '"':
  196: 	case '\'':
  197: 	case ':':
  198: 	case '?':	goto yy17;
  199: 	case '\n':
  200: 	case '\r':	goto yy12;
  201: 	default:	goto yy14;
  202: 	}
  203: yy16:
  204: 	{ RET(PDO_PARSER_TEXT); }
  205: yy17:
  206: 	++YYCURSOR;
  207: 	if (YYLIMIT <= YYCURSOR) YYFILL(1);
  208: 	yych = *YYCURSOR;
  209: 	switch (yych) {
  210: 	case '\n':
  211: 	case '\r':	goto yy16;
  212: 	default:	goto yy17;
  213: 	}
  214: yy19:
  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 ':':
  224: 	case '?':	goto yy21;
  225: 	case '*':	goto yy23;
  226: 	default:	goto yy19;
  227: 	}
  228: yy21:
  229: 	++YYCURSOR;
  230: 	if (YYLIMIT <= YYCURSOR) YYFILL(1);
  231: 	yych = *YYCURSOR;
  232: 	switch (yych) {
  233: 	case '*':	goto yy26;
  234: 	default:	goto yy21;
  235: 	}
  236: yy23:
  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 ':':
  246: 	case '?':	goto yy21;
  247: 	case '*':	goto yy23;
  248: 	case '/':	goto yy25;
  249: 	default:	goto yy19;
  250: 	}
  251: yy25:
  252: 	yych = *++YYCURSOR;
  253: 	switch (yych) {
  254: 	case 0x00:
  255: 	case '"':
  256: 	case '\'':
  257: 	case ':':
  258: 	case '?':	goto yy16;
  259: 	default:	goto yy12;
  260: 	}
  261: yy26:
  262: 	++YYCURSOR;
  263: 	if (YYLIMIT <= YYCURSOR) YYFILL(1);
  264: 	yych = *YYCURSOR;
  265: 	switch (yych) {
  266: 	case '*':	goto yy26;
  267: 	case '/':	goto yy28;
  268: 	default:	goto yy21;
  269: 	}
  270: yy28:
  271: 	yych = *++YYCURSOR;
  272: 	goto yy16;
  273: yy29:
  274: 	++YYCURSOR;
  275: 	if (YYLIMIT <= YYCURSOR) YYFILL(1);
  276: 	yych = *YYCURSOR;
  277: 	switch (yych) {
  278: 	case '?':	goto yy29;
  279: 	default:	goto yy31;
  280: 	}
  281: yy31:
  282: 	{ RET(PDO_PARSER_TEXT); }
  283: yy32:
  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':
  350: 	case 'z':	goto yy32;
  351: 	default:	goto yy34;
  352: 	}
  353: yy34:
  354: 	{ RET(PDO_PARSER_BIND); }
  355: yy35:
  356: 	++YYCURSOR;
  357: 	if (YYLIMIT <= YYCURSOR) YYFILL(1);
  358: 	yych = *YYCURSOR;
  359: 	switch (yych) {
  360: 	case ':':	goto yy35;
  361: 	default:	goto yy31;
  362: 	}
  363: yy37:
  364: 	++YYCURSOR;
  365: 	if (YYLIMIT <= YYCURSOR) YYFILL(1);
  366: 	yych = *YYCURSOR;
  367: yy38:
  368: 	switch (yych) {
  369: 	case 0x00:	goto yy2;
  370: 	case '\'':	goto yy40;
  371: 	case '\\':	goto yy39;
  372: 	default:	goto yy37;
  373: 	}
  374: yy39:
  375: 	++YYCURSOR;
  376: 	if (YYLIMIT <= YYCURSOR) YYFILL(1);
  377: 	yych = *YYCURSOR;
  378: 	if (yych <= 0x00) goto yy2;
  379: 	goto yy37;
  380: yy40:
  381: 	++YYCURSOR;
  382: 	{ RET(PDO_PARSER_TEXT); }
  383: yy42:
  384: 	++YYCURSOR;
  385: 	if (YYLIMIT <= YYCURSOR) YYFILL(1);
  386: 	yych = *YYCURSOR;
  387: yy43:
  388: 	switch (yych) {
  389: 	case 0x00:	goto yy2;
  390: 	case '"':	goto yy45;
  391: 	case '\\':	goto yy44;
  392: 	default:	goto yy42;
  393: 	}
  394: yy44:
  395: 	++YYCURSOR;
  396: 	if (YYLIMIT <= YYCURSOR) YYFILL(1);
  397: 	yych = *YYCURSOR;
  398: 	if (yych <= 0x00) goto yy2;
  399: 	goto yy42;
  400: yy45:
  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;
  433: 	s.end = inquery + inquery_len + 1;
  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**) &param) == 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**) &param);
  530: 			} else {
  531: 				ret = zend_hash_find(params, plc->pos, plc->len, (void**) &param);
  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, &param->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;
  553: 							strncpy(stmt->error_code, stmt->dbh->error_code, 6);
  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 {
  569: 					switch (Z_TYPE_P(param->parameter)) {
  570: 						case IS_NULL:
  571: 							plc->quoted = "NULL";
  572: 							plc->qlen = sizeof("NULL")-1;
  573: 							plc->freeq = 0;
  574: 							break;
  575: 
  576: 						case IS_BOOL:
  577: 							convert_to_long(param->parameter);
  578: 
  579: 						case IS_LONG:
  580: 						case IS_DOUBLE:
  581: 							convert_to_string(param->parameter);
  582: 							plc->qlen = Z_STRLEN_P(param->parameter);
  583: 							plc->quoted = Z_STRVAL_P(param->parameter);
  584: 							plc->freeq = 0;
  585: 							break;
  586: 
  587: 						default:
  588: 							convert_to_string(param->parameter);
  589: 							if (!stmt->dbh->methods->quoter(stmt->dbh, Z_STRVAL_P(param->parameter),
  590: 									Z_STRLEN_P(param->parameter), &plc->quoted, &plc->qlen,
  591: 									param->param_type TSRMLS_CC)) {
  592: 								/* bork */
  593: 								ret = -1;
  594: 								strncpy(stmt->error_code, stmt->dbh->error_code, 6);
  595: 								goto clean_up;
  596: 							}
  597: 							plc->freeq = 1;
  598: 					}
  599: 				}
  600: 			} else {
  601: 				plc->quoted = Z_STRVAL_P(param->parameter);
  602: 				plc->qlen = Z_STRLEN_P(param->parameter);
  603: 			}
  604: 			newbuffer_len += plc->qlen;
  605: 		}
  606: 
  607: rewrite:
  608: 		/* allocate output buffer */
  609: 		newbuffer = emalloc(newbuffer_len + 1);
  610: 		*outquery = newbuffer;
  611: 
  612: 		/* and build the query */
  613: 		plc = placeholders;
  614: 		ptr = inquery;
  615: 
  616: 		do {
  617: 			t = plc->pos - ptr;
  618: 			if (t) {
  619: 				memcpy(newbuffer, ptr, t);
  620: 				newbuffer += t;
  621: 			}
  622: 			memcpy(newbuffer, plc->quoted, plc->qlen);
  623: 			newbuffer += plc->qlen;
  624: 			ptr = plc->pos + plc->len;
  625: 
  626: 			plc = plc->next;
  627: 		} while (plc);
  628: 
  629: 		t = (inquery + inquery_len) - ptr;
  630: 		if (t) {
  631: 			memcpy(newbuffer, ptr, t);
  632: 			newbuffer += t;
  633: 		}
  634: 		*newbuffer = '\0';
  635: 		*outquery_len = newbuffer - *outquery;
  636: 
  637: 		ret = 1;
  638: 		goto clean_up;
  639: 
  640: 	} else if (query_type == PDO_PLACEHOLDER_POSITIONAL) {
  641: 		/* rewrite ? to :pdoX */
  642: 		char *name, *idxbuf;
  643: 		const char *tmpl = stmt->named_rewrite_template ? stmt->named_rewrite_template : ":pdo%d";
  644: 		int bind_no = 1;
  645: 		
  646: 		newbuffer_len = inquery_len;
  647: 
  648: 		if (stmt->bound_param_map == NULL) {
  649: 			ALLOC_HASHTABLE(stmt->bound_param_map);
  650: 			zend_hash_init(stmt->bound_param_map, 13, NULL, NULL, 0);
  651: 		}
  652: 
  653: 		for (plc = placeholders; plc; plc = plc->next) {
  654: 			int skip_map = 0;
  655: 			char *p;
  656: 			name = estrndup(plc->pos, plc->len);
  657: 
  658: 			/* check if bound parameter is already available */
  659: 			if (!strcmp(name, "?") || zend_hash_find(stmt->bound_param_map, name, plc->len + 1, (void**) &p) == FAILURE) {
  660: 				spprintf(&idxbuf, 0, tmpl, bind_no++);
  661: 			} else {
  662: 				idxbuf = estrdup(p);
  663: 				skip_map = 1;
  664: 			}
  665: 
  666: 			plc->quoted = idxbuf;
  667: 			plc->qlen = strlen(plc->quoted);
  668: 			plc->freeq = 1;
  669: 			newbuffer_len += plc->qlen;
  670: 
  671: 			if (!skip_map && stmt->named_rewrite_template) {
  672: 				/* create a mapping */
  673: 				zend_hash_update(stmt->bound_param_map, name, plc->len + 1, idxbuf, plc->qlen + 1, NULL);
  674: 			}
  675: 
  676: 			/* map number to name */
  677: 			zend_hash_index_update(stmt->bound_param_map, plc->bindno, idxbuf, plc->qlen + 1, NULL);
  678: 			
  679: 			efree(name);
  680: 		}
  681: 				
  682: 		goto rewrite;
  683: 
  684: 	} else {
  685: 		/* rewrite :name to ? */
  686: 		
  687: 		newbuffer_len = inquery_len;
  688: 	
  689: 		if (stmt->bound_param_map == NULL) {
  690: 			ALLOC_HASHTABLE(stmt->bound_param_map);
  691: 			zend_hash_init(stmt->bound_param_map, 13, NULL, NULL, 0);
  692: 		}
  693: 		
  694: 		for (plc = placeholders; plc; plc = plc->next) {
  695: 			char *name;
  696: 			
  697: 			name = estrndup(plc->pos, plc->len);
  698: 			zend_hash_index_update(stmt->bound_param_map, plc->bindno, name, plc->len + 1, NULL);
  699: 			efree(name);
  700: 			plc->quoted = "?";
  701: 			plc->qlen = 1;
  702: 		}
  703: 
  704: 		goto rewrite;
  705: 	}
  706: 
  707: clean_up:
  708: 
  709: 	while (placeholders) {
  710: 		plc = placeholders;
  711: 		placeholders = plc->next;
  712: 
  713: 		if (plc->freeq) {
  714: 			efree(plc->quoted);
  715: 		}
  716: 
  717: 		efree(plc);
  718: 	}
  719: 
  720: 	return ret;
  721: }
  722: 
  723: #if 0
  724: int old_pdo_parse_params(pdo_stmt_t *stmt, char *inquery, int inquery_len, char **outquery, 
  725: 		int *outquery_len TSRMLS_DC)
  726: {
  727: 	Scanner s;
  728: 	char *ptr;
  729: 	int t;
  730: 	int bindno = 0;
  731: 	int newbuffer_len;
  732: 	int padding;
  733: 	HashTable *params = stmt->bound_params;
  734: 	struct pdo_bound_param_data *param;
  735: 	/* allocate buffer for query with expanded binds, ptr is our writing pointer */
  736: 	newbuffer_len = inquery_len;
  737: 
  738: 	/* calculate the possible padding factor due to quoting */
  739: 	if(stmt->dbh->max_escaped_char_length) {
  740: 		padding = stmt->dbh->max_escaped_char_length;
  741: 	} else {
  742: 		padding = 3;
  743: 	}
  744: 	if(params) {
  745: 		zend_hash_internal_pointer_reset(params);
  746: 		while (SUCCESS == zend_hash_get_current_data(params, (void**)&param)) {
  747: 			if(param->parameter) {
  748: 				convert_to_string(param->parameter);
  749: 				/* accommodate a string that needs to be fully quoted
  750:                    bind placeholders are at least 2 characters, so
  751:                    the accommodate their own "'s
  752:                 */
  753: 				newbuffer_len += padding * Z_STRLEN_P(param->parameter);
  754: 			}
  755: 			zend_hash_move_forward(params);
  756: 		}
  757: 	}
  758: 	*outquery = (char *) emalloc(newbuffer_len + 1);
  759: 	*outquery_len = 0;
  760: 
  761: 	ptr = *outquery;
  762: 	s.cur = inquery;
  763: 	while((t = scan(&s)) != PDO_PARSER_EOI) {
  764: 		if(t == PDO_PARSER_TEXT) {
  765: 			memcpy(ptr, s.tok, s.cur - s.tok);
  766: 			ptr += (s.cur - s.tok);
  767: 			*outquery_len += (s.cur - s.tok);
  768: 		}
  769: 		else if(t == PDO_PARSER_BIND) {
  770: 			if(!params) { 
  771: 				/* error */
  772: 				efree(*outquery);
  773: 				*outquery = NULL;
  774: 				return (int) (s.cur - inquery);
  775: 			}
  776: 			/* lookup bind first via hash and then index */
  777: 			/* stupid keys need to be null-terminated, even though we know their length */
  778: 			if((SUCCESS == zend_hash_find(params, s.tok, s.cur-s.tok,(void **)&param))  
  779: 			    ||
  780: 			   (SUCCESS == zend_hash_index_find(params, bindno, (void **)&param))) 
  781: 			{
  782: 				char *quotedstr;
  783: 				int quotedstrlen;
  784: 				/* restore the in-string key, doesn't need null-termination here */
  785: 				/* currently everything is a string here */
  786: 				
  787: 				/* quote the bind value if necessary */
  788: 				if(stmt->dbh->methods->quoter(stmt->dbh, Z_STRVAL_P(param->parameter), 
  789: 					Z_STRLEN_P(param->parameter), &quotedstr, &quotedstrlen TSRMLS_CC))
  790: 				{
  791: 					memcpy(ptr, quotedstr, quotedstrlen);
  792: 					ptr += quotedstrlen;
  793: 					*outquery_len += quotedstrlen;
  794: 					efree(quotedstr);
  795: 				} else {
  796: 					memcpy(ptr, Z_STRVAL_P(param->parameter), Z_STRLEN_P(param->parameter));
  797: 					ptr += Z_STRLEN_P(param->parameter);
  798: 					*outquery_len += (Z_STRLEN_P(param->parameter));
  799: 				}
  800: 			}
  801: 			else {
  802: 				/* error and cleanup */
  803: 				efree(*outquery);
  804: 				*outquery = NULL;
  805: 				return (int) (s.cur - inquery);
  806: 			}
  807: 			bindno++;
  808: 		}
  809: 		else if(t == PDO_PARSER_BIND_POS) {
  810: 			if(!params) { 
  811: 				/* error */
  812: 				efree(*outquery);
  813: 				*outquery = NULL;
  814: 				return (int) (s.cur - inquery);
  815: 			}
  816: 			/* lookup bind by index */
  817: 			if(SUCCESS == zend_hash_index_find(params, bindno, (void **)&param)) 
  818: 			{
  819: 				char *quotedstr;
  820: 				int quotedstrlen;
  821: 				/* currently everything is a string here */
  822: 				
  823: 				/* quote the bind value if necessary */
  824: 				if(stmt->dbh->methods->quoter(stmt->dbh, Z_STRVAL_P(param->parameter), 
  825: 					Z_STRLEN_P(param->parameter), &quotedstr, &quotedstrlen TSRMLS_CC))
  826: 				{
  827: 					memcpy(ptr, quotedstr, quotedstrlen);
  828: 					ptr += quotedstrlen;
  829: 					*outquery_len += quotedstrlen;
  830: 					efree(quotedstr);
  831: 				} else {
  832: 					memcpy(ptr, Z_STRVAL_P(param->parameter), Z_STRLEN_P(param->parameter));
  833: 					ptr += Z_STRLEN_P(param->parameter);
  834: 					*outquery_len += (Z_STRLEN_P(param->parameter));
  835: 				}
  836: 			}
  837: 			else {
  838: 				/* error and cleanup */
  839: 				efree(*outquery);
  840: 				*outquery = NULL;
  841: 				return (int) (s.cur - inquery);
  842: 			}
  843: 			bindno++;
  844: 		}
  845: 	}	
  846: 	*ptr = '\0';
  847: 	return 0;
  848: }
  849: #endif
  850: 
  851: /*
  852:  * Local variables:
  853:  * tab-width: 4
  854:  * c-basic-offset: 4
  855:  * End:
  856:  * vim600: noet sw=4 ts=4 fdm=marker ft=c
  857:  * vim<600: noet sw=4 ts=4
  858:  */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>