Skip to content

Commit

Permalink
ODBC-449 Fractional seconds could be lost with SQLExecDirect
Browse files Browse the repository at this point in the history
That happend that with text protocol fractional part wasn't internally
converted to microseconds as it's expected by functions converting data
to ODBC structures. Natuarally, binary protocol, i.e. (SQLPrepare +
SQLExecute) were not affected.
The commit contains the testcase.
  • Loading branch information
lawrinn committed Jan 12, 2025
1 parent 61faaee commit 8ff6c0f
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 42 deletions.
22 changes: 21 additions & 1 deletion driver/interface/ResultSet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -342,7 +342,27 @@ namespace mariadb
time->second= static_cast<uint32_t>(std::stoll(str.substr(offset + 6, 2)));
time->second_part= 0;
if (str[offset + 8] == '.') {
time->second_part= static_cast<uint32_t>(std::stoll(str.substr(offset + 9, std::min(str.length() - offset - 9, static_cast<std::size_t>(6)))));
auto fractPartLen= std::min(str.length() - offset - 9, std::size_t(6));
time->second_part= static_cast<unsigned long>(std::stoll(str.substr(offset + 9, fractPartLen)));
// Need to make it microseconds
switch (fractPartLen) {
case 1:
time->second_part*= 10000;
break;
case 2:
time->second_part*= 10000;
break;
case 3:
time->second_part*= 1000;
break;
case 4:
time->second_part*= 100;
break;
case 5:
time->second_part*= 10;
default:
break;
}
}
}

Expand Down
1 change: 1 addition & 0 deletions driver/ma_helper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -742,6 +742,7 @@ SQLRETURN MADB_CopyMadbTimestamp(MADB_Stmt *Stmt, MYSQL_TIME *tm, SQLPOINTER Dat
ts->year= tm->year;
ts->month= tm->month;
ts->day= tm->day;
// Microseconds of MYSQL_TIME to nanoseconds of SQL_TIMESTAMP_STRUCT
ts->fraction= tm->second_part * 1000;
}
ts->hour= tm->hour;
Expand Down
53 changes: 52 additions & 1 deletion test/datetime.c
Original file line number Diff line number Diff line change
Expand Up @@ -1523,7 +1523,7 @@ ODBC_TEST(t_odbc199_time2timestamp)
SQL_TIME_STRUCT t;
SQL_TIMESTAMP_STRUCT ts= {0}, ts1= {0};
time_t sec_time;
struct tm * cur_tm;
struct tm *cur_tm;

sec_time= time(NULL);
cur_tm= localtime(&sec_time);
Expand Down Expand Up @@ -1641,6 +1641,56 @@ ODBC_TEST(t_odbc345)
}


ODBC_TEST(t_odbc449)
{
SQL_TIMESTAMP_STRUCT ts= {0}, r1= {0};
unsigned long fractional[]= {0,100000000,120000000,20000000,23000000,3000000,0};
char asStr[32];
size_t rowNum= 0;

ts.year= 2025;
ts.month= 1;
ts.day= 1;
ts.hour= 12;
ts.minute= 0;
ts.second= 0;
ts.fraction= 123000000;

OK_SIMPLE_STMT(Stmt, "DROP TABLE IF EXISTS t_odbc449");
OK_SIMPLE_STMT(Stmt, "CREATE TABLE t_odbc449 (dtf DATETIME(3) NOT NULL)");

CHECK_STMT_RC(Stmt, SQLExecDirect(Stmt, "INSERT INTO t_odbc449(dtf) VALUES ('2025-01-01 12:00:00.123'),('2025-01-01 12:00:00.1'),\
('2025-01-01 12:00:00.12'),('2025-01-01 12:00:00.02'),('2025-01-01 12:00:00.023'),('2025-01-01 12:00:00.003')", SQL_NTS));;

OK_SIMPLE_STMT(Stmt, "SELECT dtf FROM t_odbc449");

CHECK_STMT_RC(Stmt, SQLBindCol(Stmt, 1, SQL_C_TIMESTAMP, &r1,sizeof(r1), NULL));

while (SQL_SUCCEEDED(SQLFetch(Stmt)))
{
is_num(ts.year, r1.year);
is_num(ts.month, r1.month);
is_num(ts.day, r1.day);
is_num(ts.hour, r1.hour);
is_num(ts.minute, r1.minute);
is_num(ts.second, r1.second);
is_num(ts.fraction, r1.fraction);

if (!rowNum)
{
IS_STR("2025-01-01 12:00:00.123", my_fetch_str(Stmt, asStr, 1), sizeof("2025-01-01 12:00:00.123"));
}
++rowNum;
ts.fraction= fractional[rowNum];
}
is_num(6, rowNum);
CHECK_STMT_RC(Stmt, SQLCloseCursor(Stmt));

OK_SIMPLE_STMT(Stmt, "DROP TABLE t_odbc449");

return OK;
}

MA_ODBC_TESTS my_tests[]=
{
{my_ts, "my_ts", NORMAL},
Expand Down Expand Up @@ -1669,6 +1719,7 @@ MA_ODBC_TESTS my_tests[]=
{t_odbc148, "t_odbc148_datatypes_values_len", NORMAL},
{t_odbc199_time2timestamp, "t_odbc199_time2timestamp", NORMAL},
{t_odbc345, "t_odbc345", NORMAL},
{t_odbc449, "t_odbc449", NORMAL},
{NULL, NULL}
};

Expand Down
40 changes: 0 additions & 40 deletions test/relative.c
Original file line number Diff line number Diff line change
Expand Up @@ -787,48 +787,8 @@ ODBC_TEST(t_rows_fetched_ptr1)
}


ODBC_TEST(bench)
{
SQLINTEGER id= 0;
SQLCHAR val[32];
size_t i;

for (i= 0; i < 500; ++i) {
SQLExecDirect(Stmt, (SQLCHAR*)"SELECT * FROM 1000rows", SQL_NTS);

while (SQLFetch(Stmt) != SQL_NO_DATA) {
SQLGetData(Stmt, 1, SQL_INTEGER, &id, 0, NULL);
SQLGetData(Stmt, 2, SQL_VARCHAR, &val, sizeof(val), NULL);
}
SQLFreeStmt(Stmt, SQL_CLOSE);
}
return OK;
}


ODBC_TEST(bench1)
{
size_t i;

for (i= 0; i < 200; ++i) {
SQLPrepare(Stmt, (SQLCHAR*)"DO ?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?",
SQL_NTS);
for (int i = 1; i <= 1000; i++) {
SQLBindParameter(Stmt, i, SQL_PARAM_INPUT, SQL_C_LONG,
SQL_INTEGER, 0, 0, &i, 0, NULL);
}
// Execute query
SQLExecute(Stmt);
SQLFreeStmt(Stmt, SQL_CLOSE);
}
return OK;
}


MA_ODBC_TESTS my_tests[]=
{
//{bench, "bench"},
//{bench1, "bench1"},
{t_relative, "t_relative"},
{t_relative1, "t_relative1"},
{t_relative2, "t_relative2"},
Expand Down

0 comments on commit 8ff6c0f

Please sign in to comment.