File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / php / ext / pdo / pdo_sql_parser.c
Revision 1.1.1.3 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Mon Jul 22 01:31:55 2013 UTC (10 years, 11 months ago) by misho
Branches: php, MAIN
CVS tags: v5_4_17, HEAD
5.4.17

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

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