diff options
Diffstat (limited to 'ext/pdo/pdo_sql_parser.c')
-rw-r--r-- | ext/pdo/pdo_sql_parser.c | 255 |
1 files changed, 231 insertions, 24 deletions
diff --git a/ext/pdo/pdo_sql_parser.c b/ext/pdo/pdo_sql_parser.c index 26bdf21a2c..550c43154d 100644 --- a/ext/pdo/pdo_sql_parser.c +++ b/ext/pdo/pdo_sql_parser.c @@ -1,10 +1,10 @@ -/* Generated by re2c 0.5 on Fri May 21 17:33:58 2004 */ -#line 1 "/home/george/src/pecl/pdo/pdo_sql_parser.re" +/* Generated by re2c 0.9.3 on Thu Jan 20 22:49:12 2005 */ +#line 1 "pdo_sql_parser.re" /* +----------------------------------------------------------------------+ | PHP Version 5 | +----------------------------------------------------------------------+ - | Copyright (c) 1997-2005 The PHP Group | + | Copyright (c) 1997-2004 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.0 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | @@ -45,10 +45,12 @@ static int scan(Scanner *s) char *cursor = s->cur; std: s->tok = cursor; - #line 54 + #line 54 "pdo_sql_parser.re" - { + +#line 7 "<stdout>" +{ YYCTYPE yych; unsigned int yyaccept; static unsigned char yybm[] = { @@ -99,9 +101,11 @@ yy0: yy2: yyaccept = 0; yych = *(YYMARKER = ++YYCURSOR); if(yych >= '\001') goto yy24; + goto yy3; yy3: -#line 61 - { RET(PDO_PARSER_TEXT); } +#line 61 "pdo_sql_parser.re" +{ RET(PDO_PARSER_TEXT); } +#line 63 "<stdout>" yy4: yyaccept = 0; yych = *(YYMARKER = ++YYCURSOR); if(yych <= '\000') goto yy3; @@ -110,31 +114,42 @@ yy4: yyaccept = 0; yy5: yych = *++YYCURSOR; if(yybm[0+yych] & 16) goto yy13; goto yy3; -yy6: yych = *++YYCURSOR; +yy6: ++YYCURSOR; + goto yy7; yy7: -#line 60 - { RET(PDO_PARSER_BIND_POS); } +#line 60 "pdo_sql_parser.re" +{ RET(PDO_PARSER_BIND_POS); } +#line 77 "<stdout>" yy8: ++YYCURSOR; if(YYLIMIT == YYCURSOR) YYFILL(1); yych = *YYCURSOR; + goto yy9; yy9: if(yybm[0+yych] & 8) goto yy8; + goto yy10; yy10: -#line 62 - { RET(PDO_PARSER_TEXT); } -yy11: yych = *++YYCURSOR; +#line 62 "pdo_sql_parser.re" +{ RET(PDO_PARSER_TEXT); } +#line 88 "<stdout>" +yy11: ++YYCURSOR; + goto yy12; yy12: -#line 63 - { RET(PDO_PARSER_EOI); } +#line 63 "pdo_sql_parser.re" +{ RET(PDO_PARSER_EOI); } +#line 94 "<stdout>" yy13: ++YYCURSOR; if(YYLIMIT == YYCURSOR) YYFILL(1); yych = *YYCURSOR; + goto yy14; yy14: if(yybm[0+yych] & 16) goto yy13; + goto yy15; yy15: -#line 59 - { RET(PDO_PARSER_BIND); } +#line 59 "pdo_sql_parser.re" +{ RET(PDO_PARSER_BIND); } +#line 105 "<stdout>" yy16: ++YYCURSOR; if(YYLIMIT == YYCURSOR) YYFILL(1); yych = *YYCURSOR; + goto yy17; yy17: if(yybm[0+yych] & 32) goto yy16; if(yych <= '&') goto yy18; if(yych <= '\'') goto yy19; @@ -148,13 +163,15 @@ yy19: yyaccept = 1; YYMARKER = ++YYCURSOR; if(YYLIMIT == YYCURSOR) YYFILL(1); yych = *YYCURSOR; + goto yy20; yy20: if(yybm[0+yych] & 32) goto yy16; if(yych <= '&') goto yy21; if(yych <= '\'') goto yy19; goto yy22; yy21: -#line 58 - { RET(PDO_PARSER_TEXT); } +#line 58 "pdo_sql_parser.re" +{ RET(PDO_PARSER_TEXT); } +#line 132 "<stdout>" yy22: ++YYCURSOR; if(YYLIMIT == YYCURSOR) YYFILL(1); yych = *YYCURSOR; @@ -163,24 +180,213 @@ yy22: ++YYCURSOR; yy23: ++YYCURSOR; if(YYLIMIT == YYCURSOR) YYFILL(1); yych = *YYCURSOR; + goto yy24; yy24: if(yybm[0+yych] & 128) goto yy23; if(yych <= '\000') goto yy18; if(yych <= '[') goto yy26; + goto yy25; yy25: ++YYCURSOR; if(YYLIMIT == YYCURSOR) YYFILL(1); yych = *YYCURSOR; if(yych == '"') goto yy23; goto yy18; -yy26: yych = *++YYCURSOR; +yy26: ++YYCURSOR; + goto yy27; yy27: -#line 57 - { RET(PDO_PARSER_TEXT); } +#line 57 "pdo_sql_parser.re" +{ RET(PDO_PARSER_TEXT); } +#line 159 "<stdout>" } -#line 64 +#line 64 "pdo_sql_parser.re" + +} + +struct placeholder { + char *pos; + int len; + int bindno; + int qlen; /* quoted length of value */ + char *quoted; /* quoted value */ + int freeq; + struct placeholder *next; +}; + +PDO_API int pdo_parse_params(pdo_stmt_t *stmt, char *inquery, int inquery_len, + char **outquery, int *outquery_len TSRMLS_DC) +{ + Scanner s; + char *ptr, *newbuffer; + int t; + int bindno = 0; + int ret = 0; + int newbuffer_len; + int padding; + HashTable *params; + struct pdo_bound_param_data *param; + int query_type = PDO_PLACEHOLDER_NONE; + struct placeholder *placeholders = NULL, *placetail = NULL, *plc = NULL; + + ptr = *outquery; + s.cur = inquery; + s.lim = inquery + inquery_len; + + /* phase 1: look for args */ + while((t = scan(&s)) != PDO_PARSER_EOI) { + if (t == PDO_PARSER_BIND || t == PDO_PARSER_BIND_POS) { + if (t == PDO_PARSER_BIND) { + query_type |= PDO_PLACEHOLDER_NAMED; + } else { + query_type |= PDO_PLACEHOLDER_POSITIONAL; + } + + plc = emalloc(sizeof(*plc)); + memset(plc, 0, sizeof(*plc)); + plc->next = NULL; + plc->pos = s.tok; + plc->len = s.cur - s.tok; + plc->bindno = bindno++; + + if (placetail) { + placetail->next = plc; + } else { + placeholders = plc; + } + placetail = plc; + } + } + + if (bindno == 0) { + /* nothing to do; good! */ + return 0; + } + + /* did the query make sense to me? */ + if (query_type == (PDO_PLACEHOLDER_NAMED|PDO_PLACEHOLDER_POSITIONAL)) { + /* they mixed both types; punt */ + strcpy(stmt->error_code, "HY093"); /* invalid parameter number */ + return -1; + } + + if (stmt->supports_placeholders == query_type) { + /* query matches native syntax */ + ret = 0; + goto clean_up; + } + + params = stmt->bound_params; + + /* what are we going to do ? */ + if (stmt->supports_placeholders == PDO_PLACEHOLDER_NONE) { + /* query generation */ + + newbuffer_len = inquery_len; + + /* let's quote all the values */ + for (plc = placeholders; plc; plc = plc->next) { + if (query_type == PDO_PLACEHOLDER_POSITIONAL) { + ret = zend_hash_index_find(params, plc->bindno, (void**) ¶m); + } else { + ret = zend_hash_find(params, plc->pos, plc->len, (void**) ¶m); + } + if (ret == FAILURE) { + /* parameter was not defined */ + ret = -1; + strcpy(stmt->error_code, "HY093"); /* invalid parameter number */ + goto clean_up; + } + if (stmt->dbh->methods->quoter) { + if (!stmt->dbh->methods->quoter(stmt->dbh, Z_STRVAL_P(param->parameter), + Z_STRLEN_P(param->parameter), &plc->quoted, &plc->qlen TSRMLS_CC)) { + /* bork */ + ret = -1; + strcpy(stmt->error_code, stmt->dbh->error_code); + goto clean_up; + } + plc->freeq = 1; + } else { + plc->quoted = Z_STRVAL_P(param->parameter); + plc->qlen = Z_STRLEN_P(param->parameter); + } + newbuffer_len += plc->qlen; + } + +rewrite: + /* allocate output buffer */ + newbuffer = emalloc(newbuffer_len + 1); + *outquery = newbuffer; + + /* and build the query */ + plc = placeholders; + ptr = inquery; + + do { + t = plc->pos - ptr; + if (t) { + memcpy(newbuffer, ptr, t); + newbuffer += t; + } + memcpy(newbuffer, plc->quoted, plc->qlen); + newbuffer += plc->qlen; + ptr = plc->pos + plc->len; + + plc = plc->next; + } while (plc); + + t = (inquery + inquery_len) - ptr; + if (t) { + memcpy(newbuffer, ptr, t); + newbuffer += t; + } + *newbuffer = '\0'; + *outquery_len = newbuffer - *outquery; + + ret = 1; + goto clean_up; + + } else if (query_type == PDO_PLACEHOLDER_POSITIONAL) { + /* rewrite ? to :pdoX */ + char idxbuf[32]; + + newbuffer_len = inquery_len; + + for (plc = placeholders; plc; plc = plc->next) { + snprintf(idxbuf, sizeof(idxbuf), ":pdo%d", plc->bindno); + plc->quoted = estrdup(idxbuf); + plc->qlen = strlen(plc->quoted); + plc->freeq = 1; + newbuffer_len += plc->qlen; + } + + goto rewrite; + + } else { + /* rewrite :name to ? */ + + /* HARD!. We need to remember the mapping and bind those positions. */ + strcpy(stmt->error_code, "IM001"); /* Driver does not support this function */ + + ret = -1; + } + +clean_up: + + while (placeholders) { + plc = placeholders; + placeholders = plc->next; + + if (plc->freeq) { + efree(plc->quoted); + } + + efree(plc); + } + + return ret; } -int pdo_parse_params(pdo_stmt_t *stmt, char *inquery, int inquery_len, char **outquery, +#if 0 +int old_pdo_parse_params(pdo_stmt_t *stmt, char *inquery, int inquery_len, char **outquery, int *outquery_len TSRMLS_DC) { Scanner s; @@ -306,6 +512,7 @@ int pdo_parse_params(pdo_stmt_t *stmt, char *inquery, int inquery_len, char **ou *ptr = '\0'; return 0; } +#endif /* * Local variables: |