Skip to content

Commit

Permalink
ODBC-350 The fix and the testcase
Browse files Browse the repository at this point in the history
It's rather the workaround of the bug in the server - for bit(1) value in
subquery it returns string representation of the value, i.e. '0' or '1'
instead of '\0' or '\1', while reporting the type to be MYSQL_BIT

Update of C/C to v3.3.5

Removed eol'ed server versions from travis
  • Loading branch information
lawrinn committed Jun 2, 2023
1 parent 9b96270 commit 60a5bd6
Show file tree
Hide file tree
Showing 9 changed files with 90 additions and 15 deletions.
6 changes: 2 additions & 4 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -87,16 +87,14 @@ jobs:
os: windows
language: shell
name: "CS 10.6 - Windows"
- env: srv=mariadb v=10.3 local=1
name: "CS 10.3"
- env: srv=mariadb v=10.11 local=1
name: "CS 10.11"
- env: srv=mariadb v=10.4 local=1
name: "CS 10.4"
- env: srv=mariadb v=10.5 local=1
name: "CS 10.5"
- env: srv=mariadb v=10.10 local=1
name: "CS 10.10"
- env: srv=mariadb v=10.8 local=1
name: "CS 10.8"
- env: srv=mariadb v=10.9 local=1
name: "CS 10.9"
- env: srv=mysql v=5.7
Expand Down
3 changes: 1 addition & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# ************************************************************************************
# Copyright (C) 2013,2022 MariaDB Corporation AB
# Copyright (C) 2013,2023 MariaDB Corporation AB
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Library General Public
Expand Down Expand Up @@ -131,7 +131,6 @@ IF(WIN32)
STRING(REPLACE "/Zi" "/ZI" COMPILER_FLAGS ${COMPILER_FLAGS})
ENDIF(NOT WITH_ASAN)
MESSAGE (STATUS "CMAKE_${COMPILER}_FLAGS_${BUILD_TYPE}= ${COMPILER_FLAGS}")
MESSAGE (STATUS "CMAKE_SHARED_LINKER_FLAGS_${BUILD_TYPE}= ${CMAKE_SHARED_LINKER_FLAGS_${BUILD_TYPE}}")
SET(CMAKE_${COMPILER}_FLAGS_${BUILD_TYPE} ${COMPILER_FLAGS} CACHE
STRING "overwritten by mariadb-odbc" FORCE)
ENDIF()
Expand Down
2 changes: 1 addition & 1 deletion libmariadb
7 changes: 7 additions & 0 deletions ma_helper.c
Original file line number Diff line number Diff line change
Expand Up @@ -1355,4 +1355,11 @@ void MADB_InstallStmt(MADB_Stmt *Stmt, MYSQL_STMT *stmt)
MADB_StmtResetResultStructures(Stmt);
MADB_DescSetIrdMetadata(Stmt, mysql_fetch_fields(FetchMetadata(Stmt)), mysql_stmt_field_count(Stmt->stmt));
}
}


enum enum_field_types MADB_GetNativeFieldType(MADB_Stmt *Stmt, int i)
{
/* Assuming the caller knows what is it calling for - i.e. i is valid, and stmt->metadata is set. Should be */
return mysql_fetch_fields(Stmt->metadata)[i].type;
}
2 changes: 2 additions & 0 deletions ma_helper.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ BOOL MADB_IsIntType (SQLSMALLINT ConciseType);
/* For multistatement picks stmt handler pointed by stored index, and sets it as "current" stmt handler */
void MADB_InstallStmt (MADB_Stmt *Stmt, MYSQL_STMT *stmt);

enum enum_field_types MADB_GetNativeFieldType(MADB_Stmt *Stmt, int i);

/* for dummy binding */
extern my_bool DummyError;

Expand Down
8 changes: 4 additions & 4 deletions ma_odbc.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ typedef struct
{
SQLUSMALLINT *RowOperationPtr;
SQLULEN *RowOffsetPtr;
MYSQL_BIND *Bind;
/* MYSQL_BIND *Bind;*/
SQLLEN dummy;
SQLUINTEGER BindSize; /* size of each structure if using * Row-wise Binding */
SQLSMALLINT Allocated;
Expand All @@ -97,18 +97,18 @@ typedef struct
{
SQLUSMALLINT *ParamOperationPtr;
SQLULEN *ParamOffsetPtr;
MYSQL_BIND *Bind;
/* MYSQL_BIND *Bind;*/
SQLLEN ParamsetSize;
SQLUINTEGER ParamBindType;
SQLSMALLINT Allocated;
} MADB_Apd;

typedef struct
{
MADB_Stmt* stmt;
/*MADB_Stmt* stmt;*/
SQLULEN* RowsFetched;
SQLUSMALLINT* RowStatusArray;
MYSQL_FIELD* Fields;
/* MYSQL_FIELD* Fields;*/
SQLUINTEGER FieldCount;
SQLSMALLINT Allocated;
} MADB_Ird;
Expand Down
6 changes: 3 additions & 3 deletions ma_statement.c
Original file line number Diff line number Diff line change
Expand Up @@ -1887,7 +1887,6 @@ SQLRETURN MADB_PrepareBind(MADB_Stmt *Stmt, int RowNumber)
break;
}
}

return SQL_SUCCESS;
}
/* }}} */
Expand Down Expand Up @@ -1972,7 +1971,9 @@ SQLRETURN MADB_FixFetchedValues(MADB_Stmt *Stmt, int RowNumber, MYSQL_ROW_OFFSET
char *p= (char *)Stmt->result[i].buffer;
if (p)
{
*p= test(*p != '\0');
/* Workaround for server returning bit field in subquery as string interpretation, but sets binary flag, unlike the "normal" bit field */
MYSQL_FIELD *f= mysql_fetch_fields(Stmt->metadata);
*p= test(*p != '\0' && !(f[i].type == MYSQL_TYPE_BIT && f[i].flags & BINARY_FLAG && *p == '0'));
}
}
break;
Expand Down Expand Up @@ -2185,7 +2186,6 @@ SQLRETURN MADB_FixFetchedValues(MADB_Stmt *Stmt, int RowNumber, MYSQL_ROW_OFFSET
}
}
}

return rc;
}
/* }}} */
Expand Down
69 changes: 69 additions & 0 deletions test/result2.c
Original file line number Diff line number Diff line change
Expand Up @@ -1521,6 +1521,74 @@ ODBC_TEST(t_odbc214)
return OK;
}

/* The server returns '0' and '1' for bit field in subquery, while reporting it as a BIT. Connector interpreted '0'
as '\1'/true while fetched as a BIT since '0' != '\0' */
ODBC_TEST(t_odbc350)
{
SQLCHAR v1= 0, v2= 0;

OK_SIMPLE_STMT(Stmt, "DROP TABLE IF EXISTS t_odbc350");
OK_SIMPLE_STMT(Stmt, "CREATE TABLE t_odbc350 (v BIT(1), v2 BIT(8), v3 BIT(9))");
OK_SIMPLE_STMT(Stmt, "INSERT INTO t_odbc350 VALUES(0, 0, 256)");

OK_SIMPLE_STMT(Stmt, "SELECT v, (SELECT v FROM t_odbc350 LIMIT 1) FROM t_odbc350");

CHECK_STMT_RC(Stmt, SQLBindCol(Stmt, 1, SQL_C_BIT, &v1, sizeof(v1), NULL));
CHECK_STMT_RC(Stmt, SQLBindCol(Stmt, 2, SQL_C_BIT, &v2, sizeof(v2), NULL));

CHECK_STMT_RC(Stmt, SQLFetch(Stmt));
is_num(v1, 0);
is_num(v2, 0);
EXPECT_STMT(Stmt, SQLFetch(Stmt), SQL_NO_DATA);
CHECK_STMT_RC(Stmt, SQLFreeStmt(Stmt, SQL_CLOSE));

OK_SIMPLE_STMT(Stmt, "UPDATE t_odbc350 SET v=1");
OK_SIMPLE_STMT(Stmt, "SELECT v, (SELECT v FROM t_odbc350 LIMIT 1) FROM t_odbc350");

CHECK_STMT_RC(Stmt, SQLFetch(Stmt));
is_num(v1, 1);
is_num(v2, 1);
EXPECT_STMT(Stmt, SQLFetch(Stmt), SQL_NO_DATA);
CHECK_STMT_RC(Stmt, SQLFreeStmt(Stmt, SQL_CLOSE));

OK_SIMPLE_STMT(Stmt, "SELECT v2, (SELECT v2 FROM t_odbc350 LIMIT 1) FROM t_odbc350");

CHECK_STMT_RC(Stmt, SQLFetch(Stmt));
is_num(v1, 0);
is_num(v2, 0);
EXPECT_STMT(Stmt, SQLFetch(Stmt), SQL_NO_DATA);
CHECK_STMT_RC(Stmt, SQLFreeStmt(Stmt, SQL_CLOSE));

OK_SIMPLE_STMT(Stmt, "UPDATE t_odbc350 SET v2=48"); /* '0'=48*/
OK_SIMPLE_STMT(Stmt, "SELECT v2, (SELECT v2 FROM t_odbc350 LIMIT 1) FROM t_odbc350");

CHECK_STMT_RC(Stmt, SQLFetch(Stmt));
is_num(v1, 1);
is_num(v2, 1);
EXPECT_STMT(Stmt, SQLFetch(Stmt), SQL_NO_DATA);
CHECK_STMT_RC(Stmt, SQLFreeStmt(Stmt, SQL_CLOSE));

OK_SIMPLE_STMT(Stmt, "SELECT v3, (SELECT v3 FROM t_odbc350 LIMIT 1) FROM t_odbc350");

CHECK_STMT_RC(Stmt, SQLFetch(Stmt));
is_num(v1, 1);
is_num(v2, 1);
EXPECT_STMT(Stmt, SQLFetch(Stmt), SQL_NO_DATA);
CHECK_STMT_RC(Stmt, SQLFreeStmt(Stmt, SQL_CLOSE));

OK_SIMPLE_STMT(Stmt, "UPDATE t_odbc350 SET v3=0");
OK_SIMPLE_STMT(Stmt, "SELECT v3, (SELECT v3 FROM t_odbc350 LIMIT 1) FROM t_odbc350");

CHECK_STMT_RC(Stmt, SQLFetch(Stmt));
is_num(v1, 0);
is_num(v2, 0);
EXPECT_STMT(Stmt, SQLFetch(Stmt), SQL_NO_DATA);
CHECK_STMT_RC(Stmt, SQLFreeStmt(Stmt, SQL_CLOSE));
OK_SIMPLE_STMT(Stmt, "DROP TABLE IF EXISTS t_odbc350");

return OK;
}


MA_ODBC_TESTS my_tests[]=
{
Expand Down Expand Up @@ -1554,6 +1622,7 @@ MA_ODBC_TESTS my_tests[]=
{t_odbc232, "t_odbc232"},
{t_odbc274, "t_odbc274_InsDelReplace_returning"},
{t_odbc214, "t_odbc214_medium"},
{t_odbc350, "t_odbc350_bit_in_subquery"},
{NULL, NULL}
};

Expand Down
2 changes: 1 addition & 1 deletion test/tap.h
Original file line number Diff line number Diff line change
Expand Up @@ -657,7 +657,7 @@ BOOL is_str_ex(const char* str1, const char* str2, size_t len, BOOL verbose)
{
if (verbose)
{
fprintf(stdout, "# %s %s", str1, str2);
fprintf(stdout, "# %s %s\n", str1, str2);
}
return str1 == NULL || str2 == NULL || strncmp(str1, str2, len) != 0;
}
Expand Down

0 comments on commit 60a5bd6

Please sign in to comment.