Skip to content
This repository was archived by the owner on Aug 31, 2021. It is now read-only.

Commit dc77668

Browse files
Merge pull request #6510 from montegoulding/bugfix-21051
[[ Bug 21051 ]] Handle wchar_t size differences for ODBC
2 parents 01955ab + a0eec38 commit dc77668

File tree

4 files changed

+40
-9
lines changed

4 files changed

+40
-9
lines changed

docs/notes/bugfix-21051.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# Ensure revDataFromQuery on an ODBC database does not return incomplete unicode strings

revdb/src/dbodbc.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ class DBConnection_ODBC: public CDBConnection
9898
int getConnectionType(void) { return -1; }
9999
protected:
100100
void SetError(SQLHSTMT tcursor);
101-
Bool BindVariables(SQLHSTMT tcursor, DBString *args, int numargs, int *paramsizes, PlaceholderMap *p_placeholder_map);
101+
Bool BindVariables(SQLHSTMT tcursor, DBString *args, int numargs, SQLLEN *paramsizes, PlaceholderMap *p_placeholder_map);
102102
bool ExecuteQuery(char *p_query, DBString *p_arguments, int p_argument_count, SQLHSTMT &p_statement, SQLRETURN &p_result);
103103
bool handleDataAtExecutionParameters(SQLHSTMT p_statement);
104104
bool useDataAtExecution(void);

revdb/src/odbc_connection.cpp

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -399,8 +399,7 @@ bool DBConnection_ODBC::ExecuteQuery(char *p_query, DBString *p_arguments, int p
399399
#endif
400400
if (t_result == SQL_SUCCESS || t_result == SQL_SUCCESS_WITH_INFO)
401401
{
402-
int *t_argument_sizes = NULL;
403-
t_argument_sizes = new (nothrow) int[t_placeholder_map . length];
402+
SQLLEN *t_argument_sizes = new (nothrow) SQLLEN[t_placeholder_map . length];
404403
if (BindVariables(t_statement, p_arguments, p_argument_count, t_argument_sizes, &t_placeholder_map))
405404
{
406405
t_result = SQLExecute(t_statement);
@@ -528,7 +527,7 @@ char *DBConnection_ODBC::getErrorMessage(Bool p_last)
528527

529528

530529
/*BindVariables-parses querystring and binds variables*/
531-
Bool DBConnection_ODBC::BindVariables(SQLHSTMT p_cursor, DBString *p_arguments, int p_argument_count, int *p_argument_sizes, PlaceholderMap *p_placeholder_map)
530+
Bool DBConnection_ODBC::BindVariables(SQLHSTMT p_cursor, DBString *p_arguments, int p_argument_count, SQLLEN *p_argument_sizes, PlaceholderMap *p_placeholder_map)
532531
{
533532
if (p_argument_count == 0)
534533
return True;
@@ -564,15 +563,14 @@ Bool DBConnection_ODBC::BindVariables(SQLHSTMT p_cursor, DBString *p_arguments,
564563

565564
// MW-2008-07-30: [[ Bug 6415 ]] Inserting data into SQL Server doesn't work.
566565
// This is because the bind parameter call was only being issued for binary columns!
567-
SQLLEN t_argument_size;
568-
t_result = SQLBindParameter(p_cursor, i + 1, SQL_PARAM_INPUT,
566+
567+
SQLLEN * t_argument_size = &p_argument_sizes[i];
568+
t_result = SQLBindParameter(p_cursor, i + 1, SQL_PARAM_INPUT,
569569
t_value -> isbinary ? SQL_C_BINARY : SQL_C_CHAR, t_data_type,
570-
t_value -> length, 0, (void *)t_value -> sptr, t_value -> length, &t_argument_size);
570+
t_value -> length, 0, (void *)t_value -> sptr, t_value -> length, t_argument_size);
571571

572572
if (!(t_result == SQL_SUCCESS || t_result == SQL_SUCCESS_WITH_INFO))
573573
return False;
574-
575-
p_argument_sizes[i] = t_argument_size;
576574
}
577575
else
578576
{

revdb/src/odbc_cursor.cpp

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ last - move to last row of resultset
3636
*/
3737

3838
#include <stdio.h>
39+
#include <stdint.h>
3940
#include "dbodbc.h"
4041

4142
char DBCursor_ODBC::errmsg[512];
@@ -542,6 +543,37 @@ Bool DBCursor_ODBC::getRowData()
542543
ofield->dataSize = offset;
543544
}
544545
}
546+
547+
if (ofield -> fieldType == FT_WSTRING && sizeof(SQLWCHAR) != sizeof(uint16_t))
548+
{
549+
uint16_t * t_buffer = static_cast<uint16_t *>(malloc(ofield -> dataSize));
550+
551+
size_t t_in_offset;
552+
size_t t_out_offset = 0;
553+
for (t_in_offset = 0; t_in_offset < size_t(ofield -> dataSize); t_in_offset += sizeof(uint32_t))
554+
{
555+
uint32_t t_codepoint = *(uint32_t*)&ofield -> data[t_in_offset];
556+
if (t_codepoint < 0x10000)
557+
{
558+
t_buffer[t_out_offset] = uint16_t(t_codepoint);
559+
t_out_offset += 1;
560+
}
561+
else
562+
{
563+
uint16_t t_lead, t_trail;
564+
t_lead = uint16_t((t_codepoint - 0x10000) >> 10) + 0xD800;
565+
t_trail = uint16_t((t_codepoint - 0x10000) & 0x3FF) + 0xDC00;
566+
t_buffer[t_out_offset] = t_lead;
567+
t_buffer[t_out_offset + 1] = t_trail;
568+
t_out_offset += 2;
569+
}
570+
}
571+
572+
memcpy(ofield->data, t_buffer, t_out_offset * sizeof(uint16_t));
573+
free(t_buffer);
574+
575+
ofield -> dataSize = t_out_offset * sizeof(uint16_t);
576+
}
545577
}
546578
}
547579
return True;

0 commit comments

Comments
 (0)