Details
-
Bug
-
Status: Closed (View Workflow)
-
Critical
-
Resolution: Not a Bug
-
3.4.7
-
win10;
Description
Is it true that explicit insertion without bulk cannot prompt the use of default values
int main() |
{
|
|
::MYSQL *mysql = defalt_init_mysql();
|
|
// 清理测试数据 |
drop_table(mysql, "test_times"); |
|
// 创建测试表,只包含枚举字段 |
const char *create_sql = R"( |
CREATE TABLE test_times (
|
id INT PRIMARY KEY AUTO_INCREMENT, |
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
last_login TIMESTAMP NULL
|
)
|
)";
|
execute_sql(mysql, create_sql);
|
|
// NOTE: bulk OK |
{
|
// 准备插入语句 |
const char *insert_sql = "INSERT INTO test_times (id,created_at, updated_at, " |
"last_login) VALUES (?,?, ?, ?)"; |
MYSQL_STMT *stmt = mysql_stmt_init(mysql);
|
|
if (mysql_stmt_prepare(stmt, insert_sql, strlen(insert_sql))) |
{
|
show_mysql_error(mysql, "准备语句失败"); |
return -1; |
}
|
|
// 设置批量大小 |
constexpr unsigned int array_size = 3; |
mysql_stmt_attr_set(stmt, STMT_ATTR_ARRAY_SIZE, &array_size);
|
|
// 准备数据数组 |
MYSQL_TIME created_at[array_size]{}; // created_at 时间戳 |
MYSQL_TIME updated_at[array_size]{}; // updated_at 时间戳 |
MYSQL_TIME last_login[array_size]{}; // last_login 时间戳 |
my_bool created_at_null[array_size]{}; // created_at NULL 标记 |
my_bool updated_at_null[array_size]{}; // updated_at NULL 标记 |
my_bool last_login_null[array_size]{}; // last_login NULL 标记 |
|
created_at[0].year = 2023;
|
created_at[0].month = 5;
|
created_at[0].day = 15;
|
created_at[0].hour = 14;
|
created_at[0].minute = 30;
|
created_at[0].second = 45;
|
|
created_at[1].year = 2023;
|
created_at[1].month = 5;
|
created_at[1].day = 16;
|
created_at[1].hour = 15;
|
created_at[1].minute = 31;
|
created_at[1].second = 46;
|
|
created_at[2].year = 2023;
|
created_at[2].month = 5;
|
created_at[2].day = 17;
|
created_at[2].hour = 16;
|
created_at[2].minute = 32;
|
created_at[2].second = 47;
|
created_at[2].second_part = 123456;
|
|
updated_at[0].year = 2023;
|
updated_at[0].month = 5;
|
updated_at[0].day = 15;
|
updated_at[0].hour = 14;
|
updated_at[0].minute = 30;
|
updated_at[0].second = 45;
|
|
updated_at[1].year = 2023;
|
updated_at[1].month = 5;
|
updated_at[1].day = 16;
|
updated_at[1].hour = 15;
|
updated_at[1].minute = 31;
|
updated_at[1].second = 46;
|
|
updated_at[2].year = 2023;
|
updated_at[2].month = 5;
|
updated_at[2].day = 17;
|
updated_at[2].hour = 16;
|
updated_at[2].minute = 32;
|
updated_at[2].second = 47;
|
updated_at[2].second_part = 123456;
|
|
std::vector<MYSQL_TIME *> created_at_ptr{&created_at[0], &created_at[1],
|
&created_at[2]};
|
std::vector<MYSQL_TIME *> updated_at_ptr{&updated_at[0], &updated_at[1],
|
&updated_at[2]};
|
|
// 绑定参数 |
MYSQL_BIND bind[4]{};
|
memset(bind, 0, sizeof(bind)); |
char null_ind[] = {::STMT_INDICATOR_NULL, ::STMT_INDICATOR_NULL, |
::STMT_INDICATOR_NULL};
|
char default_ind[] = {::STMT_INDICATOR_DEFAULT, ::STMT_INDICATOR_DEFAULT, |
::STMT_INDICATOR_DEFAULT};
|
bind[0].buffer_type = MYSQL_TYPE_LONG;
|
bind[0].u.indicator = null_ind;
|
|
// created_at 参数 |
// bind[1].buffer_type = MYSQL_TYPE_TIMESTAMP; |
bind[1].buffer_type = MYSQL_TYPE_STRING;
|
// bind[1].buffer = created_at_ptr.data(); |
// bind[1].u.indicator = null_ind; // NOTE: 会是null |
bind[1].u.indicator = default_ind; // NOTE: 会填默认值 |
|
// updated_at 参数 |
// bind[2].buffer_type = MYSQL_TYPE_TIMESTAMP; |
bind[2].buffer_type = MYSQL_TYPE_STRING;
|
// bind[2].buffer = updated_at_ptr.data(); |
// bind[2].u.indicator = null_ind; // NOTE: 会是null |
bind[2].u.indicator = default_ind; // NOTE: 会填默认值 |
|
// last_login 参数 |
bind[3].buffer_type = MYSQL_TYPE_TIMESTAMP;
|
// bind[3].buffer = last_login; |
bind[3].u.indicator = null_ind;
|
|
if (mysql_stmt_bind_param(stmt, bind)) |
{
|
show_mysql_error(mysql, "绑定参数失败"); |
mysql_stmt_close(stmt);
|
return -1; |
}
|
|
// 执行插入 |
if (mysql_stmt_execute(stmt)) |
{
|
show_mysql_error(mysql, "执行失败"); |
}
|
else |
{
|
std::cout << "插入成功!" << std::endl; |
}
|
mysql_stmt_close(stmt);
|
}
|
|
// NOTE: has bug |
{
|
const char *insert_sql = "INSERT INTO test_times (id,created_at, updated_at, " |
"last_login) VALUES (?,?,?,?)"; |
MYSQL_STMT *stmt = mysql_stmt_init(mysql);
|
char null_ind = STMT_INDICATOR_NULL; |
char default_ind = ::STMT_INDICATOR_DEFAULT; |
|
MYSQL_BIND bind[4]{};
|
bind[0].buffer_type = MYSQL_TYPE_LONG;
|
bind[0].u.indicator = &null_ind;
|
|
bind[1].buffer_type = MYSQL_TYPE_TIMESTAMP;
|
bind[1].u.indicator = &default_ind;
|
|
bind[2].buffer_type = MYSQL_TYPE_STRING;
|
bind[2].u.indicator = &default_ind;
|
|
bind[3].buffer_type = MYSQL_TYPE_STRING;
|
// NOTE: if TEST_BUG==0 ,It is NULL instead of DEFAULT in(created_at,updated_at) |
#define TEST_BUG 1
|
#define TEST_CRASH 0
|
|
#if TEST_BUG
|
|
#if TEST_CRASH
|
bind[3].is_null_value = 1;
|
#else
|
bind[3].u.indicator = &null_ind;
|
#endif
|
|
#else
|
bind[3].is_null_value = 1;
|
#endif
|
|
if (mysql_stmt_prepare(stmt, insert_sql, strlen(insert_sql))) |
{
|
show_mysql_error(mysql, "准备语句失败"); |
return -1; |
}
|
|
#if TEST_BUG
|
// NOTE: requires all column'attr-indicator be set. other crash |
constexpr unsigned int array_size = 1; |
mysql_stmt_attr_set(stmt, STMT_ATTR_ARRAY_SIZE, &array_size);
|
#endif
|
|
if (mysql_stmt_bind_param(stmt, bind)) |
{
|
show_mysql_error(mysql, "绑定参数失败"); |
mysql_stmt_close(stmt);
|
return -1; |
}
|
|
// 执行插入 |
if (mysql_stmt_execute(stmt)) |
{
|
show_mysql_error(mysql, "执行失败"); |
}
|
else |
{
|
std::cout << "插入成功!" << std::endl; |
}
|
mysql_stmt_close(stmt);
|
}
|
// NOTE: Single insertion cannot work with mix indicator |
|
::mysql_close(mysql);
|
std::cout << "main done\n"; |
return 0; |
}
|