Skip to content

Commit

Permalink
Final version of ODBC-133 fix and extended testcase
Browse files Browse the repository at this point in the history
In case of ANSI application on Windows, we use GetACP() to recode unicode
to ANSI charset. DM uses to recode application's input
to UTF16. That supposed to get us exactly the string application sent
us.
Testcase now tests string consisting of all characted codes, and using
all 1 byte charsets.
Also fixed the bug in SQLTableW - after recoding, NULL values of
function parameters would become empty strings, and that has different
meaning for catalog functions.
Changed 1 test in catalog1 to do the same thing as on Travis - killing
connection to test connector to return correct error

Testcase for ODBC-138

Fix of merge error(of the ODBC-91 patch)
  • Loading branch information
lawrinn committed May 22, 2018
1 parent 4cd0642 commit dce6451
Show file tree
Hide file tree
Showing 8 changed files with 115 additions and 49 deletions.
5 changes: 1 addition & 4 deletions ma_connection.c
Expand Up @@ -612,7 +612,7 @@ SQLRETURN MADB_DbcConnectDB(MADB_Dbc *Connection,
goto end;
}

if (1) /* Turning new functionality off, so far //!Connection->IsAnsi) */
if (!Connection->IsAnsi)
{
/* If application is not ansi, we should convert wchar into connection string */
Connection->ConnOrSrcCharset= &Connection->Charset;
Expand Down Expand Up @@ -699,9 +699,6 @@ SQLRETURN MADB_DbcConnectDB(MADB_Dbc *Connection,
goto err;*/
}

if (!Connection->CatalogName && Dsn->Catalog)
Connection->CatalogName= my_strdup(Dsn->Catalog, MYF(0));

/* set default catalog */
if (Connection->CatalogName && Connection->CatalogName[0])
{
Expand Down
6 changes: 3 additions & 3 deletions ma_helper.c
Expand Up @@ -84,7 +84,7 @@ unsigned int GetMultiStatements(MADB_Stmt *Stmt, char *StmtStr, SQLINTEGER Lengt
if (Length)
{
end= StmtStr + Length - 1;
while (end > StmtStr && (isspace(*end) || *end == ';'))
while (end > StmtStr && (isspace(0x000000ff & *end) || *end == ';'))
{
--end;
--Length;
Expand Down Expand Up @@ -1013,7 +1013,7 @@ int MADB_CharToSQLNumeric(char *buffer, MADB_Desc *Ard, MADB_DescRecord *ArdReco
while (*p)
{
/* ignore non numbers */
if (!isdigit(*p))
if (!isdigit(0x000000ff & *p))
break;
digits_total++;
/* ignore trailing zeros */
Expand Down Expand Up @@ -1050,7 +1050,7 @@ int MADB_CharToSQLNumeric(char *buffer, MADB_Desc *Ard, MADB_DescRecord *ArdReco
else
{
char *start= p;
while (*p && isdigit(*p))
while (*p && isdigit(0x000000ff & *p))
p++;
/* check overflow */
if (p - start > number->precision)
Expand Down
3 changes: 2 additions & 1 deletion ma_platform_win32.c
Expand Up @@ -278,7 +278,8 @@ SQLLEN MADB_SetString(Client_Charset* cc, void *Dest, SQLULEN DestLength,

int GetSourceAnsiCs(Client_Charset *cc)
{
cc->CodePage= GetConsoleWindow() ? GetConsoleCP() : GetACP();
cc->CodePage= GetACP();

/* We don't need cs_info for this */
return cc->CodePage;
}
2 changes: 1 addition & 1 deletion ma_statement.c
Expand Up @@ -1070,7 +1070,7 @@ SQLRETURN MADB_StmtExecute(MADB_Stmt *Stmt)
MADB_FREE(ApdRecord->InternalBuffer);

ApdRecord->InternalBuffer= MADB_ConvertFromWChar((SQLWCHAR *)DataPtr, (SQLINTEGER)(Length / sizeof(SQLWCHAR)),
&mbLength, &Stmt->Connection->charset, NULL);
&mbLength, &Stmt->Connection->Charset, NULL);
ApdRecord->InternalLength= (unsigned long)mbLength;
Stmt->params[i-ParamOffset].length= &ApdRecord->InternalLength;
Stmt->params[i-ParamOffset].buffer= ApdRecord->InternalBuffer;
Expand Down
22 changes: 17 additions & 5 deletions odbc_3_api.c
Expand Up @@ -3189,17 +3189,29 @@ SQLRETURN SQL_API SQLTablesW(SQLHSTMT StatementHandle,
*CpSchema= NULL,
*CpTable= NULL,
*CpType= NULL;
SQLULEN CpLength1, CpLength2, CpLength3, CpLength4;
SQLULEN CpLength1= 0, CpLength2= 0, CpLength3= 0, CpLength4= 0;
SQLRETURN ret;

if (!Stmt)
return SQL_INVALID_HANDLE;
MADB_CLEAR_ERROR(&Stmt->Error);

CpCatalog= MADB_ConvertFromWChar(CatalogName, NameLength1, &CpLength1, Stmt->Connection->ConnOrSrcCharset, NULL);
CpSchema= MADB_ConvertFromWChar(SchemaName, NameLength2, &CpLength2, Stmt->Connection->ConnOrSrcCharset, NULL);
CpTable= MADB_ConvertFromWChar(TableName, NameLength3, &CpLength3, Stmt->Connection->ConnOrSrcCharset, NULL);
CpType= MADB_ConvertFromWChar(TableType, NameLength4, &CpLength4, Stmt->Connection->ConnOrSrcCharset, NULL);
if (CatalogName)
{
CpCatalog= MADB_ConvertFromWChar(CatalogName, NameLength1, &CpLength1, Stmt->Connection->ConnOrSrcCharset, NULL);
}
if (SchemaName)
{
CpSchema= MADB_ConvertFromWChar(SchemaName, NameLength2, &CpLength2, Stmt->Connection->ConnOrSrcCharset, NULL);
}
if (TableName)
{
CpTable= MADB_ConvertFromWChar(TableName, NameLength3, &CpLength3, Stmt->Connection->ConnOrSrcCharset, NULL);
}
if (TableType)
{
CpType= MADB_ConvertFromWChar(TableType, NameLength4, &CpLength4, Stmt->Connection->ConnOrSrcCharset, NULL);
}

ret= Stmt->Methods->Tables(Stmt, CpCatalog, (SQLSMALLINT)CpLength1, CpSchema, (SQLSMALLINT)CpLength2,
CpTable, (SQLSMALLINT)CpLength3, CpType, (SQLSMALLINT)CpLength4);
Expand Down
77 changes: 58 additions & 19 deletions test/basic.c
Expand Up @@ -1508,32 +1508,71 @@ ODBC_TEST(t_odbc91)

ODBC_TEST(t_odbc137)
{
SQLHDBC Hdbc;
SQLHSTMT Hstmt;
char buffer[16];

skip("This is not fixed yet");
SQLHDBC Hdbc;
SQLHSTMT Hstmt;
char buffer[256], AllAnsiChars[258], AllAnsiHex[512];
const char Charset[][16]= {"latin1", "cp850", "cp1251", "cp866", "cp852", "cp1250", "latin2", "latin5" ,"latin7",
"cp1256", "cp1257", "geostd8", "greek", "koi8u", "koi8r", "hebrew", "macce", "macroman",
"dec8", "hp8", "armscii8", "ascii", "swe7", "tis620", "keybcs2"};
/* åäöÅÄÖ in latin1(cp= 1252), åäöÅÄÖ in cp850(cp= 437_, () in win1251 */
/*const char TestStr[][8]={ "\xe5\xe4\xf6\xc5\xc4\xd6", "\x86\x84\x94\x8f\x8e\x99", "\xb4\xa2\xfa\xa5\xa1\xda" },
HexStr[][16]={ "0xE5E4F6C5C4D6", "0x8684948F8E99", "0xB4A2FAA5A1DA" };*/
const char CreateStmtTpl[]= "CREATE TABLE `t_odbc137` (\
`val` TEXT DEFAULT NULL\
) ENGINE=InnoDB DEFAULT CHARSET=%s";
char CreateStmt[sizeof(CreateStmtTpl) + sizeof(Charset[0])];
const char InsertStmtTpl[]= "INSERT INTO t_odbc137(val) VALUES('%s')";
char InsertStmt[sizeof(InsertStmtTpl) + sizeof(AllAnsiChars)];// TestStr[0])];
const char SelectStmtTpl[]= "SELECT * FROM t_odbc137 WHERE val = 0x%s";
char SelectStmt[sizeof(SelectStmtTpl) + sizeof(AllAnsiHex)];// HexStr[0])];
unsigned int i, j, Escapes= 0;

OK_SIMPLE_STMT(Stmt, "DROP TABLE IF EXISTS `t_odbc137`");
OK_SIMPLE_STMT(Stmt, "CREATE TABLE `t_odbc137` (\
`val` char(50) DEFAULT NULL\
) ENGINE=InnoDB DEFAULT CHARSET=latin1");

CHECK_ENV_RC(Env, SQLAllocConnect(Env, &Hdbc));
Hstmt= ConnectWithCharset(&Hdbc, "latin1", NULL);
FAIL_IF(Hstmt == NULL, "");

OK_SIMPLE_STMT(Hstmt, "INSERT INTO t_odbc137(val) VALUES('\xe5\xe4\xf6\xc5\xc4\xd6')");//åäöÅÄÖ
for (i= 1; i < 256; ++i)
{
if (i == '\'' || i == '\\')
{
AllAnsiChars[i-1 + Escapes]= '\\';
++Escapes;
}

AllAnsiChars[i-1 + Escapes]= i;
sprintf(AllAnsiHex + (i-1)*2, "%02x", i);
}

AllAnsiChars[255 + Escapes]= AllAnsiHex[511]= '\0';

for (i= 0; i < sizeof(Charset)/sizeof(Charset[0]); ++i)
{
diag("Charset: %s", Charset[i]);

Hstmt= ConnectWithCharset(&Hdbc, Charset[i], NULL);
FAIL_IF(Hstmt == NULL, "");

/* 0xE5E4F6C5C4D6 is hex for åäöÅÄÖ in latin1 - we are checkin that a correct sting was stored in the table*/
OK_SIMPLE_STMT(Hstmt, "SELECT * FROM t_odbc137 WHERE val=0xE5E4F6C5C4D6");
sprintf(CreateStmt, CreateStmtTpl, Charset[i]);
OK_SIMPLE_STMT(Hstmt, CreateStmt);

FAIL_IF(SQLFetch(Hstmt) == SQL_NO_DATA, "Wrong data has been stored in the table");
/* We still need to make sure that the string has been delivered correctly */
IS_STR(my_fetch_str(Hstmt, buffer, 1), "\xe5\xe4\xf6\xc5\xc4\xd6", sizeof("\xe5\xe4\xf6\xc5\xc4\xd6"));// "åäöÅÄÖ", sizeof("åäöÅÄÖ"));
sprintf(InsertStmt, InsertStmtTpl, AllAnsiChars);// TestStr[i]);
OK_SIMPLE_STMT(Hstmt, InsertStmt);

sprintf(SelectStmt, SelectStmtTpl, AllAnsiHex);// HexStr[i]);
OK_SIMPLE_STMT(Hstmt, SelectStmt);

FAIL_IF(SQLFetch(Hstmt) == SQL_NO_DATA, "Wrong data has been stored in the table");
/* We still need to make sure that the string has been delivered correctly */
my_fetch_str(Hstmt, buffer, 1);
/* AllAnsiChars is escaped, so we cannot compare result string against it */
for (j= 1; j < 256; ++j)
{
is_num((unsigned char)buffer[j - 1], j);
}
CHECK_STMT_RC(Hstmt, SQLFreeStmt(Hstmt, SQL_DROP));
OK_SIMPLE_STMT(Stmt, "DROP TABLE `t_odbc137`");
CHECK_DBC_RC(Hdbc, SQLDisconnect(Hdbc));
}

CHECK_STMT_RC(Hstmt, SQLFreeStmt(Hstmt, SQL_DROP));
CHECK_DBC_RC(Hdbc, SQLDisconnect(Hdbc));
CHECK_DBC_RC(Hdbc, SQLFreeConnect(Hdbc));

return OK;
Expand Down
24 changes: 8 additions & 16 deletions test/catalog1.c
Expand Up @@ -1212,22 +1212,14 @@ ODBC_TEST(t_bug26934)

ODBC_Connect(&Env1, &Connection1, &Stmt1);

if (Travis)
{
OK_SIMPLE_STMT(Stmt1, "SELECT connection_id()");
CHECK_STMT_RC(Stmt1, SQLFetch(Stmt1));
ConnectionId= my_fetch_int(Stmt1, 1);
CHECK_STMT_RC(Stmt1, SQLFreeStmt(Stmt1, SQL_CLOSE));

/* From another connection, kill the connection created above */
sprintf(Kill, "KILL %d", ConnectionId);
OK_SIMPLE_STMT(Stmt, Kill);
}
else
{
OK_SIMPLE_STMT(Stmt1, "SET @@wait_timeout = 1");
Sleep(3000);
}
OK_SIMPLE_STMT(Stmt1, "SELECT connection_id()");
CHECK_STMT_RC(Stmt1, SQLFetch(Stmt1));
ConnectionId= my_fetch_int(Stmt1, 1);
CHECK_STMT_RC(Stmt1, SQLFreeStmt(Stmt1, SQL_CLOSE));

/* From another connection, kill the connection created above */
sprintf(Kill, "KILL %d", ConnectionId);
OK_SIMPLE_STMT(Stmt, Kill);

EXPECT_STMT(Stmt1, SQLTables(Stmt1, (SQLCHAR *)"%", 1, NULL, SQL_NTS,
NULL, SQL_NTS, NULL, SQL_NTS), SQL_ERROR);
Expand Down
25 changes: 25 additions & 0 deletions test/datetime.c
Expand Up @@ -1396,6 +1396,30 @@ ODBC_TEST(t_bug67793)
}


ODBC_TEST(t_odbc138)
{
SQL_TIMESTAMP_STRUCT ts= { 0 };
SQLLEN ind;
unsigned int i;

for (i= 0; i < 100; ++i)
{
OK_SIMPLE_STMT(Stmt, "SELECT DATE_ADD('2018-02-01', INTERVAL -188 DAY)");

CHECK_STMT_RC(Stmt, SQLBindCol(Stmt, 1, SQL_C_TIMESTAMP, &ts, 0, &ind));

CHECK_STMT_RC(Stmt, SQLFetch(Stmt));

is_num(ts.year, 2017);
is_num(ts.month, 7);
is_num(ts.day, 28);
CHECK_STMT_RC(Stmt, SQLCloseCursor(Stmt));
}

return OK;
}


MA_ODBC_TESTS my_tests[]=
{
{my_ts, "my_ts", NORMAL},
Expand All @@ -1420,6 +1444,7 @@ MA_ODBC_TESTS my_tests[]=
{t_odbc70, "t_odbc70_zero_datetime_vals", NORMAL},
{t_17613161, "t_17613161", NORMAL},
{t_bug67793, "t_bug67793", NORMAL},
{t_odbc138, "t_odbc138_dateadd_negative", NORMAL },

{NULL, NULL}
};
Expand Down

0 comments on commit dce6451

Please sign in to comment.