Skip to content

DSN window implementation #35

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 26, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions cpp/src/arrow/flight/sql/odbc/flight_sql/system_dsn.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include "arrow/flight/sql/odbc/flight_sql/include/flight_sql/config/configuration.h"

using driver::flight_sql::config::Configuration;
using driver::odbcabstraction::Connection;

#if defined _WIN32 || defined _WIN64
/**
Expand All @@ -31,6 +32,19 @@ using driver::flight_sql::config::Configuration;
* @return True on success and false on fail.
*/
bool DisplayConnectionWindow(void* windowParent, Configuration& config);

/**
* For SQLDriverConnect.
* Display connection window for user to configure connection parameters.
*
* @param windowParent Parent window handle.
* @param config Output configuration, presumed to be empty, it will be using values from
* properties.
* @param config Output properties.
* @return True on success and false on fail.
*/
bool DisplayConnectionWindow(void* windowParent, Configuration& config,
Connection::ConnPropertyMap& properties);
#endif

/**
Expand Down
18 changes: 17 additions & 1 deletion cpp/src/arrow/flight/sql/odbc/flight_sql/win_system_dsn.cc
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ using driver::flight_sql::config::ConnectionStringParser;
using driver::flight_sql::config::DsnConfigurationWindow;
using driver::flight_sql::config::Result;
using driver::flight_sql::config::Window;
using driver::odbcabstraction::DriverException;

BOOL CALLBACK ConfigDriver(HWND hwndParent, WORD fRequest, LPCSTR lpszDriver,
LPCSTR lpszArgs, LPSTR lpszMsg, WORD cbMsgMax,
Expand All @@ -63,7 +64,7 @@ bool DisplayConnectionWindow(void* windowParent, Configuration& config) {
window.Update();

return ProcessMessages(window) == Result::OK;
} catch (const driver::odbcabstraction::DriverException& err) {
} catch (const DriverException& err) {
std::stringstream buf;
buf << "SQL State: " << err.GetSqlState() << ", Message: " << err.GetMessageText()
<< ", Code: " << err.GetNativeError();
Expand All @@ -76,6 +77,21 @@ bool DisplayConnectionWindow(void* windowParent, Configuration& config) {
return false;
}

bool DisplayConnectionWindow(void* windowParent, Configuration& config,
Connection::ConnPropertyMap& properties) {
for (const auto& [key, value] : properties) {
config.Set(key, value);
}

if (DisplayConnectionWindow(windowParent, config)) {
properties = config.GetProperties();
return true;
} else {
// TODO: log cancelled dialog after logging is enabled.
return false;
}
}

BOOL INSTAPI ConfigDSN(HWND hwndParent, WORD req, LPCSTR driver, LPCSTR attributes) {
Configuration config;
ConnectionStringParser parser(config);
Expand Down
42 changes: 34 additions & 8 deletions cpp/src/arrow/flight/sql/odbc/odbc_api.cc
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,7 @@ SQLRETURN SQLDriverConnectW(SQLHDBC conn, SQLHWND windowHandle,
// spec https://github.com/apache/arrow/issues/46560

using driver::odbcabstraction::Connection;
using driver::odbcabstraction::DriverException;
using ODBC::ODBCConnection;

return ODBCConnection::ExecuteWithDiagnostics(conn, SQL_ERROR, [=]() {
Expand All @@ -369,16 +370,41 @@ SQLRETURN SQLDriverConnectW(SQLHDBC conn, SQLHWND windowHandle,
// TODO: Implement SQL_DRIVER_COMPLETE_REQUIRED in SQLDriverConnectW according to the
// spec https://github.com/apache/arrow/issues/46448
#if defined _WIN32 || defined _WIN64
if (driverCompletion == SQL_DRIVER_PROMPT ||
((driverCompletion == SQL_DRIVER_COMPLETE ||
driverCompletion == SQL_DRIVER_COMPLETE_REQUIRED) &&
!missing_properties.empty())) {
// TODO: implement driverCompletion behavior to display connection window.
// Load the DSN window according to driverCompletion
if (driverCompletion == SQL_DRIVER_PROMPT) {
// Load DSN window before first attempt to connect
driver::flight_sql::config::Configuration config;
if (!DisplayConnectionWindow(windowHandle, config, properties)) {
return static_cast<SQLRETURN>(SQL_NO_DATA);
}
connection->connect(dsn, properties, missing_properties);
} else if (driverCompletion == SQL_DRIVER_COMPLETE ||
driverCompletion == SQL_DRIVER_COMPLETE_REQUIRED) {
try {
connection->connect(dsn, properties, missing_properties);
} catch (const DriverException&) {
// If first connection fails due to missing attributes, load
// the DSN window and try to connect again
if (!missing_properties.empty()) {
driver::flight_sql::config::Configuration config;
missing_properties.clear();

if (!DisplayConnectionWindow(windowHandle, config, properties)) {
return static_cast<SQLRETURN>(SQL_NO_DATA);
}
connection->connect(dsn, properties, missing_properties);
} else {
throw;
}
}
} else {
// Default case: attempt connection without showing DSN window
connection->connect(dsn, properties, missing_properties);
}
#endif

#else
// Attempt connection without loading DSN window on macOS/Linux
connection->connect(dsn, properties, missing_properties);

#endif
// Copy connection string to outConnectionString after connection attempt
return ODBC::GetStringAttribute(true, connection_string, true, outConnectionString,
outConnectionStringBufferLen, outConnectionStringLen,
Expand Down