This is an automated email from the ASF dual-hosted git repository.
lidavidm pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow.git
The following commit(s) were added to refs/heads/main by this push:
new fc5fd482f2 GH-47726 : [C++][FlightRPC] ODBC Unicode Support (#47771)
fc5fd482f2 is described below
commit fc5fd482f21bb51a8bd955fe6c46e8650e8105bd
Author: Alina (Xi) Li <[email protected]>
AuthorDate: Thu Oct 16 00:28:48 2025 -0700
GH-47726 : [C++][FlightRPC] ODBC Unicode Support (#47771)
### Rationale for this change
Enable ODBC unicode support, so ODBC can handle wide characters.
### What changes are included in this PR?
- Enable ODBC unicode support by setting `-DUNICODE` to 1
- DSN is read and retrieved in unicode format, and then converted to
regular strings for driver
- Fix a string reading bug in `GetAttributeSQLWCHAR`
### Are these changes tested?
Build is tested locally
### Are there any user-facing changes?
No
* GitHub Issue: #47726
Lead-authored-by: Alina (Xi) Li <[email protected]>
Co-authored-by: Alina (Xi) Li <[email protected]>
Co-authored-by: rscales <[email protected]>
Signed-off-by: David Li <[email protected]>
---
cpp/src/arrow/flight/sql/odbc/CMakeLists.txt | 2 +-
cpp/src/arrow/flight/sql/odbc/odbc.def | 4 +-
.../arrow/flight/sql/odbc/odbc_impl/CMakeLists.txt | 17 +--
.../flight/sql/odbc/odbc_impl/attribute_utils.h | 11 +-
.../sql/odbc/odbc_impl/config/configuration.cc | 49 +++---
.../sql/odbc/odbc_impl/config/configuration.h | 1 +
.../sql/odbc/odbc_impl/flight_sql_connection.cc | 2 +-
.../flight/sql/odbc/odbc_impl/odbc_connection.cc | 42 +++---
.../arrow/flight/sql/odbc/odbc_impl/system_dsn.cc | 136 ++++++++++++-----
.../sql/odbc/odbc_impl/system_trust_store.cc | 13 +-
.../flight/sql/odbc/odbc_impl/system_trust_store.h | 4 +-
.../sql/odbc/odbc_impl/ui/add_property_window.cc | 18 +--
.../sql/odbc/odbc_impl/ui/add_property_window.h | 6 +-
.../flight/sql/odbc/odbc_impl/ui/custom_window.cc | 3 +-
.../flight/sql/odbc/odbc_impl/ui/custom_window.h | 2 +-
.../odbc/odbc_impl/ui/dsn_configuration_window.cc | 166 ++++++++++++---------
.../arrow/flight/sql/odbc/odbc_impl/ui/window.cc | 58 +++----
.../arrow/flight/sql/odbc/odbc_impl/ui/window.h | 32 ++--
cpp/src/arrow/flight/sql/odbc/odbc_impl/util.h | 16 ++
19 files changed, 358 insertions(+), 224 deletions(-)
diff --git a/cpp/src/arrow/flight/sql/odbc/CMakeLists.txt
b/cpp/src/arrow/flight/sql/odbc/CMakeLists.txt
index 98a0121782..79f351ae9c 100644
--- a/cpp/src/arrow/flight/sql/odbc/CMakeLists.txt
+++ b/cpp/src/arrow/flight/sql/odbc/CMakeLists.txt
@@ -55,7 +55,7 @@ add_arrow_lib(arrow_flight_sql_odbc
DEPENDENCIES
arrow_flight_sql
DEFINITIONS
- FMT_HEADER_ONLY
+ UNICODE
SHARED_LINK_FLAGS
${ARROW_VERSION_SCRIPT_FLAGS} # Defined in
cpp/arrow/CMakeLists.txt
SHARED_LINK_LIBS
diff --git a/cpp/src/arrow/flight/sql/odbc/odbc.def
b/cpp/src/arrow/flight/sql/odbc/odbc.def
index fe7ef1a046..a8191ff662 100644
--- a/cpp/src/arrow/flight/sql/odbc/odbc.def
+++ b/cpp/src/arrow/flight/sql/odbc/odbc.def
@@ -17,8 +17,8 @@
LIBRARY arrow_flight_sql_odbc
EXPORTS
- ; TODO: update to ConfigDSNW when driver has unicode implemented
- ; ConfigDSN
+ ; GH-46574 TODO enable DSN window
+ ; ConfigDSNW
SQLAllocConnect
SQLAllocEnv
SQLAllocHandle
diff --git a/cpp/src/arrow/flight/sql/odbc/odbc_impl/CMakeLists.txt
b/cpp/src/arrow/flight/sql/odbc/odbc_impl/CMakeLists.txt
index 1ec196ec1f..b232577ee3 100644
--- a/cpp/src/arrow/flight/sql/odbc/odbc_impl/CMakeLists.txt
+++ b/cpp/src/arrow/flight/sql/odbc/odbc_impl/CMakeLists.txt
@@ -39,12 +39,16 @@ add_library(arrow_odbc_spi_impl
blocking_queue.h
calendar_utils.cc
calendar_utils.h
+ config/configuration.cc
+ config/configuration.h
+ config/connection_string_parser.cc
+ config/connection_string_parser.h
diagnostics.cc
diagnostics.h
+ error_codes.h
encoding.cc
encoding.h
encoding_utils.h
- error_codes.h
exceptions.cc
exceptions.h
flight_sql_auth_method.cc
@@ -106,16 +110,13 @@ add_library(arrow_odbc_spi_impl
type_utilities.h
util.cc
util.h)
+target_compile_definitions(arrow_odbc_spi_impl PUBLIC UNICODE)
target_include_directories(arrow_odbc_spi_impl PUBLIC include
include/odbc_impl)
target_include_directories(arrow_odbc_spi_impl PUBLIC
${CMAKE_CURRENT_LIST_DIR})
if(WIN32)
target_sources(arrow_odbc_spi_impl
- PRIVATE config/configuration.cc
- config/configuration.h
- config/connection_string_parser.cc
- config/connection_string_parser.h
- ui/add_property_window.cc
+ PRIVATE ui/add_property_window.cc
ui/add_property_window.h
ui/custom_window.cc
ui/custom_window.h
@@ -123,9 +124,7 @@ if(WIN32)
ui/dsn_configuration_window.h
ui/window.cc
ui/window.h
- win_system_dsn.cc
- system_dsn.cc
- system_dsn.h)
+ system_dsn.cc)
endif()
target_link_libraries(arrow_odbc_spi_impl PUBLIC arrow_flight_sql_shared
diff --git a/cpp/src/arrow/flight/sql/odbc/odbc_impl/attribute_utils.h
b/cpp/src/arrow/flight/sql/odbc/odbc_impl/attribute_utils.h
index 7750185b63..7baea759ed 100644
--- a/cpp/src/arrow/flight/sql/odbc/odbc_impl/attribute_utils.h
+++ b/cpp/src/arrow/flight/sql/odbc/odbc_impl/attribute_utils.h
@@ -83,18 +83,21 @@ template <typename O>
inline SQLRETURN GetAttributeSQLWCHAR(const std::string& attribute_value,
bool is_length_in_bytes, SQLPOINTER
output,
O output_size, O* output_len_ptr) {
- size_t result = ConvertToSqlWChar(
+ size_t length = ConvertToSqlWChar(
attribute_value, reinterpret_cast<SQLWCHAR*>(output),
is_length_in_bytes ? output_size : output_size * GetSqlWCharSize());
+ if (!is_length_in_bytes) {
+ length = length / GetSqlWCharSize();
+ }
+
if (output_len_ptr) {
- *output_len_ptr =
- static_cast<O>(is_length_in_bytes ? result : result /
GetSqlWCharSize());
+ *output_len_ptr = static_cast<O>(length);
}
if (output &&
output_size <
- static_cast<O>(result + (is_length_in_bytes ? GetSqlWCharSize() :
1))) {
+ static_cast<O>(length + (is_length_in_bytes ? GetSqlWCharSize() :
1))) {
return SQL_SUCCESS_WITH_INFO;
}
return SQL_SUCCESS;
diff --git a/cpp/src/arrow/flight/sql/odbc/odbc_impl/config/configuration.cc
b/cpp/src/arrow/flight/sql/odbc/odbc_impl/config/configuration.cc
index 1619a68a14..cdb889f056 100644
--- a/cpp/src/arrow/flight/sql/odbc/odbc_impl/config/configuration.cc
+++ b/cpp/src/arrow/flight/sql/odbc/odbc_impl/config/configuration.cc
@@ -17,6 +17,9 @@
#include "arrow/flight/sql/odbc/odbc_impl/config/configuration.h"
#include "arrow/flight/sql/odbc/odbc_impl/flight_sql_connection.h"
+#include "arrow/flight/sql/odbc/odbc_impl/util.h"
+#include "arrow/result.h"
+#include "arrow/util/utf8.h"
#include <odbcinst.h>
#include <boost/range/adaptor/map.hpp>
@@ -26,7 +29,6 @@
namespace arrow::flight::sql::odbc {
namespace config {
-
static const char DEFAULT_DSN[] = "Apache Arrow Flight SQL";
static const char DEFAULT_ENABLE_ENCRYPTION[] = TRUE_STR;
static const char DEFAULT_USE_CERT_STORE[] = TRUE_STR;
@@ -35,23 +37,27 @@ static const char DEFAULT_DISABLE_CERT_VERIFICATION[] =
FALSE_STR;
namespace {
std::string ReadDsnString(const std::string& dsn, const std::string_view& key,
const std::string& dflt = "") {
-#define BUFFER_SIZE (1024)
- std::vector<char> buf(BUFFER_SIZE);
+ CONVERT_WIDE_STR(const std::wstring wdsn, dsn);
+ CONVERT_WIDE_STR(const std::wstring wkey, key);
+ CONVERT_WIDE_STR(const std::wstring wdflt, dflt);
- std::string key_str = std::string(key);
+#define BUFFER_SIZE (1024)
+ std::vector<wchar_t> buf(BUFFER_SIZE);
int ret =
- SQLGetPrivateProfileString(dsn.c_str(), key_str.c_str(), dflt.c_str(),
buf.data(),
- static_cast<int>(buf.size()), "ODBC.INI");
+ SQLGetPrivateProfileString(wdsn.c_str(), wkey.c_str(), wdflt.c_str(),
buf.data(),
+ static_cast<int>(buf.size()), L"ODBC.INI");
if (ret > BUFFER_SIZE) {
// If there wasn't enough space, try again with the right size buffer.
buf.resize(ret + 1);
ret =
- SQLGetPrivateProfileString(dsn.c_str(), key_str.c_str(), dflt.c_str(),
buf.data(),
- static_cast<int>(buf.size()), "ODBC.INI");
+ SQLGetPrivateProfileString(wdsn.c_str(), wkey.c_str(), wdflt.c_str(),
buf.data(),
+ static_cast<int>(buf.size()), L"ODBC.INI");
}
- return std::string(buf.data(), ret);
+ std::wstring wresult = std::wstring(buf.data(), ret);
+ CONVERT_UTF8_STR(const std::string result, wresult);
+ return result;
}
void RemoveAllKnownKeys(std::vector<std::string>& keys) {
@@ -68,28 +74,32 @@ void RemoveAllKnownKeys(std::vector<std::string>& keys) {
}
std::vector<std::string> ReadAllKeys(const std::string& dsn) {
- std::vector<char> buf(BUFFER_SIZE);
+ CONVERT_WIDE_STR(const std::wstring wdsn, dsn);
+
+ std::vector<wchar_t> buf(BUFFER_SIZE);
- int ret = SQLGetPrivateProfileString(dsn.c_str(), NULL, "", buf.data(),
- static_cast<int>(buf.size()),
"ODBC.INI");
+ int ret = SQLGetPrivateProfileString(wdsn.c_str(), NULL, L"", buf.data(),
+ static_cast<int>(buf.size()),
L"ODBC.INI");
if (ret > BUFFER_SIZE) {
// If there wasn't enough space, try again with the right size buffer.
buf.resize(ret + 1);
- ret = SQLGetPrivateProfileString(dsn.c_str(), NULL, "", buf.data(),
- static_cast<int>(buf.size()), "ODBC.INI");
+ ret = SQLGetPrivateProfileString(wdsn.c_str(), NULL, L"", buf.data(),
+ static_cast<int>(buf.size()),
L"ODBC.INI");
}
// When you pass NULL to SQLGetPrivateProfileString it gives back a \0
delimited list of
// all the keys. The below loop simply tokenizes all the keys and places
them into a
// vector.
std::vector<std::string> keys;
- char* begin = buf.data();
+ wchar_t* begin = buf.data();
while (begin && *begin != '\0') {
- char* cur;
+ wchar_t* cur;
for (cur = begin; *cur != '\0'; ++cur) {
}
- keys.emplace_back(begin, cur);
+
+ CONVERT_UTF8_STR(const std::string key, std::wstring(begin, cur));
+ keys.emplace_back(key);
begin = ++cur;
}
return keys;
@@ -153,6 +163,11 @@ const std::string& Configuration::Get(const
std::string_view& key) const {
return itr->second;
}
+void Configuration::Set(const std::string_view& key, const std::wstring&
wvalue) {
+ CONVERT_UTF8_STR(const std::string value, wvalue);
+ Set(key, value);
+}
+
void Configuration::Set(const std::string_view& key, const std::string& value)
{
const std::string copy = boost::trim_copy(value);
if (!copy.empty()) {
diff --git a/cpp/src/arrow/flight/sql/odbc/odbc_impl/config/configuration.h
b/cpp/src/arrow/flight/sql/odbc/odbc_impl/config/configuration.h
index beca536002..77d07b1420 100644
--- a/cpp/src/arrow/flight/sql/odbc/odbc_impl/config/configuration.h
+++ b/cpp/src/arrow/flight/sql/odbc/odbc_impl/config/configuration.h
@@ -59,6 +59,7 @@ class Configuration {
void Clear();
bool IsSet(const std::string_view& key) const;
const std::string& Get(const std::string_view& key) const;
+ void Set(const std::string_view& key, const std::wstring& wvalue);
void Set(const std::string_view& key, const std::string& value);
/**
diff --git a/cpp/src/arrow/flight/sql/odbc/odbc_impl/flight_sql_connection.cc
b/cpp/src/arrow/flight/sql/odbc/odbc_impl/flight_sql_connection.cc
index 9b36718f5a..b4f9c69b39 100644
--- a/cpp/src/arrow/flight/sql/odbc/odbc_impl/flight_sql_connection.cc
+++ b/cpp/src/arrow/flight/sql/odbc/odbc_impl/flight_sql_connection.cc
@@ -71,7 +71,7 @@ namespace {
#if _WIN32 || _WIN64
constexpr auto SYSTEM_TRUST_STORE_DEFAULT = true;
-constexpr auto STORES = {"CA", "MY", "ROOT", "SPC"};
+constexpr auto STORES = {L"CA", L"MY", L"ROOT", L"SPC"};
inline std::string GetCerts() {
std::string certs;
diff --git a/cpp/src/arrow/flight/sql/odbc/odbc_impl/odbc_connection.cc
b/cpp/src/arrow/flight/sql/odbc/odbc_impl/odbc_connection.cc
index 1f2df4192e..c0a55840d5 100644
--- a/cpp/src/arrow/flight/sql/odbc/odbc_impl/odbc_connection.cc
+++ b/cpp/src/arrow/flight/sql/odbc/odbc_impl/odbc_connection.cc
@@ -17,6 +17,9 @@
#include "arrow/flight/sql/odbc/odbc_impl/odbc_connection.h"
+#include "arrow/result.h"
+#include "arrow/util/utf8.h"
+
#include "arrow/flight/sql/odbc/odbc_impl/attribute_utils.h"
#include "arrow/flight/sql/odbc/odbc_impl/exceptions.h"
#include "arrow/flight/sql/odbc/odbc_impl/odbc_descriptor.h"
@@ -24,6 +27,7 @@
#include "arrow/flight/sql/odbc/odbc_impl/odbc_statement.h"
#include "arrow/flight/sql/odbc/odbc_impl/spi/connection.h"
#include "arrow/flight/sql/odbc/odbc_impl/spi/statement.h"
+#include "arrow/flight/sql/odbc/odbc_impl/util.h"
#include <odbcinst.h>
#include <sql.h>
@@ -56,41 +60,43 @@ const boost::xpressive::sregex CONNECTION_STR_REGEX(
void loadPropertiesFromDSN(const std::string& dsn,
Connection::ConnPropertyMap& properties) {
const size_t BUFFER_SIZE = 1024 * 10;
- std::vector<char> outputBuffer;
- outputBuffer.resize(BUFFER_SIZE, '\0');
+ std::vector<wchar_t> output_buffer;
+ output_buffer.resize(BUFFER_SIZE, '\0');
SQLSetConfigMode(ODBC_BOTH_DSN);
- SQLGetPrivateProfileString(dsn.c_str(), NULL, "", &outputBuffer[0],
BUFFER_SIZE,
- "odbc.ini");
+ CONVERT_WIDE_STR(const std::wstring wdsn, dsn);
+
+ SQLGetPrivateProfileString(wdsn.c_str(), NULL, L"", &output_buffer[0],
BUFFER_SIZE,
+ L"odbc.ini");
// The output buffer holds the list of keys in a series of NUL-terminated
strings.
// The series is terminated with an empty string (eg a NUL-terminator
terminating the
// last key followed by a NUL terminator after).
- std::vector<std::string_view> keys;
+ std::vector<std::wstring_view> keys;
size_t pos = 0;
while (pos < BUFFER_SIZE) {
- std::string key(&outputBuffer[pos]);
- if (key.empty()) {
+ std::wstring wkey(&output_buffer[pos]);
+ if (wkey.empty()) {
break;
}
- size_t len = key.size();
+ size_t len = wkey.size();
// Skip over Driver or DSN keys.
- if (!boost::iequals(key, "DSN") && !boost::iequals(key, "Driver")) {
- keys.emplace_back(std::move(key));
+ if (!boost::iequals(wkey, L"DSN") && !boost::iequals(wkey, L"Driver")) {
+ keys.emplace_back(std::move(wkey));
}
pos += len + 1;
}
- for (auto& key : keys) {
- outputBuffer.clear();
- outputBuffer.resize(BUFFER_SIZE, '\0');
-
- std::string key_str = std::string(key);
- SQLGetPrivateProfileString(dsn.c_str(), key_str.c_str(), "",
&outputBuffer[0],
- BUFFER_SIZE, "odbc.ini");
+ for (auto& wkey : keys) {
+ output_buffer.clear();
+ output_buffer.resize(BUFFER_SIZE, '\0');
+ SQLGetPrivateProfileString(wdsn.c_str(), wkey.data(), L"",
&output_buffer[0],
+ BUFFER_SIZE, L"odbc.ini");
- std::string value = std::string(&outputBuffer[0]);
+ std::wstring wvalue = std::wstring(&output_buffer[0]);
+ CONVERT_UTF8_STR(const std::string value, wvalue);
+ CONVERT_UTF8_STR(const std::string key, std::wstring(wkey));
auto propIter = properties.find(key);
if (propIter == properties.end()) {
properties.emplace(std::make_pair(std::move(key), std::move(value)));
diff --git a/cpp/src/arrow/flight/sql/odbc/odbc_impl/system_dsn.cc
b/cpp/src/arrow/flight/sql/odbc/odbc_impl/system_dsn.cc
index 1c7593c317..d10eff2580 100644
--- a/cpp/src/arrow/flight/sql/odbc/odbc_impl/system_dsn.cc
+++ b/cpp/src/arrow/flight/sql/odbc/odbc_impl/system_dsn.cc
@@ -27,12 +27,13 @@
#include "arrow/flight/sql/odbc/odbc_impl/flight_sql_connection.h"
#include "arrow/flight/sql/odbc/odbc_impl/ui/dsn_configuration_window.h"
#include "arrow/flight/sql/odbc/odbc_impl/ui/window.h"
+#include "arrow/result.h"
+#include "arrow/util/utf8.h"
#include <odbcinst.h>
-#include <codecvt>
-#include <locale>
#include <sstream>
+using arrow::flight::sql::odbc::DriverException;
using arrow::flight::sql::odbc::FlightSqlConnection;
using arrow::flight::sql::odbc::config::Configuration;
using arrow::flight::sql::odbc::config::ConnectionStringParser;
@@ -40,19 +41,13 @@ using
arrow::flight::sql::odbc::config::DsnConfigurationWindow;
using arrow::flight::sql::odbc::config::Result;
using arrow::flight::sql::odbc::config::Window;
-BOOL CALLBACK ConfigDriver(HWND hwndParent, WORD fRequest, LPCSTR lpszDriver,
- LPCSTR lpszArgs, LPSTR lpszMsg, WORD cbMsgMax,
- WORD* pcbMsgOut) {
- return false;
-}
-
-bool DisplayConnectionWindow(void* windowParent, Configuration& config) {
- HWND hwndParent = (HWND)windowParent;
+bool DisplayConnectionWindow(void* window_parent, Configuration& config) {
+ HWND hwnd_parent = (HWND)window_parent;
- if (!hwndParent) return true;
+ if (!hwnd_parent) return true;
try {
- Window parent(hwndParent);
+ Window parent(hwnd_parent);
DsnConfigurationWindow window(&parent, config);
window.Create();
@@ -61,30 +56,46 @@ bool DisplayConnectionWindow(void* windowParent,
Configuration& config) {
window.Update();
return ProcessMessages(window) == Result::OK;
- } catch (arrow::flight::sql::odbc::DriverException& err) {
+ } catch (const DriverException& err) {
std::stringstream buf;
- buf << "Message: " << err.GetMessageText() << ", Code: " <<
err.GetNativeError();
- std::string message = buf.str();
- MessageBox(NULL, message.c_str(), "Error!", MB_ICONEXCLAMATION | MB_OK);
-
- SQLPostInstallerError(err.GetNativeError(), err.GetMessageText().c_str());
+ buf << "SQL State: " << err.GetSqlState() << ", Message: " <<
err.GetMessageText()
+ << ", Code: " << err.GetNativeError();
+ std::wstring wmessage =
+ arrow::util::UTF8ToWideString(buf.str()).ValueOr(L"Error during load
DSN");
+ MessageBox(NULL, wmessage.c_str(), L"Error!", MB_ICONEXCLAMATION | MB_OK);
+
+ std::wstring wmessage_text =
arrow::util::UTF8ToWideString(err.GetMessageText())
+ .ValueOr(L"Error during load DSN");
+ SQLPostInstallerError(err.GetNativeError(), wmessage_text.c_str());
}
return false;
}
+void PostError(DWORD error_code, LPCWSTR error_msg) {
+ MessageBox(NULL, error_msg, L"Error!", MB_ICONEXCLAMATION | MB_OK);
+ SQLPostInstallerError(error_code, error_msg);
+}
+
+void PostArrowUtilError(arrow::Status error_status) {
+ std::string error_msg = error_status.message();
+ std::wstring werror_msg = arrow::util::UTF8ToWideString(error_msg).ValueOr(
+ L"Error during utf8 to wide string conversion");
+
+ PostError(ODBC_ERROR_GENERAL_ERR, werror_msg.c_str());
+}
+
void PostLastInstallerError() {
#define BUFFER_SIZE (1024)
DWORD code;
- char msg[BUFFER_SIZE];
+ wchar_t msg[BUFFER_SIZE];
SQLInstallerError(1, &code, msg, BUFFER_SIZE, NULL);
- std::stringstream buf;
- buf << "Message: \"" << msg << "\", Code: " << code;
- std::string error_msg = buf.str();
+ std::wstringstream buf;
+ buf << L"Message: \"" << msg << L"\", Code: " << code;
+ std::wstring error_msg = buf.str();
- MessageBox(NULL, error_msg.c_str(), "Error!", MB_ICONEXCLAMATION | MB_OK);
- SQLPostInstallerError(code, error_msg.c_str());
+ PostError(code, error_msg.c_str());
}
/**
@@ -93,7 +104,7 @@ void PostLastInstallerError() {
* @param dsn DSN name.
* @return True on success and false on fail.
*/
-bool UnregisterDsn(const std::string& dsn) {
+bool UnregisterDsn(const std::wstring& dsn) {
if (SQLRemoveDSNFromIni(dsn.c_str())) {
return true;
}
@@ -109,10 +120,16 @@ bool UnregisterDsn(const std::string& dsn) {
* @param driver Driver.
* @return True on success and false on fail.
*/
-bool RegisterDsn(const Configuration& config, LPCSTR driver) {
+bool RegisterDsn(const Configuration& config, LPCWSTR driver) {
const std::string& dsn = config.Get(FlightSqlConnection::DSN);
+ auto wdsn_result = arrow::util::UTF8ToWideString(dsn);
+ if (!wdsn_result.status().ok()) {
+ PostArrowUtilError(wdsn_result.status());
+ return false;
+ }
+ std::wstring wdsn = wdsn_result.ValueOrDie();
- if (!SQLWriteDSNToIni(dsn.c_str(), driver)) {
+ if (!SQLWriteDSNToIni(wdsn.c_str(), driver)) {
PostLastInstallerError();
return false;
}
@@ -125,9 +142,22 @@ bool RegisterDsn(const Configuration& config, LPCSTR
driver) {
continue;
}
- std::string key_str = std::string(key);
- if (!SQLWritePrivateProfileString(dsn.c_str(), key_str.c_str(),
it->second.c_str(),
- "ODBC.INI")) {
+ auto wkey_result = arrow::util::UTF8ToWideString(key);
+ if (!wkey_result.status().ok()) {
+ PostArrowUtilError(wkey_result.status());
+ return false;
+ }
+ std::wstring wkey = wkey_result.ValueOrDie();
+
+ auto wvalue_result = arrow::util::UTF8ToWideString(it->second);
+ if (!wvalue_result.status().ok()) {
+ PostArrowUtilError(wvalue_result.status());
+ return false;
+ }
+ std::wstring wvalue = wvalue_result.ValueOrDie();
+
+ if (!SQLWritePrivateProfileString(wdsn.c_str(), wkey.c_str(),
wvalue.c_str(),
+ L"ODBC.INI")) {
PostLastInstallerError();
return false;
}
@@ -136,15 +166,24 @@ bool RegisterDsn(const Configuration& config, LPCSTR
driver) {
return true;
}
-BOOL INSTAPI ConfigDSN(HWND hwndParent, WORD req, LPCSTR driver, LPCSTR
attributes) {
+BOOL INSTAPI ConfigDSNW(HWND hwnd_parent, WORD req, LPCWSTR wdriver,
+ LPCWSTR wattributes) {
Configuration config;
ConnectionStringParser parser(config);
- parser.ParseConfigAttributes(attributes);
+
+ auto attributes_result =
arrow::util::WideStringToUTF8(std::wstring(wattributes));
+ if (!attributes_result.status().ok()) {
+ PostArrowUtilError(attributes_result.status());
+ return FALSE;
+ }
+ std::string attributes = attributes_result.ValueOrDie();
+
+ parser.ParseConfigAttributes(attributes.c_str());
switch (req) {
case ODBC_ADD_DSN: {
config.LoadDefaults();
- if (!DisplayConnectionWindow(hwndParent, config) || !RegisterDsn(config,
driver))
+ if (!DisplayConnectionWindow(hwnd_parent, config) ||
!RegisterDsn(config, wdriver))
return FALSE;
break;
@@ -152,13 +191,28 @@ BOOL INSTAPI ConfigDSN(HWND hwndParent, WORD req, LPCSTR
driver, LPCSTR attribut
case ODBC_CONFIG_DSN: {
const std::string& dsn = config.Get(FlightSqlConnection::DSN);
- if (!SQLValidDSN(dsn.c_str())) return FALSE;
+ auto wdsn_result = arrow::util::UTF8ToWideString(dsn);
+ if (!wdsn_result.status().ok()) {
+ PostArrowUtilError(wdsn_result.status());
+ return FALSE;
+ }
+ std::wstring wdsn = wdsn_result.ValueOrDie();
+ if (!SQLValidDSN(wdsn.c_str())) return FALSE;
Configuration loaded(config);
- loaded.LoadDsn(dsn);
+ try {
+ loaded.LoadDsn(dsn);
+ } catch (const DriverException& err) {
+ std::string error_msg = err.GetMessageText();
+ std::wstring werror_msg =
+ arrow::util::UTF8ToWideString(error_msg).ValueOr(L"Error during
DSN load");
+
+ PostError(err.GetNativeError(), werror_msg.c_str());
+ return FALSE;
+ }
- if (!DisplayConnectionWindow(hwndParent, loaded) ||
!UnregisterDsn(dsn.c_str()) ||
- !RegisterDsn(loaded, driver))
+ if (!DisplayConnectionWindow(hwnd_parent, loaded) ||
!UnregisterDsn(wdsn.c_str()) ||
+ !RegisterDsn(loaded, wdriver))
return FALSE;
break;
@@ -166,7 +220,13 @@ BOOL INSTAPI ConfigDSN(HWND hwndParent, WORD req, LPCSTR
driver, LPCSTR attribut
case ODBC_REMOVE_DSN: {
const std::string& dsn = config.Get(FlightSqlConnection::DSN);
- if (!SQLValidDSN(dsn.c_str()) || !UnregisterDsn(dsn)) return FALSE;
+ auto wdsn_result = arrow::util::UTF8ToWideString(dsn);
+ if (!wdsn_result.status().ok()) {
+ PostArrowUtilError(wdsn_result.status());
+ return FALSE;
+ }
+ std::wstring wdsn = wdsn_result.ValueOrDie();
+ if (!SQLValidDSN(wdsn.c_str()) || !UnregisterDsn(wdsn)) return FALSE;
break;
}
diff --git a/cpp/src/arrow/flight/sql/odbc/odbc_impl/system_trust_store.cc
b/cpp/src/arrow/flight/sql/odbc/odbc_impl/system_trust_store.cc
index 673be40fb1..d7d2e72b4b 100644
--- a/cpp/src/arrow/flight/sql/odbc/odbc_impl/system_trust_store.cc
+++ b/cpp/src/arrow/flight/sql/odbc/odbc_impl/system_trust_store.cc
@@ -15,6 +15,9 @@
// specific language governing permissions and limitations
// under the License.
+#include "arrow/result.h"
+#include "arrow/util/utf8.h"
+
#include "arrow/flight/sql/odbc/odbc_impl/system_trust_store.h"
#if defined _WIN32 || defined _WIN64
@@ -28,13 +31,13 @@ bool SystemTrustStore::HasNext() {
std::string SystemTrustStore::GetNext() const {
DWORD size = 0;
- CryptBinaryToString(p_context_->pbCertEncoded, p_context_->cbCertEncoded,
- CRYPT_STRING_BASE64HEADER, nullptr, &size);
+ CryptBinaryToStringA(p_context_->pbCertEncoded, p_context_->cbCertEncoded,
+ CRYPT_STRING_BASE64HEADER, nullptr, &size);
std::string cert;
cert.resize(size);
- CryptBinaryToString(p_context_->pbCertEncoded, p_context_->cbCertEncoded,
- CRYPT_STRING_BASE64HEADER, &cert[0], &size);
+ CryptBinaryToStringA(p_context_->pbCertEncoded, p_context_->cbCertEncoded,
+ CRYPT_STRING_BASE64HEADER, &cert[0], &size);
cert.resize(size);
return cert;
@@ -42,7 +45,7 @@ std::string SystemTrustStore::GetNext() const {
bool SystemTrustStore::SystemHasStore() { return h_store_ != nullptr; }
-SystemTrustStore::SystemTrustStore(const char* store)
+SystemTrustStore::SystemTrustStore(const wchar_t* store)
: stores_(store), h_store_(CertOpenSystemStore(NULL, store)),
p_context_(nullptr) {}
SystemTrustStore::~SystemTrustStore() {
diff --git a/cpp/src/arrow/flight/sql/odbc/odbc_impl/system_trust_store.h
b/cpp/src/arrow/flight/sql/odbc/odbc_impl/system_trust_store.h
index 52bdaf628e..94ad924aaa 100644
--- a/cpp/src/arrow/flight/sql/odbc/odbc_impl/system_trust_store.h
+++ b/cpp/src/arrow/flight/sql/odbc/odbc_impl/system_trust_store.h
@@ -37,12 +37,12 @@ namespace arrow::flight::sql::odbc {
///
https://github.com/apache/drill/blob/master/contrib/native/client/src/clientlib/wincert.ipp.
class SystemTrustStore {
private:
- const char* stores_;
+ const wchar_t* stores_;
HCERTSTORE h_store_;
PCCERT_CONTEXT p_context_;
public:
- explicit SystemTrustStore(const char* store);
+ explicit SystemTrustStore(const wchar_t* store);
~SystemTrustStore();
diff --git a/cpp/src/arrow/flight/sql/odbc/odbc_impl/ui/add_property_window.cc
b/cpp/src/arrow/flight/sql/odbc/odbc_impl/ui/add_property_window.cc
index 0bf4b7d2a0..634fd77862 100644
--- a/cpp/src/arrow/flight/sql/odbc/odbc_impl/ui/add_property_window.cc
+++ b/cpp/src/arrow/flight/sql/odbc/odbc_impl/ui/add_property_window.cc
@@ -32,7 +32,7 @@ namespace arrow::flight::sql::odbc {
namespace config {
AddPropertyWindow::AddPropertyWindow(Window* parent)
- : CustomWindow(parent, "AddProperty", "Add Property"),
+ : CustomWindow(parent, L"AddProperty", L"Add Property"),
width_(300),
height_(120),
accepted_(false),
@@ -70,7 +70,7 @@ void AddPropertyWindow::Create() {
}
}
-bool AddPropertyWindow::GetProperty(std::string& key, std::string& value) {
+bool AddPropertyWindow::GetProperty(std::wstring& key, std::wstring& value) {
if (accepted_) {
key = this->key_;
value = this->value_;
@@ -88,10 +88,10 @@ void AddPropertyWindow::OnCreate() {
int cancel_pos_x = width_ - MARGIN - BUTTON_WIDTH;
int ok_pos_x = cancel_pos_x - INTERVAL - BUTTON_WIDTH;
- ok_button_ = CreateButton(ok_pos_x, group_pos_y, BUTTON_WIDTH,
BUTTON_HEIGHT, "Ok",
+ ok_button_ = CreateButton(ok_pos_x, group_pos_y, BUTTON_WIDTH,
BUTTON_HEIGHT, L"Ok",
ChildId::OK_BUTTON, BS_DEFPUSHBUTTON);
cancel_button_ = CreateButton(cancel_pos_x, group_pos_y, BUTTON_WIDTH,
BUTTON_HEIGHT,
- "Cancel", ChildId::CANCEL_BUTTON);
+ L"Cancel", ChildId::CANCEL_BUTTON);
is_initialized_ = true;
CheckEnableOk();
}
@@ -105,16 +105,16 @@ int AddPropertyWindow::CreateEdits(int pos_x, int pos_y,
int size_x) {
int row_pos = pos_y;
labels_.push_back(
- CreateLabel(pos_x, row_pos, LABEL_WIDTH, ROW_HEIGHT, "Key:",
ChildId::KEY_LABEL));
+ CreateLabel(pos_x, row_pos, LABEL_WIDTH, ROW_HEIGHT, L"Key:",
ChildId::KEY_LABEL));
key_edit_ =
- CreateEdit(edit_pos_x, row_pos, edit_size_x, ROW_HEIGHT, "",
ChildId::KEY_EDIT);
+ CreateEdit(edit_pos_x, row_pos, edit_size_x, ROW_HEIGHT, L"",
ChildId::KEY_EDIT);
row_pos += INTERVAL + ROW_HEIGHT;
- labels_.push_back(CreateLabel(pos_x, row_pos, LABEL_WIDTH, ROW_HEIGHT,
- "Value:", ChildId::VALUE_LABEL));
+ labels_.push_back(CreateLabel(pos_x, row_pos, LABEL_WIDTH, ROW_HEIGHT,
L"Value:",
+ ChildId::VALUE_LABEL));
value_edit_ =
- CreateEdit(edit_pos_x, row_pos, edit_size_x, ROW_HEIGHT, "",
ChildId::VALUE_EDIT);
+ CreateEdit(edit_pos_x, row_pos, edit_size_x, ROW_HEIGHT, L"",
ChildId::VALUE_EDIT);
row_pos += INTERVAL + ROW_HEIGHT;
diff --git a/cpp/src/arrow/flight/sql/odbc/odbc_impl/ui/add_property_window.h
b/cpp/src/arrow/flight/sql/odbc/odbc_impl/ui/add_property_window.h
index 0aad617c29..e334fd2f90 100644
--- a/cpp/src/arrow/flight/sql/odbc/odbc_impl/ui/add_property_window.h
+++ b/cpp/src/arrow/flight/sql/odbc/odbc_impl/ui/add_property_window.h
@@ -69,7 +69,7 @@ class AddPropertyWindow : public CustomWindow {
*
* @return true if the dialog was OK'd, false otherwise.
*/
- bool GetProperty(std::string& key, std::string& value);
+ bool GetProperty(std::wstring& key, std::wstring& value);
private:
/**
@@ -96,9 +96,9 @@ class AddPropertyWindow : public CustomWindow {
std::unique_ptr<Window> value_edit_;
- std::string key_;
+ std::wstring key_;
- std::string value_;
+ std::wstring value_;
/** Window width. */
int width_;
diff --git a/cpp/src/arrow/flight/sql/odbc/odbc_impl/ui/custom_window.cc
b/cpp/src/arrow/flight/sql/odbc/odbc_impl/ui/custom_window.cc
index 4571398104..9aded323d0 100644
--- a/cpp/src/arrow/flight/sql/odbc/odbc_impl/ui/custom_window.cc
+++ b/cpp/src/arrow/flight/sql/odbc/odbc_impl/ui/custom_window.cc
@@ -82,7 +82,8 @@ LRESULT CALLBACK CustomWindow::WndProc(HWND hwnd, UINT msg,
WPARAM wparam,
return DefWindowProc(hwnd, msg, wparam, lparam);
}
-CustomWindow::CustomWindow(Window* parent, const char* class_name, const char*
title)
+CustomWindow::CustomWindow(Window* parent, const wchar_t* class_name,
+ const wchar_t* title)
: Window(parent, class_name, title) {
WNDCLASS wcx;
diff --git a/cpp/src/arrow/flight/sql/odbc/odbc_impl/ui/custom_window.h
b/cpp/src/arrow/flight/sql/odbc/odbc_impl/ui/custom_window.h
index 93b72d5a94..a658001148 100644
--- a/cpp/src/arrow/flight/sql/odbc/odbc_impl/ui/custom_window.h
+++ b/cpp/src/arrow/flight/sql/odbc/odbc_impl/ui/custom_window.h
@@ -64,7 +64,7 @@ class CustomWindow : public Window {
* @param class_name Window class name.
* @param title Window title.
*/
- CustomWindow(Window* parent, const char* class_name, const char* title);
+ CustomWindow(Window* parent, const wchar_t* class_name, const wchar_t*
title);
/**
* Destructor.
diff --git
a/cpp/src/arrow/flight/sql/odbc/odbc_impl/ui/dsn_configuration_window.cc
b/cpp/src/arrow/flight/sql/odbc/odbc_impl/ui/dsn_configuration_window.cc
index 81af697667..3f49690daa 100644
--- a/cpp/src/arrow/flight/sql/odbc/odbc_impl/ui/dsn_configuration_window.cc
+++ b/cpp/src/arrow/flight/sql/odbc/odbc_impl/ui/dsn_configuration_window.cc
@@ -15,6 +15,9 @@
// specific language governing permissions and limitations
// under the License.
+#include "arrow/result.h"
+#include "arrow/util/utf8.h"
+
#include "arrow/flight/sql/odbc/odbc_impl/ui/dsn_configuration_window.h"
#include "arrow/flight/sql/odbc/odbc_impl/flight_sql_connection.h"
@@ -54,7 +57,7 @@ std::string TestConnection(const config::Configuration&
config) {
namespace config {
DsnConfigurationWindow::DsnConfigurationWindow(Window* parent, Configuration&
config)
- : CustomWindow(parent, "FlightConfigureDSN", "Configure Apache Arrow
Flight SQL"),
+ : CustomWindow(parent, L"FlightConfigureDSN", L"Configure Apache Arrow
Flight SQL"),
width_(480),
height_(375),
config_(config),
@@ -95,8 +98,8 @@ void DsnConfigurationWindow::Create() {
void DsnConfigurationWindow::OnCreate() {
tab_control_ = CreateTabControl(ChildId::TAB_CONTROL);
- tab_control_->AddTab("Common", COMMON_TAB);
- tab_control_->AddTab("Advanced", ADVANCED_TAB);
+ tab_control_->AddTab(L"Common", COMMON_TAB);
+ tab_control_->AddTab(L"Advanced", ADVANCED_TAB);
int group_pos_y = 3 * MARGIN;
int group_size_y = width_ - 2 * MARGIN;
@@ -119,11 +122,11 @@ void DsnConfigurationWindow::OnCreate() {
int button_pos_y = std::max(common_group_pos_y, advanced_group_pos_y);
test_button_ = CreateButton(test_pos_x, button_pos_y, BUTTON_WIDTH + 20,
BUTTON_HEIGHT,
- "Test Connection",
ChildId::TEST_CONNECTION_BUTTON);
- ok_button_ = CreateButton(ok_pos_x, button_pos_y, BUTTON_WIDTH,
BUTTON_HEIGHT, "Ok",
+ L"Test Connection",
ChildId::TEST_CONNECTION_BUTTON);
+ ok_button_ = CreateButton(ok_pos_x, button_pos_y, BUTTON_WIDTH,
BUTTON_HEIGHT, L"Ok",
ChildId::OK_BUTTON);
cancel_button_ = CreateButton(cancel_pos_x, button_pos_y, BUTTON_WIDTH,
BUTTON_HEIGHT,
- "Cancel", ChildId::CANCEL_BUTTON);
+ L"Cancel", ChildId::CANCEL_BUTTON);
is_initialized_ = true;
CheckEnableOk();
SelectTab(COMMON_TAB);
@@ -140,32 +143,35 @@ int
DsnConfigurationWindow::CreateConnectionSettingsGroup(int pos_x, int pos_y,
int row_pos = pos_y + 2 * INTERVAL;
- const char* val = config_.Get(FlightSqlConnection::DSN).c_str();
+ std::string dsn = config_.Get(FlightSqlConnection::DSN);
+ CONVERT_WIDE_STR(const std::wstring wdsn, dsn);
labels_.push_back(CreateLabel(label_pos_x, row_pos, LABEL_WIDTH, ROW_HEIGHT,
- "Data Source Name:", ChildId::NAME_LABEL));
- name_edit_ =
- CreateEdit(edit_pos_x, row_pos, edit_size_x, ROW_HEIGHT, val,
ChildId::NAME_EDIT);
+ L"Data Source Name:", ChildId::NAME_LABEL));
+ name_edit_ = CreateEdit(edit_pos_x, row_pos, edit_size_x, ROW_HEIGHT,
wdsn.c_str(),
+ ChildId::NAME_EDIT);
row_pos += INTERVAL + ROW_HEIGHT;
- val = config_.Get(FlightSqlConnection::HOST).c_str();
+ std::string host = config_.Get(FlightSqlConnection::HOST);
+ CONVERT_WIDE_STR(const std::wstring whost, host);
labels_.push_back(CreateLabel(label_pos_x, row_pos, LABEL_WIDTH, ROW_HEIGHT,
- "Host Name:", ChildId::SERVER_LABEL));
- server_edit_ =
- CreateEdit(edit_pos_x, row_pos, edit_size_x, ROW_HEIGHT, val,
ChildId::SERVER_EDIT);
+ L"Host Name:", ChildId::SERVER_LABEL));
+ server_edit_ = CreateEdit(edit_pos_x, row_pos, edit_size_x, ROW_HEIGHT,
whost.c_str(),
+ ChildId::SERVER_EDIT);
row_pos += INTERVAL + ROW_HEIGHT;
- val = config_.Get(FlightSqlConnection::PORT).c_str();
- labels_.push_back(CreateLabel(label_pos_x, row_pos, LABEL_WIDTH, ROW_HEIGHT,
- "Port:", ChildId::PORT_LABEL));
- port_edit_ = CreateEdit(edit_pos_x, row_pos, edit_size_x, ROW_HEIGHT, val,
+ std::string port = config_.Get(FlightSqlConnection::PORT);
+ CONVERT_WIDE_STR(const std::wstring wport, port);
+ labels_.push_back(CreateLabel(label_pos_x, row_pos, LABEL_WIDTH, ROW_HEIGHT,
L"Port:",
+ ChildId::PORT_LABEL));
+ port_edit_ = CreateEdit(edit_pos_x, row_pos, edit_size_x, ROW_HEIGHT,
wport.c_str(),
ChildId::PORT_EDIT, ES_NUMBER);
row_pos += INTERVAL + ROW_HEIGHT;
connection_settings_group_box_ =
- CreateGroupBox(pos_x, pos_y, size_x, row_pos - pos_y, "Connection
settings",
+ CreateGroupBox(pos_x, pos_y, size_x, row_pos - pos_y, L"Connection
settings",
ChildId::CONNECTION_SETTINGS_GROUP_BOX);
return row_pos - pos_y;
@@ -182,38 +188,40 @@ int DsnConfigurationWindow::CreateAuthSettingsGroup(int
pos_x, int pos_y, int si
int row_pos = pos_y + 2 * INTERVAL;
labels_.push_back(CreateLabel(label_pos_x, row_pos, LABEL_WIDTH, ROW_HEIGHT,
- "Authentication Type:",
ChildId::AUTH_TYPE_LABEL));
+ L"Authentication Type:",
ChildId::AUTH_TYPE_LABEL));
auth_type_combo_box_ =
CreateComboBox(edit_pos_x, row_pos, edit_size_x, ROW_HEIGHT,
- "Authentication Type:", ChildId::AUTH_TYPE_COMBOBOX);
- auth_type_combo_box_->AddString("Basic Authentication");
- auth_type_combo_box_->AddString("Token Authentication");
+ L"Authentication Type:", ChildId::AUTH_TYPE_COMBOBOX);
+ auth_type_combo_box_->AddString(L"Basic Authentication");
+ auth_type_combo_box_->AddString(L"Token Authentication");
row_pos += INTERVAL + ROW_HEIGHT;
- const char* val = config_.Get(FlightSqlConnection::UID).c_str();
+ std::string uid = config_.Get(FlightSqlConnection::UID);
+ CONVERT_WIDE_STR(const std::wstring wuid, uid);
- labels_.push_back(CreateLabel(label_pos_x, row_pos, LABEL_WIDTH, ROW_HEIGHT,
- "User:", ChildId::USER_LABEL));
- user_edit_ =
- CreateEdit(edit_pos_x, row_pos, edit_size_x, ROW_HEIGHT, val,
ChildId::USER_EDIT);
+ labels_.push_back(CreateLabel(label_pos_x, row_pos, LABEL_WIDTH, ROW_HEIGHT,
L"User:",
+ ChildId::USER_LABEL));
+ user_edit_ = CreateEdit(edit_pos_x, row_pos, edit_size_x, ROW_HEIGHT,
wuid.c_str(),
+ ChildId::USER_EDIT);
row_pos += INTERVAL + ROW_HEIGHT;
- val = config_.Get(FlightSqlConnection::PWD).c_str();
+ std::string pwd = config_.Get(FlightSqlConnection::PWD);
+ CONVERT_WIDE_STR(const std::wstring wpwd, pwd);
labels_.push_back(CreateLabel(label_pos_x, row_pos, LABEL_WIDTH, ROW_HEIGHT,
- "Password:", ChildId::PASSWORD_LABEL));
- password_edit_ = CreateEdit(edit_pos_x, row_pos, edit_size_x, ROW_HEIGHT,
val,
+ L"Password:", ChildId::PASSWORD_LABEL));
+ password_edit_ = CreateEdit(edit_pos_x, row_pos, edit_size_x, ROW_HEIGHT,
wpwd.c_str(),
ChildId::USER_EDIT, ES_PASSWORD);
row_pos += INTERVAL + ROW_HEIGHT;
const auto& token = config_.Get(FlightSqlConnection::TOKEN);
- val = token.c_str();
+ CONVERT_WIDE_STR(const std::wstring wtoken, token);
labels_.push_back(CreateLabel(label_pos_x, row_pos, LABEL_WIDTH, ROW_HEIGHT,
- "Authentication Token:",
ChildId::AUTH_TOKEN_LABEL));
- auth_token_edit_ = CreateEdit(edit_pos_x, row_pos, edit_size_x, ROW_HEIGHT,
val,
- ChildId::AUTH_TOKEN_EDIT);
+ L"Authentication Token:",
ChildId::AUTH_TOKEN_LABEL));
+ auth_token_edit_ = CreateEdit(edit_pos_x, row_pos, edit_size_x, ROW_HEIGHT,
+ wtoken.c_str(), ChildId::AUTH_TOKEN_EDIT);
auth_token_edit_->SetEnabled(false);
// Ensure the right elements are selected.
@@ -223,7 +231,7 @@ int DsnConfigurationWindow::CreateAuthSettingsGroup(int
pos_x, int pos_y, int si
row_pos += INTERVAL + ROW_HEIGHT;
auth_settings_group_box_ =
- CreateGroupBox(pos_x, pos_y, size_x, row_pos - pos_y, "Authentication
settings",
+ CreateGroupBox(pos_x, pos_y, size_x, row_pos - pos_y, L"Authentication
settings",
ChildId::AUTH_SETTINGS_GROUP_BOX);
return row_pos - pos_y;
@@ -240,37 +248,39 @@ int
DsnConfigurationWindow::CreateEncryptionSettingsGroup(int pos_x, int pos_y,
int row_pos = pos_y + 2 * INTERVAL;
- const char* val = config_.Get(FlightSqlConnection::USE_ENCRYPTION).c_str();
+ std::string val = config_.Get(FlightSqlConnection::USE_ENCRYPTION);
const bool enable_encryption = util::AsBool(val).value_or(true);
labels_.push_back(CreateLabel(label_pos_x, row_pos, LABEL_WIDTH, ROW_HEIGHT,
- "Use Encryption:",
ChildId::ENABLE_ENCRYPTION_LABEL));
+ L"Use Encryption:",
ChildId::ENABLE_ENCRYPTION_LABEL));
enable_encryption_check_box_ =
- CreateCheckBox(edit_pos_x, row_pos - 2, edit_size_x, ROW_HEIGHT, "",
+ CreateCheckBox(edit_pos_x, row_pos - 2, edit_size_x, ROW_HEIGHT, L"",
ChildId::ENABLE_ENCRYPTION_CHECKBOX, enable_encryption);
row_pos += INTERVAL + ROW_HEIGHT;
- val = config_.Get(FlightSqlConnection::TRUSTED_CERTS).c_str();
+ std::string trusted_certs = config_.Get(FlightSqlConnection::TRUSTED_CERTS);
+ CONVERT_WIDE_STR(const std::wstring wtrusted_certs, trusted_certs);
labels_.push_back(CreateLabel(label_pos_x, row_pos, LABEL_WIDTH, ROW_HEIGHT,
- "Certificate:", ChildId::CERTIFICATE_LABEL));
- certificate_edit_ = CreateEdit(edit_pos_x, row_pos, edit_size_x - MARGIN -
BUTTON_WIDTH,
- ROW_HEIGHT, val, ChildId::CERTIFICATE_EDIT);
+ L"Certificate:", ChildId::CERTIFICATE_LABEL));
+ certificate_edit_ =
+ CreateEdit(edit_pos_x, row_pos, edit_size_x - MARGIN - BUTTON_WIDTH,
ROW_HEIGHT,
+ wtrusted_certs.c_str(), ChildId::CERTIFICATE_EDIT);
certificate_browse_button_ =
CreateButton(edit_pos_x + edit_size_x - BUTTON_WIDTH, row_pos - 2,
BUTTON_WIDTH,
- BUTTON_HEIGHT, "Browse",
ChildId::CERTIFICATE_BROWSE_BUTTON);
+ BUTTON_HEIGHT, L"Browse",
ChildId::CERTIFICATE_BROWSE_BUTTON);
row_pos += INTERVAL + ROW_HEIGHT;
val = config_.Get(FlightSqlConnection::USE_SYSTEM_TRUST_STORE).c_str();
const bool use_system_cert_store = util::AsBool(val).value_or(true);
- labels_.push_back(
- CreateLabel(label_pos_x, row_pos, LABEL_WIDTH, 2 * ROW_HEIGHT,
- "Use System Certificate Store:",
ChildId::USE_SYSTEM_CERT_STORE_LABEL));
+ labels_.push_back(CreateLabel(label_pos_x, row_pos, LABEL_WIDTH, 2 *
ROW_HEIGHT,
+ L"Use System Certificate Store:",
+ ChildId::USE_SYSTEM_CERT_STORE_LABEL));
use_system_cert_store_check_box_ =
- CreateCheckBox(edit_pos_x, row_pos - 2, 20, 2 * ROW_HEIGHT, "",
+ CreateCheckBox(edit_pos_x, row_pos - 2, 20, 2 * ROW_HEIGHT, L"",
ChildId::USE_SYSTEM_CERT_STORE_CHECKBOX,
use_system_cert_store);
val =
config_.Get(FlightSqlConnection::DISABLE_CERTIFICATE_VERIFICATION).c_str();
@@ -278,19 +288,24 @@ int
DsnConfigurationWindow::CreateEncryptionSettingsGroup(int pos_x, int pos_y,
const int right_pos_x = label_pos_x + (size_x - (2 * INTERVAL)) / 2;
const int right_check_pos_x = right_pos_x + (edit_pos_x - label_pos_x);
const bool disable_cert_verification = util::AsBool(val).value_or(false);
- labels_.push_back(CreateLabel(
- right_pos_x, row_pos, LABEL_WIDTH, 2 * ROW_HEIGHT,
- "Disable Certificate Verification:",
ChildId::DISABLE_CERT_VERIFICATION_LABEL));
+ labels_.push_back(CreateLabel(right_pos_x, row_pos, LABEL_WIDTH, 2 *
ROW_HEIGHT,
+ L"Disable Certificate Verification:",
+ ChildId::DISABLE_CERT_VERIFICATION_LABEL));
disable_cert_verification_check_box_ = CreateCheckBox(
- right_check_pos_x, row_pos - 2, 20, 2 * ROW_HEIGHT, "",
+ right_check_pos_x, row_pos - 2, 20, 2 * ROW_HEIGHT, L"",
ChildId::DISABLE_CERT_VERIFICATION_CHECKBOX, disable_cert_verification);
row_pos += INTERVAL + static_cast<int>(1.5 * static_cast<int>(ROW_HEIGHT));
encryption_settings_group_box_ =
- CreateGroupBox(pos_x, pos_y, size_x, row_pos - pos_y, "Encryption
settings",
+ CreateGroupBox(pos_x, pos_y, size_x, row_pos - pos_y, L"Encryption
settings",
ChildId::AUTH_SETTINGS_GROUP_BOX);
+ certificate_edit_->SetEnabled(enable_encryption);
+ certificate_browse_button_->SetEnabled(enable_encryption);
+ use_system_cert_store_check_box_->SetEnabled(enable_encryption);
+ disable_cert_verification_check_box_->SetEnabled(enable_encryption);
+
return row_pos - pos_y;
}
@@ -306,12 +321,15 @@ int DsnConfigurationWindow::CreatePropertiesGroup(int
pos_x, int pos_y, int size
property_list_ =
CreateList(label_pos_x, row_pos, list_size, list_height,
ChildId::PROPERTY_LIST);
- property_list_->ListAddColumn("Key", 0, column_size);
- property_list_->ListAddColumn("Value", 1, column_size);
+ property_list_->ListAddColumn(L"Key", 0, column_size);
+ property_list_->ListAddColumn(L"Value", 1, column_size);
const auto keys = config_.GetCustomKeys();
for (const auto& key : keys) {
- property_list_->ListAddItem({std::string(key), config_.Get(key)});
+ CONVERT_WIDE_STR(const std::wstring wkey, key);
+ CONVERT_WIDE_STR(const std::wstring wval, config_.Get(key));
+
+ property_list_->ListAddItem({wkey, wval});
}
SendMessage(property_list_->GetHandle(), LVM_SETEXTENDEDLISTVIEWSTYLE,
@@ -321,15 +339,15 @@ int DsnConfigurationWindow::CreatePropertiesGroup(int
pos_x, int pos_y, int size
int delete_pos_x = width_ - INTERVAL - MARGIN - BUTTON_WIDTH;
int add_pos_x = delete_pos_x - INTERVAL - BUTTON_WIDTH;
- add_button_ = CreateButton(add_pos_x, row_pos, BUTTON_WIDTH, BUTTON_HEIGHT,
"Add",
+ add_button_ = CreateButton(add_pos_x, row_pos, BUTTON_WIDTH, BUTTON_HEIGHT,
L"Add",
ChildId::ADD_BUTTON);
delete_button_ = CreateButton(delete_pos_x, row_pos, BUTTON_WIDTH,
BUTTON_HEIGHT,
- "Delete", ChildId::DELETE_BUTTON);
+ L"Delete", ChildId::DELETE_BUTTON);
row_pos += INTERVAL + BUTTON_HEIGHT;
property_group_box_ =
- CreateGroupBox(pos_x, pos_y, size_x, row_pos - pos_y, "Advanced
properties",
+ CreateGroupBox(pos_x, pos_y, size_x, row_pos - pos_y, L"Advanced
properties",
ChildId::PROPERTY_GROUP_BOX);
return row_pos - pos_y;
@@ -390,7 +408,7 @@ void DsnConfigurationWindow::CheckEnableOk() {
void DsnConfigurationWindow::SaveParameters(Configuration& target_config) {
target_config.Clear();
- std::string text;
+ std::wstring text;
name_edit_->GetText(text);
target_config.Set(FlightSqlConnection::DSN, text);
server_edit_->GetText(text);
@@ -429,13 +447,17 @@ void
DsnConfigurationWindow::SaveParameters(Configuration& target_config) {
FlightSqlConnection::DISABLE_CERTIFICATE_VERIFICATION,
disable_cert_verification_check_box_->IsChecked() ? TRUE_STR :
FALSE_STR);
} else {
+ // System trust store verification requires encryption
target_config.Set(FlightSqlConnection::USE_ENCRYPTION, FALSE_STR);
+ target_config.Set(FlightSqlConnection::USE_SYSTEM_TRUST_STORE, FALSE_STR);
}
// Get all the list properties.
const auto properties = property_list_->ListGetAll();
for (const auto& property : properties) {
- target_config.Set(property[0], property[1]);
+ std::string property_key =
arrow::util::WideStringToUTF8(property[0]).ValueOr("");
+ std::string property_value =
arrow::util::WideStringToUTF8(property[1]).ValueOr("");
+ target_config.Set(property_key, property_value);
}
}
@@ -471,9 +493,14 @@ bool DsnConfigurationWindow::OnMessage(UINT msg, WPARAM
wparam, LPARAM lparam) {
SaveParameters(test_config);
std::string test_message = TestConnection(test_config);
- MessageBox(NULL, test_message.c_str(), "Test Connection Success",
MB_OK);
+ CONVERT_WIDE_STR(const std::wstring w_test_message, test_message);
+
+ MessageBox(NULL, w_test_message.c_str(), L"Test Connection
Success", MB_OK);
} catch (DriverException& err) {
- MessageBox(NULL, err.GetMessageText().c_str(), "Error!",
+ const std::wstring w_message_text =
+ arrow::util::UTF8ToWideString(err.GetMessageText())
+ .ValueOr(L"Test failed");
+ MessageBox(NULL, w_message_text.c_str(), L"Error!",
MB_ICONEXCLAMATION | MB_OK);
}
@@ -485,7 +512,10 @@ bool DsnConfigurationWindow::OnMessage(UINT msg, WPARAM
wparam, LPARAM lparam) {
accepted_ = true;
PostMessage(GetHandle(), WM_CLOSE, 0, 0);
} catch (DriverException& err) {
- MessageBox(NULL, err.GetMessageText().c_str(), "Error!",
+ const std::wstring w_message_text =
+ arrow::util::UTF8ToWideString(err.GetMessageText())
+ .ValueOr(L"Error when saving DSN");
+ MessageBox(NULL, w_message_text.c_str(), L"Error!",
MB_ICONEXCLAMATION | MB_OK);
}
@@ -528,7 +558,7 @@ bool DsnConfigurationWindow::OnMessage(UINT msg, WPARAM
wparam, LPARAM lparam) {
case ChildId::CERTIFICATE_BROWSE_BUTTON: {
OPENFILENAME open_file_name;
- char file_name[FILENAME_MAX];
+ wchar_t file_name[FILENAME_MAX];
ZeroMemory(&open_file_name, sizeof(open_file_name));
open_file_name.lStructSize = sizeof(open_file_name);
@@ -537,7 +567,7 @@ bool DsnConfigurationWindow::OnMessage(UINT msg, WPARAM
wparam, LPARAM lparam) {
open_file_name.lpstrFile[0] = '\0';
open_file_name.nMaxFile = FILENAME_MAX;
// TODO: What type should this be?
- open_file_name.lpstrFilter = "All\0*.*";
+ open_file_name.lpstrFilter = L"All\0*.*";
open_file_name.nFilterIndex = 1;
open_file_name.lpstrFileTitle = NULL;
open_file_name.nMaxFileTitle = 0;
@@ -574,8 +604,8 @@ bool DsnConfigurationWindow::OnMessage(UINT msg, WPARAM
wparam, LPARAM lparam) {
add_window.Update();
if (ProcessMessages(add_window) == Result::OK) {
- std::string key;
- std::string value;
+ std::wstring key;
+ std::wstring value;
add_window.GetProperty(key, value);
property_list_->ListAddItem({key, value});
}
diff --git a/cpp/src/arrow/flight/sql/odbc/odbc_impl/ui/window.cc
b/cpp/src/arrow/flight/sql/odbc/odbc_impl/ui/window.cc
index e31887521b..f21329977b 100644
--- a/cpp/src/arrow/flight/sql/odbc/odbc_impl/ui/window.cc
+++ b/cpp/src/arrow/flight/sql/odbc/odbc_impl/ui/window.cc
@@ -48,7 +48,7 @@ HINSTANCE GetHInstance() {
return h_instance;
}
-Window::Window(Window* parent, const char* class_name, const char* title)
+Window::Window(Window* parent, const wchar_t* class_name, const wchar_t* title)
: class_name_(class_name),
title_(title),
handle_(NULL),
@@ -91,7 +91,7 @@ void Window::Create(DWORD style, int pos_x, int pos_y, int
width, int height, in
}
std::unique_ptr<Window> Window::CreateTabControl(int id) {
- std::unique_ptr<Window> child(new Window(this, WC_TABCONTROL, ""));
+ std::unique_ptr<Window> child(new Window(this, WC_TABCONTROL, L""));
// Get the dimensions of the parent window's client area, and
// create a tab control child window of that size.
@@ -106,7 +106,7 @@ std::unique_ptr<Window> Window::CreateTabControl(int id) {
std::unique_ptr<Window> Window::CreateList(int pos_x, int pos_y, int size_x,
int size_y,
int id) {
- std::unique_ptr<Window> child(new Window(this, WC_LISTVIEW, ""));
+ std::unique_ptr<Window> child(new Window(this, WC_LISTVIEW, L""));
child->Create(
WS_CHILD | WS_VISIBLE | WS_BORDER | LVS_REPORT | LVS_EDITLABELS |
WS_TABSTOP, pos_x,
@@ -116,8 +116,8 @@ std::unique_ptr<Window> Window::CreateList(int pos_x, int
pos_y, int size_x, int
}
std::unique_ptr<Window> Window::CreateGroupBox(int pos_x, int pos_y, int
size_x,
- int size_y, const char* title,
int id) {
- std::unique_ptr<Window> child(new Window(this, "Button", title));
+ int size_y, const wchar_t*
title, int id) {
+ std::unique_ptr<Window> child(new Window(this, L"Button", title));
child->Create(WS_CHILD | WS_VISIBLE | BS_GROUPBOX, pos_x, pos_y, size_x,
size_y, id);
@@ -125,8 +125,8 @@ std::unique_ptr<Window> Window::CreateGroupBox(int pos_x,
int pos_y, int size_x,
}
std::unique_ptr<Window> Window::CreateLabel(int pos_x, int pos_y, int size_x,
int size_y,
- const char* title, int id) {
- std::unique_ptr<Window> child(new Window(this, "Static", title));
+ const wchar_t* title, int id) {
+ std::unique_ptr<Window> child(new Window(this, L"Static", title));
child->Create(WS_CHILD | WS_VISIBLE, pos_x, pos_y, size_x, size_y, id);
@@ -134,8 +134,8 @@ std::unique_ptr<Window> Window::CreateLabel(int pos_x, int
pos_y, int size_x, in
}
std::unique_ptr<Window> Window::CreateEdit(int pos_x, int pos_y, int size_x,
int size_y,
- const char* title, int id, int
style) {
- std::unique_ptr<Window> child(new Window(this, "Edit", title));
+ const wchar_t* title, int id, int
style) {
+ std::unique_ptr<Window> child(new Window(this, L"Edit", title));
child->Create(WS_CHILD | WS_VISIBLE | WS_BORDER | ES_AUTOHSCROLL |
WS_TABSTOP | style,
pos_x, pos_y, size_x, size_y, id);
@@ -144,8 +144,8 @@ std::unique_ptr<Window> Window::CreateEdit(int pos_x, int
pos_y, int size_x, int
}
std::unique_ptr<Window> Window::CreateButton(int pos_x, int pos_y, int size_x,
int size_y,
- const char* title, int id, int
style) {
- std::unique_ptr<Window> child(new Window(this, "Button", title));
+ const wchar_t* title, int id, int
style) {
+ std::unique_ptr<Window> child(new Window(this, L"Button", title));
child->Create(WS_CHILD | WS_VISIBLE | WS_TABSTOP | style, pos_x, pos_y,
size_x, size_y,
id);
@@ -154,9 +154,9 @@ std::unique_ptr<Window> Window::CreateButton(int pos_x, int
pos_y, int size_x, i
}
std::unique_ptr<Window> Window::CreateCheckBox(int pos_x, int pos_y, int
size_x,
- int size_y, const char* title,
int id,
+ int size_y, const wchar_t*
title, int id,
bool state) {
- std::unique_ptr<Window> child(new Window(this, "Button", title));
+ std::unique_ptr<Window> child(new Window(this, L"Button", title));
child->Create(WS_CHILD | WS_VISIBLE | BS_CHECKBOX | WS_TABSTOP, pos_x,
pos_y, size_x,
size_y, id);
@@ -167,8 +167,8 @@ std::unique_ptr<Window> Window::CreateCheckBox(int pos_x,
int pos_y, int size_x,
}
std::unique_ptr<Window> Window::CreateComboBox(int pos_x, int pos_y, int
size_x,
- int size_y, const char* title,
int id) {
- std::unique_ptr<Window> child(new Window(this, "Combobox", title));
+ int size_y, const wchar_t*
title, int id) {
+ std::unique_ptr<Window> child(new Window(this, L"Combobox", title));
child->Create(WS_CHILD | WS_VISIBLE | CBS_DROPDOWNLIST | WS_TABSTOP, pos_x,
pos_y,
size_x, size_y, id);
@@ -199,12 +199,12 @@ bool Window::IsTextEmpty() const {
return (len <= 0);
}
-void Window::ListAddColumn(const std::string& name, int index, int width) {
+void Window::ListAddColumn(const std::wstring& name, int index, int width) {
LVCOLUMN lvc;
lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
lvc.fmt = LVCFMT_LEFT;
lvc.cx = width;
- lvc.pszText = const_cast<char*>(name.c_str());
+ lvc.pszText = const_cast<wchar_t*>(name.c_str());
lvc.iSubItem = index;
if (ListView_InsertColumn(handle_, index, &lvc) == -1) {
@@ -214,10 +214,10 @@ void Window::ListAddColumn(const std::string& name, int
index, int width) {
}
}
-void Window::ListAddItem(const std::vector<std::string>& items) {
+void Window::ListAddItem(const std::vector<std::wstring>& items) {
LVITEM lvi = {0};
lvi.mask = LVIF_TEXT;
- lvi.pszText = const_cast<char*>(items[0].c_str());
+ lvi.pszText = const_cast<wchar_t*>(items[0].c_str());
int ret = ListView_InsertItem(handle_, &lvi);
if (ret < 0) {
@@ -228,7 +228,7 @@ void Window::ListAddItem(const std::vector<std::string>&
items) {
for (size_t i = 1; i < items.size(); ++i) {
ListView_SetItemText(handle_, ret, static_cast<int>(i),
- const_cast<char*>(items[i].c_str()));
+ const_cast<wchar_t*>(items[i].c_str()));
}
}
@@ -243,15 +243,15 @@ void Window::ListDeleteSelectedItem() {
}
}
-std::vector<std::vector<std::string> > Window::ListGetAll() {
+std::vector<std::vector<std::wstring> > Window::ListGetAll() {
#define BUF_LEN 1024
- char buf[BUF_LEN];
+ wchar_t buf[BUF_LEN];
- std::vector<std::vector<std::string> > values;
+ std::vector<std::vector<std::wstring> > values;
const int num_columns = Header_GetItemCount(ListView_GetHeader(handle_));
const int num_items = ListView_GetItemCount(handle_);
for (int i = 0; i < num_items; ++i) {
- std::vector<std::string> row;
+ std::vector<std::wstring> row;
for (int j = 0; j < num_columns; ++j) {
ListView_GetItemText(handle_, i, j, buf, BUF_LEN);
row.emplace_back(buf);
@@ -262,11 +262,11 @@ std::vector<std::vector<std::string> >
Window::ListGetAll() {
return values;
}
-void Window::AddTab(const std::string& name, int index) {
+void Window::AddTab(const std::wstring& name, int index) {
TCITEM tab_control_item;
tab_control_item.mask = TCIF_TEXT | TCIF_IMAGE;
tab_control_item.iImage = -1;
- tab_control_item.pszText = const_cast<char*>(name.c_str());
+ tab_control_item.pszText = const_cast<wchar_t*>(name.c_str());
if (TabCtrl_InsertItem(handle_, index, &tab_control_item) == -1) {
std::stringstream buf;
buf << "Can not add tab, error code: " << GetLastError();
@@ -274,7 +274,7 @@ void Window::AddTab(const std::string& name, int index) {
}
}
-void Window::GetText(std::string& text) const {
+void Window::GetText(std::wstring& text) const {
if (!IsEnabled()) {
text.clear();
@@ -297,7 +297,7 @@ void Window::GetText(std::string& text) const {
boost::algorithm::trim(text);
}
-void Window::SetText(const std::string& text) const {
+void Window::SetText(const std::wstring& text) const {
SNDMSG(handle_, WM_SETTEXT, 0, reinterpret_cast<LPARAM>(text.c_str()));
}
@@ -309,7 +309,7 @@ void Window::SetChecked(bool state) {
Button_SetCheck(handle_, state ? BST_CHECKED : BST_UNCHECKED);
}
-void Window::AddString(const std::string& str) {
+void Window::AddString(const std::wstring& str) {
SNDMSG(handle_, CB_ADDSTRING, 0, reinterpret_cast<LPARAM>(str.c_str()));
}
diff --git a/cpp/src/arrow/flight/sql/odbc/odbc_impl/ui/window.h
b/cpp/src/arrow/flight/sql/odbc/odbc_impl/ui/window.h
index 0ca7ba329c..b8aa438d9a 100644
--- a/cpp/src/arrow/flight/sql/odbc/odbc_impl/ui/window.h
+++ b/cpp/src/arrow/flight/sql/odbc/odbc_impl/ui/window.h
@@ -43,7 +43,7 @@ class Window {
* @param class_name Window class name.
* @param title Window title.
*/
- Window(Window* parent, const char* class_name, const char* title);
+ Window(Window* parent, const wchar_t* class_name, const wchar_t* title);
/**
* Constructor for the existing window.
@@ -102,7 +102,7 @@ class Window {
* @return Auto pointer containing new window.
*/
std::unique_ptr<Window> CreateGroupBox(int pos_x, int pos_y, int size_x, int
size_y,
- const char* title, int id);
+ const wchar_t* title, int id);
/**
* Create child label window.
@@ -116,7 +116,7 @@ class Window {
* @return Auto pointer containing new window.
*/
std::unique_ptr<Window> CreateLabel(int pos_x, int pos_y, int size_x, int
size_y,
- const char* title, int id);
+ const wchar_t* title, int id);
/**
* Create child Edit window.
@@ -131,7 +131,7 @@ class Window {
* @return Auto pointer containing new window.
*/
std::unique_ptr<Window> CreateEdit(int pos_x, int pos_y, int size_x, int
size_y,
- const char* title, int id, int style = 0);
+ const wchar_t* title, int id, int style =
0);
/**
* Create child button window.
@@ -146,7 +146,7 @@ class Window {
* @return Auto pointer containing new window.
*/
std::unique_ptr<Window> CreateButton(int pos_x, int pos_y, int size_x, int
size_y,
- const char* title, int id, int style =
0);
+ const wchar_t* title, int id, int style
= 0);
/**
* Create child CheckBox window.
@@ -161,7 +161,7 @@ class Window {
* @return Auto pointer containing new window.
*/
std::unique_ptr<Window> CreateCheckBox(int pos_x, int pos_y, int size_x, int
size_y,
- const char* title, int id, bool
state);
+ const wchar_t* title, int id, bool
state);
/**
* Create child ComboBox window.
@@ -175,7 +175,7 @@ class Window {
* @return Auto pointer containing new window.
*/
std::unique_ptr<Window> CreateComboBox(int pos_x, int pos_y, int size_x, int
size_y,
- const char* title, int id);
+ const wchar_t* title, int id);
/**
* Show window.
@@ -201,15 +201,15 @@ class Window {
void SetVisible(bool isVisible);
- void ListAddColumn(const std::string& name, int index, int width);
+ void ListAddColumn(const std::wstring& name, int index, int width);
- void ListAddItem(const std::vector<std::string>& items);
+ void ListAddItem(const std::vector<std::wstring>& items);
void ListDeleteSelectedItem();
- std::vector<std::vector<std::string> > ListGetAll();
+ std::vector<std::vector<std::wstring> > ListGetAll();
- void AddTab(const std::string& name, int index);
+ void AddTab(const std::wstring& name, int index);
bool IsTextEmpty() const;
@@ -218,14 +218,14 @@ class Window {
*
* @param text Text.
*/
- void GetText(std::string& text) const;
+ void GetText(std::wstring& text) const;
/**
* Set window text.
*
* @param text Text.
*/
- void SetText(const std::string& text) const;
+ void SetText(const std::wstring& text) const;
/**
* Get CheckBox state.
@@ -246,7 +246,7 @@ class Window {
*
* @param str String.
*/
- void AddString(const std::string& str);
+ void AddString(const std::wstring& str);
/**
* Set current ComboBox selection.
@@ -285,10 +285,10 @@ class Window {
void SetHandle(HWND value) { handle_ = value; }
/** Window class name. */
- std::string class_name_;
+ std::wstring class_name_;
/** Window title. */
- std::string title_;
+ std::wstring title_;
/** Window handle. */
HWND handle_;
diff --git a/cpp/src/arrow/flight/sql/odbc/odbc_impl/util.h
b/cpp/src/arrow/flight/sql/odbc/odbc_impl/util.h
index 32c2c90747..8197f741d1 100644
--- a/cpp/src/arrow/flight/sql/odbc/odbc_impl/util.h
+++ b/cpp/src/arrow/flight/sql/odbc/odbc_impl/util.h
@@ -17,6 +17,8 @@
#pragma once
+#include "arrow/util/utf8.h"
+
#include "arrow/flight/sql/odbc/odbc_impl/exceptions.h"
#include "arrow/flight/sql/odbc/odbc_impl/spi/connection.h"
#include "arrow/flight/sql/odbc/odbc_impl/types.h"
@@ -27,6 +29,20 @@
#include <functional>
#include <optional>
+#define CONVERT_WIDE_STR(wstring_var, utf8_target)
\
+ wstring_var = [&] {
\
+ arrow::Result<std::wstring> res =
arrow::util::UTF8ToWideString(utf8_target); \
+ arrow::flight::sql::odbc::util::ThrowIfNotOK(res.status());
\
+ return res.ValueOrDie();
\
+ }()
+
+#define CONVERT_UTF8_STR(string_var, wide_str_target)
\
+ string_var = [&] {
\
+ arrow::Result<std::string> res =
arrow::util::WideStringToUTF8(wide_str_target); \
+ arrow::flight::sql::odbc::util::ThrowIfNotOK(res.status());
\
+ return res.ValueOrDie();
\
+ }()
+
namespace arrow::flight::sql::odbc {
namespace util {