diff --git a/include/my_stmt.h b/include/my_stmt.h index 6b8bd67a..37c952fe 100644 --- a/include/my_stmt.h +++ b/include/my_stmt.h @@ -255,3 +255,5 @@ unsigned long STDCALL mysql_stmt_param_count(MYSQL_STMT *stmt); my_bool STDCALL mysql_stmt_send_long_data(MYSQL_STMT *stmt, unsigned int param_number, const char *data, unsigned long length); my_ulonglong STDCALL mysql_stmt_insert_id(MYSQL_STMT *stmt); my_ulonglong STDCALL mysql_stmt_num_rows(MYSQL_STMT *stmt); +MYSQL_RES* STDCALL mysql_stmt_param_metadata(MYSQL_STMT *stmt); +int STDCALL mysql_stmt_next_result(MYSQL_STMT *stmt); diff --git a/include/mysql.h b/include/mysql.h index 451d7381..c02a4939 100644 --- a/include/mysql.h +++ b/include/mysql.h @@ -394,7 +394,7 @@ int STDCALL mysql_real_query(MYSQL *mysql, const char *q, unsigned int length); int STDCALL mysql_create_db(MYSQL *mysql, const char *DB); int STDCALL mysql_drop_db(MYSQL *mysql, const char *DB); -int STDCALL mysql_shutdown(MYSQL *mysql); +int STDCALL mysql_shutdown(MYSQL *mysql, enum mysql_enum_shutdown_level shutdown_level); int STDCALL mysql_dump_debug_info(MYSQL *mysql); int STDCALL mysql_refresh(MYSQL *mysql, unsigned int refresh_options); diff --git a/include/mysql_com.h b/include/mysql_com.h index 93f127fa..0fb8e461 100644 --- a/include/mysql_com.h +++ b/include/mysql_com.h @@ -48,6 +48,12 @@ #define MYSQL_SERVICENAME "MySql" #endif /* _WIN32 */ +enum mysql_enum_shutdown_level +{ + SHUTDOWN_DEFAULT = 0, + KILL_QUERY= 254, + KILL_CONNECTION= 255 +}; enum enum_server_command { @@ -189,7 +195,9 @@ enum enum_server_command #define SERVER_STATUS_LAST_ROW_SENT 128 #define SERVER_STATUS_DB_DROPPED 256 #define SERVER_STATUS_NO_BACKSLASH_ESCAPES 512 - +#define SERVER_STATUS_METADATA_CHANGED 1024 +#define SERVER_QUERY_WAS_SLOW 2048 +#define SERVER_PS_OUT_PARAMS 4096 #define MYSQL_ERRMSG_SIZE 512 #define NET_READ_TIMEOUT 30 /* Timeout on read */ @@ -215,7 +223,6 @@ typedef struct st_net { unsigned char *buff_end,*write_pos,*read_pos; my_socket fd; /* For Perl DBI/dbd */ unsigned long remain_in_buf,length; - unsigned long cmd_buffer_length; unsigned long buf_length, where_b; unsigned long max_packet, max_packet_size; unsigned int pkt_nr, compress_pkt_nr; diff --git a/libmysql/errmsg.c b/libmysql/errmsg.c index a89a58ad..eac53bf5 100644 --- a/libmysql/errmsg.c +++ b/libmysql/errmsg.c @@ -110,13 +110,13 @@ const char *client_errors[]= /* 2027 */ "received malformed packet", /* 2028 */ "", /* 2029 */ "", -/* 2030 */ "", -/* 2031 */ "", +/* 2030 */ "Statement is not prepared", +/* 2031 */ "No data supplied for parameters in prepared statement", /* 2032 */ "", /* 2033 */ "", /* 2034 */ "", /* 2035 */ "", -/* 2036 */ "", +/* 2036 */ "Buffer type is not supported", /* 2037 */ "", /* 2038 */ "", /* 2039 */ "", @@ -132,9 +132,9 @@ const char *client_errors[]= /* 2049 */ "", /* 2050 */ "", /* 2051 */ "", -/* 2052 */ "", +/* 2052 */ "Prepared statement contains no metadata", /* 2053 */ "", -/* 2054 */ "", +/* 2054 */ "This feature is not implemented or disabled", /* 2055 */ "", /* 2056 */ "", /* 2057 */ "The number of parameters in bound buffers differs from number of columns in resultset", diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index cda58b1d..02541bf9 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -2434,15 +2434,16 @@ mysql_drop_db(MYSQL *mysql, const char *db) DBUG_RETURN(simple_command(mysql,MYSQL_COM_DROP_DB,db,(uint) strlen(db),0)); } - +/* In 5.0 this version became an additional parameter shutdown_level */ int STDCALL -mysql_shutdown(MYSQL *mysql) +mysql_shutdown(MYSQL *mysql, enum mysql_enum_shutdown_level shutdown_level) { + uchar s_level[2]; DBUG_ENTER("mysql_shutdown"); - DBUG_RETURN(simple_command(mysql,MYSQL_COM_SHUTDOWN,0,0,0)); + s_level[0]= (uchar)shutdown_level; + DBUG_RETURN(simple_command(mysql, MYSQL_COM_SHUTDOWN, (char *)s_level, 1, 0)); } - int STDCALL mysql_refresh(MYSQL *mysql,uint options) { diff --git a/libmysql/libmysql_exports.def b/libmysql/libmysql_exports.def index 07866b58..306a74d2 100644 --- a/libmysql/libmysql_exports.def +++ b/libmysql/libmysql_exports.def @@ -53,7 +53,7 @@ EXPORTS mysql_num_rows mysql_options mysql_stmt_param_count - ;mysql_stmt_param_metadata + mysql_stmt_param_metadata mysql_ping mysql_stmt_result_metadata mysql_query @@ -102,6 +102,6 @@ EXPORTS mysql_server_end mysql_set_character_set mysql_get_character_set_info - ;mysql_stmt_next_result + mysql_stmt_next_result diff --git a/libmysql/my_auth.c b/libmysql/my_auth.c index 9b58b012..361f611d 100644 --- a/libmysql/my_auth.c +++ b/libmysql/my_auth.c @@ -324,7 +324,7 @@ static int send_client_reply_packet(MCPVIO_EXT *mpvio, Send mysql->client_flag, max_packet_size - unencrypted otherwise the server does not know we want to do SSL */ - if (my_net_write(net, (uchar*)buff, (size_t) (end-buff)) || net_flush(net)) + if (my_net_write(net, (char*)buff, (size_t) (end-buff)) || net_flush(net)) { my_set_error(mysql, CR_SERVER_LOST, SQLSTATE_UNKNOWN, ER(CR_SERVER_LOST_EXTENDED), diff --git a/libmysql/my_stmt.c b/libmysql/my_stmt.c index ab2a5249..66ea1fb1 100644 --- a/libmysql/my_stmt.c +++ b/libmysql/my_stmt.c @@ -58,8 +58,6 @@ static my_bool is_not_null= 0; static my_bool is_null= 1; -const char * const mysql_stmt_not_prepared = "Statement not prepared"; - my_bool is_supported_buffer_type(enum enum_field_types type) { switch (type) { @@ -477,7 +475,7 @@ int store_param(MYSQL_STMT *stmt, int column, unsigned char **p) break; default: /* unsupported parameter type */ - SET_CLIENT_STMT_ERROR(stmt, CR_UNSUPPORTED_PARAM_TYPE, SQLSTATE_UNKNOWN, ""); + SET_CLIENT_STMT_ERROR(stmt, CR_UNSUPPORTED_PARAM_TYPE, SQLSTATE_UNKNOWN, 0); DBUG_RETURN(1); } DBUG_RETURN(0); @@ -637,7 +635,7 @@ unsigned char* mysql_stmt_execute_generate_request(MYSQL_STMT *stmt, size_t *req mem_error: SET_CLIENT_STMT_ERROR(stmt, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0); - my_free((gptr)start, MYF(ALLOW_ZERO_PTR)); + my_free((gptr)start, MYF(MY_ALLOW_ZERO_PTR)); *request_len= 0; DBUG_RETURN(NULL); } @@ -689,7 +687,7 @@ my_bool STDCALL mysql_stmt_attr_set(MYSQL_STMT *stmt, enum enum_stmt_attr_type a case STMT_ATTR_CURSOR_TYPE: { if (*(ulong *)value > (unsigned long) CURSOR_TYPE_READ_ONLY) { - SET_CLIENT_STMT_ERROR(stmt, CR_NOT_IMPLEMENTED, SQLSTATE_UNKNOWN, "Not implemented"); + SET_CLIENT_STMT_ERROR(stmt, CR_NOT_IMPLEMENTED, SQLSTATE_UNKNOWN, 0); DBUG_RETURN(1); } stmt->flags = *(ulong *)value; @@ -703,7 +701,7 @@ my_bool STDCALL mysql_stmt_attr_set(MYSQL_STMT *stmt, enum enum_stmt_attr_type a break; } default: - SET_CLIENT_STMT_ERROR(stmt, CR_NOT_IMPLEMENTED, SQLSTATE_UNKNOWN, "Not implemented"); + SET_CLIENT_STMT_ERROR(stmt, CR_NOT_IMPLEMENTED, SQLSTATE_UNKNOWN, 0); DBUG_RETURN(1); } DBUG_RETURN(0); @@ -714,7 +712,7 @@ my_bool STDCALL mysql_stmt_bind_param(MYSQL_STMT *stmt, MYSQL_BIND *bind) DBUG_ENTER("mysql_stmt_bind_param"); if (stmt->state < MYSQL_STMT_PREPARED) { - SET_CLIENT_STMT_ERROR(stmt, CR_NO_PREPARE_STMT, SQLSTATE_UNKNOWN, mysql_stmt_not_prepared); + SET_CLIENT_STMT_ERROR(stmt, CR_NO_PREPARE_STMT, SQLSTATE_UNKNOWN, 0); DBUG_RETURN(1); } @@ -794,26 +792,38 @@ my_bool STDCALL mysql_stmt_bind_result(MYSQL_STMT *stmt, MYSQL_BIND *bind) if (stmt->state < MYSQL_STMT_PREPARED) { - SET_CLIENT_STMT_ERROR(stmt, CR_NO_PREPARE_STMT, SQLSTATE_UNKNOWN, mysql_stmt_not_prepared); + SET_CLIENT_STMT_ERROR(stmt, CR_NO_PREPARE_STMT, SQLSTATE_UNKNOWN, 0); DBUG_RETURN(1); } if (!stmt->field_count) { - SET_CLIENT_STMT_ERROR(stmt, CR_NO_STMT_METADATA, SQLSTATE_UNKNOWN, "todo: metadata error"); + SET_CLIENT_STMT_ERROR(stmt, CR_NO_STMT_METADATA, SQLSTATE_UNKNOWN, 0); DBUG_RETURN(1); } if (!bind) DBUG_RETURN(1); + /* In case of a stored procedure we don't allocate memory for bind + in mysql_stmt_prepare + */ + if (stmt->field_count && !stmt->bind) + { + if (!(stmt->bind= (MYSQL_BIND *)alloc_root(&stmt->mem_root, stmt->field_count * sizeof(MYSQL_BIND)))) + { + SET_CLIENT_STMT_ERROR(stmt, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0); + DBUG_RETURN(1); + } + } + memcpy(stmt->bind, bind, sizeof(MYSQL_BIND) * stmt->field_count); for (i=0; i < stmt->field_count; i++) { if (!is_supported_buffer_type(bind[i].buffer_type)) { - SET_CLIENT_STMT_ERROR(stmt, CR_UNSUPPORTED_PARAM_TYPE, SQLSTATE_UNKNOWN, ""); + SET_CLIENT_STMT_ERROR(stmt, CR_UNSUPPORTED_PARAM_TYPE, SQLSTATE_UNKNOWN, 0); DBUG_RETURN(1); } @@ -1279,8 +1289,7 @@ int STDCALL mysql_stmt_execute(MYSQL_STMT *stmt) if (stmt->param_count && !stmt->bind_param_done) { - SET_CLIENT_STMT_ERROR(stmt, CR_PARAMS_NOT_BOUND, SQLSTATE_UNKNOWN, - "No data supplied for parameters in prepared statement"); + SET_CLIENT_STMT_ERROR(stmt, CR_PARAMS_NOT_BOUND, SQLSTATE_UNKNOWN, 0); DBUG_RETURN(1); } @@ -1529,7 +1538,7 @@ my_bool STDCALL mysql_stmt_send_long_data(MYSQL_STMT *stmt, uint param_number, if (stmt->state < MYSQL_STMT_PREPARED || !stmt->params) { - SET_CLIENT_STMT_ERROR(stmt, CR_NO_PREPARE_STMT, SQLSTATE_UNKNOWN, mysql_stmt_not_prepared); + SET_CLIENT_STMT_ERROR(stmt, CR_NO_PREPARE_STMT, SQLSTATE_UNKNOWN, 0); DBUG_RETURN(1); } @@ -1565,3 +1574,47 @@ my_ulonglong STDCALL mysql_stmt_num_rows(MYSQL_STMT *stmt) return stmt->result.rows; } +MYSQL_RES* STDCALL mysql_stmt_param_metadata(MYSQL_STMT *stmt) +{ + DBUG_ENTER("mysql_stmt_param_metadata"); + /* server doesn't deliver any information yet, + so we just return NULL + */ + DBUG_RETURN(NULL); +} + +int STDCALL mysql_stmt_next_result(MYSQL_STMT *stmt) +{ + DBUG_ENTER("mysql_stmt_next_result"); + + if (!stmt->mysql) + { + SET_CLIENT_STMT_ERROR(stmt, CR_SERVER_LOST, SQLSTATE_UNKNOWN, 0); + DBUG_RETURN(1); + } + + /* test_pure_coverage requires checking of error_no */ + if (stmt->last_errno) + DBUG_RETURN(1); + + if (stmt->state < MYSQL_STMT_EXECUTED) + { + SET_CLIENT_ERROR(stmt->mysql, CR_COMMANDS_OUT_OF_SYNC, SQLSTATE_UNKNOWN, 0); + SET_CLIENT_STMT_ERROR(stmt, CR_COMMANDS_OUT_OF_SYNC, SQLSTATE_UNKNOWN, 0); + DBUG_RETURN(1); + } + + if (!mysql_more_results(stmt->mysql)) + DBUG_RETURN(-1); + + mysql_stmt_reset(stmt); + stmt->state= MYSQL_STMT_WAITING_USE_OR_STORE; + + if (mysql_next_result(stmt->mysql)) + { + SET_CLIENT_STMT_ERROR(stmt, stmt->mysql->net.last_errno, stmt->mysql->net.sqlstate, + stmt->mysql->net.last_error); + DBUG_RETURN(1); + } + DBUG_RETURN(0); +}