PDO: Store/pass query_string as zend_string

Rather than storing char* + size_t, use a zend_string*. Also
avoid various copies of the query string.
This commit is contained in:
Nikita Popov 2020-12-11 17:13:38 +01:00
parent c288b5294b
commit 2d51c203f0
15 changed files with 81 additions and 102 deletions

View file

@ -452,10 +452,9 @@ static void pdo_stmt_construct(zend_execute_data *execute_data, pdo_stmt_t *stmt
zval query_string; zval query_string;
zend_string *key; zend_string *key;
ZVAL_STRINGL(&query_string, stmt->query_string, stmt->query_stringlen); ZVAL_STR(&query_string, stmt->query_string);
key = zend_string_init("queryString", sizeof("queryString") - 1, 0); key = zend_string_init("queryString", sizeof("queryString") - 1, 0);
zend_std_write_property(Z_OBJ_P(object), key, &query_string, NULL); zend_std_write_property(Z_OBJ_P(object), key, &query_string, NULL);
zval_ptr_dtor(&query_string);
zend_string_release_ex(key, 0); zend_string_release_ex(key, 0);
if (dbstmt_ce->constructor) { if (dbstmt_ce->constructor) {
@ -490,22 +489,21 @@ static void pdo_stmt_construct(zend_execute_data *execute_data, pdo_stmt_t *stmt
PHP_METHOD(PDO, prepare) PHP_METHOD(PDO, prepare)
{ {
pdo_stmt_t *stmt; pdo_stmt_t *stmt;
char *statement; zend_string *statement;
size_t statement_len;
zval *options = NULL, *value, *item, ctor_args; zval *options = NULL, *value, *item, ctor_args;
zend_class_entry *dbstmt_ce, *pce; zend_class_entry *dbstmt_ce, *pce;
pdo_dbh_object_t *dbh_obj = Z_PDO_OBJECT_P(ZEND_THIS); pdo_dbh_object_t *dbh_obj = Z_PDO_OBJECT_P(ZEND_THIS);
pdo_dbh_t *dbh = dbh_obj->inner; pdo_dbh_t *dbh = dbh_obj->inner;
ZEND_PARSE_PARAMETERS_START(1, 2) ZEND_PARSE_PARAMETERS_START(1, 2)
Z_PARAM_STRING(statement, statement_len) Z_PARAM_STR(statement)
Z_PARAM_OPTIONAL Z_PARAM_OPTIONAL
Z_PARAM_ARRAY(options) Z_PARAM_ARRAY(options)
ZEND_PARSE_PARAMETERS_END(); ZEND_PARSE_PARAMETERS_END();
PDO_CONSTRUCT_CHECK; PDO_CONSTRUCT_CHECK;
if (statement_len == 0) { if (ZSTR_LEN(statement) == 0) {
zend_argument_value_error(1, "cannot be empty"); zend_argument_value_error(1, "cannot be empty");
RETURN_THROWS(); RETURN_THROWS();
} }
@ -557,8 +555,7 @@ PHP_METHOD(PDO, prepare)
stmt = Z_PDO_STMT_P(return_value); stmt = Z_PDO_STMT_P(return_value);
/* unconditionally keep this for later reference */ /* unconditionally keep this for later reference */
stmt->query_string = estrndup(statement, statement_len); stmt->query_string = zend_string_copy(statement);
stmt->query_stringlen = statement_len;
stmt->default_fetch_type = dbh->default_fetch_type; stmt->default_fetch_type = dbh->default_fetch_type;
stmt->dbh = dbh; stmt->dbh = dbh;
/* give it a reference to me */ /* give it a reference to me */
@ -566,7 +563,7 @@ PHP_METHOD(PDO, prepare)
/* we haven't created a lazy object yet */ /* we haven't created a lazy object yet */
ZVAL_UNDEF(&stmt->lazy_object_ref); ZVAL_UNDEF(&stmt->lazy_object_ref);
if (dbh->methods->preparer(dbh, statement, statement_len, stmt, options)) { if (dbh->methods->preparer(dbh, statement, stmt, options)) {
pdo_stmt_construct(execute_data, stmt, return_value, dbstmt_ce, &ctor_args); pdo_stmt_construct(execute_data, stmt, return_value, dbstmt_ce, &ctor_args);
return; return;
} }
@ -1051,8 +1048,7 @@ fill_array:
PHP_METHOD(PDO, query) PHP_METHOD(PDO, query)
{ {
pdo_stmt_t *stmt; pdo_stmt_t *stmt;
char *statement; zend_string *statement;
size_t statement_len;
zend_long fetch_mode; zend_long fetch_mode;
zend_bool fetch_mode_is_null = 1; zend_bool fetch_mode_is_null = 1;
zval *args = NULL; zval *args = NULL;
@ -1060,14 +1056,14 @@ PHP_METHOD(PDO, query)
pdo_dbh_object_t *dbh_obj = Z_PDO_OBJECT_P(ZEND_THIS); pdo_dbh_object_t *dbh_obj = Z_PDO_OBJECT_P(ZEND_THIS);
pdo_dbh_t *dbh = dbh_obj->inner; pdo_dbh_t *dbh = dbh_obj->inner;
if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS(), "s|l!*", &statement, &statement_len, if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS(), "S|l!*", &statement,
&fetch_mode, &fetch_mode_is_null, &args, &num_args)) { &fetch_mode, &fetch_mode_is_null, &args, &num_args)) {
RETURN_THROWS(); RETURN_THROWS();
} }
PDO_CONSTRUCT_CHECK; PDO_CONSTRUCT_CHECK;
if (statement_len == 0) { if (ZSTR_LEN(statement) == 0) {
zend_argument_value_error(1, "cannot be empty"); zend_argument_value_error(1, "cannot be empty");
RETURN_THROWS(); RETURN_THROWS();
} }
@ -1080,19 +1076,16 @@ PHP_METHOD(PDO, query)
stmt = Z_PDO_STMT_P(return_value); stmt = Z_PDO_STMT_P(return_value);
/* unconditionally keep this for later reference */ /* unconditionally keep this for later reference */
stmt->query_string = estrndup(statement, statement_len); stmt->query_string = zend_string_copy(statement);
stmt->query_stringlen = statement_len; stmt->active_query_string = zend_string_copy(stmt->query_string);
stmt->default_fetch_type = dbh->default_fetch_type; stmt->default_fetch_type = dbh->default_fetch_type;
stmt->active_query_string = stmt->query_string;
stmt->active_query_stringlen = statement_len;
stmt->dbh = dbh; stmt->dbh = dbh;
/* give it a reference to me */ /* give it a reference to me */
ZVAL_OBJ_COPY(&stmt->database_object_handle, &dbh_obj->std); ZVAL_OBJ_COPY(&stmt->database_object_handle, &dbh_obj->std);
/* we haven't created a lazy object yet */ /* we haven't created a lazy object yet */
ZVAL_UNDEF(&stmt->lazy_object_ref); ZVAL_UNDEF(&stmt->lazy_object_ref);
if (dbh->methods->preparer(dbh, statement, statement_len, stmt, NULL)) { if (dbh->methods->preparer(dbh, statement, stmt, NULL)) {
PDO_STMT_CLEAR_ERR(); PDO_STMT_CLEAR_ERR();
if (fetch_mode_is_null || pdo_stmt_setup_fetch_mode(stmt, fetch_mode, 2, args, num_args)) { if (fetch_mode_is_null || pdo_stmt_setup_fetch_mode(stmt, fetch_mode, 2, args, num_args)) {
/* now execute the statement */ /* now execute the statement */

View file

@ -81,11 +81,9 @@ static void free_param_name(zval *el) {
efree(Z_PTR_P(el)); efree(Z_PTR_P(el));
} }
PDO_API int pdo_parse_params(pdo_stmt_t *stmt, const char *inquery, size_t inquery_len, PDO_API int pdo_parse_params(pdo_stmt_t *stmt, zend_string *inquery, zend_string **outquery)
char **outquery, size_t *outquery_len)
{ {
Scanner s; Scanner s;
const char *ptr;
char *newbuffer; char *newbuffer;
ptrdiff_t t; ptrdiff_t t;
uint32_t bindno = 0; uint32_t bindno = 0;
@ -96,9 +94,8 @@ PDO_API int pdo_parse_params(pdo_stmt_t *stmt, const char *inquery, size_t inque
int query_type = PDO_PLACEHOLDER_NONE; int query_type = PDO_PLACEHOLDER_NONE;
struct placeholder *placeholders = NULL, *placetail = NULL, *plc = NULL; struct placeholder *placeholders = NULL, *placetail = NULL, *plc = NULL;
ptr = *outquery; s.cur = ZSTR_VAL(inquery);
s.cur = inquery; s.end = s.cur + ZSTR_LEN(inquery) + 1;
s.end = inquery + inquery_len + 1;
/* phase 1: look for args */ /* phase 1: look for args */
while((t = scan(&s)) != PDO_PARSER_EOI) { while((t = scan(&s)) != PDO_PARSER_EOI) {
@ -110,7 +107,7 @@ PDO_API int pdo_parse_params(pdo_stmt_t *stmt, const char *inquery, size_t inque
if (t == PDO_PARSER_BIND) { if (t == PDO_PARSER_BIND) {
ptrdiff_t len = s.cur - s.tok; ptrdiff_t len = s.cur - s.tok;
if ((inquery < (s.cur - len)) && isalnum(*(s.cur - len - 1))) { if ((ZSTR_VAL(inquery) < (s.cur - len)) && isalnum(*(s.cur - len - 1))) {
continue; continue;
} }
query_type |= PDO_PLACEHOLDER_NAMED; query_type |= PDO_PLACEHOLDER_NAMED;
@ -179,7 +176,7 @@ PDO_API int pdo_parse_params(pdo_stmt_t *stmt, const char *inquery, size_t inque
if (stmt->supports_placeholders == query_type && !stmt->named_rewrite_template) { if (stmt->supports_placeholders == query_type && !stmt->named_rewrite_template) {
/* query matches native syntax */ /* query matches native syntax */
if (escapes) { if (escapes) {
newbuffer_len = inquery_len; newbuffer_len = ZSTR_LEN(inquery);
goto rewrite; goto rewrite;
} }
@ -201,7 +198,7 @@ safe:
if (stmt->supports_placeholders == PDO_PLACEHOLDER_NONE) { if (stmt->supports_placeholders == PDO_PLACEHOLDER_NONE) {
/* query generation */ /* query generation */
newbuffer_len = inquery_len; newbuffer_len = ZSTR_LEN(inquery);
/* let's quote all the values */ /* let's quote all the values */
for (plc = placeholders; plc && params; plc = plc->next) { for (plc = placeholders; plc && params; plc = plc->next) {
@ -328,12 +325,12 @@ safe:
rewrite: rewrite:
/* allocate output buffer */ /* allocate output buffer */
newbuffer = emalloc(newbuffer_len + 1); *outquery = zend_string_alloc(newbuffer_len, 0);
*outquery = newbuffer; newbuffer = ZSTR_VAL(*outquery);
/* and build the query */ /* and build the query */
const char *ptr = ZSTR_VAL(inquery);
plc = placeholders; plc = placeholders;
ptr = inquery;
do { do {
t = plc->pos - ptr; t = plc->pos - ptr;
@ -353,13 +350,13 @@ rewrite:
plc = plc->next; plc = plc->next;
} while (plc); } while (plc);
t = (inquery + inquery_len) - ptr; t = ZSTR_VAL(inquery) + ZSTR_LEN(inquery) - ptr;
if (t) { if (t) {
memcpy(newbuffer, ptr, t); memcpy(newbuffer, ptr, t);
newbuffer += t; newbuffer += t;
} }
*newbuffer = '\0'; *newbuffer = '\0';
*outquery_len = newbuffer - *outquery; ZSTR_LEN(*outquery) = newbuffer - ZSTR_VAL(*outquery);
ret = 1; ret = 1;
goto clean_up; goto clean_up;
@ -370,7 +367,7 @@ rewrite:
const char *tmpl = stmt->named_rewrite_template ? stmt->named_rewrite_template : ":pdo%d"; const char *tmpl = stmt->named_rewrite_template ? stmt->named_rewrite_template : ":pdo%d";
int bind_no = 1; int bind_no = 1;
newbuffer_len = inquery_len; newbuffer_len = ZSTR_LEN(inquery);
if (stmt->bound_param_map == NULL) { if (stmt->bound_param_map == NULL) {
ALLOC_HASHTABLE(stmt->bound_param_map); ALLOC_HASHTABLE(stmt->bound_param_map);
@ -416,7 +413,7 @@ rewrite:
} else { } else {
/* rewrite :name to ? */ /* rewrite :name to ? */
newbuffer_len = inquery_len; newbuffer_len = ZSTR_LEN(inquery);
if (stmt->bound_param_map == NULL) { if (stmt->bound_param_map == NULL) {
ALLOC_HASHTABLE(stmt->bound_param_map); ALLOC_HASHTABLE(stmt->bound_param_map);

View file

@ -443,18 +443,16 @@ PHP_METHOD(PDOStatement, execute)
*/ */
/* string is leftover from previous calls so PDOStatement::debugDumpParams() can access */ /* string is leftover from previous calls so PDOStatement::debugDumpParams() can access */
if (stmt->active_query_string && stmt->active_query_string != stmt->query_string) { if (stmt->active_query_string) {
efree(stmt->active_query_string); zend_string_release(stmt->active_query_string);
stmt->active_query_string = NULL;
} }
stmt->active_query_string = NULL;
ret = pdo_parse_params(stmt, stmt->query_string, stmt->query_stringlen, ret = pdo_parse_params(stmt, stmt->query_string, &stmt->active_query_string);
&stmt->active_query_string, &stmt->active_query_stringlen);
if (ret == 0) { if (ret == 0) {
/* no changes were made */ /* no changes were made */
stmt->active_query_string = stmt->query_string; stmt->active_query_string = zend_string_copy(stmt->query_string);
stmt->active_query_stringlen = stmt->query_stringlen;
ret = 1; ret = 1;
} else if (ret == -1) { } else if (ret == -1) {
/* something broke */ /* something broke */
@ -2035,16 +2033,16 @@ PHP_METHOD(PDOStatement, debugDumpParams)
} }
/* break into multiple operations so query string won't be truncated at FORMAT_CONV_MAX_PRECISION */ /* break into multiple operations so query string won't be truncated at FORMAT_CONV_MAX_PRECISION */
php_stream_printf(out, "SQL: [%zd] ", stmt->query_stringlen); php_stream_printf(out, "SQL: [%zd] ", ZSTR_LEN(stmt->query_string));
php_stream_write(out, stmt->query_string, stmt->query_stringlen); php_stream_write(out, ZSTR_VAL(stmt->query_string), ZSTR_LEN(stmt->query_string));
php_stream_write(out, "\n", 1); php_stream_write(out, "\n", 1);
/* show parsed SQL if emulated prepares enabled */ /* show parsed SQL if emulated prepares enabled */
/* pointers will be equal if PDO::query() was invoked */ /* pointers will be equal if PDO::query() was invoked */
if (stmt->active_query_string != NULL && stmt->active_query_string != stmt->query_string) { if (stmt->active_query_string != NULL && stmt->active_query_string != stmt->query_string) {
/* break into multiple operations so query string won't be truncated at FORMAT_CONV_MAX_PRECISION */ /* break into multiple operations so query string won't be truncated at FORMAT_CONV_MAX_PRECISION */
php_stream_printf(out, "Sent SQL: [%zd] ", stmt->active_query_stringlen); php_stream_printf(out, "Sent SQL: [%zd] ", ZSTR_LEN(stmt->active_query_string));
php_stream_write(out, stmt->active_query_string, stmt->active_query_stringlen); php_stream_write(out, ZSTR_VAL(stmt->active_query_string), ZSTR_LEN(stmt->active_query_string));
php_stream_write(out, "\n", 1); php_stream_write(out, "\n", 1);
} }
@ -2175,11 +2173,11 @@ PDO_API void php_pdo_free_statement(pdo_stmt_t *stmt)
if (stmt->methods && stmt->methods->dtor) { if (stmt->methods && stmt->methods->dtor) {
stmt->methods->dtor(stmt); stmt->methods->dtor(stmt);
} }
if (stmt->active_query_string && stmt->active_query_string != stmt->query_string) { if (stmt->active_query_string) {
efree(stmt->active_query_string); zend_string_release(stmt->active_query_string);
} }
if (stmt->query_string) { if (stmt->query_string) {
efree(stmt->query_string); zend_string_release(stmt->query_string);
} }
pdo_stmt_reset_columns(stmt); pdo_stmt_reset_columns(stmt);

View file

@ -247,7 +247,7 @@ typedef struct {
typedef int (*pdo_dbh_close_func)(pdo_dbh_t *dbh); typedef int (*pdo_dbh_close_func)(pdo_dbh_t *dbh);
/* prepare a statement and stash driver specific portion into stmt */ /* prepare a statement and stash driver specific portion into stmt */
typedef int (*pdo_dbh_prepare_func)(pdo_dbh_t *dbh, const char *sql, size_t sql_len, pdo_stmt_t *stmt, zval *driver_options); typedef int (*pdo_dbh_prepare_func)(pdo_dbh_t *dbh, zend_string *sql, pdo_stmt_t *stmt, zval *driver_options);
/* execute a statement (that does not return a result set) */ /* execute a statement (that does not return a result set) */
typedef zend_long (*pdo_dbh_do_func)(pdo_dbh_t *dbh, const char *sql, size_t sql_len); typedef zend_long (*pdo_dbh_do_func)(pdo_dbh_t *dbh, const char *sql, size_t sql_len);
@ -604,12 +604,10 @@ struct _pdo_stmt_t {
zend_long row_count; zend_long row_count;
/* used to hold the statement's current query */ /* used to hold the statement's current query */
char *query_string; zend_string *query_string;
size_t query_stringlen;
/* the copy of the query with expanded binds ONLY for emulated-prepare drivers */ /* the copy of the query with expanded binds ONLY for emulated-prepare drivers */
char *active_query_string; zend_string *active_query_string;
size_t active_query_stringlen;
/* the cursor specific error code. */ /* the cursor specific error code. */
pdo_error_type error_code; pdo_error_type error_code;
@ -685,8 +683,7 @@ PDO_API int php_pdo_parse_data_source(const char *data_source,
PDO_API zend_class_entry *php_pdo_get_dbh_ce(void); PDO_API zend_class_entry *php_pdo_get_dbh_ce(void);
PDO_API zend_class_entry *php_pdo_get_exception(void); PDO_API zend_class_entry *php_pdo_get_exception(void);
PDO_API int pdo_parse_params(pdo_stmt_t *stmt, const char *inquery, size_t inquery_len, PDO_API int pdo_parse_params(pdo_stmt_t *stmt, zend_string *inquery, zend_string **outquery);
char **outquery, size_t *outquery_len);
PDO_API void pdo_raise_impl_error(pdo_dbh_t *dbh, pdo_stmt_t *stmt, PDO_API void pdo_raise_impl_error(pdo_dbh_t *dbh, pdo_stmt_t *stmt,
const char *sqlstate, const char *supp); const char *sqlstate, const char *supp);

View file

@ -59,7 +59,7 @@ static int dblib_fetch_error(pdo_dbh_t *dbh, pdo_stmt_t *stmt, zval *info)
} }
spprintf(&message, 0, "%s [%d] (severity %d) [%s]", spprintf(&message, 0, "%s [%d] (severity %d) [%s]",
msg, einfo->dberr, einfo->severity, stmt ? stmt->active_query_string : ""); msg, einfo->dberr, einfo->severity, stmt ? ZSTR_VAL(stmt->active_query_string) : "");
add_next_index_long(info, einfo->dberr); add_next_index_long(info, einfo->dberr);
add_next_index_string(info, message); add_next_index_string(info, message);
@ -94,7 +94,7 @@ static int dblib_handle_closer(pdo_dbh_t *dbh)
return 0; return 0;
} }
static int dblib_handle_preparer(pdo_dbh_t *dbh, const char *sql, size_t sql_len, pdo_stmt_t *stmt, zval *driver_options) static int dblib_handle_preparer(pdo_dbh_t *dbh, zend_string *sql, pdo_stmt_t *stmt, zval *driver_options)
{ {
pdo_dblib_db_handle *H = (pdo_dblib_db_handle *)dbh->driver_data; pdo_dblib_db_handle *H = (pdo_dblib_db_handle *)dbh->driver_data;
pdo_dblib_stmt *S = ecalloc(1, sizeof(*S)); pdo_dblib_stmt *S = ecalloc(1, sizeof(*S));

View file

@ -177,7 +177,7 @@ static int pdo_dblib_stmt_execute(pdo_stmt_t *stmt)
pdo_dblib_stmt_cursor_closer(stmt); pdo_dblib_stmt_cursor_closer(stmt);
if (FAIL == dbcmd(H->link, stmt->active_query_string)) { if (FAIL == dbcmd(H->link, ZSTR_VAL(stmt->active_query_string))) {
return 0; return 0;
} }

View file

@ -504,7 +504,7 @@ static int firebird_handle_closer(pdo_dbh_t *dbh) /* {{{ */
/* }}} */ /* }}} */
/* called by PDO to prepare an SQL query */ /* called by PDO to prepare an SQL query */
static int firebird_handle_preparer(pdo_dbh_t *dbh, const char *sql, size_t sql_len, /* {{{ */ static int firebird_handle_preparer(pdo_dbh_t *dbh, zend_string *sql, /* {{{ */
pdo_stmt_t *stmt, zval *driver_options) pdo_stmt_t *stmt, zval *driver_options)
{ {
pdo_firebird_db_handle *H = (pdo_firebird_db_handle *)dbh->driver_data; pdo_firebird_db_handle *H = (pdo_firebird_db_handle *)dbh->driver_data;
@ -524,7 +524,7 @@ static int firebird_handle_preparer(pdo_dbh_t *dbh, const char *sql, size_t sql_
zend_hash_init(np, 8, NULL, NULL, 0); zend_hash_init(np, 8, NULL, NULL, 0);
/* allocate and prepare statement */ /* allocate and prepare statement */
if (!firebird_alloc_prepare_stmt(dbh, sql, sql_len, &num_sqlda, &s, np)) { if (!firebird_alloc_prepare_stmt(dbh, ZSTR_VAL(sql), ZSTR_LEN(sql), &num_sqlda, &s, np)) {
break; break;
} }

View file

@ -162,18 +162,17 @@ static int mysql_handle_closer(pdo_dbh_t *dbh)
/* }}} */ /* }}} */
/* {{{ mysql_handle_preparer */ /* {{{ mysql_handle_preparer */
static int mysql_handle_preparer(pdo_dbh_t *dbh, const char *sql, size_t sql_len, pdo_stmt_t *stmt, zval *driver_options) static int mysql_handle_preparer(pdo_dbh_t *dbh, zend_string *sql, pdo_stmt_t *stmt, zval *driver_options)
{ {
pdo_mysql_db_handle *H = (pdo_mysql_db_handle *)dbh->driver_data; pdo_mysql_db_handle *H = (pdo_mysql_db_handle *)dbh->driver_data;
pdo_mysql_stmt *S = ecalloc(1, sizeof(pdo_mysql_stmt)); pdo_mysql_stmt *S = ecalloc(1, sizeof(pdo_mysql_stmt));
char *nsql = NULL; zend_string *nsql = NULL;
size_t nsql_len = 0;
int ret; int ret;
int server_version; int server_version;
PDO_DBG_ENTER("mysql_handle_preparer"); PDO_DBG_ENTER("mysql_handle_preparer");
PDO_DBG_INF_FMT("dbh=%p", dbh); PDO_DBG_INF_FMT("dbh=%p", dbh);
PDO_DBG_INF_FMT("sql=%.*s", (int)sql_len, sql); PDO_DBG_INF_FMT("sql=%.*s", ZSTR_LEN(sql), ZSTR_VAL(sql));
S->H = H; S->H = H;
stmt->driver_data = S; stmt->driver_data = S;
@ -188,12 +187,11 @@ static int mysql_handle_preparer(pdo_dbh_t *dbh, const char *sql, size_t sql_len
goto fallback; goto fallback;
} }
stmt->supports_placeholders = PDO_PLACEHOLDER_POSITIONAL; stmt->supports_placeholders = PDO_PLACEHOLDER_POSITIONAL;
ret = pdo_parse_params(stmt, (char*)sql, sql_len, &nsql, &nsql_len); ret = pdo_parse_params(stmt, sql, &nsql);
if (ret == 1) { if (ret == 1) {
/* query was rewritten */ /* query was rewritten */
sql = nsql; sql = nsql;
sql_len = nsql_len;
} else if (ret == -1) { } else if (ret == -1) {
/* failed to parse */ /* failed to parse */
strcpy(dbh->error_code, stmt->error_code); strcpy(dbh->error_code, stmt->error_code);
@ -203,14 +201,14 @@ static int mysql_handle_preparer(pdo_dbh_t *dbh, const char *sql, size_t sql_len
if (!(S->stmt = mysql_stmt_init(H->server))) { if (!(S->stmt = mysql_stmt_init(H->server))) {
pdo_mysql_error(dbh); pdo_mysql_error(dbh);
if (nsql) { if (nsql) {
efree(nsql); zend_string_release(nsql);
} }
PDO_DBG_RETURN(0); PDO_DBG_RETURN(0);
} }
if (mysql_stmt_prepare(S->stmt, sql, sql_len)) { if (mysql_stmt_prepare(S->stmt, ZSTR_VAL(sql), ZSTR_LEN(sql))) {
if (nsql) { if (nsql) {
efree(nsql); zend_string_release(nsql);
} }
/* TODO: might need to pull statement specific info here? */ /* TODO: might need to pull statement specific info here? */
/* if the query isn't supported by the protocol, fallback to emulation */ /* if the query isn't supported by the protocol, fallback to emulation */
@ -223,7 +221,7 @@ static int mysql_handle_preparer(pdo_dbh_t *dbh, const char *sql, size_t sql_len
PDO_DBG_RETURN(0); PDO_DBG_RETURN(0);
} }
if (nsql) { if (nsql) {
efree(nsql); zend_string_release(nsql);
} }
S->num_params = mysql_stmt_param_count(S->stmt); S->num_params = mysql_stmt_param_count(S->stmt);

View file

@ -317,7 +317,7 @@ static int pdo_mysql_stmt_execute(pdo_stmt_t *stmt) /* {{{ */
PDO_DBG_RETURN(pdo_mysql_stmt_execute_prepared(stmt)); PDO_DBG_RETURN(pdo_mysql_stmt_execute_prepared(stmt));
} }
if (mysql_real_query(H->server, stmt->active_query_string, stmt->active_query_stringlen) != 0) { if (mysql_real_query(H->server, ZSTR_VAL(stmt->active_query_string), ZSTR_LEN(stmt->active_query_string)) != 0) {
pdo_mysql_error_stmt(stmt); pdo_mysql_error_stmt(stmt);
PDO_DBG_RETURN(0); PDO_DBG_RETURN(0);
} }

View file

@ -238,13 +238,12 @@ static int oci_handle_closer(pdo_dbh_t *dbh) /* {{{ */
} }
/* }}} */ /* }}} */
static int oci_handle_preparer(pdo_dbh_t *dbh, const char *sql, size_t sql_len, pdo_stmt_t *stmt, zval *driver_options) /* {{{ */ static int oci_handle_preparer(pdo_dbh_t *dbh, zend_string *sql, pdo_stmt_t *stmt, zval *driver_options) /* {{{ */
{ {
pdo_oci_db_handle *H = (pdo_oci_db_handle *)dbh->driver_data; pdo_oci_db_handle *H = (pdo_oci_db_handle *)dbh->driver_data;
pdo_oci_stmt *S = ecalloc(1, sizeof(*S)); pdo_oci_stmt *S = ecalloc(1, sizeof(*S));
ub4 prefetch; ub4 prefetch;
char *nsql = NULL; zend_string *nsql = NULL;
size_t nsql_len = 0;
int ret; int ret;
#ifdef HAVE_OCISTMTFETCH2 #ifdef HAVE_OCISTMTFETCH2
@ -257,12 +256,11 @@ static int oci_handle_preparer(pdo_dbh_t *dbh, const char *sql, size_t sql_len,
S->H = H; S->H = H;
stmt->supports_placeholders = PDO_PLACEHOLDER_NAMED; stmt->supports_placeholders = PDO_PLACEHOLDER_NAMED;
ret = pdo_parse_params(stmt, (char*)sql, sql_len, &nsql, &nsql_len); ret = pdo_parse_params(stmt, sql, &nsql);
if (ret == 1) { if (ret == 1) {
/* query was re-written */ /* query was re-written */
sql = nsql; sql = nsql;
sql_len = nsql_len;
} else if (ret == -1) { } else if (ret == -1) {
/* couldn't grok it */ /* couldn't grok it */
strcpy(dbh->error_code, stmt->error_code); strcpy(dbh->error_code, stmt->error_code);
@ -276,10 +274,10 @@ static int oci_handle_preparer(pdo_dbh_t *dbh, const char *sql, size_t sql_len,
/* and our own private error handle */ /* and our own private error handle */
OCIHandleAlloc(H->env, (dvoid*)&S->err, OCI_HTYPE_ERROR, 0, NULL); OCIHandleAlloc(H->env, (dvoid*)&S->err, OCI_HTYPE_ERROR, 0, NULL);
if (sql_len) { if (ZSTR_LEN(sql) != 0) {
H->last_err = OCIStmtPrepare(S->stmt, H->err, (text*)sql, (ub4) sql_len, OCI_NTV_SYNTAX, OCI_DEFAULT); H->last_err = OCIStmtPrepare(S->stmt, H->err, (text*) ZSTR_VAL(sql), (ub4) ZSTR_LEN(sql), OCI_NTV_SYNTAX, OCI_DEFAULT);
if (nsql) { if (nsql) {
efree(nsql); zend_string_release(nsql);
nsql = NULL; nsql = NULL;
} }
if (H->last_err) { if (H->last_err) {
@ -304,7 +302,7 @@ static int oci_handle_preparer(pdo_dbh_t *dbh, const char *sql, size_t sql_len,
stmt->driver_data = S; stmt->driver_data = S;
stmt->methods = &oci_stmt_methods; stmt->methods = &oci_stmt_methods;
if (nsql) { if (nsql) {
efree(nsql); zend_string_release(nsql);
nsql = NULL; nsql = NULL;
} }

View file

@ -138,15 +138,14 @@ static int odbc_handle_closer(pdo_dbh_t *dbh)
return 0; return 0;
} }
static int odbc_handle_preparer(pdo_dbh_t *dbh, const char *sql, size_t sql_len, pdo_stmt_t *stmt, zval *driver_options) static int odbc_handle_preparer(pdo_dbh_t *dbh, zend_string *sql, pdo_stmt_t *stmt, zval *driver_options)
{ {
RETCODE rc; RETCODE rc;
pdo_odbc_db_handle *H = (pdo_odbc_db_handle *)dbh->driver_data; pdo_odbc_db_handle *H = (pdo_odbc_db_handle *)dbh->driver_data;
pdo_odbc_stmt *S = ecalloc(1, sizeof(*S)); pdo_odbc_stmt *S = ecalloc(1, sizeof(*S));
enum pdo_cursor_type cursor_type = PDO_CURSOR_FWDONLY; enum pdo_cursor_type cursor_type = PDO_CURSOR_FWDONLY;
int ret; int ret;
char *nsql = NULL; zend_string *nsql = NULL;
size_t nsql_len = 0;
S->H = H; S->H = H;
S->assume_utf8 = H->assume_utf8; S->assume_utf8 = H->assume_utf8;
@ -154,7 +153,7 @@ static int odbc_handle_preparer(pdo_dbh_t *dbh, const char *sql, size_t sql_len,
/* before we prepare, we need to peek at the query; if it uses named parameters, /* before we prepare, we need to peek at the query; if it uses named parameters,
* we want PDO to rewrite them for us */ * we want PDO to rewrite them for us */
stmt->supports_placeholders = PDO_PLACEHOLDER_POSITIONAL; stmt->supports_placeholders = PDO_PLACEHOLDER_POSITIONAL;
ret = pdo_parse_params(stmt, (char*)sql, sql_len, &nsql, &nsql_len); ret = pdo_parse_params(stmt, sql, &nsql);
if (ret == 1) { if (ret == 1) {
/* query was re-written */ /* query was re-written */
@ -171,7 +170,7 @@ static int odbc_handle_preparer(pdo_dbh_t *dbh, const char *sql, size_t sql_len,
if (rc == SQL_INVALID_HANDLE || rc == SQL_ERROR) { if (rc == SQL_INVALID_HANDLE || rc == SQL_ERROR) {
efree(S); efree(S);
if (nsql) { if (nsql) {
efree(nsql); zend_string_release(nsql);
} }
pdo_odbc_drv_error("SQLAllocStmt"); pdo_odbc_drv_error("SQLAllocStmt");
return 0; return 0;
@ -186,15 +185,15 @@ static int odbc_handle_preparer(pdo_dbh_t *dbh, const char *sql, size_t sql_len,
pdo_odbc_stmt_error("SQLSetStmtAttr: SQL_ATTR_CURSOR_SCROLLABLE"); pdo_odbc_stmt_error("SQLSetStmtAttr: SQL_ATTR_CURSOR_SCROLLABLE");
SQLFreeHandle(SQL_HANDLE_STMT, S->stmt); SQLFreeHandle(SQL_HANDLE_STMT, S->stmt);
if (nsql) { if (nsql) {
efree(nsql); zend_string_release(nsql);
} }
return 0; return 0;
} }
} }
rc = SQLPrepare(S->stmt, (SQLCHAR *) sql, SQL_NTS); rc = SQLPrepare(S->stmt, (SQLCHAR *) ZSTR_VAL(sql), SQL_NTS);
if (nsql) { if (nsql) {
efree(nsql); zend_string_release(nsql);
} }
stmt->methods = &odbc_stmt_methods; stmt->methods = &odbc_stmt_methods;

View file

@ -222,14 +222,13 @@ static int pgsql_handle_closer(pdo_dbh_t *dbh) /* {{{ */
} }
/* }}} */ /* }}} */
static int pgsql_handle_preparer(pdo_dbh_t *dbh, const char *sql, size_t sql_len, pdo_stmt_t *stmt, zval *driver_options) static int pgsql_handle_preparer(pdo_dbh_t *dbh, zend_string *sql, pdo_stmt_t *stmt, zval *driver_options)
{ {
pdo_pgsql_db_handle *H = (pdo_pgsql_db_handle *)dbh->driver_data; pdo_pgsql_db_handle *H = (pdo_pgsql_db_handle *)dbh->driver_data;
pdo_pgsql_stmt *S = ecalloc(1, sizeof(pdo_pgsql_stmt)); pdo_pgsql_stmt *S = ecalloc(1, sizeof(pdo_pgsql_stmt));
int scrollable; int scrollable;
int ret; int ret;
char *nsql = NULL; zend_string *nsql = NULL;
size_t nsql_len = 0;
int emulate = 0; int emulate = 0;
int execute_only = 0; int execute_only = 0;
@ -269,7 +268,7 @@ static int pgsql_handle_preparer(pdo_dbh_t *dbh, const char *sql, size_t sql_len
stmt->named_rewrite_template = "$%d"; stmt->named_rewrite_template = "$%d";
} }
ret = pdo_parse_params(stmt, (char*)sql, sql_len, &nsql, &nsql_len); ret = pdo_parse_params(stmt, sql, &nsql);
if (ret == -1) { if (ret == -1) {
/* couldn't grok it */ /* couldn't grok it */
@ -279,7 +278,7 @@ static int pgsql_handle_preparer(pdo_dbh_t *dbh, const char *sql, size_t sql_len
/* query was re-written */ /* query was re-written */
S->query = nsql; S->query = nsql;
} else { } else {
S->query = estrdup(sql); S->query = zend_string_copy(sql);
} }
if (!emulate && !execute_only) { if (!emulate && !execute_only) {

View file

@ -100,7 +100,7 @@ static int pgsql_stmt_dtor(pdo_stmt_t *stmt)
S->param_types = NULL; S->param_types = NULL;
} }
if (S->query) { if (S->query) {
efree(S->query); zend_string_release(S->query);
S->query = NULL; S->query = NULL;
} }
@ -151,7 +151,7 @@ static int pgsql_stmt_execute(pdo_stmt_t *stmt)
efree(q); efree(q);
} }
spprintf(&q, 0, "DECLARE %s SCROLL CURSOR WITH HOLD FOR %s", S->cursor_name, stmt->active_query_string); spprintf(&q, 0, "DECLARE %s SCROLL CURSOR WITH HOLD FOR %s", S->cursor_name, ZSTR_VAL(stmt->active_query_string));
S->result = PQexec(H->server, q); S->result = PQexec(H->server, q);
efree(q); efree(q);
@ -177,7 +177,7 @@ static int pgsql_stmt_execute(pdo_stmt_t *stmt)
stmt_retry: stmt_retry:
/* we deferred the prepare until now, because we didn't /* we deferred the prepare until now, because we didn't
* know anything about the parameter types; now we do */ * know anything about the parameter types; now we do */
S->result = PQprepare(H->server, S->stmt_name, S->query, S->result = PQprepare(H->server, S->stmt_name, ZSTR_VAL(S->query),
stmt->bound_params ? zend_hash_num_elements(stmt->bound_params) : 0, stmt->bound_params ? zend_hash_num_elements(stmt->bound_params) : 0,
S->param_types); S->param_types);
status = PQresultStatus(S->result); status = PQresultStatus(S->result);
@ -222,7 +222,7 @@ stmt_retry:
0); 0);
} else if (stmt->supports_placeholders == PDO_PLACEHOLDER_NAMED) { } else if (stmt->supports_placeholders == PDO_PLACEHOLDER_NAMED) {
/* execute query with parameters */ /* execute query with parameters */
S->result = PQexecParams(H->server, S->query, S->result = PQexecParams(H->server, ZSTR_VAL(S->query),
stmt->bound_params ? zend_hash_num_elements(stmt->bound_params) : 0, stmt->bound_params ? zend_hash_num_elements(stmt->bound_params) : 0,
S->param_types, S->param_types,
(const char**)S->param_values, (const char**)S->param_values,
@ -231,7 +231,7 @@ stmt_retry:
0); 0);
} else { } else {
/* execute plain query (with embedded parameters) */ /* execute plain query (with embedded parameters) */
S->result = PQexec(H->server, stmt->active_query_string); S->result = PQexec(H->server, ZSTR_VAL(stmt->active_query_string));
} }
status = PQresultStatus(S->result); status = PQresultStatus(S->result);

View file

@ -60,7 +60,7 @@ typedef struct {
pdo_pgsql_column *cols; pdo_pgsql_column *cols;
char *cursor_name; char *cursor_name;
char *stmt_name; char *stmt_name;
char *query; zend_string *query;
char **param_values; char **param_values;
int *param_lengths; int *param_lengths;
int *param_formats; int *param_formats;

View file

@ -175,7 +175,7 @@ static int sqlite_handle_closer(pdo_dbh_t *dbh) /* {{{ */
} }
/* }}} */ /* }}} */
static int sqlite_handle_preparer(pdo_dbh_t *dbh, const char *sql, size_t sql_len, pdo_stmt_t *stmt, zval *driver_options) static int sqlite_handle_preparer(pdo_dbh_t *dbh, zend_string *sql, pdo_stmt_t *stmt, zval *driver_options)
{ {
pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data; pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
pdo_sqlite_stmt *S = ecalloc(1, sizeof(pdo_sqlite_stmt)); pdo_sqlite_stmt *S = ecalloc(1, sizeof(pdo_sqlite_stmt));
@ -193,7 +193,7 @@ static int sqlite_handle_preparer(pdo_dbh_t *dbh, const char *sql, size_t sql_le
return 0; return 0;
} }
i = sqlite3_prepare_v2(H->db, sql, sql_len, &S->stmt, &tail); i = sqlite3_prepare_v2(H->db, ZSTR_VAL(sql), ZSTR_LEN(sql), &S->stmt, &tail);
if (i == SQLITE_OK) { if (i == SQLITE_OK) {
return 1; return 1;
} }