/*Compiling: gcc -o prepare_statement_bug prepare_statement_bug.cpp `mysql_config --include --libs_r`*/ #include #include #include #include int execute_statement_as_date(MYSQL_STMT* stmt, MYSQL_TIME value) { MYSQL_BIND bind = {0}; bind.buffer_type = MYSQL_TYPE_DATE; bind.buffer = (char*)&value; bind.is_null = 0; bind.length = 0; if (mysql_stmt_bind_param(stmt, &bind)) { fprintf(stderr, "File %s, line %d, Error: %d:%s\n", __FILE__, __LINE__, mysql_stmt_errno(stmt), mysql_stmt_error(stmt)); return EXIT_FAILURE; } if ( mysql_stmt_execute(stmt) != 0) { fprintf(stderr, "File %s, line %d, Error: %d:%s\n", __FILE__, __LINE__, mysql_stmt_errno(stmt), mysql_stmt_error(stmt)); return EXIT_FAILURE; } return EXIT_SUCCESS; } int execute_statement_as_string(MYSQL_STMT* stmt, const char* value) { MYSQL_BIND bind = {0}; unsigned long str_length = strlen(value); bind.buffer_type = MYSQL_TYPE_STRING; bind.buffer = (char*)value; bind.buffer_length = str_length; bind.is_null = 0; bind.length = &str_length; if (mysql_stmt_bind_param(stmt, &bind)) { fprintf(stderr, "File %s, line %d, Error: %d:%s\n", __FILE__, __LINE__, mysql_stmt_errno(stmt), mysql_stmt_error(stmt)); return EXIT_FAILURE; } if ( mysql_stmt_execute(stmt) != 0) { fprintf(stderr, "File %s, line %d, Error: %d:%s\n", __FILE__, __LINE__, mysql_stmt_errno(stmt), mysql_stmt_error(stmt)); return EXIT_FAILURE; } return EXIT_SUCCESS; } int check_prepared_statement(MYSQL* mysql, bool b) { MYSQL_STMT* stmt = mysql_stmt_init(mysql); if (!stmt) { fprintf(stderr, "File %s, line %d, Error: %s\n", __FILE__, __LINE__, mysql_error(mysql)); return EXIT_FAILURE; } const char query[] = "INSERT INTO testDB.testTable VALUES (?)"; if (mysql_stmt_prepare(stmt, query, sizeof(query) - 1)) { fprintf(stderr, "File %s, line %d, Error: %s\n", __FILE__, __LINE__, mysql_error(mysql)); return EXIT_FAILURE; } if (b) { if (execute_statement_as_date(stmt, {2021, 1, 1, 0, 0, 0})) { fprintf(stderr, "File %s, line %d, Error: %s\n", __FILE__, __LINE__, mysql_error(mysql)); return EXIT_FAILURE; } } if (execute_statement_as_string(stmt, "2021-01-01 12:00:00")) { fprintf(stdout, "execute_statement_as_string() is failing and is correct behaviour\n"); mysql_stmt_close(stmt); return EXIT_SUCCESS; } else { fprintf(stdout, "execute_statement_as_string() is NOT failing and is incorrect behaviour\n"); } mysql_stmt_close(stmt); return EXIT_FAILURE; } int main(int argc, char** argv) { MYSQL* mysql = mysql_init(NULL); if (!mysql) { fprintf(stderr, "File %s, line %d, Error: %s\n", __FILE__, __LINE__, mysql_error(mysql)); return EXIT_FAILURE; } if (!mysql_real_connect(mysql, "testinfra-mysql8gr1", "root", "root", NULL, 33306, NULL, 0)) { fprintf(stderr, "File %s, line %d, Error: %s\n", __FILE__, __LINE__, mysql_error(mysql)); return EXIT_FAILURE; } if (mysql_query(mysql, "CREATE DATABASE IF NOT EXISTS testDB")) { fprintf(stderr, "File %s, line %d, Error: %s\n", __FILE__, __LINE__, mysql_error(mysql)); return EXIT_FAILURE; } if (mysql_query(mysql, "DROP TABLE IF EXISTS testDB.testTable")) { fprintf(stderr, "File %s, line %d, Error: %s\n", __FILE__, __LINE__, mysql_error(mysql)); return EXIT_FAILURE; } if (mysql_query(mysql, "CREATE TABLE IF NOT EXISTS testDB.testTable (y YEAR)")) { fprintf(stderr, "File %s, line %d, Error: %s\n", __FILE__, __LINE__, mysql_error(mysql)); return EXIT_FAILURE; } if (mysql_query(mysql, "SET sql_mode='ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION'")) { fprintf(stderr, "File %s, line %d, Error: %s\n", __FILE__, __LINE__, mysql_error(mysql)); return EXIT_FAILURE; } fprintf(stdout, ">> Executing statement with DATE and STRING type ...\n"); check_prepared_statement(mysql, true); fprintf(stdout, ">> Done\n"); fprintf(stdout, ">> Executing statement with STRING type only ...\n"); check_prepared_statement(mysql, false); fprintf(stdout, ">> Done\n"); mysql_close(mysql); return EXIT_SUCCESS; }