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

Commit 31840bd

Browse files
committed
[[ Bug 21051 ]] Handle wchar_t size differences for ODBC
This patch works around `wchar_t` size difference on unix machines which was causing unicode results from ODBC databases to be truncated after the first character due to null bytes.
1 parent fe3b22c commit 31840bd

File tree

2 files changed

+33
-0
lines changed

2 files changed

+33
-0
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/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)