diff --git a/libmariadb/mariadb_stmt.c b/libmariadb/mariadb_stmt.c index 7c575721..998aae9b 100644 --- a/libmariadb/mariadb_stmt.c +++ b/libmariadb/mariadb_stmt.c @@ -647,6 +647,9 @@ unsigned char* mysql_stmt_execute_generate_request(MYSQL_STMT *stmt, size_t *req int4store(p, num_rows); p+= 4; + if (!stmt->param_count && stmt->prebind_params) + stmt->param_count= stmt->prebind_params; + if (stmt->param_count) { if (!stmt->array_size) @@ -690,7 +693,8 @@ unsigned char* mysql_stmt_execute_generate_request(MYSQL_STMT *stmt, size_t *req /* this differs from mysqlnd, c api supports unsinged !! */ uint buffer_type= stmt->params[i].buffer_type | (stmt->params[i].is_unsigned ? 32768 : 0); /* check if parameter requires indicator variable */ - if (bulk_supported && stmt->params[i].u.indicator) + if (bulk_supported && + (stmt->params[i].u.indicator || stmt->params[i].buffer_type == MYSQL_TYPE_NULL)) buffer_type|= 16384; int2store(p, buffer_type); p+= 2; @@ -706,9 +710,14 @@ unsigned char* mysql_stmt_execute_generate_request(MYSQL_STMT *stmt, size_t *req my_bool has_data= TRUE; char indicator= 0; - if (bulk_supported && stmt->params[i].u.indicator) + if (bulk_supported && + (stmt->params[i].u.indicator || stmt->params[i].buffer_type == MYSQL_TYPE_NULL)) { - if (stmt->row_size) + if (stmt->params[i].buffer_type == MYSQL_TYPE_NULL) + { + indicator= STMT_INDICATOR_NULL; + } + else if (stmt->row_size) indicator= *(char *)(stmt->params[i].u.indicator + j * stmt->row_size); else indicator= stmt->params[i].u.indicator[j]; @@ -773,21 +782,21 @@ unsigned char* mysql_stmt_execute_generate_request(MYSQL_STMT *stmt, size_t *req goto mem_error; p= start + offset; } + if ((stmt->params[i].is_null && *stmt->params[i].is_null) || + stmt->params[i].buffer_type == MYSQL_TYPE_NULL || + !stmt->params[i].buffer) + { + has_data= FALSE; + if (!stmt->array_size) + (start + null_byte_offset)[i/8] |= (unsigned char) (1 << (i & 7)); + else + indicator= STMT_INDICATOR_NULL; + } if (bulk_supported && (indicator || stmt->params[i].u.indicator)) { int1store(p, indicator); p++; } - if (!stmt->array_size) - { - if ((stmt->params[i].is_null && *stmt->params[i].is_null) || - stmt->params[i].buffer_type == MYSQL_TYPE_NULL || - !stmt->params[i].buffer) - { - (start + null_byte_offset)[i/8] |= (unsigned char) (1 << (i & 7)); - has_data= FALSE; - } - } if (has_data) { store_param(stmt, i, &p, j); diff --git a/unittest/libmariadb/bulk1.c b/unittest/libmariadb/bulk1.c index 14dc8612..405cdf58 100644 --- a/unittest/libmariadb/bulk1.c +++ b/unittest/libmariadb/bulk1.c @@ -63,7 +63,7 @@ static int bulk1(MYSQL *mysql) 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))"); + rc= mysql_query(mysql, "CREATE TABLE bulk1 (a int , b VARCHAR(255))"); check_mysql_rc(rc, mysql); rc= mysql_stmt_prepare(stmt, stmt_str, strlen(stmt_str)); @@ -83,7 +83,7 @@ static int bulk1(MYSQL *mysql) memset(bind, 0, sizeof(MYSQL_BIND) * 2); bind[0].buffer_type= MYSQL_TYPE_LONG; - bind[0].buffer= (int *)&vals[0]; + bind[0].buffer= vals; bind[1].buffer_type= MYSQL_TYPE_STRING; bind[1].buffer= (void *)buffer; bind[1].length= (unsigned long *)lengths; @@ -94,11 +94,11 @@ static int bulk1(MYSQL *mysql) rc= mysql_stmt_bind_param(stmt, bind); check_stmt_rc(rc, stmt); - for (i=0; i < 10; i++) + for (i=0; i < 100; i++) { rc= mysql_stmt_execute(stmt); check_stmt_rc(rc, stmt); - diag("Affected rows: %lld", mysql_stmt_affected_rows(stmt)); + FAIL_IF(mysql_stmt_affected_rows(stmt) != TEST_ARRAY_SIZE, "affected_rows != TEST_ARRAY_SIZE"); } for (i=0; i < array_size; i++) @@ -118,7 +118,7 @@ static int bulk1(MYSQL *mysql) row= mysql_fetch_row(res); intval= atoi(row[0]); mysql_free_result(res); - FAIL_IF(intval != array_size * 10, "Expected 10240 rows"); + FAIL_IF(intval != array_size * 100, "Expected 102400 rows"); rc= mysql_query(mysql, "SELECT MAX(a) FROM bulk1"); check_mysql_rc(rc, mysql); @@ -235,11 +235,57 @@ static int bulk3(MYSQL *mysql) return OK; } +static int bulk_null(MYSQL *mysql) +{ + MYSQL_STMT *stmt= mysql_stmt_init(mysql); + int rc; + MYSQL_BIND bind[2]; + unsigned int param_count= 2; + unsigned int array_size= 2; + unsigned long lengths[2]= {-1, -1}; + const char **buf= calloc(1, 2 * sizeof(char *)); + + buf[0]= strdup("foo"); + buf[1]= strdup("foobar"); + + rc= mariadb_stmt_execute_direct(stmt, "DROP TABLE IF EXISTS bulk_null", -1); + check_stmt_rc(rc, stmt); + + rc= mariadb_stmt_execute_direct(stmt, "CREATE TABLE bulk_null (a int not null auto_increment primary key, b varchar(20))", -1); + check_stmt_rc(rc, stmt); + + memset(bind, 0, 2 * sizeof(MYSQL_BIND)); + bind[0].buffer_type= MYSQL_TYPE_NULL; + bind[1].buffer_type= MYSQL_TYPE_STRING; + bind[1].buffer= buf; + bind[1].length= lengths; + + mysql_stmt_close(stmt); + stmt= mysql_stmt_init(mysql); + + rc= mysql_stmt_attr_set(stmt, STMT_ATTR_PREBIND_PARAMS, ¶m_count); + check_stmt_rc(rc, stmt); + + 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); + + rc= mariadb_stmt_execute_direct(stmt, "INSERT INTO bulk_null VALUES (?, ?)", -1); + check_stmt_rc(rc, stmt); + + mysql_stmt_close(stmt); + return OK; + +} + struct my_tests_st my_tests[] = { {"check_bulk", check_bulk, TEST_CONNECTION_DEFAULT, 0, NULL, NULL}, {"bulk1", bulk1, TEST_CONNECTION_DEFAULT, 0, NULL, NULL}, {"bulk2", bulk2, TEST_CONNECTION_DEFAULT, 0, NULL, NULL}, {"bulk3", bulk3, TEST_CONNECTION_DEFAULT, 0, NULL, NULL}, + {"bulk_null", bulk_null, TEST_CONNECTION_DEFAULT, 0, NULL, NULL}, {NULL, NULL, 0, 0, NULL, NULL} };