diff options
Diffstat (limited to 'ext/mysqlnd/mysqlnd_ps.c')
-rw-r--r-- | ext/mysqlnd/mysqlnd_ps.c | 777 |
1 files changed, 397 insertions, 380 deletions
diff --git a/ext/mysqlnd/mysqlnd_ps.c b/ext/mysqlnd/mysqlnd_ps.c index 7053ebe8e7..432bc78ade 100644 --- a/ext/mysqlnd/mysqlnd_ps.c +++ b/ext/mysqlnd/mysqlnd_ps.c @@ -14,14 +14,15 @@ +----------------------------------------------------------------------+ | Authors: Andrey Hristov <andrey@php.net> | | Ulf Wendel <uw@php.net> | - | Georg Richter <georg@php.net> | +----------------------------------------------------------------------+ */ #include "php.h" #include "mysqlnd.h" #include "mysqlnd_wireprotocol.h" +#include "mysqlnd_connection.h" #include "mysqlnd_priv.h" +#include "mysqlnd_ps.h" #include "mysqlnd_result.h" #include "mysqlnd_result_meta.h" #include "mysqlnd_statistics.h" @@ -29,9 +30,6 @@ #include "mysqlnd_block_alloc.h" #include "mysqlnd_ext_plugin.h" -#define MYSQLND_SILENT - - const char * const mysqlnd_not_bound_as_blob = "Can't send long data for non-string/non-binary data types"; const char * const mysqlnd_stmt_not_prepared = "Statement not prepared"; @@ -40,25 +38,23 @@ enum_func_status mysqlnd_stmt_execute_generate_request(MYSQLND_STMT * const s, z enum_func_status mysqlnd_stmt_execute_batch_generate_request(MYSQLND_STMT * const s, zend_uchar ** request, size_t *request_len, zend_bool * free_buffer); static void mysqlnd_stmt_separate_result_bind(MYSQLND_STMT * const stmt); -static void mysqlnd_stmt_separate_one_result_bind(MYSQLND_STMT * const stmt, unsigned int param_no); +static void mysqlnd_stmt_separate_one_result_bind(MYSQLND_STMT * const stmt, const unsigned int param_no); /* {{{ mysqlnd_stmt::store_result */ static MYSQLND_RES * MYSQLND_METHOD(mysqlnd_stmt, store_result)(MYSQLND_STMT * const s) { - MYSQLND_STMT_DATA * stmt = s? s->data:NULL; enum_func_status ret; - MYSQLND_CONN_DATA * conn; + MYSQLND_STMT_DATA * stmt = s? s->data : NULL; + MYSQLND_CONN_DATA * conn = stmt? stmt->conn : NULL; MYSQLND_RES * result; DBG_ENTER("mysqlnd_stmt::store_result"); - if (!stmt || !stmt->conn || !stmt->result) { + if (!stmt || !conn || !stmt->result) { DBG_RETURN(NULL); } DBG_INF_FMT("stmt=%lu", stmt->stmt_id); - conn = stmt->conn; - /* be compliant with libmysql - NULL will turn */ if (!stmt->field_count) { DBG_RETURN(NULL); @@ -70,18 +66,16 @@ MYSQLND_METHOD(mysqlnd_stmt, store_result)(MYSQLND_STMT * const s) } /* Nothing to store for UPSERT/LOAD DATA*/ - if (CONN_GET_STATE(conn) != CONN_FETCHING_DATA || - stmt->state != MYSQLND_STMT_WAITING_USE_OR_STORE) + if (GET_CONNECTION_STATE(&conn->state) != CONN_FETCHING_DATA || stmt->state != MYSQLND_STMT_WAITING_USE_OR_STORE) { - SET_CLIENT_ERROR(*conn->error_info, CR_COMMANDS_OUT_OF_SYNC, - UNKNOWN_SQLSTATE, mysqlnd_out_of_sync); + SET_CLIENT_ERROR(conn->error_info, CR_COMMANDS_OUT_OF_SYNC, UNKNOWN_SQLSTATE, mysqlnd_out_of_sync); DBG_RETURN(NULL); } stmt->default_rset_handler = s->m->store_result; - SET_EMPTY_ERROR(*stmt->error_info); - SET_EMPTY_ERROR(*conn->error_info); + SET_EMPTY_ERROR(stmt->error_info); + SET_EMPTY_ERROR(conn->error_info); MYSQLND_INC_CONN_STATISTIC(conn->stats, STAT_PS_BUFFERED_SETS); result = stmt->result; @@ -90,7 +84,7 @@ MYSQLND_METHOD(mysqlnd_stmt, store_result)(MYSQLND_STMT * const s) result->stored_data = (MYSQLND_RES_BUFFERED *) mysqlnd_result_buffered_zval_init(result->field_count, TRUE, result->persistent); if (!result->stored_data) { - SET_OOM_ERROR(*conn->error_info); + SET_OOM_ERROR(conn->error_info); DBG_RETURN(NULL); } @@ -99,19 +93,18 @@ MYSQLND_METHOD(mysqlnd_stmt, store_result)(MYSQLND_STMT * const s) result->stored_data->m.fetch_row = mysqlnd_stmt_fetch_row_buffered; if (PASS == ret) { - /* Overflow ? */ if (result->stored_data->type == MYSQLND_BUFFERED_TYPE_ZVAL) { MYSQLND_RES_BUFFERED_ZVAL * set = (MYSQLND_RES_BUFFERED_ZVAL *) result->stored_data; if (result->stored_data->row_count) { /* don't try to allocate more than possible - mnd_XXalloc expects size_t, and it can have narrower range than uint64_t */ if (result->stored_data->row_count * result->meta->field_count * sizeof(zval *) > SIZE_MAX) { - SET_OOM_ERROR(*conn->error_info); + SET_OOM_ERROR(conn->error_info); DBG_RETURN(NULL); } /* if pecalloc is used valgrind barks gcc version 4.3.1 20080507 (prerelease) [gcc-4_3-branch revision 135036] (SUSE Linux) */ set->data = mnd_emalloc((size_t)(result->stored_data->row_count * result->meta->field_count * sizeof(zval))); if (!set->data) { - SET_OOM_ERROR(*conn->error_info); + SET_OOM_ERROR(conn->error_info); DBG_RETURN(NULL); } memset(set->data, 0, (size_t)(result->stored_data->row_count * result->meta->field_count * sizeof(zval))); @@ -123,11 +116,11 @@ MYSQLND_METHOD(mysqlnd_stmt, store_result)(MYSQLND_STMT * const s) } /* libmysql API docs say it should be so for SELECT statements */ - stmt->upsert_status->affected_rows = stmt->result->stored_data->row_count; + UPSERT_STATUS_SET_AFFECTED_ROWS(stmt->upsert_status, stmt->result->stored_data->row_count); stmt->state = MYSQLND_STMT_USE_OR_STORE_CALLED; } else { - COPY_CLIENT_ERROR(*conn->error_info, result->stored_data->error_info); + COPY_CLIENT_ERROR(conn->error_info, result->stored_data->error_info); stmt->result->m.free_result_contents(stmt->result); mnd_efree(stmt->result); stmt->result = NULL; @@ -143,18 +136,16 @@ MYSQLND_METHOD(mysqlnd_stmt, store_result)(MYSQLND_STMT * const s) static MYSQLND_RES * MYSQLND_METHOD(mysqlnd_stmt, get_result)(MYSQLND_STMT * const s) { - MYSQLND_STMT_DATA * stmt = s? s->data:NULL; - MYSQLND_CONN_DATA * conn; - MYSQLND_RES *result; + MYSQLND_STMT_DATA * stmt = s? s->data : NULL; + MYSQLND_CONN_DATA * conn = stmt? stmt->conn : NULL; + MYSQLND_RES * result; DBG_ENTER("mysqlnd_stmt::get_result"); - if (!stmt || !stmt->conn || !stmt->result) { + if (!stmt || !conn || !stmt->result) { DBG_RETURN(NULL); } DBG_INF_FMT("stmt=%lu", stmt->stmt_id); - conn = stmt->conn; - /* be compliant with libmysql - NULL will turn */ if (!stmt->field_count) { DBG_RETURN(NULL); @@ -166,35 +157,34 @@ MYSQLND_METHOD(mysqlnd_stmt, get_result)(MYSQLND_STMT * const s) } /* Nothing to store for UPSERT/LOAD DATA*/ - if (CONN_GET_STATE(conn) != CONN_FETCHING_DATA || stmt->state != MYSQLND_STMT_WAITING_USE_OR_STORE) { - SET_CLIENT_ERROR(*conn->error_info, CR_COMMANDS_OUT_OF_SYNC, - UNKNOWN_SQLSTATE, mysqlnd_out_of_sync); + if (GET_CONNECTION_STATE(&conn->state) != CONN_FETCHING_DATA || stmt->state != MYSQLND_STMT_WAITING_USE_OR_STORE) { + SET_CLIENT_ERROR(conn->error_info, CR_COMMANDS_OUT_OF_SYNC, UNKNOWN_SQLSTATE, mysqlnd_out_of_sync); DBG_RETURN(NULL); } - SET_EMPTY_ERROR(*stmt->error_info); - SET_EMPTY_ERROR(*conn->error_info); + SET_EMPTY_ERROR(stmt->error_info); + SET_EMPTY_ERROR(conn->error_info); MYSQLND_INC_CONN_STATISTIC(conn->stats, STAT_BUFFERED_SETS); do { result = conn->m->result_init(stmt->result->field_count, stmt->persistent); if (!result) { - SET_OOM_ERROR(*conn->error_info); + SET_OOM_ERROR(conn->error_info); break; } result->meta = stmt->result->meta->m->clone_metadata(stmt->result->meta, FALSE); if (!result->meta) { - SET_OOM_ERROR(*conn->error_info); + SET_OOM_ERROR(conn->error_info); break; } if ((result = result->m.store_result(result, conn, MYSQLND_STORE_PS | MYSQLND_STORE_NO_COPY))) { - stmt->upsert_status->affected_rows = result->stored_data->row_count; + UPSERT_STATUS_SET_AFFECTED_ROWS(stmt->upsert_status, result->stored_data->row_count); stmt->state = MYSQLND_STMT_PREPARED; result->type = MYSQLND_RES_PS_BUF; } else { - COPY_CLIENT_ERROR(*stmt->error_info, *conn->error_info); + COPY_CLIENT_ERROR(stmt->error_info, *conn->error_info); stmt->state = MYSQLND_STMT_PREPARED; break; } @@ -213,12 +203,11 @@ MYSQLND_METHOD(mysqlnd_stmt, get_result)(MYSQLND_STMT * const s) static zend_bool MYSQLND_METHOD(mysqlnd_stmt, more_results)(const MYSQLND_STMT * s) { - MYSQLND_STMT_DATA * stmt = s? s->data:NULL; + MYSQLND_STMT_DATA * stmt = s? s->data : NULL; + MYSQLND_CONN_DATA * conn = stmt? stmt->conn : NULL; DBG_ENTER("mysqlnd_stmt::more_results"); /* (conn->state == CONN_NEXT_RESULT_PENDING) too */ - DBG_RETURN((stmt && stmt->conn && (stmt->conn->m->get_server_status(stmt->conn) & SERVER_MORE_RESULTS_EXISTS))? - TRUE: - FALSE); + DBG_RETURN((stmt && conn && (conn->m->get_server_status(conn) & SERVER_MORE_RESULTS_EXISTS))? TRUE: FALSE); } /* }}} */ @@ -227,21 +216,20 @@ MYSQLND_METHOD(mysqlnd_stmt, more_results)(const MYSQLND_STMT * s) static enum_func_status MYSQLND_METHOD(mysqlnd_stmt, next_result)(MYSQLND_STMT * s) { - MYSQLND_STMT_DATA * stmt = s? s->data:NULL; - MYSQLND_CONN_DATA * conn; + MYSQLND_STMT_DATA * stmt = s? s->data : NULL; + MYSQLND_CONN_DATA * conn = stmt? stmt->conn : NULL; DBG_ENTER("mysqlnd_stmt::next_result"); - if (!stmt || !stmt->conn || !stmt->result) { + if (!stmt || !conn || !stmt->result) { DBG_RETURN(FAIL); } - conn = stmt->conn; DBG_INF_FMT("stmt=%lu", stmt->stmt_id); - if (CONN_GET_STATE(conn) != CONN_NEXT_RESULT_PENDING || !(conn->upsert_status->server_status & SERVER_MORE_RESULTS_EXISTS)) { + if (GET_CONNECTION_STATE(&conn->state) != CONN_NEXT_RESULT_PENDING || !(UPSERT_STATUS_GET_SERVER_STATUS(conn->upsert_status) & SERVER_MORE_RESULTS_EXISTS)) { DBG_RETURN(FAIL); } - DBG_INF_FMT("server_status=%u cursor=%u", stmt->upsert_status->server_status, stmt->upsert_status->server_status & SERVER_STATUS_CURSOR_EXISTS); + DBG_INF_FMT("server_status=%u cursor=%u", UPSERT_STATUS_GET_SERVER_STATUS(conn->upsert_status), UPSERT_STATUS_GET_SERVER_STATUS(conn->upsert_status) & SERVER_STATUS_CURSOR_EXISTS); /* Free space for next result */ s->m->free_stmt_result(s); @@ -257,27 +245,28 @@ MYSQLND_METHOD(mysqlnd_stmt, next_result)(MYSQLND_STMT * s) static enum_func_status mysqlnd_stmt_skip_metadata(MYSQLND_STMT * s) { - MYSQLND_STMT_DATA * stmt = s? s->data:NULL; + MYSQLND_STMT_DATA * stmt = s? s->data : NULL; + MYSQLND_CONN_DATA * conn = stmt? stmt->conn : NULL; /* Follows parameter metadata, we have just to skip it, as libmysql does */ unsigned int i = 0; enum_func_status ret = FAIL; MYSQLND_PACKET_RES_FIELD * field_packet; DBG_ENTER("mysqlnd_stmt_skip_metadata"); - if (!stmt || !stmt->conn || !stmt->conn->protocol) { + if (!stmt || !conn) { DBG_RETURN(FAIL); } DBG_INF_FMT("stmt=%lu", stmt->stmt_id); - field_packet = stmt->conn->protocol->m.get_result_field_packet(stmt->conn->protocol, FALSE); + field_packet = conn->payload_decoder_factory->m.get_result_field_packet(conn->payload_decoder_factory, FALSE); if (!field_packet) { - SET_OOM_ERROR(*stmt->error_info); - SET_OOM_ERROR(*stmt->conn->error_info); + SET_OOM_ERROR(stmt->error_info); + SET_OOM_ERROR(conn->error_info); } else { ret = PASS; field_packet->skip_parsing = TRUE; for (;i < stmt->param_count; i++) { - if (FAIL == PACKET_READ(field_packet, stmt->conn)) { + if (FAIL == PACKET_READ(field_packet)) { ret = FAIL; break; } @@ -294,38 +283,39 @@ mysqlnd_stmt_skip_metadata(MYSQLND_STMT * s) static enum_func_status mysqlnd_stmt_read_prepare_response(MYSQLND_STMT * s) { - MYSQLND_STMT_DATA * stmt = s? s->data:NULL; + MYSQLND_STMT_DATA * stmt = s? s->data : NULL; + MYSQLND_CONN_DATA * conn = stmt? stmt->conn : NULL; MYSQLND_PACKET_PREPARE_RESPONSE * prepare_resp; enum_func_status ret = FAIL; DBG_ENTER("mysqlnd_stmt_read_prepare_response"); - if (!stmt || !stmt->conn || !stmt->conn->protocol) { + if (!stmt || !conn) { DBG_RETURN(FAIL); } DBG_INF_FMT("stmt=%lu", stmt->stmt_id); - prepare_resp = stmt->conn->protocol->m.get_prepare_response_packet(stmt->conn->protocol, FALSE); + prepare_resp = conn->payload_decoder_factory->m.get_prepare_response_packet(conn->payload_decoder_factory, FALSE); if (!prepare_resp) { - SET_OOM_ERROR(*stmt->error_info); - SET_OOM_ERROR(*stmt->conn->error_info); + SET_OOM_ERROR(stmt->error_info); + SET_OOM_ERROR(conn->error_info); goto done; } - if (FAIL == PACKET_READ(prepare_resp, stmt->conn)) { + if (FAIL == PACKET_READ(prepare_resp)) { goto done; } if (0xFF == prepare_resp->error_code) { - COPY_CLIENT_ERROR(*stmt->error_info, prepare_resp->error_info); - COPY_CLIENT_ERROR(*stmt->conn->error_info, prepare_resp->error_info); + COPY_CLIENT_ERROR(stmt->error_info, prepare_resp->error_info); + COPY_CLIENT_ERROR(conn->error_info, prepare_resp->error_info); goto done; } ret = PASS; stmt->stmt_id = prepare_resp->stmt_id; - stmt->warning_count = stmt->conn->upsert_status->warning_count = prepare_resp->warning_count; - stmt->field_count = stmt->conn->field_count = prepare_resp->field_count; + UPSERT_STATUS_SET_WARNINGS(conn->upsert_status, prepare_resp->warning_count); + UPSERT_STATUS_SET_AFFECTED_ROWS(stmt->upsert_status, 0); /* be like libmysql */ + stmt->field_count = conn->field_count = prepare_resp->field_count; stmt->param_count = prepare_resp->param_count; - stmt->upsert_status->affected_rows = 0; /* be like libmysql */ done: PACKET_FREE(prepare_resp); @@ -338,31 +328,37 @@ done: static enum_func_status mysqlnd_stmt_prepare_read_eof(MYSQLND_STMT * s) { - MYSQLND_STMT_DATA * stmt = s? s->data:NULL; + MYSQLND_STMT_DATA * stmt = s? s->data : NULL; + MYSQLND_CONN_DATA * conn = stmt? stmt->conn : NULL; MYSQLND_PACKET_EOF * fields_eof; enum_func_status ret = FAIL; DBG_ENTER("mysqlnd_stmt_prepare_read_eof"); - if (!stmt || !stmt->conn || !stmt->conn->protocol) { + if (!stmt || !conn) { DBG_RETURN(FAIL); } DBG_INF_FMT("stmt=%lu", stmt->stmt_id); - fields_eof = stmt->conn->protocol->m.get_eof_packet(stmt->conn->protocol, FALSE); + fields_eof = conn->payload_decoder_factory->m.get_eof_packet(conn->payload_decoder_factory, FALSE); if (!fields_eof) { - SET_OOM_ERROR(*stmt->error_info); - SET_OOM_ERROR(*stmt->conn->error_info); + SET_OOM_ERROR(stmt->error_info); + SET_OOM_ERROR(conn->error_info); } else { - if (FAIL == (ret = PACKET_READ(fields_eof, stmt->conn))) { + if (FAIL == (ret = PACKET_READ(fields_eof))) { if (stmt->result) { stmt->result->m.free_result_contents(stmt->result); mnd_efree(stmt->result); + /* XXX: This will crash, because we will null also the methods. + But seems it happens in extreme cases or doesn't. Should be fixed by exporting a function + (from mysqlnd_driver.c?) to do the reset. + This bad handling is also in mysqlnd_result.c + */ memset(stmt, 0, sizeof(MYSQLND_STMT_DATA)); stmt->state = MYSQLND_STMT_INITTED; } } else { - stmt->upsert_status->server_status = fields_eof->server_status; - stmt->upsert_status->warning_count = fields_eof->warning_count; + UPSERT_STATUS_SET_SERVER_STATUS(stmt->upsert_status, fields_eof->server_status); + UPSERT_STATUS_SET_WARNINGS(stmt->upsert_status, fields_eof->warning_count); stmt->state = MYSQLND_STMT_PREPARED; } PACKET_FREE(fields_eof); @@ -375,24 +371,25 @@ mysqlnd_stmt_prepare_read_eof(MYSQLND_STMT * s) /* {{{ mysqlnd_stmt::prepare */ static enum_func_status -MYSQLND_METHOD(mysqlnd_stmt, prepare)(MYSQLND_STMT * const s, const char * const query, unsigned int query_len) +MYSQLND_METHOD(mysqlnd_stmt, prepare)(MYSQLND_STMT * const s, const char * const query, const size_t query_len) { - MYSQLND_STMT_DATA * stmt = s? s->data:NULL; + MYSQLND_STMT_DATA * stmt = s? s->data : NULL; + MYSQLND_CONN_DATA * conn = stmt? stmt->conn : NULL; MYSQLND_STMT * s_to_prepare = s; MYSQLND_STMT_DATA * stmt_to_prepare = stmt; DBG_ENTER("mysqlnd_stmt::prepare"); - if (!stmt || !stmt->conn) { + if (!stmt || !conn) { DBG_RETURN(FAIL); } DBG_INF_FMT("stmt=%lu", stmt->stmt_id); DBG_INF_FMT("query=%s", query); - SET_ERROR_AFF_ROWS(stmt); - SET_ERROR_AFF_ROWS(stmt->conn); + UPSERT_STATUS_SET_AFFECTED_ROWS_TO_ERROR(stmt->upsert_status); + UPSERT_STATUS_SET_AFFECTED_ROWS_TO_ERROR(conn->upsert_status); - SET_EMPTY_ERROR(*stmt->error_info); - SET_EMPTY_ERROR(*stmt->conn->error_info); + SET_EMPTY_ERROR(stmt->error_info); + SET_EMPTY_ERROR(conn->error_info); if (stmt->state > MYSQLND_STMT_INITTED) { /* See if we have to clean the wire */ @@ -409,16 +406,27 @@ MYSQLND_METHOD(mysqlnd_stmt, prepare)(MYSQLND_STMT * const s, const char * const Create a new test statement, which we will prepare, but if anything fails, we will scrap it. */ - s_to_prepare = stmt->conn->m->stmt_init(stmt->conn); + s_to_prepare = conn->m->stmt_init(conn); if (!s_to_prepare) { goto fail; } stmt_to_prepare = s_to_prepare->data; } - if (FAIL == stmt_to_prepare->conn->m->simple_command(stmt_to_prepare->conn, COM_STMT_PREPARE, (const zend_uchar *) query, query_len, PROT_LAST, FALSE, TRUE) || - FAIL == mysqlnd_stmt_read_prepare_response(s_to_prepare)) { + enum_func_status ret = FAIL; + const MYSQLND_CSTRING query_string = {query, query_len}; + struct st_mysqlnd_protocol_command * command = conn->command_factory(COM_STMT_PREPARE, conn, query_string); + if (command) { + ret = command->run(command); + command->free_command(command); + } + if (FAIL == ret) { + goto fail; + } + } + + if (FAIL == mysqlnd_stmt_read_prepare_response(s_to_prepare)) { goto fail; } @@ -436,19 +444,19 @@ MYSQLND_METHOD(mysqlnd_stmt, prepare)(MYSQLND_STMT * const s, const char * const no metadata at prepare. */ if (stmt_to_prepare->field_count) { - MYSQLND_RES * result = stmt->conn->m->result_init(stmt_to_prepare->field_count, stmt_to_prepare->persistent); + MYSQLND_RES * result = conn->m->result_init(stmt_to_prepare->field_count, stmt_to_prepare->persistent); if (!result) { - SET_OOM_ERROR(*stmt->conn->error_info); + SET_OOM_ERROR(conn->error_info); goto fail; } /* Allocate the result now as it is needed for the reading of metadata */ stmt_to_prepare->result = result; - result->conn = stmt_to_prepare->conn->m->get_reference(stmt_to_prepare->conn); + result->conn = conn->m->get_reference(conn); result->type = MYSQLND_RES_PS_BUF; - if (FAIL == result->m.read_result_metadata(result, stmt_to_prepare->conn) || + if (FAIL == result->m.read_result_metadata(result, conn) || FAIL == mysqlnd_stmt_prepare_read_eof(s_to_prepare)) { goto fail; @@ -490,23 +498,22 @@ fail: static enum_func_status mysqlnd_stmt_execute_parse_response(MYSQLND_STMT * const s, enum_mysqlnd_parse_exec_response_type type) { - MYSQLND_STMT_DATA * stmt = s? s->data:NULL; + MYSQLND_STMT_DATA * stmt = s? s->data : NULL; + MYSQLND_CONN_DATA * conn = stmt? stmt->conn : NULL; enum_func_status ret; - MYSQLND_CONN_DATA * conn; DBG_ENTER("mysqlnd_stmt_execute_parse_response"); - if (!stmt || !stmt->conn) { + if (!stmt || !conn) { DBG_RETURN(FAIL); } - conn = stmt->conn; - CONN_SET_STATE(conn, CONN_QUERY_SENT); + SET_CONNECTION_STATE(&conn->state, CONN_QUERY_SENT); - ret = mysqlnd_query_read_result_set_header(stmt->conn, s); + ret = conn->m->query_read_result_set_header(conn, s); if (ret == FAIL) { - COPY_CLIENT_ERROR(*stmt->error_info, *conn->error_info); - memset(stmt->upsert_status, 0, sizeof(*stmt->upsert_status)); - stmt->upsert_status->affected_rows = conn->upsert_status->affected_rows; - if (CONN_GET_STATE(conn) == CONN_QUIT_SENT) { + COPY_CLIENT_ERROR(stmt->error_info, *conn->error_info); + UPSERT_STATUS_RESET(stmt->upsert_status); + UPSERT_STATUS_SET_AFFECTED_ROWS(stmt->upsert_status, UPSERT_STATUS_GET_AFFECTED_ROWS(conn->upsert_status)); + if (GET_CONNECTION_STATE(&conn->state) == CONN_QUIT_SENT) { /* close the statement here, the connection has been closed */ } stmt->state = MYSQLND_STMT_PREPARED; @@ -519,9 +526,13 @@ mysqlnd_stmt_execute_parse_response(MYSQLND_STMT * const s, enum_mysqlnd_parse_e value is > LONG_MAX or < LONG_MIN, there is string conversion and we have to resend the types. Next execution will also need to resend the type. */ - SET_EMPTY_ERROR(*stmt->error_info); - SET_EMPTY_ERROR(*stmt->conn->error_info); - *stmt->upsert_status = *conn->upsert_status; /* copy status */ + SET_EMPTY_ERROR(stmt->error_info); + SET_EMPTY_ERROR(conn->error_info); + UPSERT_STATUS_SET_WARNINGS(stmt->upsert_status, UPSERT_STATUS_GET_WARNINGS(conn->upsert_status)); + UPSERT_STATUS_SET_AFFECTED_ROWS(stmt->upsert_status, UPSERT_STATUS_GET_AFFECTED_ROWS(conn->upsert_status)); + UPSERT_STATUS_SET_SERVER_STATUS(stmt->upsert_status, UPSERT_STATUS_GET_SERVER_STATUS(conn->upsert_status)); + UPSERT_STATUS_SET_LAST_INSERT_ID(stmt->upsert_status, UPSERT_STATUS_GET_LAST_INSERT_ID(conn->upsert_status)); + stmt->state = MYSQLND_STMT_EXECUTED; if (conn->last_query_type == QUERY_UPSERT || conn->last_query_type == QUERY_LOAD_LOCAL) { DBG_INF("PASS"); @@ -534,7 +545,7 @@ mysqlnd_stmt_execute_parse_response(MYSQLND_STMT * const s, enum_mysqlnd_parse_e For SHOW we don't create (bypasses PS in server) a result set at prepare and thus a connection was missing */ - stmt->result->conn = stmt->conn->m->get_reference(stmt->conn); + stmt->result->conn = conn->m->get_reference(conn); } /* Update stmt->field_count as SHOW sets it to 0 at prepare */ @@ -551,13 +562,13 @@ mysqlnd_stmt_execute_parse_response(MYSQLND_STMT * const s, enum_mysqlnd_parse_e use_result() or store_result() and we should be able to scrap the data on the line, if he just decides to close the statement. */ - DBG_INF_FMT("server_status=%u cursor=%u", stmt->upsert_status->server_status, - stmt->upsert_status->server_status & SERVER_STATUS_CURSOR_EXISTS); + DBG_INF_FMT("server_status=%u cursor=%u", UPSERT_STATUS_GET_SERVER_STATUS(stmt->upsert_status), + UPSERT_STATUS_GET_SERVER_STATUS(stmt->upsert_status) & SERVER_STATUS_CURSOR_EXISTS); - if (stmt->upsert_status->server_status & SERVER_STATUS_CURSOR_EXISTS) { + if (UPSERT_STATUS_GET_SERVER_STATUS(stmt->upsert_status) & SERVER_STATUS_CURSOR_EXISTS) { DBG_INF("cursor exists"); stmt->cursor_exists = TRUE; - CONN_SET_STATE(conn, CONN_READY); + SET_CONNECTION_STATE(&conn->state, CONN_READY); /* Only cursor read */ stmt->default_rset_handler = s->m->use_result; DBG_INF("use_result"); @@ -585,7 +596,7 @@ mysqlnd_stmt_execute_parse_response(MYSQLND_STMT * const s, enum_mysqlnd_parse_e } } #ifndef MYSQLND_DONT_SKIP_OUT_PARAMS_RESULTSET - if (stmt->upsert_status->server_status & SERVER_PS_OUT_PARAMS) { + if (UPSERT_STATUS_GET_SERVER_STATUS(stmt->upsert_status) & SERVER_PS_OUT_PARAMS) { s->m->free_stmt_content(s); DBG_INF("PS OUT Variable RSet, skipping"); /* OUT params result set. Skip for now to retain compatibility */ @@ -593,10 +604,10 @@ mysqlnd_stmt_execute_parse_response(MYSQLND_STMT * const s, enum_mysqlnd_parse_e } #endif - DBG_INF_FMT("server_status=%u cursor=%u", stmt->upsert_status->server_status, stmt->upsert_status->server_status & SERVER_STATUS_CURSOR_EXISTS); + DBG_INF_FMT("server_status=%u cursor=%u", UPSERT_STATUS_GET_SERVER_STATUS(stmt->upsert_status), UPSERT_STATUS_GET_SERVER_STATUS(stmt->upsert_status) & SERVER_STATUS_CURSOR_EXISTS); - if (ret == PASS && conn->last_query_type == QUERY_UPSERT && stmt->upsert_status->affected_rows) { - MYSQLND_INC_CONN_STATISTIC_W_VALUE(conn->stats, STAT_ROWS_AFFECTED_PS, stmt->upsert_status->affected_rows); + if (ret == PASS && conn->last_query_type == QUERY_UPSERT && UPSERT_STATUS_GET_AFFECTED_ROWS(stmt->upsert_status)) { + MYSQLND_INC_CONN_STATISTIC_W_VALUE(conn->stats, STAT_ROWS_AFFECTED_PS, UPSERT_STATUS_GET_AFFECTED_ROWS(stmt->upsert_status)); } DBG_INF(ret == PASS? "PASS":"FAIL"); @@ -622,24 +633,23 @@ MYSQLND_METHOD(mysqlnd_stmt, execute)(MYSQLND_STMT * const s) /* {{{ mysqlnd_stmt::send_execute */ static enum_func_status -MYSQLND_METHOD(mysqlnd_stmt, send_execute)(MYSQLND_STMT * const s, enum_mysqlnd_send_execute_type type, zval * read_cb, zval * err_cb) +MYSQLND_METHOD(mysqlnd_stmt, send_execute)(MYSQLND_STMT * const s, const enum_mysqlnd_send_execute_type type, zval * read_cb, zval * err_cb) { - MYSQLND_STMT_DATA * stmt = s? s->data:NULL; + MYSQLND_STMT_DATA * stmt = s? s->data : NULL; + MYSQLND_CONN_DATA * conn = stmt? stmt->conn : NULL; enum_func_status ret; - MYSQLND_CONN_DATA * conn; zend_uchar *request = NULL; size_t request_len; zend_bool free_request; DBG_ENTER("mysqlnd_stmt::send_execute"); - if (!stmt || !stmt->conn) { + if (!stmt || !conn) { DBG_RETURN(FAIL); } - conn = stmt->conn; DBG_INF_FMT("stmt=%lu", stmt->stmt_id); - SET_ERROR_AFF_ROWS(stmt); - SET_ERROR_AFF_ROWS(stmt->conn); + UPSERT_STATUS_SET_AFFECTED_ROWS_TO_ERROR(stmt->upsert_status); + UPSERT_STATUS_SET_AFFECTED_ROWS_TO_ERROR(conn->upsert_status); if (stmt->result && stmt->state >= MYSQLND_STMT_PREPARED && stmt->field_count) { /* @@ -687,9 +697,7 @@ MYSQLND_METHOD(mysqlnd_stmt, send_execute)(MYSQLND_STMT * const s, enum_mysqlnd_ stmt->state = MYSQLND_STMT_PREPARED; } else if (stmt->state < MYSQLND_STMT_PREPARED) { /* Only initted - error */ - SET_CLIENT_ERROR(*conn->error_info, CR_COMMANDS_OUT_OF_SYNC, UNKNOWN_SQLSTATE, - mysqlnd_out_of_sync); - SET_STMT_ERROR(stmt, CR_COMMANDS_OUT_OF_SYNC, UNKNOWN_SQLSTATE, mysqlnd_out_of_sync); + SET_CLIENT_ERROR(stmt->error_info, CR_COMMANDS_OUT_OF_SYNC, UNKNOWN_SQLSTATE, mysqlnd_out_of_sync); DBG_INF("FAIL"); DBG_RETURN(FAIL); } @@ -697,8 +705,7 @@ MYSQLND_METHOD(mysqlnd_stmt, send_execute)(MYSQLND_STMT * const s, enum_mysqlnd_ if (stmt->param_count) { unsigned int i, not_bound = 0; if (!stmt->param_bind) { - SET_STMT_ERROR(stmt, CR_PARAMS_NOT_BOUND, UNKNOWN_SQLSTATE, - "No data supplied for parameters in prepared statement"); + SET_CLIENT_ERROR(stmt->error_info, CR_PARAMS_NOT_BOUND, UNKNOWN_SQLSTATE, "No data supplied for parameters in prepared statement"); DBG_INF("FAIL"); DBG_RETURN(FAIL); } @@ -711,7 +718,7 @@ MYSQLND_METHOD(mysqlnd_stmt, send_execute)(MYSQLND_STMT * const s, enum_mysqlnd_ char * msg; mnd_sprintf(&msg, 0, "No data supplied for %u parameter%s in prepared statement", not_bound, not_bound>1 ?"s":""); - SET_STMT_ERROR(stmt, CR_PARAMS_NOT_BOUND, UNKNOWN_SQLSTATE, msg); + SET_CLIENT_ERROR(stmt->error_info, CR_PARAMS_NOT_BOUND, UNKNOWN_SQLSTATE, msg); if (msg) { mnd_sprintf_free(msg); } @@ -721,12 +728,15 @@ MYSQLND_METHOD(mysqlnd_stmt, send_execute)(MYSQLND_STMT * const s, enum_mysqlnd_ } ret = s->m->generate_execute_request(s, &request, &request_len, &free_request); if (ret == PASS) { - /* support for buffer types should be added here ! */ - ret = stmt->conn->m->simple_command(stmt->conn, COM_STMT_EXECUTE, request, request_len, - PROT_LAST /* we will handle the response packet*/, - FALSE, FALSE); + const MYSQLND_CSTRING payload = {(const char*) request, request_len}; + struct st_mysqlnd_protocol_command * command = conn->command_factory(COM_STMT_EXECUTE, conn, payload); + ret = FAIL; + if (command) { + ret = command->run(command); + command->free_command(command); + } } else { - SET_STMT_ERROR(stmt, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, "Couldn't generate the request. Possibly OOM."); + SET_CLIENT_ERROR(stmt->error_info, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, "Couldn't generate the request. Possibly OOM."); } if (free_request) { @@ -734,7 +744,7 @@ MYSQLND_METHOD(mysqlnd_stmt, send_execute)(MYSQLND_STMT * const s, enum_mysqlnd_ } if (ret == FAIL) { - COPY_CLIENT_ERROR(*stmt->error_info, *conn->error_info); + COPY_CLIENT_ERROR(stmt->error_info, *conn->error_info); DBG_INF("FAIL"); DBG_RETURN(FAIL); } @@ -747,10 +757,10 @@ MYSQLND_METHOD(mysqlnd_stmt, send_execute)(MYSQLND_STMT * const s, enum_mysqlnd_ /* {{{ mysqlnd_stmt_fetch_row_buffered */ enum_func_status -mysqlnd_stmt_fetch_row_buffered(MYSQLND_RES * result, void * param, unsigned int flags, zend_bool * fetched_anything) +mysqlnd_stmt_fetch_row_buffered(MYSQLND_RES * result, void * param, const unsigned int flags, zend_bool * fetched_anything) { MYSQLND_STMT * s = (MYSQLND_STMT *) param; - MYSQLND_STMT_DATA * stmt = s? s->data:NULL; + MYSQLND_STMT_DATA * stmt = s? s->data : NULL; const MYSQLND_RES_METADATA * const meta = result->meta; unsigned int field_count = meta->field_count; @@ -848,12 +858,13 @@ mysqlnd_stmt_fetch_row_buffered(MYSQLND_RES * result, void * param, unsigned int /* {{{ mysqlnd_stmt_fetch_row_unbuffered */ enum_func_status -mysqlnd_stmt_fetch_row_unbuffered(MYSQLND_RES * result, void * param, unsigned int flags, zend_bool * fetched_anything) +mysqlnd_stmt_fetch_row_unbuffered(MYSQLND_RES * result, void * param, const unsigned int flags, zend_bool * fetched_anything) { enum_func_status ret; MYSQLND_STMT * s = (MYSQLND_STMT *) param; - MYSQLND_STMT_DATA * stmt = s? s->data:NULL; + MYSQLND_STMT_DATA * stmt = s? s->data : NULL; MYSQLND_PACKET_ROW * row_packet; + MYSQLND_CONN_DATA * conn = result->conn; const MYSQLND_RES_METADATA * const meta = result->meta; DBG_ENTER("mysqlnd_stmt_fetch_row_unbuffered"); @@ -865,9 +876,8 @@ mysqlnd_stmt_fetch_row_unbuffered(MYSQLND_RES * result, void * param, unsigned i DBG_INF("EOF already reached"); DBG_RETURN(PASS); } - if (CONN_GET_STATE(result->conn) != CONN_FETCHING_DATA) { - SET_CLIENT_ERROR(*result->conn->error_info, CR_COMMANDS_OUT_OF_SYNC, - UNKNOWN_SQLSTATE, mysqlnd_out_of_sync); + if (GET_CONNECTION_STATE(&conn->state) != CONN_FETCHING_DATA) { + SET_CLIENT_ERROR(conn->error_info, CR_COMMANDS_OUT_OF_SYNC, UNKNOWN_SQLSTATE, mysqlnd_out_of_sync); DBG_ERR("command out of sync"); DBG_RETURN(FAIL); } @@ -882,11 +892,11 @@ mysqlnd_stmt_fetch_row_unbuffered(MYSQLND_RES * result, void * param, unsigned i If we skip rows (stmt == NULL || stmt->result_bind == NULL) we have to result->unbuf->m.free_last_data() before it. The function returns always true. */ - if (PASS == (ret = PACKET_READ(row_packet, result->conn)) && !row_packet->eof) { + if (PASS == (ret = PACKET_READ(row_packet)) && !row_packet->eof) { unsigned int i, field_count = result->field_count; if (!row_packet->skip_extraction) { - result->unbuf->m.free_last_data(result->unbuf, result->conn? result->conn->stats : NULL); + result->unbuf->m.free_last_data(result->unbuf, conn->stats); result->unbuf->last_row_data = row_packet->fields; result->unbuf->last_row_buffer = row_packet->row_buffer; @@ -897,8 +907,8 @@ mysqlnd_stmt_fetch_row_unbuffered(MYSQLND_RES * result, void * param, unsigned i result->unbuf->last_row_data, row_packet->field_count, row_packet->fields_metadata, - result->conn->options->int_and_float_native, - result->conn->stats)) + conn->options->int_and_float_native, + conn->stats)) { DBG_RETURN(FAIL); } @@ -917,8 +927,7 @@ mysqlnd_stmt_fetch_row_unbuffered(MYSQLND_RES * result, void * param, unsigned i zval_dtor(result); #endif if (!Z_ISNULL_P(data)) { - if ((Z_TYPE_P(data) == IS_STRING) && - (meta->fields[i].max_length < (zend_ulong) Z_STRLEN_P(data))) { + if ((Z_TYPE_P(data) == IS_STRING) && (meta->fields[i].max_length < (zend_ulong) Z_STRLEN_P(data))){ meta->fields[i].max_length = Z_STRLEN_P(data); } ZVAL_COPY_VALUE(result, data); @@ -929,7 +938,7 @@ mysqlnd_stmt_fetch_row_unbuffered(MYSQLND_RES * result, void * param, unsigned i } } } - MYSQLND_INC_CONN_STATISTIC(stmt->conn->stats, STAT_ROWS_FETCHED_FROM_CLIENT_PS_UNBUF); + MYSQLND_INC_CONN_STATISTIC(conn->stats, STAT_ROWS_FETCHED_FROM_CLIENT_PS_UNBUF); } else { DBG_INF("skipping extraction"); /* @@ -938,7 +947,8 @@ mysqlnd_stmt_fetch_row_unbuffered(MYSQLND_RES * result, void * param, unsigned i the bound variables. Thus we need to do part of what it does or Zend will report leaks. */ - row_packet->row_buffer->free_chunk(row_packet->row_buffer); + row_packet->result_set_memory_pool->free_chunk( + row_packet->result_set_memory_pool, row_packet->row_buffer); row_packet->row_buffer = NULL; } @@ -946,26 +956,27 @@ mysqlnd_stmt_fetch_row_unbuffered(MYSQLND_RES * result, void * param, unsigned i *fetched_anything = TRUE; } else if (ret == FAIL) { if (row_packet->error_info.error_no) { - COPY_CLIENT_ERROR(*stmt->conn->error_info, row_packet->error_info); - COPY_CLIENT_ERROR(*stmt->error_info, row_packet->error_info); + COPY_CLIENT_ERROR(conn->error_info, row_packet->error_info); + COPY_CLIENT_ERROR(stmt->error_info, row_packet->error_info); } - CONN_SET_STATE(result->conn, CONN_READY); + SET_CONNECTION_STATE(&conn->state, CONN_READY); result->unbuf->eof_reached = TRUE; /* so next time we won't get an error */ } else if (row_packet->eof) { DBG_INF("EOF"); /* Mark the connection as usable again */ result->unbuf->eof_reached = TRUE; - memset(result->conn->upsert_status, 0, sizeof(*result->conn->upsert_status)); - result->conn->upsert_status->warning_count = row_packet->warning_count; - result->conn->upsert_status->server_status = row_packet->server_status; + UPSERT_STATUS_RESET(conn->upsert_status); + UPSERT_STATUS_SET_WARNINGS(conn->upsert_status, row_packet->warning_count); + UPSERT_STATUS_SET_SERVER_STATUS(conn->upsert_status, row_packet->server_status); + /* result->row_packet will be cleaned when destroying the result object */ - if (result->conn->upsert_status->server_status & SERVER_MORE_RESULTS_EXISTS) { - CONN_SET_STATE(result->conn, CONN_NEXT_RESULT_PENDING); + if (UPSERT_STATUS_GET_SERVER_STATUS(conn->upsert_status) & SERVER_MORE_RESULTS_EXISTS) { + SET_CONNECTION_STATE(&conn->state, CONN_NEXT_RESULT_PENDING); } else { - CONN_SET_STATE(result->conn, CONN_READY); + SET_CONNECTION_STATE(&conn->state, CONN_READY); } } @@ -979,32 +990,29 @@ mysqlnd_stmt_fetch_row_unbuffered(MYSQLND_RES * result, void * param, unsigned i static MYSQLND_RES * MYSQLND_METHOD(mysqlnd_stmt, use_result)(MYSQLND_STMT * s) { - MYSQLND_STMT_DATA * stmt = s? s->data:NULL; + MYSQLND_STMT_DATA * stmt = s? s->data : NULL; + MYSQLND_CONN_DATA * conn = stmt? stmt->conn : NULL; MYSQLND_RES * result; - MYSQLND_CONN_DATA * conn; DBG_ENTER("mysqlnd_stmt::use_result"); - if (!stmt || !stmt->conn || !stmt->result) { + if (!stmt || !conn || !stmt->result) { DBG_RETURN(NULL); } DBG_INF_FMT("stmt=%lu", stmt->stmt_id); - conn = stmt->conn; - if (!stmt->field_count || - (!stmt->cursor_exists && CONN_GET_STATE(conn) != CONN_FETCHING_DATA) || - (stmt->cursor_exists && CONN_GET_STATE(conn) != CONN_READY) || + (!stmt->cursor_exists && GET_CONNECTION_STATE(&conn->state) != CONN_FETCHING_DATA) || + (stmt->cursor_exists && GET_CONNECTION_STATE(&conn->state) != CONN_READY) || (stmt->state != MYSQLND_STMT_WAITING_USE_OR_STORE)) { - SET_CLIENT_ERROR(*conn->error_info, CR_COMMANDS_OUT_OF_SYNC, - UNKNOWN_SQLSTATE, mysqlnd_out_of_sync); + SET_CLIENT_ERROR(conn->error_info, CR_COMMANDS_OUT_OF_SYNC, UNKNOWN_SQLSTATE, mysqlnd_out_of_sync); DBG_ERR("command out of sync"); DBG_RETURN(NULL); } - SET_EMPTY_ERROR(*stmt->error_info); + SET_EMPTY_ERROR(stmt->error_info); - MYSQLND_INC_CONN_STATISTIC(stmt->conn->stats, STAT_PS_UNBUFFERED_SETS); + MYSQLND_INC_CONN_STATISTIC(conn->stats, STAT_PS_UNBUFFERED_SETS); result = stmt->result; result->m.use_result(stmt->result, TRUE); @@ -1018,16 +1026,15 @@ MYSQLND_METHOD(mysqlnd_stmt, use_result)(MYSQLND_STMT * s) /* }}} */ -#define STMT_ID_LENGTH 4 - /* {{{ mysqlnd_fetch_row_cursor */ enum_func_status -mysqlnd_fetch_stmt_row_cursor(MYSQLND_RES * result, void * param, unsigned int flags, zend_bool * fetched_anything) +mysqlnd_fetch_stmt_row_cursor(MYSQLND_RES * result, void * param, const unsigned int flags, zend_bool * fetched_anything) { enum_func_status ret; MYSQLND_STMT * s = (MYSQLND_STMT *) param; - MYSQLND_STMT_DATA * stmt = s? s->data:NULL; - zend_uchar buf[STMT_ID_LENGTH /* statement id */ + 4 /* number of rows to fetch */]; + MYSQLND_STMT_DATA * stmt = s? s->data : NULL; + MYSQLND_CONN_DATA * conn = stmt? stmt->conn : NULL; + zend_uchar buf[MYSQLND_STMT_ID_LENGTH /* statement id */ + 4 /* number of rows to fetch */]; MYSQLND_PACKET_ROW * row_packet; DBG_ENTER("mysqlnd_fetch_stmt_row_cursor"); @@ -1036,13 +1043,11 @@ mysqlnd_fetch_stmt_row_cursor(MYSQLND_RES * result, void * param, unsigned int f DBG_ERR("no statement"); DBG_RETURN(FAIL); } - DBG_INF_FMT("stmt=%lu flags=%u", stmt->stmt_id, flags); if (stmt->state < MYSQLND_STMT_USER_FETCHING) { /* Only initted - error */ - SET_CLIENT_ERROR(*stmt->conn->error_info, CR_COMMANDS_OUT_OF_SYNC, UNKNOWN_SQLSTATE, - mysqlnd_out_of_sync); + SET_CLIENT_ERROR(conn->error_info, CR_COMMANDS_OUT_OF_SYNC, UNKNOWN_SQLSTATE, mysqlnd_out_of_sync); DBG_ERR("command out of sync"); DBG_RETURN(FAIL); } @@ -1050,28 +1055,38 @@ mysqlnd_fetch_stmt_row_cursor(MYSQLND_RES * result, void * param, unsigned int f DBG_RETURN(FAIL); } - SET_EMPTY_ERROR(*stmt->error_info); - SET_EMPTY_ERROR(*stmt->conn->error_info); + SET_EMPTY_ERROR(stmt->error_info); + SET_EMPTY_ERROR(conn->error_info); int4store(buf, stmt->stmt_id); - int4store(buf + STMT_ID_LENGTH, 1); /* for now fetch only one row */ + int4store(buf + MYSQLND_STMT_ID_LENGTH, 1); /* for now fetch only one row */ + + { + const MYSQLND_CSTRING payload = {(const char*) buf, sizeof(buf)}; + struct st_mysqlnd_protocol_command * command = conn->command_factory(COM_STMT_FETCH, conn, payload); + ret = FAIL; + if (command) { + ret = command->run(command); + command->free_command(command); + if (ret == FAIL) { + COPY_CLIENT_ERROR(stmt->error_info, *conn->error_info); + } + } + if (FAIL == ret) { + DBG_RETURN(FAIL); + } - if (FAIL == stmt->conn->m->simple_command(stmt->conn, COM_STMT_FETCH, buf, sizeof(buf), - PROT_LAST /* we will handle the response packet*/, - FALSE, TRUE)) { - COPY_CLIENT_ERROR(*stmt->error_info, *stmt->conn->error_info); - DBG_RETURN(FAIL); } row_packet->skip_extraction = stmt->result_bind? FALSE:TRUE; - memset(stmt->upsert_status, 0, sizeof(*stmt->upsert_status)); - if (PASS == (ret = PACKET_READ(row_packet, result->conn)) && !row_packet->eof) { + UPSERT_STATUS_RESET(stmt->upsert_status); + if (PASS == (ret = PACKET_READ(row_packet)) && !row_packet->eof) { const MYSQLND_RES_METADATA * const meta = result->meta; unsigned int i, field_count = result->field_count; if (!row_packet->skip_extraction) { - result->unbuf->m.free_last_data(result->unbuf, result->conn? result->conn->stats : NULL); + result->unbuf->m.free_last_data(result->unbuf, conn->stats); result->unbuf->last_row_data = row_packet->fields; result->unbuf->last_row_buffer = row_packet->row_buffer; @@ -1082,8 +1097,8 @@ mysqlnd_fetch_stmt_row_cursor(MYSQLND_RES * result, void * param, unsigned int f result->unbuf->last_row_data, row_packet->field_count, row_packet->fields_metadata, - result->conn->options->int_and_float_native, - result->conn->stats)) + conn->options->int_and_float_native, + conn->stats)) { DBG_RETURN(FAIL); } @@ -1127,38 +1142,36 @@ mysqlnd_fetch_stmt_row_cursor(MYSQLND_RES * result, void * param, unsigned int f the bound variables. Thus we need to do part of what it does or Zend will report leaks. */ - row_packet->row_buffer->free_chunk(row_packet->row_buffer); + row_packet->result_set_memory_pool->free_chunk( + row_packet->result_set_memory_pool, row_packet->row_buffer); row_packet->row_buffer = NULL; } /* We asked for one row, the next one should be EOF, eat it */ - ret = PACKET_READ(row_packet, result->conn); + ret = PACKET_READ(row_packet); if (row_packet->row_buffer) { - row_packet->row_buffer->free_chunk(row_packet->row_buffer); + row_packet->result_set_memory_pool->free_chunk( + row_packet->result_set_memory_pool, row_packet->row_buffer); row_packet->row_buffer = NULL; } - MYSQLND_INC_CONN_STATISTIC(stmt->conn->stats, STAT_ROWS_FETCHED_FROM_CLIENT_PS_CURSOR); + MYSQLND_INC_CONN_STATISTIC(conn->stats, STAT_ROWS_FETCHED_FROM_CLIENT_PS_CURSOR); result->unbuf->row_count++; *fetched_anything = TRUE; } else { *fetched_anything = FALSE; + UPSERT_STATUS_SET_WARNINGS(stmt->upsert_status, row_packet->warning_count); + UPSERT_STATUS_SET_WARNINGS(conn->upsert_status, row_packet->warning_count); - stmt->upsert_status->warning_count = - stmt->conn->upsert_status->warning_count = - row_packet->warning_count; - - stmt->upsert_status->server_status = - stmt->conn->upsert_status->server_status = - row_packet->server_status; + UPSERT_STATUS_SET_SERVER_STATUS(stmt->upsert_status, row_packet->server_status); + UPSERT_STATUS_SET_SERVER_STATUS(conn->upsert_status, row_packet->server_status); result->unbuf->eof_reached = row_packet->eof; } - stmt->upsert_status->warning_count = - stmt->conn->upsert_status->warning_count = - row_packet->warning_count; - stmt->upsert_status->server_status = - stmt->conn->upsert_status->server_status = - row_packet->server_status; + UPSERT_STATUS_SET_WARNINGS(stmt->upsert_status, row_packet->warning_count); + UPSERT_STATUS_SET_WARNINGS(conn->upsert_status, row_packet->warning_count); + + UPSERT_STATUS_SET_SERVER_STATUS(stmt->upsert_status, row_packet->server_status); + UPSERT_STATUS_SET_SERVER_STATUS(conn->upsert_status, row_packet->server_status); DBG_INF_FMT("ret=%s fetched=%u server_status=%u warnings=%u eof=%u", ret == PASS? "PASS":"FAIL", *fetched_anything, @@ -1173,7 +1186,8 @@ mysqlnd_fetch_stmt_row_cursor(MYSQLND_RES * result, void * param, unsigned int f static enum_func_status MYSQLND_METHOD(mysqlnd_stmt, fetch)(MYSQLND_STMT * const s, zend_bool * const fetched_anything) { - MYSQLND_STMT_DATA * stmt = s? s->data:NULL; + MYSQLND_STMT_DATA * stmt = s? s->data : NULL; + MYSQLND_CONN_DATA * conn = stmt? stmt->conn : NULL; enum_func_status ret; DBG_ENTER("mysqlnd_stmt::fetch"); if (!stmt || !stmt->conn) { @@ -1181,10 +1195,8 @@ MYSQLND_METHOD(mysqlnd_stmt, fetch)(MYSQLND_STMT * const s, zend_bool * const fe } DBG_INF_FMT("stmt=%lu", stmt->stmt_id); - if (!stmt->result || - stmt->state < MYSQLND_STMT_WAITING_USE_OR_STORE) { - SET_STMT_ERROR(stmt, CR_COMMANDS_OUT_OF_SYNC, UNKNOWN_SQLSTATE, mysqlnd_out_of_sync); - + if (!stmt->result || stmt->state < MYSQLND_STMT_WAITING_USE_OR_STORE) { + SET_CLIENT_ERROR(stmt->error_info, CR_COMMANDS_OUT_OF_SYNC, UNKNOWN_SQLSTATE, mysqlnd_out_of_sync); DBG_ERR("command out of sync"); DBG_RETURN(FAIL); } else if (stmt->state == MYSQLND_STMT_WAITING_USE_OR_STORE) { @@ -1194,8 +1206,8 @@ MYSQLND_METHOD(mysqlnd_stmt, fetch)(MYSQLND_STMT * const s, zend_bool * const fe } stmt->state = MYSQLND_STMT_USER_FETCHING; - SET_EMPTY_ERROR(*stmt->error_info); - SET_EMPTY_ERROR(*stmt->conn->error_info); + SET_EMPTY_ERROR(stmt->error_info); + SET_EMPTY_ERROR(conn->error_info); DBG_INF_FMT("result_bind=%p separated_once=%u", &stmt->result_bind, stmt->result_zvals_separated_once); /* @@ -1229,18 +1241,18 @@ MYSQLND_METHOD(mysqlnd_stmt, fetch)(MYSQLND_STMT * const s, zend_bool * const fe static enum_func_status MYSQLND_METHOD(mysqlnd_stmt, reset)(MYSQLND_STMT * const s) { - MYSQLND_STMT_DATA * stmt = s? s->data:NULL; enum_func_status ret = PASS; - zend_uchar cmd_buf[STMT_ID_LENGTH /* statement id */]; + MYSQLND_STMT_DATA * stmt = s? s->data : NULL; + MYSQLND_CONN_DATA * conn = stmt? stmt->conn : NULL; DBG_ENTER("mysqlnd_stmt::reset"); - if (!stmt || !stmt->conn) { + if (!stmt || !conn) { DBG_RETURN(FAIL); } DBG_INF_FMT("stmt=%lu", stmt->stmt_id); - SET_EMPTY_ERROR(*stmt->error_info); - SET_EMPTY_ERROR(*stmt->conn->error_info); + SET_EMPTY_ERROR(stmt->error_info); + SET_EMPTY_ERROR(conn->error_info); if (stmt->stmt_id) { MYSQLND_CONN_DATA * conn = stmt->conn; @@ -1263,12 +1275,18 @@ MYSQLND_METHOD(mysqlnd_stmt, reset)(MYSQLND_STMT * const s) be separated before that. */ - int4store(cmd_buf, stmt->stmt_id); - if (CONN_GET_STATE(conn) == CONN_READY && - FAIL == (ret = conn->m->simple_command(conn, COM_STMT_RESET, cmd_buf, - sizeof(cmd_buf), PROT_OK_PACKET, - FALSE, TRUE))) { - COPY_CLIENT_ERROR(*stmt->error_info, *conn->error_info); + if (GET_CONNECTION_STATE(&conn->state) == CONN_READY) { + size_t stmt_id = stmt->stmt_id; + struct st_mysqlnd_protocol_command * command = stmt->conn->command_factory(COM_STMT_RESET, stmt->conn, stmt_id); + ret = FAIL; + if (command) { + ret = command->run(command); + command->free_command(command); + + if (ret == FAIL) { + COPY_CLIENT_ERROR(stmt->error_info, *conn->error_info); + } + } } *stmt->upsert_status = *conn->upsert_status; } @@ -1282,11 +1300,12 @@ MYSQLND_METHOD(mysqlnd_stmt, reset)(MYSQLND_STMT * const s) static enum_func_status MYSQLND_METHOD(mysqlnd_stmt, flush)(MYSQLND_STMT * const s) { - MYSQLND_STMT_DATA * stmt = s? s->data:NULL; enum_func_status ret = PASS; + MYSQLND_STMT_DATA * stmt = s? s->data : NULL; + MYSQLND_CONN_DATA * conn = stmt? stmt->conn : NULL; DBG_ENTER("mysqlnd_stmt::flush"); - if (!stmt || !stmt->conn) { + if (!stmt || !conn) { DBG_RETURN(FAIL); } DBG_INF_FMT("stmt=%lu", stmt->stmt_id); @@ -1319,76 +1338,72 @@ MYSQLND_METHOD(mysqlnd_stmt, flush)(MYSQLND_STMT * const s) /* {{{ mysqlnd_stmt::send_long_data */ static enum_func_status MYSQLND_METHOD(mysqlnd_stmt, send_long_data)(MYSQLND_STMT * const s, unsigned int param_no, - const char * const data, zend_ulong length) + const char * const data, zend_ulong data_length) { - MYSQLND_STMT_DATA * stmt = s? s->data:NULL; enum_func_status ret = FAIL; - MYSQLND_CONN_DATA * conn; + MYSQLND_STMT_DATA * stmt = s? s->data : NULL; + MYSQLND_CONN_DATA * conn = stmt? stmt->conn : NULL; zend_uchar * cmd_buf; - enum php_mysqlnd_server_command cmd = COM_STMT_SEND_LONG_DATA; DBG_ENTER("mysqlnd_stmt::send_long_data"); - if (!stmt || !stmt->conn) { + if (!stmt || !conn) { DBG_RETURN(FAIL); } - DBG_INF_FMT("stmt=%lu param_no=%u data_len=%lu", stmt->stmt_id, param_no, length); + DBG_INF_FMT("stmt=%lu param_no=%u data_len=%lu", stmt->stmt_id, param_no, data_length); - conn = stmt->conn; - - SET_EMPTY_ERROR(*stmt->error_info); - SET_EMPTY_ERROR(*stmt->conn->error_info); + SET_EMPTY_ERROR(stmt->error_info); + SET_EMPTY_ERROR(conn->error_info); if (stmt->state < MYSQLND_STMT_PREPARED) { - SET_STMT_ERROR(stmt, CR_NO_PREPARE_STMT, UNKNOWN_SQLSTATE, mysqlnd_stmt_not_prepared); + SET_CLIENT_ERROR(stmt->error_info, CR_NO_PREPARE_STMT, UNKNOWN_SQLSTATE, mysqlnd_stmt_not_prepared); DBG_ERR("not prepared"); DBG_RETURN(FAIL); } if (!stmt->param_bind) { - SET_STMT_ERROR(stmt, CR_COMMANDS_OUT_OF_SYNC, UNKNOWN_SQLSTATE, mysqlnd_out_of_sync); + SET_CLIENT_ERROR(stmt->error_info, CR_COMMANDS_OUT_OF_SYNC, UNKNOWN_SQLSTATE, mysqlnd_out_of_sync); DBG_ERR("command out of sync"); DBG_RETURN(FAIL); } if (param_no >= stmt->param_count) { - SET_STMT_ERROR(stmt, CR_INVALID_PARAMETER_NO, UNKNOWN_SQLSTATE, "Invalid parameter number"); + SET_CLIENT_ERROR(stmt->error_info, CR_INVALID_PARAMETER_NO, UNKNOWN_SQLSTATE, "Invalid parameter number"); DBG_ERR("invalid param_no"); DBG_RETURN(FAIL); } if (stmt->param_bind[param_no].type != MYSQL_TYPE_LONG_BLOB) { - SET_STMT_ERROR(stmt, CR_INVALID_BUFFER_USE, UNKNOWN_SQLSTATE, mysqlnd_not_bound_as_blob); + SET_CLIENT_ERROR(stmt->error_info, CR_INVALID_BUFFER_USE, UNKNOWN_SQLSTATE, mysqlnd_not_bound_as_blob); DBG_ERR("param_no is not of a blob type"); DBG_RETURN(FAIL); } - /* - XXX: Unfortunately we have to allocate additional buffer to be able the - additional data, which is like a header inside the payload. - This should be optimised, but it will be a pervasive change, so - conn->m->simple_command() will accept not a buffer, but actually MYSQLND_STRING* - terminated by NULL, to send. If the strings are not big, we can collapse them - on the buffer every connection has, but otherwise we will just send them - one by one to the wire. - */ - - if (CONN_GET_STATE(conn) == CONN_READY) { - size_t packet_len; - cmd_buf = mnd_emalloc(packet_len = STMT_ID_LENGTH + 2 + length); + if (GET_CONNECTION_STATE(&conn->state) == CONN_READY) { + const size_t packet_len = MYSQLND_STMT_ID_LENGTH + 2 + data_length; + cmd_buf = mnd_emalloc(packet_len); if (cmd_buf) { stmt->param_bind[param_no].flags |= MYSQLND_PARAM_BIND_BLOB_USED; int4store(cmd_buf, stmt->stmt_id); - int2store(cmd_buf + STMT_ID_LENGTH, param_no); - memcpy(cmd_buf + STMT_ID_LENGTH + 2, data, length); + int2store(cmd_buf + MYSQLND_STMT_ID_LENGTH, param_no); + memcpy(cmd_buf + MYSQLND_STMT_ID_LENGTH + 2, data, data_length); - /* COM_STMT_SEND_LONG_DATA doesn't send an OK packet*/ - ret = conn->m->simple_command(conn, cmd, cmd_buf, packet_len, PROT_LAST , FALSE, TRUE); - mnd_efree(cmd_buf); - if (FAIL == ret) { - COPY_CLIENT_ERROR(*stmt->error_info, *conn->error_info); + /* COM_STMT_SEND_LONG_DATA doesn't acknowledge with an OK packet */ + { + const MYSQLND_CSTRING payload = {(const char *) cmd_buf, packet_len}; + struct st_mysqlnd_protocol_command * command = conn->command_factory(COM_STMT_SEND_LONG_DATA, conn, payload); + ret = FAIL; + if (command) { + ret = command->run(command); + command->free_command(command); + if (ret == FAIL) { + COPY_CLIENT_ERROR(stmt->error_info, *conn->error_info); + } + } } + + mnd_efree(cmd_buf); } else { ret = FAIL; - SET_OOM_ERROR(*stmt->error_info); - SET_OOM_ERROR(*conn->error_info); + SET_OOM_ERROR(stmt->error_info); + SET_OOM_ERROR(conn->error_info); } /* Cover protocol error: COM_STMT_SEND_LONG_DATA was designed to be quick and not @@ -1410,12 +1425,12 @@ MYSQLND_METHOD(mysqlnd_stmt, send_long_data)(MYSQLND_STMT * const s, unsigned in #if HAVE_USLEEP && !defined(PHP_WIN32) usleep(120000); #endif - if ((packet_len = conn->net->m.consume_uneaten_data(conn->net, cmd))) { + if ((packet_len = conn->protocol_frame_codec->m.consume_uneaten_data(conn->protocol_frame_codec, COM_STMT_SEND_LONG_DATA))) { php_error_docref(NULL, E_WARNING, "There was an error " "while sending long data. Probably max_allowed_packet_size " "is smaller than the data. You have to increase it or send " "smaller chunks of data. Answer was "MYSQLND_SZ_T_SPEC" bytes long.", packet_len); - SET_STMT_ERROR(stmt, CR_CONNECTION_ERROR, UNKNOWN_SQLSTATE, + SET_CLIENT_ERROR(stmt->error_info, CR_CONNECTION_ERROR, UNKNOWN_SQLSTATE, "Server responded to COM_STMT_SEND_LONG_DATA."); ret = FAIL; } @@ -1432,15 +1447,17 @@ MYSQLND_METHOD(mysqlnd_stmt, send_long_data)(MYSQLND_STMT * const s, unsigned in static enum_func_status MYSQLND_METHOD(mysqlnd_stmt, bind_parameters)(MYSQLND_STMT * const s, MYSQLND_PARAM_BIND * const param_bind) { - MYSQLND_STMT_DATA * stmt = s? s->data:NULL; + MYSQLND_STMT_DATA * stmt = s? s->data : NULL; + MYSQLND_CONN_DATA * conn = stmt? stmt->conn : NULL; + DBG_ENTER("mysqlnd_stmt::bind_param"); - if (!stmt || !stmt->conn) { + if (!stmt || !conn) { DBG_RETURN(FAIL); } DBG_INF_FMT("stmt=%lu param_count=%u", stmt->stmt_id, stmt->param_count); if (stmt->state < MYSQLND_STMT_PREPARED) { - SET_STMT_ERROR(stmt, CR_NO_PREPARE_STMT, UNKNOWN_SQLSTATE, mysqlnd_stmt_not_prepared); + SET_CLIENT_ERROR(stmt->error_info, CR_NO_PREPARE_STMT, UNKNOWN_SQLSTATE, mysqlnd_stmt_not_prepared); DBG_ERR("not prepared"); if (param_bind) { s->m->free_parameter_bind(s, param_bind); @@ -1448,14 +1465,14 @@ MYSQLND_METHOD(mysqlnd_stmt, bind_parameters)(MYSQLND_STMT * const s, MYSQLND_PA DBG_RETURN(FAIL); } - SET_EMPTY_ERROR(*stmt->error_info); - SET_EMPTY_ERROR(*stmt->conn->error_info); + SET_EMPTY_ERROR(stmt->error_info); + SET_EMPTY_ERROR(conn->error_info); if (stmt->param_count) { unsigned int i = 0; if (!param_bind) { - SET_STMT_ERROR(stmt, CR_COMMANDS_OUT_OF_SYNC, UNKNOWN_SQLSTATE, "Re-binding (still) not supported"); + SET_CLIENT_ERROR(stmt->error_info, CR_COMMANDS_OUT_OF_SYNC, UNKNOWN_SQLSTATE, "Re-binding (still) not supported"); DBG_ERR("Re-binding (still) not supported"); DBG_RETURN(FAIL); } else if (stmt->param_bind) { @@ -1501,26 +1518,28 @@ static enum_func_status MYSQLND_METHOD(mysqlnd_stmt, bind_one_parameter)(MYSQLND_STMT * const s, unsigned int param_no, zval * const zv, zend_uchar type) { - MYSQLND_STMT_DATA * stmt = s? s->data:NULL; + MYSQLND_STMT_DATA * stmt = s? s->data : NULL; + MYSQLND_CONN_DATA * conn = stmt? stmt->conn : NULL; + DBG_ENTER("mysqlnd_stmt::bind_one_parameter"); - if (!stmt || !stmt->conn) { + if (!stmt || !conn) { DBG_RETURN(FAIL); } DBG_INF_FMT("stmt=%lu param_no=%u param_count=%u type=%u", stmt->stmt_id, param_no, stmt->param_count, type); if (stmt->state < MYSQLND_STMT_PREPARED) { - SET_STMT_ERROR(stmt, CR_NO_PREPARE_STMT, UNKNOWN_SQLSTATE, mysqlnd_stmt_not_prepared); + SET_CLIENT_ERROR(stmt->error_info, CR_NO_PREPARE_STMT, UNKNOWN_SQLSTATE, mysqlnd_stmt_not_prepared); DBG_ERR("not prepared"); DBG_RETURN(FAIL); } if (param_no >= stmt->param_count) { - SET_STMT_ERROR(stmt, CR_INVALID_PARAMETER_NO, UNKNOWN_SQLSTATE, "Invalid parameter number"); + SET_CLIENT_ERROR(stmt->error_info, CR_INVALID_PARAMETER_NO, UNKNOWN_SQLSTATE, "Invalid parameter number"); DBG_ERR("invalid param_no"); DBG_RETURN(FAIL); } - SET_EMPTY_ERROR(*stmt->error_info); - SET_EMPTY_ERROR(*stmt->conn->error_info); + SET_EMPTY_ERROR(stmt->error_info); + SET_EMPTY_ERROR(conn->error_info); if (stmt->param_count) { if (!stmt->param_bind) { @@ -1555,21 +1574,23 @@ MYSQLND_METHOD(mysqlnd_stmt, bind_one_parameter)(MYSQLND_STMT * const s, unsigne static enum_func_status MYSQLND_METHOD(mysqlnd_stmt, refresh_bind_param)(MYSQLND_STMT * const s) { - MYSQLND_STMT_DATA * stmt = s? s->data:NULL; + MYSQLND_STMT_DATA * stmt = s? s->data : NULL; + MYSQLND_CONN_DATA * conn = stmt? stmt->conn : NULL; + DBG_ENTER("mysqlnd_stmt::refresh_bind_param"); - if (!stmt || !stmt->conn) { + if (!stmt || !conn) { DBG_RETURN(FAIL); } DBG_INF_FMT("stmt=%lu param_count=%u", stmt->stmt_id, stmt->param_count); if (stmt->state < MYSQLND_STMT_PREPARED) { - SET_STMT_ERROR(stmt, CR_NO_PREPARE_STMT, UNKNOWN_SQLSTATE, mysqlnd_stmt_not_prepared); + SET_CLIENT_ERROR(stmt->error_info, CR_NO_PREPARE_STMT, UNKNOWN_SQLSTATE, mysqlnd_stmt_not_prepared); DBG_ERR("not prepared"); DBG_RETURN(FAIL); } - SET_EMPTY_ERROR(*stmt->error_info); - SET_EMPTY_ERROR(*stmt->conn->error_info); + SET_EMPTY_ERROR(stmt->error_info); + SET_EMPTY_ERROR(conn->error_info); if (stmt->param_count) { stmt->send_types_to_server = 1; @@ -1584,15 +1605,17 @@ static enum_func_status MYSQLND_METHOD(mysqlnd_stmt, bind_result)(MYSQLND_STMT * const s, MYSQLND_RESULT_BIND * const result_bind) { - MYSQLND_STMT_DATA * stmt = s? s->data:NULL; + MYSQLND_STMT_DATA * stmt = s? s->data : NULL; + MYSQLND_CONN_DATA * conn = stmt? stmt->conn : NULL; + DBG_ENTER("mysqlnd_stmt::bind_result"); - if (!stmt || !stmt->conn) { + if (!stmt || !conn) { DBG_RETURN(FAIL); } DBG_INF_FMT("stmt=%lu field_count=%u", stmt->stmt_id, stmt->field_count); if (stmt->state < MYSQLND_STMT_PREPARED) { - SET_STMT_ERROR(stmt, CR_NO_PREPARE_STMT, UNKNOWN_SQLSTATE, mysqlnd_stmt_not_prepared); + SET_CLIENT_ERROR(stmt->error_info, CR_NO_PREPARE_STMT, UNKNOWN_SQLSTATE, mysqlnd_stmt_not_prepared); if (result_bind) { s->m->free_result_bind(s, result_bind); } @@ -1600,8 +1623,8 @@ MYSQLND_METHOD(mysqlnd_stmt, bind_result)(MYSQLND_STMT * const s, DBG_RETURN(FAIL); } - SET_EMPTY_ERROR(*stmt->error_info); - SET_EMPTY_ERROR(*stmt->conn->error_info); + SET_EMPTY_ERROR(stmt->error_info); + SET_EMPTY_ERROR(conn->error_info); if (stmt->field_count) { unsigned int i = 0; @@ -1640,27 +1663,29 @@ MYSQLND_METHOD(mysqlnd_stmt, bind_result)(MYSQLND_STMT * const s, static enum_func_status MYSQLND_METHOD(mysqlnd_stmt, bind_one_result)(MYSQLND_STMT * const s, unsigned int param_no) { - MYSQLND_STMT_DATA * stmt = s? s->data:NULL; + MYSQLND_STMT_DATA * stmt = s? s->data : NULL; + MYSQLND_CONN_DATA * conn = stmt? stmt->conn : NULL; + DBG_ENTER("mysqlnd_stmt::bind_result"); - if (!stmt || !stmt->conn) { + if (!stmt || !conn) { DBG_RETURN(FAIL); } DBG_INF_FMT("stmt=%lu field_count=%u", stmt->stmt_id, stmt->field_count); if (stmt->state < MYSQLND_STMT_PREPARED) { - SET_STMT_ERROR(stmt, CR_NO_PREPARE_STMT, UNKNOWN_SQLSTATE, mysqlnd_stmt_not_prepared); + SET_CLIENT_ERROR(stmt->error_info, CR_NO_PREPARE_STMT, UNKNOWN_SQLSTATE, mysqlnd_stmt_not_prepared); DBG_ERR("not prepared"); DBG_RETURN(FAIL); } if (param_no >= stmt->field_count) { - SET_STMT_ERROR(stmt, CR_INVALID_PARAMETER_NO, UNKNOWN_SQLSTATE, "Invalid parameter number"); + SET_CLIENT_ERROR(stmt->error_info, CR_INVALID_PARAMETER_NO, UNKNOWN_SQLSTATE, "Invalid parameter number"); DBG_ERR("invalid param_no"); DBG_RETURN(FAIL); } - SET_EMPTY_ERROR(*stmt->error_info); - SET_EMPTY_ERROR(*stmt->conn->error_info); + SET_EMPTY_ERROR(stmt->error_info); + SET_EMPTY_ERROR(conn->error_info); if (stmt->field_count) { mysqlnd_stmt_separate_one_result_bind(s, param_no); @@ -1691,8 +1716,8 @@ MYSQLND_METHOD(mysqlnd_stmt, bind_one_result)(MYSQLND_STMT * const s, unsigned i static uint64_t MYSQLND_METHOD(mysqlnd_stmt, insert_id)(const MYSQLND_STMT * const s) { - MYSQLND_STMT_DATA * stmt = s? s->data:NULL; - return stmt? stmt->upsert_status->last_insert_id : 0; + MYSQLND_STMT_DATA * stmt = s? s->data : NULL; + return stmt? UPSERT_STATUS_GET_LAST_INSERT_ID(stmt->upsert_status) : 0; } /* }}} */ @@ -1701,8 +1726,8 @@ MYSQLND_METHOD(mysqlnd_stmt, insert_id)(const MYSQLND_STMT * const s) static uint64_t MYSQLND_METHOD(mysqlnd_stmt, affected_rows)(const MYSQLND_STMT * const s) { - MYSQLND_STMT_DATA * stmt = s? s->data:NULL; - return stmt? stmt->upsert_status->affected_rows : 0; + MYSQLND_STMT_DATA * stmt = s? s->data : NULL; + return stmt? UPSERT_STATUS_GET_AFFECTED_ROWS(stmt->upsert_status) : 0; } /* }}} */ @@ -1711,7 +1736,7 @@ MYSQLND_METHOD(mysqlnd_stmt, affected_rows)(const MYSQLND_STMT * const s) static uint64_t MYSQLND_METHOD(mysqlnd_stmt, num_rows)(const MYSQLND_STMT * const s) { - MYSQLND_STMT_DATA * stmt = s? s->data:NULL; + MYSQLND_STMT_DATA * stmt = s? s->data : NULL; return stmt && stmt->result? mysqlnd_num_rows(stmt->result):0; } /* }}} */ @@ -1721,8 +1746,8 @@ MYSQLND_METHOD(mysqlnd_stmt, num_rows)(const MYSQLND_STMT * const s) static unsigned int MYSQLND_METHOD(mysqlnd_stmt, warning_count)(const MYSQLND_STMT * const s) { - MYSQLND_STMT_DATA * stmt = s? s->data:NULL; - return stmt? stmt->upsert_status->warning_count : 0; + MYSQLND_STMT_DATA * stmt = s? s->data : NULL; + return stmt? UPSERT_STATUS_GET_WARNINGS(stmt->upsert_status) : 0; } /* }}} */ @@ -1731,8 +1756,8 @@ MYSQLND_METHOD(mysqlnd_stmt, warning_count)(const MYSQLND_STMT * const s) static unsigned int MYSQLND_METHOD(mysqlnd_stmt, server_status)(const MYSQLND_STMT * const s) { - MYSQLND_STMT_DATA * stmt = s? s->data:NULL; - return stmt? stmt->upsert_status->server_status : 0; + MYSQLND_STMT_DATA * stmt = s? s->data : NULL; + return stmt? UPSERT_STATUS_GET_SERVER_STATUS(stmt->upsert_status) : 0; } /* }}} */ @@ -1741,7 +1766,7 @@ MYSQLND_METHOD(mysqlnd_stmt, server_status)(const MYSQLND_STMT * const s) static unsigned int MYSQLND_METHOD(mysqlnd_stmt, field_count)(const MYSQLND_STMT * const s) { - MYSQLND_STMT_DATA * stmt = s? s->data:NULL; + MYSQLND_STMT_DATA * stmt = s? s->data : NULL; return stmt? stmt->field_count : 0; } /* }}} */ @@ -1751,7 +1776,7 @@ MYSQLND_METHOD(mysqlnd_stmt, field_count)(const MYSQLND_STMT * const s) static unsigned int MYSQLND_METHOD(mysqlnd_stmt, param_count)(const MYSQLND_STMT * const s) { - MYSQLND_STMT_DATA * stmt = s? s->data:NULL; + MYSQLND_STMT_DATA * stmt = s? s->data : NULL; return stmt? stmt->param_count : 0; } /* }}} */ @@ -1761,7 +1786,7 @@ MYSQLND_METHOD(mysqlnd_stmt, param_count)(const MYSQLND_STMT * const s) static unsigned int MYSQLND_METHOD(mysqlnd_stmt, errno)(const MYSQLND_STMT * const s) { - MYSQLND_STMT_DATA * stmt = s? s->data:NULL; + MYSQLND_STMT_DATA * stmt = s? s->data : NULL; return stmt? stmt->error_info->error_no : 0; } /* }}} */ @@ -1771,7 +1796,7 @@ MYSQLND_METHOD(mysqlnd_stmt, errno)(const MYSQLND_STMT * const s) static const char * MYSQLND_METHOD(mysqlnd_stmt, error)(const MYSQLND_STMT * const s) { - MYSQLND_STMT_DATA * stmt = s? s->data:NULL; + MYSQLND_STMT_DATA * stmt = s? s->data : NULL; return stmt? stmt->error_info->error : 0; } /* }}} */ @@ -1781,7 +1806,7 @@ MYSQLND_METHOD(mysqlnd_stmt, error)(const MYSQLND_STMT * const s) static const char * MYSQLND_METHOD(mysqlnd_stmt, sqlstate)(const MYSQLND_STMT * const s) { - MYSQLND_STMT_DATA * stmt = s? s->data:NULL; + MYSQLND_STMT_DATA * stmt = s? s->data : NULL; return stmt && stmt->error_info->sqlstate[0] ? stmt->error_info->sqlstate:MYSQLND_SQLSTATE_NULL; } /* }}} */ @@ -1791,7 +1816,7 @@ MYSQLND_METHOD(mysqlnd_stmt, sqlstate)(const MYSQLND_STMT * const s) static enum_func_status MYSQLND_METHOD(mysqlnd_stmt, data_seek)(const MYSQLND_STMT * const s, uint64_t row) { - MYSQLND_STMT_DATA * stmt = s? s->data:NULL; + MYSQLND_STMT_DATA * stmt = s? s->data : NULL; return stmt && stmt->result? stmt->result->m.seek_data(stmt->result, row) : FAIL; } /* }}} */ @@ -1801,7 +1826,7 @@ MYSQLND_METHOD(mysqlnd_stmt, data_seek)(const MYSQLND_STMT * const s, uint64_t r static MYSQLND_RES * MYSQLND_METHOD(mysqlnd_stmt, param_metadata)(MYSQLND_STMT * const s) { - MYSQLND_STMT_DATA * stmt = s? s->data:NULL; + MYSQLND_STMT_DATA * stmt = s? s->data : NULL; if (!stmt || !stmt->param_count) { return NULL; } @@ -1814,57 +1839,57 @@ MYSQLND_METHOD(mysqlnd_stmt, param_metadata)(MYSQLND_STMT * const s) static MYSQLND_RES * MYSQLND_METHOD(mysqlnd_stmt, result_metadata)(MYSQLND_STMT * const s) { - MYSQLND_STMT_DATA * stmt = s? s->data:NULL; - MYSQLND_RES *result; + MYSQLND_STMT_DATA * stmt = s? s->data : NULL; + MYSQLND_CONN_DATA * conn = stmt? stmt->conn : NULL; + MYSQLND_RES * result_meta = NULL; DBG_ENTER("mysqlnd_stmt::result_metadata"); - if (!stmt) { + if (!stmt || ! conn) { DBG_RETURN(NULL); } DBG_INF_FMT("stmt=%u field_count=%u", stmt->stmt_id, stmt->field_count); - if (!stmt->field_count || !stmt->conn || !stmt->result || !stmt->result->meta) { + if (!stmt->field_count || !stmt->result || !stmt->result->meta) { DBG_INF("NULL"); DBG_RETURN(NULL); } if (stmt->update_max_length && stmt->result->stored_data) { /* stored result, we have to update the max_length before we clone the meta data :( */ - stmt->result->stored_data->m.initialize_result_set_rest(stmt->result->stored_data, stmt->result->meta, stmt->conn->stats, - stmt->conn->options->int_and_float_native); + stmt->result->stored_data->m.initialize_result_set_rest(stmt->result->stored_data, + stmt->result->meta, + conn->stats, + conn->options->int_and_float_native); } /* TODO: This implementation is kind of a hack, find a better way to do it. In different functions I have put fuses to check for result->m.fetch_row() being NULL. This should be handled in a better way. - - In the meantime we don't need a zval cache reference for this fake - result set, so we don't get one. */ do { - result = stmt->conn->m->result_init(stmt->field_count, stmt->persistent); - if (!result) { + result_meta = conn->m->result_init(stmt->field_count, stmt->persistent); + if (!result_meta) { break; } - result->type = MYSQLND_RES_NORMAL; - result->unbuf = mysqlnd_result_unbuffered_init(stmt->field_count, TRUE, result->persistent); - if (!result->unbuf) { + result_meta->type = MYSQLND_RES_NORMAL; + result_meta->unbuf = mysqlnd_result_unbuffered_init(stmt->field_count, TRUE, result_meta->persistent); + if (!result_meta->unbuf) { break; } - result->unbuf->eof_reached = TRUE; - result->meta = stmt->result->meta->m->clone_metadata(stmt->result->meta, FALSE); - if (!result->meta) { + result_meta->unbuf->eof_reached = TRUE; + result_meta->meta = stmt->result->meta->m->clone_metadata(stmt->result->meta, FALSE); + if (!result_meta->meta) { break; } - DBG_INF_FMT("result=%p", result); - DBG_RETURN(result); + DBG_INF_FMT("result_meta=%p", result_meta); + DBG_RETURN(result_meta); } while (0); - SET_OOM_ERROR(*stmt->conn->error_info); - if (result) { - result->m.free_result(result, TRUE); + SET_OOM_ERROR(conn->error_info); + if (result_meta) { + result_meta->m.free_result(result_meta, TRUE); } DBG_RETURN(NULL); } @@ -1877,7 +1902,7 @@ MYSQLND_METHOD(mysqlnd_stmt, attr_set)(MYSQLND_STMT * const s, enum mysqlnd_stmt_attr attr_type, const void * const value) { - MYSQLND_STMT_DATA * stmt = s? s->data:NULL; + MYSQLND_STMT_DATA * stmt = s? s->data : NULL; DBG_ENTER("mysqlnd_stmt::attr_set"); if (!stmt) { DBG_RETURN(FAIL); @@ -1897,7 +1922,7 @@ MYSQLND_METHOD(mysqlnd_stmt, attr_set)(MYSQLND_STMT * const s, case STMT_ATTR_CURSOR_TYPE: { unsigned int ival = *(unsigned int *) value; if (ival > (zend_ulong) CURSOR_TYPE_READ_ONLY) { - SET_STMT_ERROR(stmt, CR_NOT_IMPLEMENTED, UNKNOWN_SQLSTATE, "Not implemented"); + SET_CLIENT_ERROR(stmt->error_info, CR_NOT_IMPLEMENTED, UNKNOWN_SQLSTATE, "Not implemented"); DBG_INF("FAIL"); DBG_RETURN(FAIL); } @@ -1909,7 +1934,7 @@ MYSQLND_METHOD(mysqlnd_stmt, attr_set)(MYSQLND_STMT * const s, if (ival == 0) { ival = MYSQLND_DEFAULT_PREFETCH_ROWS; } else if (ival > 1) { - SET_STMT_ERROR(stmt, CR_NOT_IMPLEMENTED, UNKNOWN_SQLSTATE, "Not implemented"); + SET_CLIENT_ERROR(stmt->error_info, CR_NOT_IMPLEMENTED, UNKNOWN_SQLSTATE, "Not implemented"); DBG_INF("FAIL"); DBG_RETURN(FAIL); } @@ -1917,7 +1942,7 @@ MYSQLND_METHOD(mysqlnd_stmt, attr_set)(MYSQLND_STMT * const s, break; } default: - SET_STMT_ERROR(stmt, CR_NOT_IMPLEMENTED, UNKNOWN_SQLSTATE, "Not implemented"); + SET_CLIENT_ERROR(stmt->error_info, CR_NOT_IMPLEMENTED, UNKNOWN_SQLSTATE, "Not implemented"); DBG_RETURN(FAIL); } DBG_INF("PASS"); @@ -1932,7 +1957,7 @@ MYSQLND_METHOD(mysqlnd_stmt, attr_get)(const MYSQLND_STMT * const s, enum mysqlnd_stmt_attr attr_type, void * const value) { - MYSQLND_STMT_DATA * stmt = s? s->data:NULL; + MYSQLND_STMT_DATA * stmt = s? s->data : NULL; DBG_ENTER("mysqlnd_stmt::attr_set"); if (!stmt) { DBG_RETURN(FAIL); @@ -1963,9 +1988,11 @@ MYSQLND_METHOD(mysqlnd_stmt, attr_get)(const MYSQLND_STMT * const s, static enum_func_status MYSQLND_METHOD(mysqlnd_stmt, free_result)(MYSQLND_STMT * const s) { - MYSQLND_STMT_DATA * stmt = s? s->data:NULL; + MYSQLND_STMT_DATA * stmt = s? s->data : NULL; + MYSQLND_CONN_DATA * conn = stmt? stmt->conn : NULL; + DBG_ENTER("mysqlnd_stmt::free_result"); - if (!stmt || !stmt->conn) { + if (!stmt || !conn) { DBG_RETURN(FAIL); } DBG_INF_FMT("stmt=%lu", stmt->stmt_id); @@ -2006,7 +2033,7 @@ MYSQLND_METHOD(mysqlnd_stmt, free_result)(MYSQLND_STMT * const s) } /* Line is free! */ - CONN_SET_STATE(stmt->conn, CONN_READY); + SET_CONNECTION_STATE(&conn->state, CONN_READY); DBG_RETURN(PASS); } @@ -2017,7 +2044,7 @@ MYSQLND_METHOD(mysqlnd_stmt, free_result)(MYSQLND_STMT * const s) static void mysqlnd_stmt_separate_result_bind(MYSQLND_STMT * const s) { - MYSQLND_STMT_DATA * stmt = s? s->data:NULL; + MYSQLND_STMT_DATA * stmt = s? s->data : NULL; unsigned int i; DBG_ENTER("mysqlnd_stmt_separate_result_bind"); @@ -2038,8 +2065,7 @@ mysqlnd_stmt_separate_result_bind(MYSQLND_STMT * const s) for (i = 0; i < stmt->field_count; i++) { /* Let's try with no cache */ if (stmt->result_bind[i].bound == TRUE) { - DBG_INF_FMT("%u has refcount=%u", i, - Z_REFCOUNTED(stmt->result_bind[i].zv)? Z_REFCOUNT(stmt->result_bind[i].zv) : 0); + DBG_INF_FMT("%u has refcount=%u", i, Z_REFCOUNTED(stmt->result_bind[i].zv)? Z_REFCOUNT(stmt->result_bind[i].zv) : 0); zval_ptr_dtor(&stmt->result_bind[i].zv); } } @@ -2054,9 +2080,9 @@ mysqlnd_stmt_separate_result_bind(MYSQLND_STMT * const s) /* {{{ mysqlnd_stmt_separate_one_result_bind */ static void -mysqlnd_stmt_separate_one_result_bind(MYSQLND_STMT * const s, unsigned int param_no) +mysqlnd_stmt_separate_one_result_bind(MYSQLND_STMT * const s, const unsigned int param_no) { - MYSQLND_STMT_DATA * stmt = s? s->data:NULL; + MYSQLND_STMT_DATA * stmt = s? s->data : NULL; DBG_ENTER("mysqlnd_stmt_separate_one_result_bind"); if (!stmt) { DBG_VOID_RETURN; @@ -2074,9 +2100,7 @@ mysqlnd_stmt_separate_one_result_bind(MYSQLND_STMT * const s, unsigned int param */ /* Let's try with no cache */ if (stmt->result_bind[param_no].bound == TRUE) { - DBG_INF_FMT("%u has refcount=%u", param_no, - Z_REFCOUNTED(stmt->result_bind[param_no].zv)? - Z_REFCOUNT(stmt->result_bind[param_no].zv) : 0); + DBG_INF_FMT("%u has refcount=%u", param_no, Z_REFCOUNTED(stmt->result_bind[param_no].zv)? Z_REFCOUNT(stmt->result_bind[param_no].zv) : 0); zval_ptr_dtor(&stmt->result_bind[param_no].zv); } @@ -2089,7 +2113,7 @@ mysqlnd_stmt_separate_one_result_bind(MYSQLND_STMT * const s, unsigned int param static void MYSQLND_METHOD(mysqlnd_stmt, free_stmt_result)(MYSQLND_STMT * const s) { - MYSQLND_STMT_DATA * stmt = s? s->data:NULL; + MYSQLND_STMT_DATA * stmt = s? s->data : NULL; DBG_ENTER("mysqlnd_stmt::free_stmt_result"); if (!stmt) { DBG_VOID_RETURN; @@ -2120,7 +2144,7 @@ MYSQLND_METHOD(mysqlnd_stmt, free_stmt_result)(MYSQLND_STMT * const s) static void MYSQLND_METHOD(mysqlnd_stmt, free_stmt_content)(MYSQLND_STMT * const s) { - MYSQLND_STMT_DATA * stmt = s? s->data:NULL; + MYSQLND_STMT_DATA * stmt = s? s->data : NULL; DBG_ENTER("mysqlnd_stmt::free_stmt_content"); if (!stmt) { DBG_VOID_RETURN; @@ -2152,25 +2176,22 @@ MYSQLND_METHOD(mysqlnd_stmt, free_stmt_content)(MYSQLND_STMT * const s) /* }}} */ -/* {{{ mysqlnd_stmt::net_close */ +/* {{{ mysqlnd_stmt::close_on_server */ static enum_func_status -MYSQLND_METHOD_PRIVATE(mysqlnd_stmt, net_close)(MYSQLND_STMT * const s, zend_bool implicit) +MYSQLND_METHOD_PRIVATE(mysqlnd_stmt, close_on_server)(MYSQLND_STMT * const s, zend_bool implicit) { - MYSQLND_STMT_DATA * stmt = s? s->data:NULL; - MYSQLND_CONN_DATA * conn; - zend_uchar cmd_buf[STMT_ID_LENGTH /* statement id */]; + MYSQLND_STMT_DATA * stmt = s? s->data : NULL; + MYSQLND_CONN_DATA * conn = stmt? stmt->conn : NULL; enum_mysqlnd_collected_stats statistic = STAT_LAST; - DBG_ENTER("mysqlnd_stmt::net_close"); - if (!stmt || !stmt->conn) { + DBG_ENTER("mysqlnd_stmt::close_on_server"); + if (!stmt || !conn) { DBG_RETURN(FAIL); } DBG_INF_FMT("stmt=%lu", stmt->stmt_id); - conn = stmt->conn; - - SET_EMPTY_ERROR(*stmt->error_info); - SET_EMPTY_ERROR(*stmt->conn->error_info); + SET_EMPTY_ERROR(stmt->error_info); + SET_EMPTY_ERROR(conn->error_info); /* If the user decided to close the statement right after execute() @@ -2198,13 +2219,21 @@ MYSQLND_METHOD_PRIVATE(mysqlnd_stmt, net_close)(MYSQLND_STMT * const s, zend_boo MYSQLND_INC_GLOBAL_STATISTIC(implicit == TRUE? STAT_FREE_RESULT_IMPLICIT: STAT_FREE_RESULT_EXPLICIT); - int4store(cmd_buf, stmt->stmt_id); - if (CONN_GET_STATE(conn) == CONN_READY && - FAIL == conn->m->simple_command(conn, COM_STMT_CLOSE, cmd_buf, sizeof(cmd_buf), - PROT_LAST /* COM_STMT_CLOSE doesn't send an OK packet*/, - FALSE, TRUE)) { - COPY_CLIENT_ERROR(*stmt->error_info, *conn->error_info); - DBG_RETURN(FAIL); + if (GET_CONNECTION_STATE(&conn->state) == CONN_READY) { + enum_func_status ret = FAIL; + size_t stmt_id = stmt->stmt_id; + struct st_mysqlnd_protocol_command * command = conn->command_factory(COM_STMT_CLOSE, conn, stmt_id); + if (command) { + ret = command->run(command); + command->free_command(command); + + if (ret == FAIL) { + COPY_CLIENT_ERROR(stmt->error_info, *conn->error_info); + } + } + if (ret == FAIL) { + DBG_RETURN(FAIL); + } } } switch (stmt->execute_count) { @@ -2228,8 +2257,8 @@ MYSQLND_METHOD_PRIVATE(mysqlnd_stmt, net_close)(MYSQLND_STMT * const s, zend_boo s->m->free_stmt_content(s); - if (stmt->conn) { - stmt->conn->m->free_reference(stmt->conn); + if (conn) { + conn->m->free_reference(conn); stmt->conn = NULL; } @@ -2252,7 +2281,7 @@ MYSQLND_METHOD(mysqlnd_stmt, dtor)(MYSQLND_STMT * const s, zend_bool implicit) MYSQLND_INC_GLOBAL_STATISTIC(implicit == TRUE? STAT_STMT_CLOSE_IMPLICIT: STAT_STMT_CLOSE_EXPLICIT); - ret = s->m->net_close(s, implicit); + ret = s->m->close_on_server(s, implicit); mnd_pefree(stmt, persistent); } mnd_pefree(s, persistent); @@ -2267,7 +2296,7 @@ MYSQLND_METHOD(mysqlnd_stmt, dtor)(MYSQLND_STMT * const s, zend_bool implicit) static MYSQLND_PARAM_BIND * MYSQLND_METHOD(mysqlnd_stmt, alloc_param_bind)(MYSQLND_STMT * const s) { - MYSQLND_STMT_DATA * stmt = s? s->data:NULL; + MYSQLND_STMT_DATA * stmt = s? s->data : NULL; DBG_ENTER("mysqlnd_stmt::alloc_param_bind"); if (!stmt) { DBG_RETURN(NULL); @@ -2281,7 +2310,7 @@ MYSQLND_METHOD(mysqlnd_stmt, alloc_param_bind)(MYSQLND_STMT * const s) static MYSQLND_RESULT_BIND * MYSQLND_METHOD(mysqlnd_stmt, alloc_result_bind)(MYSQLND_STMT * const s) { - MYSQLND_STMT_DATA * stmt = s? s->data:NULL; + MYSQLND_STMT_DATA * stmt = s? s->data : NULL; DBG_ENTER("mysqlnd_stmt::alloc_result_bind"); if (!stmt) { DBG_RETURN(NULL); @@ -2295,7 +2324,7 @@ MYSQLND_METHOD(mysqlnd_stmt, alloc_result_bind)(MYSQLND_STMT * const s) PHPAPI void MYSQLND_METHOD(mysqlnd_stmt, free_parameter_bind)(MYSQLND_STMT * const s, MYSQLND_PARAM_BIND * param_bind) { - MYSQLND_STMT_DATA * stmt = s? s->data:NULL; + MYSQLND_STMT_DATA * stmt = s? s->data : NULL; if (stmt) { mnd_pefree(param_bind, stmt->persistent); } @@ -2307,7 +2336,7 @@ MYSQLND_METHOD(mysqlnd_stmt, free_parameter_bind)(MYSQLND_STMT * const s, MYSQLN PHPAPI void MYSQLND_METHOD(mysqlnd_stmt, free_result_bind)(MYSQLND_STMT * const s, MYSQLND_RESULT_BIND * result_bind) { - MYSQLND_STMT_DATA * stmt = s? s->data:NULL; + MYSQLND_STMT_DATA * stmt = s? s->data : NULL; if (stmt) { mnd_pefree(result_bind, stmt->persistent); } @@ -2328,7 +2357,7 @@ MYSQLND_CLASS_METHODS_START(mysqlnd_stmt) MYSQLND_METHOD(mysqlnd_stmt, free_result), MYSQLND_METHOD(mysqlnd_stmt, data_seek), MYSQLND_METHOD(mysqlnd_stmt, reset), - MYSQLND_METHOD_PRIVATE(mysqlnd_stmt, net_close), + MYSQLND_METHOD_PRIVATE(mysqlnd_stmt, close_on_server), MYSQLND_METHOD(mysqlnd_stmt, dtor), MYSQLND_METHOD(mysqlnd_stmt, fetch), @@ -2371,18 +2400,6 @@ MYSQLND_CLASS_METHODS_START(mysqlnd_stmt) MYSQLND_CLASS_METHODS_END; -/* {{{ _mysqlnd_stmt_init */ -MYSQLND_STMT * -_mysqlnd_stmt_init(MYSQLND_CONN_DATA * const conn) -{ - MYSQLND_STMT * ret; - DBG_ENTER("_mysqlnd_stmt_init"); - ret = MYSQLND_CLASS_METHOD_TABLE_NAME(mysqlnd_object_factory).get_prepared_statement(conn); - DBG_RETURN(ret); -} -/* }}} */ - - /* {{{ _mysqlnd_init_ps_subsystem */ void _mysqlnd_init_ps_subsystem() { |