*/
}
-int pdo_parse_params(pdo_stmt_t *stmt, char *inquery, int inquery_len, char **outquery,
+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;
+}
+
+#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;
*ptr = '\0';
return 0;
}
+#endif
/*
* Local variables:
#include "php_pdo.h"
#include "php_pdo_driver.h"
#include "php_pdo_int.h"
-#include "php_pdo_sql_parser.h"
#include "zend_exceptions.h"
#if COMPILE_DL_PDO
}
}
- /* TODO: handle the non-native types too... doh. */
if (PDO_PLACEHOLDER_NONE == stmt->supports_placeholders) {
- int error_pos;
/* handle the emulated parameter binding,
* stmt->active_query_string holds the query with binds expanded and
* quoted.
*/
- if((error_pos = pdo_parse_params(stmt, stmt->query_string, stmt->query_stringlen,
- &stmt->active_query_string, &stmt->active_query_stringlen)) != 0) {
- // parse error in handling the query
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error emulating placeholder binding in query at %.*s....", error_pos, stmt->query_string);
+
+ ret = pdo_parse_params(stmt, stmt->query_string, stmt->query_stringlen,
+ &stmt->active_query_string, &stmt->active_query_stringlen TSRMLS_CC);
+
+ if (ret == 0) {
+ /* no changes were made */
+ stmt->active_query_string = stmt->query_string;
+ stmt->active_query_stringlen = stmt->active_query_stringlen;
+ } else if (ret == -1) {
+ /* something broke */
+ PDO_HANDLE_STMT_ERR();
RETURN_FALSE;
}
} else if (!dispatch_param_event(stmt, PDO_PARAM_EVT_EXEC_PRE TSRMLS_CC)) {
RETURN_FALSE;
}
if (stmt->methods->executer(stmt TSRMLS_CC)) {
- if (stmt->active_query_string) {
+ if (stmt->active_query_string && stmt->active_query_string != stmt->query_string) {
efree(stmt->active_query_string);
- stmt->active_query_string = NULL;
}
+ stmt->active_query_string = NULL;
if (!stmt->executed) {
/* this is the first execute */
RETURN_BOOL(ret);
}
- if (stmt->active_query_string) {
+ if (stmt->active_query_string && stmt->active_query_string != stmt->query_string) {
efree(stmt->active_query_string);
- stmt->active_query_string = NULL;
}
+ stmt->active_query_string = NULL;
PDO_HANDLE_STMT_ERR();
RETURN_FALSE;
}
+++ /dev/null
-/*
- +----------------------------------------------------------------------+
- | PHP Version 5 |
- +----------------------------------------------------------------------+
- | Copyright (c) 1997-2005 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 |
- | available through the world-wide-web at the following url: |
- | http://www.php.net/license/3_0.txt. |
- | If you did not receive a copy of the PHP license and are unable to |
- | obtain it through the world-wide-web, please send a note to |
- | license@php.net so we can mail you a copy immediately. |
- +----------------------------------------------------------------------+
- | Author: George Schlossnagle <george@omniti.com> |
- +----------------------------------------------------------------------+
-*/
-
-/* $Id$ */
-
-#ifndef PHP_PDO_MYSQL_SQL_PARSER_H
-#define PHP_PDO_MYSQL_SQL_PARSER_H
-#include "php.h"
-int pdo_parse_params(pdo_stmt_t *stmt, char *inquery, int inquery_len, char **outquery,
- int *outquery_len);
-
-#endif