Skip to content
Open
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
7 changes: 7 additions & 0 deletions google/cloud/odbc/bq_driver/internal/odbc_conn_attr.cc
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ ConnectionAttr::ConnectionAttr() {
{SQL_ATTR_LOGIN_TIMEOUT,
{"SQL_ATTR_LOGIN_TIMEOUT", ConnectionValidation::kBefore,
SupportedAttribute::kBoth, (SQLPOINTER)0}},
{SQL_ATTR_ANSI_APP,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please see how to write test case for this

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

existing test cases will be utilsied

{"SQL_ATTR_ANSI_APP", ConnectionValidation::kEither,
SupportedAttribute::kSet, (SQLPOINTER)SQL_AA_FALSE}},
{SQL_ATTR_METADATA_ID,
{"SQL_ATTR_METADATA_ID", ConnectionValidation::kEither,
SupportedAttribute::kBoth, (SQLPOINTER)SQL_FALSE}},
Expand Down Expand Up @@ -76,6 +79,10 @@ ConnectionAttr::ConnectionAttr() {
{"SQL_ATTR_AUTOCOMMIT",
ConnectionValueType::kSqlUInt,
{(SQLPOINTER)SQL_AUTOCOMMIT_OFF, (SQLPOINTER)SQL_AUTOCOMMIT_ON}}},
{SQL_ATTR_ANSI_APP,
{"SQL_ATTR_ANSI_APP",
ConnectionValueType::kSqlULen,
{(SQLPOINTER)SQL_AA_TRUE, (SQLPOINTER)SQL_AA_FALSE}}},
{SQL_ATTR_METADATA_ID,
{"SQL_ATTR_METADATA_ID",
ConnectionValueType::kSqlUInt,
Expand Down
10 changes: 10 additions & 0 deletions google/cloud/odbc/bq_driver/internal/odbc_conn_handle.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ struct Authentication {
std::string refresh_token;
};

enum struct ApplicationType { kUnknown = 0, kAnsi = 1, kUnicode = 2 };

// This is populated by SQL*Connect APIs after parsing the DSN section from
// odbc.ini/Windows Registry
struct Dsn {
Expand Down Expand Up @@ -133,6 +135,12 @@ class ConnectionHandle : public Handle {

void SetUp(Section& dsn_section, std::string const& dsn_name);

void SetApplicationType(ApplicationType type) { type_ = type; };

ApplicationType GetApplicationType() { return type_; }

bool IsAnsiApplication() { return type_ == ApplicationType::kAnsi; }

Dsn GetDsn() const { return dsn_; }

std::shared_ptr<ODBCBQClient> GetClient() { return client_; }
Expand Down Expand Up @@ -197,6 +205,8 @@ class ConnectionHandle : public Handle {
// storage of all explicitly allocated descriptor handles associated with this
// connection handle
std::set<DescriptorHandle*> desc_handles_;

ApplicationType type_ = ApplicationType::kUnknown;
EnvironmentHandle* env_handle_{nullptr};
mutable std::mutex connection_handle_mutex_;
// Session ID of the started session.
Expand Down
7 changes: 7 additions & 0 deletions google/cloud/odbc/bq_driver/odbc_connection.cc
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ namespace google::cloud::odbc_bq_driver {

using google::cloud::odbc_bigquery_client_interface::OauthMechanism;
using google::cloud::odbc_bq_driver::ToCharStr;
using google::cloud::odbc_bq_driver_internal::ApplicationType;
using google::cloud::odbc_bq_driver_internal::Authentication;
using google::cloud::odbc_bq_driver_internal::ConnectionHandle;
using google::cloud::odbc_bq_driver_internal::DescriptorHandle;
Expand Down Expand Up @@ -472,6 +473,12 @@ SQLRETURN SQLSetConnectAttrInternal(SQLHDBC connection_handle,
return LogAndReturnCode(*conn_handle, status_record);
}

if (attribute == SQL_ATTR_ANSI_APP) {
conn_handle->SetApplicationType(
(reinterpret_cast<SQLULEN>(value) == SQL_AA_TRUE)
? ApplicationType::kAnsi
: ApplicationType::kUnicode);
}
// Additionally set these attributes to all associated statement handles
if (attribute == SQL_ATTR_METADATA_ID || attribute == SQL_ATTR_ASYNC_ENABLE) {
for (auto* const stmt_handle : conn_handle->GetStatementHandles()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -581,6 +581,26 @@ TEST(MultipleConnectionTest, SQLDriverConnect) {
}
}

TEST(ConnectionTest, VerifySQLANSIAttributes) {
auto conn = std::make_shared<ODBCHandles>();
SQLRETURN status;
SQLCHAR data_source[kBufferLength];
SQLSMALLINT buflen = 0;
SetAttributes(conn, 30, true);
StrToChar(reinterpret_cast<char*>(data_source), kDefaultConnectionString);

status =
SQLDriverConnectA(conn->hdbc, nullptr, data_source, SQL_NTS,
reinterpret_cast<SQLCHAR*>(conn->outdsn),
sizeof(conn->outdsn), &buflen, SQL_DRIVER_COMPLETE);
CheckError(status, "SQLDriverConnectA", conn, true);

// SQL_ATTR_ANSI_APP is expected to be successful after connection.
status = SQLSetConnectAttr(conn->hdbc, SQL_ATTR_ANSI_APP,
ToSqlPointer(SQL_AA_FALSE), 0);
EXPECT_EQ(status, SQL_SUCCESS);
}

TEST(ConnectionTest, SQLDriverConnectA) {
auto conn = std::make_shared<ODBCHandles>();
EXPECT_EQ(Connect(kDefaultConnectionString, conn, true), SQL_SUCCESS);
Expand Down
14 changes: 12 additions & 2 deletions google/cloud/odbc/testing/odbc_utils/connection.cc
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,11 @@ void SetAttributes(std::shared_ptr<ODBCHandles> const& conn, int timeout,
status = SQLSetConnectAttrA(conn->hdbc, SQL_ATTR_CONNECTION_TIMEOUT,
ToSqlPointer(timeout), 0);
CheckError(status, "SQLSetConnectAttr", conn, use_ansi);
#ifndef WIN32
status = SQLSetConnectAttrA(conn->hdbc, SQL_ATTR_ANSI_APP,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's verify if driver manager is allowed to dynamically change the bahaviour by setting SQL_ATTR_ANSI_APP to true/false.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added attribute value change after connection creation, driver has same behavior as Simba BQ driver and also same same behavior as official doc.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see where we are setting the attribute after making the connection. SetAttributes function is called before.

ToSqlPointer(SQL_AA_TRUE), 0);
CheckError(status, "SQLSetConnectAttr", conn, use_ansi);
#endif // WIN32
} else {
status = SQLSetConnectAttr(conn->hdbc, SQL_ATTR_LOGIN_TIMEOUT,
ToSqlPointer(10), 0);
Expand All @@ -44,12 +49,17 @@ void SetAttributes(std::shared_ptr<ODBCHandles> const& conn, int timeout,
status = SQLSetConnectAttr(conn->hdbc, SQL_ATTR_CONNECTION_TIMEOUT,
ToSqlPointer(timeout), 0);
CheckError(status, "SQLSetConnectAttr", conn, use_ansi);
#ifndef WIN32
status = SQLSetConnectAttr(conn->hdbc, SQL_ATTR_ANSI_APP,
ToSqlPointer(SQL_AA_FALSE), 0);
CheckError(status, "SQLSetConnectAttr", conn, use_ansi);
#endif // WIN32
}
}

SQLRETURN Connect(std::string const& conn_str,
std::shared_ptr<ODBCHandles> const& conn, int timeout,
bool use_ansi) {
std::shared_ptr<ODBCHandles> const& conn, bool use_ansi,
int timeout) {
SQLSMALLINT buflen;
SQLCHAR data_source[kBufferLength];
SQLSMALLINT out_len;
Expand Down
2 changes: 1 addition & 1 deletion google/cloud/odbc/testing/odbc_utils/connection.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ std::string const kImpersonatedAccountEmail =
// Connect using a <conn_str> and populate the ODBCHandles
SQLRETURN
Connect(std::string const& conn_str, std::shared_ptr<ODBCHandles> const& conn,
int timeout = 30, bool use_ansi = false);
bool use_ansi = false, int timeout = 30);

// To validate SQLDriverConnect and SQLDriverConnectW with NULL output
// parameters.
Expand Down
Loading