From ccfd9cd744c700dfc26f73ae47036fb5ad780b4a Mon Sep 17 00:00:00 2001 From: Andrey Hristov Date: Fri, 12 Mar 2010 13:03:46 +0000 Subject: [PATCH] allow persistency of PS --- ext/mysqli/mysqli_api.c | 8 +- ext/mysqlnd/mysqlnd.c | 6 +- ext/mysqlnd/mysqlnd.h | 24 +++-- ext/mysqlnd/mysqlnd_ps.c | 142 ++++++++++++++--------------- ext/mysqlnd/mysqlnd_result.c | 19 ++-- ext/mysqlnd/mysqlnd_result.h | 4 +- ext/mysqlnd/mysqlnd_result_meta.c | 29 +++--- ext/mysqlnd/mysqlnd_result_meta.h | 2 +- ext/mysqlnd/mysqlnd_structs.h | 24 +++-- ext/mysqlnd/mysqlnd_wireprotocol.c | 7 +- ext/mysqlnd/mysqlnd_wireprotocol.h | 1 + 11 files changed, 137 insertions(+), 129 deletions(-) diff --git a/ext/mysqli/mysqli_api.c b/ext/mysqli/mysqli_api.c index 5c9cd6e0a29..f156346990d 100644 --- a/ext/mysqli/mysqli_api.c +++ b/ext/mysqli/mysqli_api.c @@ -166,7 +166,7 @@ int mysqli_stmt_bind_param_do_bind(MY_STMT *stmt, unsigned int argc, unsigned in if (argc == start) { return PASS; } - params = safe_emalloc(argc - start, sizeof(MYSQLND_PARAM_BIND), 0); + params = mysqlnd_stmt_alloc_param_bind(stmt->stmt); for (i = 0; i < (argc - start); i++) { zend_uchar type; switch (types[i]) { @@ -190,7 +190,7 @@ int mysqli_stmt_bind_param_do_bind(MY_STMT *stmt, unsigned int argc, unsigned in /* We count parameters from 1 */ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Undefined fieldtype %c (parameter %d)", types[i], i + start + 1); ret = FAIL; - efree(params); + mysqlnd_stmt_free_param_bind(stmt->stmt, params); goto end; } params[i].zv = *(args[i + start]); @@ -452,9 +452,7 @@ static int mysqli_stmt_bind_result_do_bind(MY_STMT *stmt, zval ***args, unsigned int argc, unsigned int start TSRMLS_DC) { unsigned int i; - MYSQLND_RESULT_BIND *params; - - params = safe_emalloc(argc - start, sizeof(MYSQLND_RESULT_BIND), 0); + MYSQLND_RESULT_BIND * params = mysqlnd_stmt_alloc_result_bind(stmt->stmt); for (i = 0; i < (argc - start); i++) { params[i].zv = *(args[i + start]); } diff --git a/ext/mysqlnd/mysqlnd.c b/ext/mysqlnd/mysqlnd.c index 7940cead3a6..3a31a1d7e60 100644 --- a/ext/mysqlnd/mysqlnd.c +++ b/ext/mysqlnd/mysqlnd.c @@ -142,8 +142,8 @@ MYSQLND_METHOD(mysqlnd_conn, free_contents)(MYSQLND *conn TSRMLS_DC) mysqlnd_local_infile_default(conn); if (conn->current_result) { - conn->current_result->m.free_result_contents(conn->current_result TSRMLS_CC); - mnd_efree(conn->current_result); + conn->current_result->m.free_result(conn->current_result, TRUE TSRMLS_CC); +// mnd_pefree(conn->current_result, conn->current_result->persistent); conn->current_result = NULL; } @@ -1089,7 +1089,7 @@ MYSQLND_METHOD(mysqlnd_conn, list_fields)(MYSQLND *conn, const char *table, cons Prepare for the worst case. MyISAM goes to 2500 BIT columns, double it for safety. */ - result = mysqlnd_result_init(5000 TSRMLS_CC); + result = mysqlnd_result_init(5000, conn->persistent TSRMLS_CC); if (FAIL == result->m.read_result_metadata(result, conn TSRMLS_CC)) { diff --git a/ext/mysqlnd/mysqlnd.h b/ext/mysqlnd/mysqlnd.h index c3b2f6bf4de..b372d95cad5 100644 --- a/ext/mysqlnd/mysqlnd.h +++ b/ext/mysqlnd/mysqlnd.h @@ -242,6 +242,8 @@ PHPAPI unsigned int mysqlnd_get_client_version(); PHPAPI void mysqlnd_efree_param_bind_dtor(MYSQLND_PARAM_BIND * param_bind TSRMLS_DC); PHPAPI void mysqlnd_efree_result_bind_dtor(MYSQLND_RESULT_BIND * result_bind TSRMLS_DC); +PHPAPI void mysqlnd_free_param_bind_dtor(MYSQLND_PARAM_BIND * param_bind TSRMLS_DC); +PHPAPI void mysqlnd_free_result_bind_dtor(MYSQLND_RESULT_BIND * result_bind TSRMLS_DC); PHPAPI const char * mysqlnd_field_type_name(enum mysqlnd_field_types field_type); @@ -288,16 +290,18 @@ PHPAPI ulong mysqlnd_old_escape_string(char *newstr, const char *escapestr, size #define mysqlnd_stmt_data_seek(stmt, row) (stmt)->m->seek_data((stmt), (row) TSRMLS_CC) #define mysqlnd_stmt_prepare(stmt, q, qlen) (stmt)->m->prepare((stmt), (q), (qlen) TSRMLS_CC) #define mysqlnd_stmt_execute(stmt) (stmt)->m->execute((stmt) TSRMLS_CC) -#define mysqlnd_stmt_send_long_data(s,p,d,l) (s)->m->send_long_data((s), (p), (d), (l) TSRMLS_CC) -#define mysqlnd_stmt_bind_param(stmt,bind) (stmt)->m->bind_parameters((stmt), (bind) TSRMLS_CC) -#define mysqlnd_stmt_bind_one_param(s,n,z,t) (s)->m->bind_one_parameter((s), (n), (z), (t) TSRMLS_CC) -#define mysqlnd_stmt_refresh_bind_param(s) (s)->m->refresh_bind_param((s) TSRMLS_CC) -#define mysqlnd_stmt_set_param_bind_dtor(s,d) (s)->m->set_param_bind_dtor((s), (d) TSRMLS_CC) -#define mysqlnd_stmt_bind_result(stmt,bind) (stmt)->m->bind_result((stmt), (bind) TSRMLS_CC) -#define mysqlnd_stmt_bind_one_result(s,no) (s)->m->bind_one_result((s), (no) TSRMLS_CC) -#define mysqlnd_stmt_set_result_bind_dtor(s,d) (s)->m->set_result_bind_dtor((s), (d) TSRMLS_CC) -#define mysqlnd_stmt_param_metadata(stmt) (stmt)->m->get_parameter_metadata((stmt)) -#define mysqlnd_stmt_result_metadata(stmt) (stmt)->m->get_result_metadata((stmt) TSRMLS_CC) +#define mysqlnd_stmt_send_long_data(stmt,p,d,l) (stmt)->m->send_long_data((stmt), (p), (d), (l) TSRMLS_CC) +#define mysqlnd_stmt_alloc_param_bind(stmt) (stmt)->m->alloc_parameter_bind((stmt) TSRMLS_CC) +#define mysqlnd_stmt_free_param_bind(stmt,bind) (stmt)->m->free_parameter_bind((stmt), (bind) TSRMLS_CC) +#define mysqlnd_stmt_bind_param(stmt,bind) (stmt)->m->bind_parameters((stmt), (bind) TSRMLS_CC) +#define mysqlnd_stmt_bind_one_param(stmt,n,z,t) (stmt)->m->bind_one_parameter((stmt), (n), (z), (t) TSRMLS_CC) +#define mysqlnd_stmt_refresh_bind_param(s) (s)->m->refresh_bind_param((s) TSRMLS_CC) +#define mysqlnd_stmt_alloc_result_bind(stmt) (stmt)->m->alloc_result_bind((stmt) TSRMLS_CC) +#define mysqlnd_stmt_free_result_bind(stmt,bind) (stmt)->m->free_result_bind((stmt), (bind) TSRMLS_CC) +#define mysqlnd_stmt_bind_result(stmt,bind) (stmt)->m->bind_result((stmt), (bind) TSRMLS_CC) +#define mysqlnd_stmt_bind_one_result(s,no) (s)->m->bind_one_result((s), (no) TSRMLS_CC) +#define mysqlnd_stmt_param_metadata(stmt) (stmt)->m->get_parameter_metadata((stmt)) +#define mysqlnd_stmt_result_metadata(stmt) (stmt)->m->get_result_metadata((stmt) TSRMLS_CC) #define mysqlnd_stmt_free_result(stmt) (stmt)->m->free_result((stmt) TSRMLS_CC) #define mysqlnd_stmt_close(stmt, implicit) (stmt)->m->dtor((stmt), (implicit) TSRMLS_CC) diff --git a/ext/mysqlnd/mysqlnd_ps.c b/ext/mysqlnd/mysqlnd_ps.c index a22aaa3dcae..4401c3d5d17 100644 --- a/ext/mysqlnd/mysqlnd_ps.c +++ b/ext/mysqlnd/mysqlnd_ps.c @@ -154,7 +154,7 @@ MYSQLND_METHOD(mysqlnd_stmt, get_result)(MYSQLND_STMT * const stmt TSRMLS_DC) SET_EMPTY_ERROR(stmt->conn->error_info); MYSQLND_INC_CONN_STATISTIC(conn->stats, STAT_BUFFERED_SETS); - result = mysqlnd_result_init(stmt->result->field_count TSRMLS_CC); + result = mysqlnd_result_init(stmt->result->field_count, stmt->persistent TSRMLS_CC); result->meta = stmt->result->meta->m->clone_metadata(stmt->result->meta, FALSE TSRMLS_CC); @@ -335,9 +335,9 @@ MYSQLND_METHOD(mysqlnd_stmt, prepare)(MYSQLND_STMT * const stmt, const char * co stmt_to_prepare = mysqlnd_stmt_init(stmt->conn); } - if (FAIL == stmt_to_prepare->conn->m->simple_command(stmt_to_prepare->conn, COM_STMT_PREPARE, query, - query_len, PROT_LAST, FALSE, TRUE TSRMLS_CC) || - FAIL == mysqlnd_stmt_read_prepare_response(stmt_to_prepare TSRMLS_CC)) { + if (FAIL == stmt_to_prepare->conn->m->simple_command(stmt_to_prepare->conn, COM_STMT_PREPARE, query, query_len, PROT_LAST, FALSE, TRUE TSRMLS_CC) || + FAIL == mysqlnd_stmt_read_prepare_response(stmt_to_prepare TSRMLS_CC)) + { goto fail; } @@ -355,7 +355,7 @@ MYSQLND_METHOD(mysqlnd_stmt, prepare)(MYSQLND_STMT * const stmt, const char * co no metadata at prepare. */ if (stmt_to_prepare->field_count) { - MYSQLND_RES *result = mysqlnd_result_init(stmt_to_prepare->field_count TSRMLS_CC); + MYSQLND_RES * result = mysqlnd_result_init(stmt_to_prepare->field_count, stmt_to_prepare->persistent TSRMLS_CC); /* Allocate the result now as it is needed for the reading of metadata */ stmt_to_prepare->result = result; @@ -376,7 +376,7 @@ MYSQLND_METHOD(mysqlnd_stmt, prepare)(MYSQLND_STMT * const stmt, const char * co memcpy(stmt, stmt_to_prepare, sizeof(MYSQLND_STMT)); /* Now we will have a clean new statement object */ - mnd_efree(stmt_to_prepare); + mnd_pefree(stmt_to_prepare, stmt_to_prepare->persistent); } stmt->state = MYSQLND_STMT_PREPARED; DBG_INF("PASS"); @@ -1248,8 +1248,8 @@ MYSQLND_METHOD(mysqlnd_stmt, bind_parameters)(MYSQLND_STMT * const stmt, MYSQLND if (stmt->state < MYSQLND_STMT_PREPARED) { SET_STMT_ERROR(stmt, CR_NO_PREPARE_STMT, UNKNOWN_SQLSTATE, mysqlnd_stmt_not_prepared); DBG_ERR("not prepared"); - if (param_bind && stmt->param_bind_dtor) { - stmt->param_bind_dtor(param_bind TSRMLS_CC); + if (param_bind) { + stmt->m->free_parameter_bind(stmt, param_bind TSRMLS_CC); } DBG_RETURN(FAIL); } @@ -1281,8 +1281,8 @@ MYSQLND_METHOD(mysqlnd_stmt, bind_parameters)(MYSQLND_STMT * const stmt, MYSQLND zval_ptr_dtor(&stmt->param_bind[i].zv); } } - if (stmt->param_bind != param_bind && stmt->param_bind_dtor) { - stmt->param_bind_dtor(stmt->param_bind TSRMLS_CC); + if (stmt->param_bind != param_bind) { + stmt->m->free_parameter_bind(stmt, stmt->param_bind TSRMLS_CC); } } @@ -1382,19 +1382,6 @@ MYSQLND_METHOD(mysqlnd_stmt, refresh_bind_param)(MYSQLND_STMT * const stmt TSRML /* }}} */ -/* {{{ mysqlnd_stmt::set_bind_param_dtor */ -static void -MYSQLND_METHOD(mysqlnd_stmt, set_param_bind_dtor)(MYSQLND_STMT * const stmt, - void (*param_bind_dtor)(MYSQLND_PARAM_BIND * dtor TSRMLS_DC) TSRMLS_DC) -{ - DBG_ENTER("mysqlnd_stmt::set_bind_param_dtor"); - DBG_INF_FMT("stmt=%p", param_bind_dtor); - stmt->param_bind_dtor = param_bind_dtor; - DBG_VOID_RETURN; -} -/* }}} */ - - /* {{{ mysqlnd_stmt::bind_result */ static enum_func_status MYSQLND_METHOD(mysqlnd_stmt, bind_result)(MYSQLND_STMT * const stmt, @@ -1406,8 +1393,8 @@ MYSQLND_METHOD(mysqlnd_stmt, bind_result)(MYSQLND_STMT * const stmt, if (stmt->state < MYSQLND_STMT_PREPARED) { SET_STMT_ERROR(stmt, CR_NO_PREPARE_STMT, UNKNOWN_SQLSTATE, mysqlnd_stmt_not_prepared); - if (result_bind && stmt->result_bind_dtor) { - stmt->result_bind_dtor(result_bind TSRMLS_CC); + if (result_bind) { + stmt->m->free_result_bind(stmt, result_bind TSRMLS_CC); } DBG_ERR("not prepared"); DBG_RETURN(FAIL); @@ -1438,8 +1425,8 @@ MYSQLND_METHOD(mysqlnd_stmt, bind_result)(MYSQLND_STMT * const stmt, */ stmt->result_bind[i].bound = TRUE; } - } else if (result_bind && stmt->result_bind_dtor) { - stmt->result_bind_dtor(result_bind TSRMLS_CC); + } else if (result_bind) { + stmt->m->free_result_bind(stmt, result_bind TSRMLS_CC); } DBG_INF("PASS"); DBG_RETURN(PASS); @@ -1491,19 +1478,6 @@ MYSQLND_METHOD(mysqlnd_stmt, bind_one_result)(MYSQLND_STMT * const stmt, unsigne /* }}} */ -/* {{{ mysqlnd_stmt::set_bind_result_dtor */ -static void -MYSQLND_METHOD(mysqlnd_stmt, set_result_bind_dtor)(MYSQLND_STMT * const stmt, - void (*result_bind_dtor)(MYSQLND_RESULT_BIND * dtor TSRMLS_DC) TSRMLS_DC) -{ - DBG_ENTER("mysqlnd_stmt::set_bind_param_dtor"); - DBG_INF_FMT("stmt=%p", result_bind_dtor); - stmt->result_bind_dtor = result_bind_dtor; - DBG_VOID_RETURN; -} -/* }}} */ - - /* {{{ mysqlnd_stmt::insert_id */ static uint64_t MYSQLND_METHOD(mysqlnd_stmt, insert_id)(const MYSQLND_STMT * const stmt TSRMLS_DC) @@ -1634,7 +1608,7 @@ MYSQLND_METHOD(mysqlnd_stmt, result_metadata)(MYSQLND_STMT * const stmt TSRMLS_D In the meantime we don't need a zval cache reference for this fake result set, so we don't get one. */ - result = mysqlnd_result_init(stmt->field_count TSRMLS_CC); + result = mysqlnd_result_init(stmt->field_count, stmt->persistent TSRMLS_CC); result->type = MYSQLND_RES_NORMAL; result->m.fetch_row = result->m.fetch_row_normal_unbuffered; result->unbuf = mnd_ecalloc(1, sizeof(MYSQLND_RES_UNBUFFERED)); @@ -1817,9 +1791,7 @@ void mysqlnd_stmt_separate_result_bind(MYSQLND_STMT * const stmt TSRMLS_DC) } } } - if (stmt->result_bind_dtor) { - stmt->result_bind_dtor(stmt->result_bind TSRMLS_CC); - } + stmt->m->free_result_bind(stmt, stmt->result_bind TSRMLS_CC); stmt->result_bind = NULL; DBG_VOID_RETURN; @@ -1898,9 +1870,7 @@ void mysqlnd_internal_free_stmt_content(MYSQLND_STMT * const stmt TSRMLS_DC) zval_ptr_dtor(&stmt->param_bind[i].zv); } } - if (stmt->param_bind_dtor) { - stmt->param_bind_dtor(stmt->param_bind TSRMLS_CC); - } + stmt->m->free_parameter_bind(stmt, stmt->param_bind TSRMLS_CC); stmt->param_bind = NULL; } @@ -1985,7 +1955,7 @@ MYSQLND_METHOD_PRIVATE(mysqlnd_stmt, net_close)(MYSQLND_STMT * const stmt, zend_ } if (stmt->execute_cmd_buffer.buffer) { - mnd_efree(stmt->execute_cmd_buffer.buffer); + mnd_pefree(stmt->execute_cmd_buffer.buffer, stmt->persistent); stmt->execute_cmd_buffer.buffer = NULL; } @@ -2013,7 +1983,7 @@ MYSQLND_METHOD(mysqlnd_stmt, dtor)(MYSQLND_STMT * const stmt, zend_bool implicit STAT_STMT_CLOSE_EXPLICIT); ret = stmt->m->net_close(stmt, implicit TSRMLS_CC); - mnd_efree(stmt); + mnd_pefree(stmt, stmt->persistent); DBG_INF(ret == PASS? "PASS":"FAIL"); DBG_RETURN(ret); @@ -2021,6 +1991,45 @@ MYSQLND_METHOD(mysqlnd_stmt, dtor)(MYSQLND_STMT * const stmt, zend_bool implicit /* }}} */ +/* {{{ mysqlnd_stmt::alloc_param_bind */ +static MYSQLND_PARAM_BIND * +MYSQLND_METHOD(mysqlnd_stmt, alloc_param_bind)(MYSQLND_STMT * const stmt TSRMLS_DC) +{ + DBG_ENTER("mysqlnd_stmt::alloc_param_bind"); + DBG_RETURN(safe_pemalloc(stmt->param_count, sizeof(MYSQLND_PARAM_BIND), 0, stmt->persistent)); +} +/* }}} */ + + +/* {{{ mysqlnd_stmt::alloc_result_bind */ +static MYSQLND_RESULT_BIND * +MYSQLND_METHOD(mysqlnd_stmt, alloc_result_bind)(MYSQLND_STMT * const stmt TSRMLS_DC) +{ + DBG_ENTER("mysqlnd_stmt::alloc_result_bind"); + DBG_RETURN(safe_pemalloc(stmt->field_count, sizeof(MYSQLND_RESULT_BIND), 0, stmt->persistent)); +} +/* }}} */ + + +/* {{{ param_bind::free_parameter_bind */ +PHPAPI void +MYSQLND_METHOD(mysqlnd_stmt, free_parameter_bind)(MYSQLND_STMT * const stmt, MYSQLND_PARAM_BIND * param_bind TSRMLS_DC) +{ + mnd_pefree(param_bind, stmt->persistent); +} +/* }}} */ + + +/* {{{ mysqlnd_stmt::free_result_bind */ +PHPAPI void +MYSQLND_METHOD(mysqlnd_stmt, free_result_bind)(MYSQLND_STMT * const stmt, MYSQLND_RESULT_BIND * result_bind TSRMLS_DC) +{ + mnd_pefree(result_bind, stmt->persistent); +} +/* }}} */ + + + MYSQLND_CLASS_METHODS_START(mysqlnd_stmt) MYSQLND_METHOD(mysqlnd_stmt, prepare), MYSQLND_METHOD(mysqlnd_stmt, execute), @@ -2040,10 +2049,8 @@ MYSQLND_CLASS_METHODS_START(mysqlnd_stmt) MYSQLND_METHOD(mysqlnd_stmt, bind_parameters), MYSQLND_METHOD(mysqlnd_stmt, bind_one_parameter), MYSQLND_METHOD(mysqlnd_stmt, refresh_bind_param), - MYSQLND_METHOD(mysqlnd_stmt, set_param_bind_dtor), MYSQLND_METHOD(mysqlnd_stmt, bind_result), MYSQLND_METHOD(mysqlnd_stmt, bind_one_result), - MYSQLND_METHOD(mysqlnd_stmt, set_result_bind_dtor), MYSQLND_METHOD(mysqlnd_stmt, send_long_data), MYSQLND_METHOD(mysqlnd_stmt, param_metadata), MYSQLND_METHOD(mysqlnd_stmt, result_metadata), @@ -2061,7 +2068,13 @@ MYSQLND_CLASS_METHODS_START(mysqlnd_stmt) MYSQLND_METHOD(mysqlnd_stmt, sqlstate), MYSQLND_METHOD(mysqlnd_stmt, attr_get), - MYSQLND_METHOD(mysqlnd_stmt, attr_set), + MYSQLND_METHOD(mysqlnd_stmt, attr_set), + + + MYSQLND_METHOD(mysqlnd_stmt, alloc_param_bind), + MYSQLND_METHOD(mysqlnd_stmt, alloc_result_bind), + MYSQLND_METHOD(mysqlnd_stmt, free_parameter_bind), + MYSQLND_METHOD(mysqlnd_stmt, free_result_bind) MYSQLND_CLASS_METHODS_END; @@ -2069,15 +2082,16 @@ MYSQLND_CLASS_METHODS_END; MYSQLND_STMT * _mysqlnd_stmt_init(MYSQLND * const conn TSRMLS_DC) { size_t alloc_size = sizeof(MYSQLND_STMT) + mysqlnd_plugin_count() * sizeof(void *); - MYSQLND_STMT *stmt = mnd_ecalloc(1, alloc_size); + MYSQLND_STMT * stmt = mnd_pecalloc(1, alloc_size, conn->persistent); DBG_ENTER("_mysqlnd_stmt_init"); DBG_INF_FMT("stmt=%p", stmt); + stmt->persistent = conn->persistent; stmt->m = mysqlnd_stmt_methods; stmt->state = MYSQLND_STMT_INITTED; stmt->execute_cmd_buffer.length = 4096; - stmt->execute_cmd_buffer.buffer = mnd_emalloc(stmt->execute_cmd_buffer.length); + stmt->execute_cmd_buffer.buffer = mnd_pemalloc(stmt->execute_cmd_buffer.length, stmt->persistent); stmt->prefetch_rows = MYSQLND_DEFAULT_PREFETCH_ROWS; /* @@ -2086,10 +2100,6 @@ MYSQLND_STMT * _mysqlnd_stmt_init(MYSQLND * const conn TSRMLS_DC) or normal query result will close it then. */ stmt->conn = conn->m->get_reference(conn TSRMLS_CC); - - stmt->m->set_param_bind_dtor(stmt, mysqlnd_efree_param_bind_dtor TSRMLS_CC); - stmt->m->set_result_bind_dtor(stmt, mysqlnd_efree_result_bind_dtor TSRMLS_CC); - DBG_RETURN(stmt); } /* }}} */ @@ -2108,22 +2118,6 @@ PHPAPI void ** _mysqlnd_plugin_get_plugin_stmt_data(const MYSQLND_STMT * stmt, u /* }}} */ -/* {{{ mysqlnd_efree_param_bind_dtor */ -PHPAPI void -mysqlnd_efree_param_bind_dtor(MYSQLND_PARAM_BIND * param_bind TSRMLS_DC) -{ - mnd_efree(param_bind); -} -/* }}} */ - - -/* {{{ mysqlnd_efree_result_bind_dtor */ -PHPAPI void -mysqlnd_efree_result_bind_dtor(MYSQLND_RESULT_BIND * result_bind TSRMLS_DC) -{ - mnd_efree(result_bind); -} -/* }}} */ /* {{{ _mysqlnd_init_ps_subsystem */ void _mysqlnd_init_ps_subsystem() diff --git a/ext/mysqlnd/mysqlnd_result.c b/ext/mysqlnd/mysqlnd_result.c index 1c9af8472bc..3739c603263 100644 --- a/ext/mysqlnd/mysqlnd_result.c +++ b/ext/mysqlnd/mysqlnd_result.c @@ -280,7 +280,7 @@ void mysqlnd_internal_free_result_contents(MYSQLND_RES *result TSRMLS_DC) result->m.free_result_buffers(result TSRMLS_CC); if (result->meta) { - result->meta->m->free_metadata(result->meta, FALSE TSRMLS_CC); + result->meta->m->free_metadata(result->meta TSRMLS_CC); result->meta = NULL; } @@ -301,7 +301,7 @@ void mysqlnd_internal_free_result(MYSQLND_RES *result TSRMLS_DC) result->conn = NULL; } - mnd_efree(result); + mnd_pefree(result, result->persistent); DBG_VOID_RETURN; } @@ -321,11 +321,11 @@ MYSQLND_METHOD(mysqlnd_res, read_result_metadata)(MYSQLND_RES *result, MYSQLND * infrastructure! */ if (result->meta) { - result->meta->m->free_metadata(result->meta, FALSE TSRMLS_CC); + result->meta->m->free_metadata(result->meta TSRMLS_CC); result->meta = NULL; } - result->meta = mysqlnd_result_meta_init(result->field_count TSRMLS_CC); + result->meta = mysqlnd_result_meta_init(result->field_count, result->persistent TSRMLS_CC); /* 1. Read all fields metadata */ @@ -440,7 +440,7 @@ mysqlnd_query_read_result_set_header(MYSQLND *conn, MYSQLND_STMT *stmt TSRMLS_DC /* PS has already allocated it */ conn->field_count = rset_header->field_count; if (!stmt) { - result = conn->current_result = mysqlnd_result_init(rset_header->field_count TSRMLS_CC); + result = conn->current_result = mysqlnd_result_init(rset_header->field_count, conn->persistent TSRMLS_CC); } else { if (!stmt->result) { DBG_INF("This is 'SHOW'/'EXPLAIN'-like query."); @@ -449,7 +449,7 @@ mysqlnd_query_read_result_set_header(MYSQLND *conn, MYSQLND_STMT *stmt TSRMLS_DC prepared statements can't send result set metadata for these queries on prepare stage. Read it now. */ - result = stmt->result = mysqlnd_result_init(rset_header->field_count TSRMLS_CC); + result = stmt->result = mysqlnd_result_init(rset_header->field_count, stmt->persistent TSRMLS_CC); } else { /* Update result set metadata if it for some reason changed between @@ -1524,16 +1524,17 @@ MYSQLND_METHOD(mysqlnd_res, fetch_field_data)(MYSQLND_RES *result, unsigned int /* }}} */ -/* {{{ mysqlnd_result_init */ +/* {{{ mysqlnd_result_init_ex */ PHPAPI MYSQLND_RES * -mysqlnd_result_init(unsigned int field_count TSRMLS_DC) +mysqlnd_result_init(unsigned int field_count, zend_bool persistent TSRMLS_DC) { size_t alloc_size = sizeof(MYSQLND_RES) + mysqlnd_plugin_count() * sizeof(void *); - MYSQLND_RES *ret = mnd_ecalloc(1, alloc_size); + MYSQLND_RES *ret = mnd_pecalloc(1, alloc_size, persistent); DBG_ENTER("mysqlnd_result_init"); DBG_INF_FMT("field_count=%u", field_count); + ret->persistent = persistent; ret->field_count = field_count; ret->m.use_result = MYSQLND_METHOD(mysqlnd_res, use_result); diff --git a/ext/mysqlnd/mysqlnd_result.h b/ext/mysqlnd/mysqlnd_result.h index 1e9494419be..088fc697028 100644 --- a/ext/mysqlnd/mysqlnd_result.h +++ b/ext/mysqlnd/mysqlnd_result.h @@ -23,9 +23,9 @@ #ifndef MYSQLND_RESULT_H #define MYSQLND_RESULT_H -PHPAPI MYSQLND_RES * mysqlnd_result_init(unsigned int field_count TSRMLS_DC); +PHPAPI MYSQLND_RES * mysqlnd_result_init(unsigned int field_count, zend_bool persistent TSRMLS_DC); -enum_func_status mysqlnd_query_read_result_set_header(MYSQLND *conn, MYSQLND_STMT *stmt TSRMLS_DC); +enum_func_status mysqlnd_query_read_result_set_header(MYSQLND * conn, MYSQLND_STMT * stmt TSRMLS_DC); #endif /* MYSQLND_RESULT_H */ diff --git a/ext/mysqlnd/mysqlnd_result_meta.c b/ext/mysqlnd/mysqlnd_result_meta.c index 5186f6d94f9..0ceee4bac31 100644 --- a/ext/mysqlnd/mysqlnd_result_meta.c +++ b/ext/mysqlnd/mysqlnd_result_meta.c @@ -150,12 +150,13 @@ MYSQLND_METHOD(mysqlnd_res_meta, read_metadata)(MYSQLND_RES_METADATA * const met DBG_ENTER("mysqlnd_res_meta::read_metadata"); field_packet = conn->protocol->m.get_result_field_packet(conn->protocol, FALSE TSRMLS_CC); + field_packet->persistent_alloc = meta->persistent; for (;i < meta->field_count; i++) { long idx; if (meta->fields[i].root) { /* We re-read metadata for PS */ - mnd_efree(meta->fields[i].root); + mnd_pefree(meta->fields[i].root, meta->persistent); meta->fields[i].root = NULL; } @@ -260,21 +261,20 @@ MYSQLND_METHOD(mysqlnd_res_meta, read_metadata)(MYSQLND_RES_METADATA * const met /* {{{ mysqlnd_res_meta::free */ static void -MYSQLND_METHOD(mysqlnd_res_meta, free)(MYSQLND_RES_METADATA *meta, zend_bool persistent TSRMLS_DC) +MYSQLND_METHOD(mysqlnd_res_meta, free)(MYSQLND_RES_METADATA * meta TSRMLS_DC) { int i; MYSQLND_FIELD *fields; - DBG_ENTER("mysqlnd_res_meta::free"); - DBG_INF_FMT("persistent=%d", persistent); + DBG_INF_FMT("persistent=%d", meta->persistent); if ((fields = meta->fields)) { DBG_INF("Freeing fields metadata"); i = meta->field_count; while (i--) { - php_mysqlnd_free_field_metadata(fields++, persistent TSRMLS_CC); + php_mysqlnd_free_field_metadata(fields++, meta->persistent TSRMLS_CC); } - mnd_pefree(meta->fields, persistent); + mnd_pefree(meta->fields, meta->persistent); meta->fields = NULL; } @@ -284,16 +284,16 @@ MYSQLND_METHOD(mysqlnd_res_meta, free)(MYSQLND_RES_METADATA *meta, zend_bool per if (UG(unicode)) { for (i = 0; i < meta->field_count; i++) { if (meta->zend_hash_keys[i].ustr.v) { - mnd_pefree(meta->zend_hash_keys[i].ustr.v, persistent); + mnd_pefree(meta->zend_hash_keys[i].ustr.v, meta->persistent); } } } #endif - mnd_pefree(meta->zend_hash_keys, persistent); + mnd_pefree(meta->zend_hash_keys, meta->persistent); meta->zend_hash_keys = NULL; } DBG_INF("Freeing metadata structure"); - mnd_pefree(meta, persistent); + mnd_pefree(meta, meta->persistent); DBG_VOID_RETURN; } @@ -314,6 +314,7 @@ MYSQLND_METHOD(mysqlnd_res_meta, clone_metadata)(const MYSQLND_RES_METADATA * co DBG_ENTER("mysqlnd_res_meta::clone_metadata"); DBG_INF_FMT("persistent=%d", persistent); + new_meta->persistent = persistent; new_meta->zend_hash_keys = mnd_pemalloc(len, persistent); memcpy(new_meta->zend_hash_keys, meta->zend_hash_keys, len); new_meta->m = meta->m; @@ -435,16 +436,18 @@ MYSQLND_CLASS_METHODS_END; /* {{{ mysqlnd_result_meta_init */ PHPAPI MYSQLND_RES_METADATA * -mysqlnd_result_meta_init(unsigned int field_count TSRMLS_DC) +mysqlnd_result_meta_init(unsigned int field_count, zend_bool persistent TSRMLS_DC) { MYSQLND_RES_METADATA *ret; DBG_ENTER("mysqlnd_result_meta_init"); + DBG_INF_FMT("persistent=%d", persistent); /* +1 is to have empty marker at the end */ - ret = mnd_ecalloc(1, sizeof(MYSQLND_RES_METADATA)); + ret = mnd_pecalloc(1, sizeof(MYSQLND_RES_METADATA), persistent); + ret->persistent = persistent; ret->field_count = field_count; - ret->fields = mnd_ecalloc(field_count + 1, sizeof(MYSQLND_FIELD)); - ret->zend_hash_keys = mnd_ecalloc(field_count, sizeof(struct mysqlnd_field_hash_key)); + ret->fields = mnd_pecalloc(field_count + 1, sizeof(MYSQLND_FIELD), ret->persistent); + ret->zend_hash_keys = mnd_pecalloc(field_count, sizeof(struct mysqlnd_field_hash_key), ret->persistent); ret->m = & mysqlnd_mysqlnd_res_meta_methods; DBG_INF_FMT("meta=%p", ret); diff --git a/ext/mysqlnd/mysqlnd_result_meta.h b/ext/mysqlnd/mysqlnd_result_meta.h index 84e495d4c49..05d868e3a9f 100644 --- a/ext/mysqlnd/mysqlnd_result_meta.h +++ b/ext/mysqlnd/mysqlnd_result_meta.h @@ -24,7 +24,7 @@ #define MYSQLND_RESULT_META_H -PHPAPI MYSQLND_RES_METADATA * mysqlnd_result_meta_init(unsigned int field_count TSRMLS_DC); +PHPAPI MYSQLND_RES_METADATA * mysqlnd_result_meta_init(unsigned int field_count, zend_bool persistent TSRMLS_DC); diff --git a/ext/mysqlnd/mysqlnd_structs.h b/ext/mysqlnd/mysqlnd_structs.h index e9a7681b6e0..e81ad59196a 100644 --- a/ext/mysqlnd/mysqlnd_structs.h +++ b/ext/mysqlnd/mysqlnd_structs.h @@ -527,9 +527,9 @@ typedef const MYSQLND_FIELD * (*func_mysqlnd_res_meta__fetch_field)(MYSQLND_RES_ typedef const MYSQLND_FIELD * (*func_mysqlnd_res_meta__fetch_field_direct)(const MYSQLND_RES_METADATA * const meta, MYSQLND_FIELD_OFFSET fieldnr TSRMLS_DC); typedef const MYSQLND_FIELD * (*func_mysqlnd_res_meta__fetch_fields)(MYSQLND_RES_METADATA * const meta TSRMLS_DC); typedef MYSQLND_FIELD_OFFSET (*func_mysqlnd_res_meta__field_tell)(const MYSQLND_RES_METADATA * const meta TSRMLS_DC); -typedef enum_func_status (*func_mysqlnd_res_meta__read_metadata)(MYSQLND_RES_METADATA * const meta, MYSQLND *conn TSRMLS_DC); +typedef enum_func_status (*func_mysqlnd_res_meta__read_metadata)(MYSQLND_RES_METADATA * const meta, MYSQLND * conn TSRMLS_DC); typedef MYSQLND_RES_METADATA * (*func_mysqlnd_res_meta__clone_metadata)(const MYSQLND_RES_METADATA * const meta, zend_bool persistent TSRMLS_DC); -typedef void (*func_mysqlnd_res_meta__free_metadata)(MYSQLND_RES_METADATA *meta, zend_bool persistent TSRMLS_DC); +typedef void (*func_mysqlnd_res_meta__free_metadata)(MYSQLND_RES_METADATA * meta TSRMLS_DC); struct st_mysqlnd_res_meta_methods { @@ -559,10 +559,8 @@ typedef enum_func_status (*func_mysqlnd_stmt__fetch)(MYSQLND_STMT * const stmt, typedef enum_func_status (*func_mysqlnd_stmt__bind_parameters)(MYSQLND_STMT * const stmt, MYSQLND_PARAM_BIND * const param_bind TSRMLS_DC); typedef enum_func_status (*func_mysqlnd_stmt__bind_one_parameter)(MYSQLND_STMT * const stmt, unsigned int param_no, zval * const zv, zend_uchar type TSRMLS_DC); typedef enum_func_status (*func_mysqlnd_stmt__refresh_bind_param)(MYSQLND_STMT * const stmt TSRMLS_DC); -typedef void (*func_mysqlnd_stmt__set_param_bind_dtor)(MYSQLND_STMT * const stmt, void (*param_bind_dtor)(MYSQLND_PARAM_BIND * TSRMLS_DC) TSRMLS_DC); typedef enum_func_status (*func_mysqlnd_stmt__bind_result)(MYSQLND_STMT * const stmt, MYSQLND_RESULT_BIND * const result_bind TSRMLS_DC); typedef enum_func_status (*func_mysqlnd_stmt__bind_one_result)(MYSQLND_STMT * const stmt, unsigned int param_no TSRMLS_DC); -typedef void (*func_mysqlnd_stmt__set_result_bind_dtor)(MYSQLND_STMT * const stmt, void (*result_bind_dtor)(MYSQLND_RESULT_BIND * TSRMLS_DC) TSRMLS_DC); typedef enum_func_status (*func_mysqlnd_stmt__send_long_data)(MYSQLND_STMT * const stmt, unsigned int param_num, const char * const data, unsigned long length TSRMLS_DC); typedef MYSQLND_RES * (*func_mysqlnd_stmt__get_parameter_metadata)(MYSQLND_STMT * const stmt TSRMLS_DC); typedef MYSQLND_RES * (*func_mysqlnd_stmt__get_result_metadata)(MYSQLND_STMT * const stmt TSRMLS_DC); @@ -577,6 +575,10 @@ typedef const char * (*func_mysqlnd_stmt__get_error_str)(const MYSQLND_STMT * c typedef const char * (*func_mysqlnd_stmt__get_sqlstate)(const MYSQLND_STMT * const stmt TSRMLS_DC); typedef enum_func_status (*func_mysqlnd_stmt__get_attribute)(const MYSQLND_STMT * const stmt, enum mysqlnd_stmt_attr attr_type, void * const value TSRMLS_DC); typedef enum_func_status (*func_mysqlnd_stmt__set_attribute)(MYSQLND_STMT * const stmt, enum mysqlnd_stmt_attr attr_type, const void * const value TSRMLS_DC); +typedef MYSQLND_PARAM_BIND *(*func_mysqlnd_stmt__alloc_param_bind)(MYSQLND_STMT * const stmt TSRMLS_DC); +typedef MYSQLND_RESULT_BIND*(*func_mysqlnd_stmt__alloc_result_bind)(MYSQLND_STMT * const stmt TSRMLS_DC); +typedef void (*func_mysqlnd_stmt__free_parameter_bind)(MYSQLND_STMT * const stmt, MYSQLND_PARAM_BIND * TSRMLS_DC); +typedef void (*func_mysqlnd_stmt__free_result_bind)(MYSQLND_STMT * const stmt, MYSQLND_RESULT_BIND * TSRMLS_DC); struct st_mysqlnd_stmt_methods @@ -598,10 +600,8 @@ struct st_mysqlnd_stmt_methods func_mysqlnd_stmt__bind_parameters bind_parameters; func_mysqlnd_stmt__bind_one_parameter bind_one_parameter; func_mysqlnd_stmt__refresh_bind_param refresh_bind_param; - func_mysqlnd_stmt__set_param_bind_dtor set_param_bind_dtor; func_mysqlnd_stmt__bind_result bind_result; func_mysqlnd_stmt__bind_one_result bind_one_result; - func_mysqlnd_stmt__set_result_bind_dtor set_result_bind_dtor; func_mysqlnd_stmt__send_long_data send_long_data; func_mysqlnd_stmt__get_parameter_metadata get_parameter_metadata; func_mysqlnd_stmt__get_result_metadata get_result_metadata; @@ -620,6 +620,12 @@ struct st_mysqlnd_stmt_methods func_mysqlnd_stmt__get_attribute get_attribute; func_mysqlnd_stmt__set_attribute set_attribute; + + func_mysqlnd_stmt__alloc_param_bind alloc_parameter_bind; + func_mysqlnd_stmt__alloc_result_bind alloc_result_bind; + + func_mysqlnd_stmt__free_parameter_bind free_parameter_bind; + func_mysqlnd_stmt__free_result_bind free_result_bind; }; @@ -748,6 +754,7 @@ struct st_mysqlnd_result_metadata /* We need this to make fast allocs in rowp_read */ unsigned int bit_fields_count; size_t bit_fields_total_len; /* trailing \0 not counted */ + zend_bool persistent; struct st_mysqlnd_res_meta_methods *m; }; @@ -803,6 +810,7 @@ struct st_mysqlnd_res struct st_mysqlnd_packet_row * row_packet; MYSQLND_MEMORY_POOL * result_set_memory_pool; + zend_bool persistent; }; @@ -834,6 +842,7 @@ struct st_mysqlnd_stmt MYSQLND_PARAM_BIND *param_bind; MYSQLND_RESULT_BIND *result_bind; zend_bool result_zvals_separated_once; + zend_bool persistent; MYSQLND_UPSERT_STATUS upsert_status; @@ -848,9 +857,6 @@ struct st_mysqlnd_stmt MYSQLND_CMD_BUFFER execute_cmd_buffer; unsigned int execute_count;/* count how many times the stmt was executed */ - void (*param_bind_dtor)(MYSQLND_PARAM_BIND * TSRMLS_DC); - void (*result_bind_dtor)(MYSQLND_RESULT_BIND * TSRMLS_DC); - struct st_mysqlnd_stmt_methods *m; }; diff --git a/ext/mysqlnd/mysqlnd_wireprotocol.c b/ext/mysqlnd/mysqlnd_wireprotocol.c index 5710377882e..ea41a9a1377 100644 --- a/ext/mysqlnd/mysqlnd_wireprotocol.c +++ b/ext/mysqlnd/mysqlnd_wireprotocol.c @@ -929,8 +929,8 @@ php_mysqlnd_rset_field_read(void *_packet, MYSQLND *conn TSRMLS_DC) (len = php_mysqlnd_net_field_length(&p)) && len != MYSQLND_NULL_LENGTH) { - DBG_INF_FMT("Def found, length %lu", len); - meta->def = mnd_emalloc(len + 1); + DBG_INF_FMT("Def found, length %lu, persistent=%d", len, packet->persistent_alloc); + meta->def = mnd_pemalloc(len + 1, packet->persistent_alloc); memcpy(meta->def, p, len); meta->def[len] = '\0'; meta->def_length = len; @@ -943,7 +943,8 @@ php_mysqlnd_rset_field_read(void *_packet, MYSQLND *conn TSRMLS_DC) "shorter than expected", p - begin - packet->header.size); } - root_ptr = meta->root = mnd_emalloc(total_len); + DBG_INF_FMT("allocing root. persistent=%d", packet->persistent_alloc); + root_ptr = meta->root = mnd_pemalloc(total_len, packet->persistent_alloc); meta->root_len = total_len; /* Now do allocs */ if (meta->catalog && meta->catalog != mysqlnd_empty_string) { diff --git a/ext/mysqlnd/mysqlnd_wireprotocol.h b/ext/mysqlnd/mysqlnd_wireprotocol.h index beb54845ed4..6d5cdff421c 100644 --- a/ext/mysqlnd/mysqlnd_wireprotocol.h +++ b/ext/mysqlnd/mysqlnd_wireprotocol.h @@ -174,6 +174,7 @@ typedef struct st_mysqlnd_packet_res_field { /* For table definitions, empty for result sets */ zend_bool skip_parsing; zend_bool stupid_list_fields_eof; + zend_bool persistent_alloc; MYSQLND_ERROR_INFO error_info; } MYSQLND_PACKET_RES_FIELD;