diff --git a/include/errmsg.h b/include/errmsg.h index f22db164..7d63580f 100644 --- a/include/errmsg.h +++ b/include/errmsg.h @@ -115,10 +115,11 @@ extern const char *mariadb_client_errors[]; /* Error messages */ #define CR_BINLOG_INVALID_FILE 5022 #define CR_BINLOG_SEMI_SYNC_ERROR 5023 #define CR_INVALID_CLIENT_FLAG 5024 +#define CR_ERR_MISSING_ERROR_INFO 5026 /* Always last, if you add new error codes please update the value for CR_MARIADB_LAST_ERROR */ -#define CR_MARIADB_LAST_ERROR CR_INVALID_CLIENT_FLAG +#define CR_MARIADB_LAST_ERROR CR_ERR_MISSING_ERROR_INFO #endif diff --git a/libmariadb/ma_errmsg.c b/libmariadb/ma_errmsg.c index 90218573..14e2e3b5 100644 --- a/libmariadb/ma_errmsg.c +++ b/libmariadb/ma_errmsg.c @@ -119,6 +119,8 @@ const char *mariadb_client_errors[] = /* 5022 */ "File '%s' is not a binary log file", /* 5023 */ "Semi sync request error: %s", /* 5024 */ "Invalid client flags (%lu) specified. Supported flags: %lu", + /* 5025 */ "", + /* 5026 */ "Server returned an error packet without further information", "" }; diff --git a/libmariadb/mariadb_lib.c b/libmariadb/mariadb_lib.c index f1053dd3..02d0f872 100644 --- a/libmariadb/mariadb_lib.c +++ b/libmariadb/mariadb_lib.c @@ -274,6 +274,11 @@ restart: ma_strmake(net->last_error,(char*) pos, min(len,sizeof(net->last_error)-1)); } + /* MDEV-35935: if server sends error packet without error, we have to + set error manually */ + if (!net->last_errno) { + my_set_error(mysql, CR_ERR_MISSING_ERROR_INFO, SQLSTATE_UNKNOWN, 0); + } } else { diff --git a/unittest/libmariadb/errors.c b/unittest/libmariadb/errors.c index b0914782..2f895c9d 100644 --- a/unittest/libmariadb/errors.c +++ b/unittest/libmariadb/errors.c @@ -272,8 +272,77 @@ static int test_parse_error_and_bad_length(MYSQL *mysql) return OK; } +#define TEST_ARRAY_SIZE 1024 + +static int test_mdev35935(MYSQL *mysql) +{ + MYSQL_STMT *stmt= mysql_stmt_init(mysql); + const char *stmt_str= "INSERT INTO bulk1 (a,b) VALUES (?,?)"; + unsigned int array_size= TEST_ARRAY_SIZE; + int rc; + unsigned int i; + char **buffer; + unsigned long *lengths; + unsigned int *vals; + MYSQL_BIND bind[2]; + const char *data= "test"; + + SKIP_MYSQL(mysql); + + rc= mysql_select_db(mysql, schema); + + rc= mysql_query(mysql, "DROP TABLE IF EXISTS bulk1"); + check_mysql_rc(rc, mysql); + + rc= mysql_query(mysql, "CREATE TABLE bulk1 (a int , b VARCHAR(255))"); + check_mysql_rc(rc, mysql); + + rc= mysql_stmt_prepare(stmt, SL(stmt_str)); + check_stmt_rc(rc, stmt); + + rc= mysql_query(mysql, "ALTER TABLE bulk1 ADD c int"); + check_mysql_rc(rc, mysql); + + /* allocate memory */ + buffer= calloc(TEST_ARRAY_SIZE, sizeof(char *)); + lengths= calloc(TEST_ARRAY_SIZE, sizeof *lengths); + vals= calloc(TEST_ARRAY_SIZE, sizeof *vals); + + for (i=0; i < TEST_ARRAY_SIZE; i++) + { + buffer[i]= (void *)data; + lengths[i]= -1; + vals[i]= i; + } + + memset(bind, 0, sizeof(MYSQL_BIND) * 2); + bind[0].buffer_type= MYSQL_TYPE_LONG; + bind[0].buffer= vals; + bind[1].buffer_type= MYSQL_TYPE_STRING; + bind[1].buffer= (void *)buffer; + bind[1].length= (unsigned long *)lengths; + + rc= mysql_stmt_attr_set(stmt, STMT_ATTR_ARRAY_SIZE, &array_size); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_bind_param(stmt, bind); + check_stmt_rc(rc, stmt); + + if ((rc= mysql_stmt_execute(stmt))) + { + FAIL_IF((!mysql_stmt_errno(stmt) || !mysql_errno(mysql)), "Error number > 0 expected"); + } + + mysql_stmt_close(stmt); + rc= mysql_query(mysql, "DROP TABLE IF EXISTS bulk1"); + check_mysql_rc(rc, mysql); + return OK; +} + + struct my_tests_st my_tests[] = { + {"test_mdev35935", test_mdev35935, TEST_CONNECTION_DEFAULT, 0, NULL , NULL}, {"test_client_warnings", test_client_warnings, TEST_CONNECTION_DEFAULT, 0, NULL , NULL}, {"test_ps_client_warnings", test_ps_client_warnings, TEST_CONNECTION_DEFAULT, 0, NULL , NULL}, {"test_server_warnings", test_server_warnings, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},