From 488800aecf13a5c30a335c1a243a4bb973c46b4f Mon Sep 17 00:00:00 2001 From: Shigehisa KYODA Date: Sat, 5 Sep 2026 13:52:14 +0900 Subject: [PATCH] Fix sign extension for unsigned TINYINT in SSPS --- driver/my_prepared_stmt.cc | 2 +- test/my_prepare.c | 58 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+), 1 deletion(-) diff --git a/driver/my_prepared_stmt.cc b/driver/my_prepared_stmt.cc index d23070727..7d4c5830e 100644 --- a/driver/my_prepared_stmt.cc +++ b/driver/my_prepared_stmt.cc @@ -1463,7 +1463,7 @@ T ssps_get_int64(STMT *stmt, ulong column_number, char *value, ulong length) case 1: if (is_it_unsigned) { - ret = !is_it_null? ((char *)col_rbind->buffer)[0]:0; + ret = !is_it_null? ((unsigned char *)col_rbind->buffer)[0]:0; } else { diff --git a/test/my_prepare.c b/test/my_prepare.c index c7cec4279..1f8b18b21 100644 --- a/test/my_prepare.c +++ b/test/my_prepare.c @@ -91,6 +91,62 @@ DECLARE_TEST(t_prep_basic) } +/* + TINYINT UNSIGNED values >= 128 must be fetched without sign extension + through server-side prepared statements. +*/ +DECLARE_TEST(t_prep_tinyint_unsigned) +{ + char value[32]; + SQLLEN length; + + ok_sql(hstmt, "DROP TABLE IF EXISTS t_prep_tinyint_unsigned"); + + ok_sql(hstmt, + "CREATE TABLE t_prep_tinyint_unsigned " + "(value_u TINYINT UNSIGNED)"); + + ok_sql(hstmt, + "INSERT INTO t_prep_tinyint_unsigned VALUES " + "(0),(127),(128),(200),(255)"); + + ok_stmt(hstmt, + SQLPrepare(hstmt, + SC_NTS("SELECT value_u " + "FROM t_prep_tinyint_unsigned " + "ORDER BY value_u"))); + + ok_stmt(hstmt, SQLExecute(hstmt)); + + ok_stmt(hstmt, + SQLBindCol(hstmt, 1, SQL_C_CHAR, + value, sizeof(value), &length)); + + ok_stmt(hstmt, SQLFetch(hstmt)); + is_str(value, "0", 2); + + ok_stmt(hstmt, SQLFetch(hstmt)); + is_str(value, "127", 4); + + ok_stmt(hstmt, SQLFetch(hstmt)); + is_str(value, "128", 4); + + ok_stmt(hstmt, SQLFetch(hstmt)); + is_str(value, "200", 4); + + ok_stmt(hstmt, SQLFetch(hstmt)); + is_str(value, "255", 4); + + expect_stmt(hstmt, SQLFetch(hstmt), SQL_NO_DATA); + + ok_stmt(hstmt, SQLFreeStmt(hstmt, SQL_CLOSE)); + + ok_sql(hstmt, "DROP TABLE IF EXISTS t_prep_tinyint_unsigned"); + + return OK; +} + + /* to test buffer length */ DECLARE_TEST(t_prep_buffer_length) { @@ -1275,8 +1331,10 @@ DECLARE_TEST(t_bug31667091) return OK; } + BEGIN_TESTS ADD_TEST(t_prep_basic) + ADD_TEST(t_prep_tinyint_unsigned) ADD_TEST(t_prep_buffer_length) ADD_TEST(t_prep_truncate) ADD_TEST(t_prep_scroll)