File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / php / ext / pdo / pdo_sql_parser.c
Revision 1.1: download - view: text, annotated - select for diffs - revision graph
Tue Feb 21 23:47:58 2012 UTC (12 years, 4 months ago) by misho
CVS tags: MAIN, HEAD
Initial revision

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

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