Skip to content

Commit c22f3c8

Browse files
committed
Extract SQLCloseCursor implementation
Update doxygen Co-Authored-By: alinalibq <[email protected]>
1 parent dcfb211 commit c22f3c8

File tree

4 files changed

+41
-14
lines changed

4 files changed

+41
-14
lines changed

cpp/src/arrow/flight/sql/odbc/odbc_api.cc

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1065,8 +1065,16 @@ SQLRETURN SQLBindCol(SQLHSTMT stmt, SQLUSMALLINT record_number, SQLSMALLINT c_ty
10651065

10661066
SQLRETURN SQLCloseCursor(SQLHSTMT stmt) {
10671067
ARROW_LOG(DEBUG) << "SQLCloseCursor called with stmt: " << stmt;
1068-
// GH-47717 TODO: Implement SQLCloseCursor
1069-
return SQL_INVALID_HANDLE;
1068+
1069+
using ODBC::ODBCStatement;
1070+
return ODBCStatement::ExecuteWithDiagnostics(stmt, SQL_ERROR, [=]() {
1071+
ODBCStatement* statement = reinterpret_cast<ODBCStatement*>(stmt);
1072+
1073+
// Close cursor with suppressErrors set to false
1074+
statement->CloseCursor(false);
1075+
1076+
return SQL_SUCCESS;
1077+
});
10701078
}
10711079

10721080
SQLRETURN SQLGetData(SQLHSTMT stmt, SQLUSMALLINT record_number, SQLSMALLINT c_type,

cpp/src/arrow/flight/sql/odbc/odbc_impl/odbc_statement.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -693,7 +693,7 @@ void ODBCStatement::RevertAppDescriptor(bool isApd) {
693693

694694
void ODBCStatement::CloseCursor(bool suppress_errors) {
695695
if (!suppress_errors && !current_result_) {
696-
throw DriverException("Invalid cursor state", "28000");
696+
throw DriverException("Invalid cursor state", "24000");
697697
}
698698

699699
if (current_result_) {

cpp/src/arrow/flight/sql/odbc/odbc_impl/odbc_statement.h

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -80,15 +80,11 @@ class ODBCStatement : public ODBCHandle<ODBCStatement> {
8080
bool GetData(SQLSMALLINT record_number, SQLSMALLINT c_type, SQLPOINTER data_ptr,
8181
SQLLEN buffer_length, SQLLEN* indicator_ptr);
8282

83-
/**
84-
* @brief Closes the cursor. This does _not_ un-prepare the statement or change
85-
* bindings.
86-
*/
83+
/// \brief Closes the cursor. This does _not_ un-prepare the statement or change
84+
/// bindings.
8785
void CloseCursor(bool suppress_errors);
8886

89-
/**
90-
* @brief Releases this statement from memory.
91-
*/
87+
/// \brief Releases this statement from memory.
9288
void ReleaseStatement();
9389

9490
void GetTables(const std::string* catalog, const std::string* schema,

cpp/src/arrow/flight/sql/odbc/tests/statement_test.cc

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ TYPED_TEST_SUITE(StatementTest, TestTypes);
3939

4040
TYPED_TEST(StatementTest, TestSQLNativeSqlReturnsInputString) {
4141
SQLWCHAR buf[1024];
42-
SQLINTEGER buf_char_len = sizeof(buf) / ODBC::GetSqlWCharSize();
42+
SQLINTEGER buf_char_len = sizeof(buf) / GetSqlWCharSize();
4343
SQLWCHAR input_str[] = L"SELECT * FROM mytable WHERE id == 1";
4444
SQLINTEGER input_char_len = static_cast<SQLINTEGER>(wcslen(input_str));
4545
SQLINTEGER output_char_len = 0;
@@ -58,7 +58,7 @@ TYPED_TEST(StatementTest, TestSQLNativeSqlReturnsInputString) {
5858

5959
TYPED_TEST(StatementTest, TestSQLNativeSqlReturnsNTSInputString) {
6060
SQLWCHAR buf[1024];
61-
SQLINTEGER buf_char_len = sizeof(buf) / ODBC::GetSqlWCharSize();
61+
SQLINTEGER buf_char_len = sizeof(buf) / GetSqlWCharSize();
6262
SQLWCHAR input_str[] = L"SELECT * FROM mytable WHERE id == 1";
6363
SQLINTEGER input_char_len = static_cast<SQLINTEGER>(wcslen(input_str));
6464
SQLINTEGER output_char_len = 0;
@@ -95,7 +95,7 @@ TYPED_TEST(StatementTest, TestSQLNativeSqlReturnsInputStringLength) {
9595
TYPED_TEST(StatementTest, TestSQLNativeSqlReturnsTruncatedString) {
9696
const SQLINTEGER small_buf_size_in_char = 11;
9797
SQLWCHAR small_buf[small_buf_size_in_char];
98-
SQLINTEGER small_buf_char_len = sizeof(small_buf) / ODBC::GetSqlWCharSize();
98+
SQLINTEGER small_buf_char_len = sizeof(small_buf) / GetSqlWCharSize();
9999
SQLWCHAR input_str[] = L"SELECT * FROM mytable WHERE id == 1";
100100
SQLINTEGER input_char_len = static_cast<SQLINTEGER>(wcslen(input_str));
101101
SQLINTEGER output_char_len = 0;
@@ -122,7 +122,7 @@ TYPED_TEST(StatementTest, TestSQLNativeSqlReturnsTruncatedString) {
122122

123123
TYPED_TEST(StatementTest, TestSQLNativeSqlReturnsErrorOnBadInputs) {
124124
SQLWCHAR buf[1024];
125-
SQLINTEGER buf_char_len = sizeof(buf) / ODBC::GetSqlWCharSize();
125+
SQLINTEGER buf_char_len = sizeof(buf) / GetSqlWCharSize();
126126
SQLWCHAR input_str[] = L"SELECT * FROM mytable WHERE id == 1";
127127
SQLINTEGER input_char_len = static_cast<SQLINTEGER>(wcslen(input_str));
128128
SQLINTEGER output_char_len = 0;
@@ -140,4 +140,27 @@ TYPED_TEST(StatementTest, TestSQLNativeSqlReturnsErrorOnBadInputs) {
140140
VerifyOdbcErrorState(SQL_HANDLE_DBC, this->conn, kErrorStateHY090);
141141
}
142142

143+
TYPED_TEST(StatementTest, TestSQLCloseCursor) {
144+
std::wstring wsql = L"SELECT 1;";
145+
std::vector<SQLWCHAR> sql0(wsql.begin(), wsql.end());
146+
147+
ASSERT_EQ(SQL_SUCCESS,
148+
SQLExecDirect(this->stmt, &sql0[0], static_cast<SQLINTEGER>(sql0.size())));
149+
150+
ASSERT_EQ(SQL_SUCCESS, SQLCloseCursor(this->stmt));
151+
}
152+
153+
TYPED_TEST(StatementTest, TestSQLFreeStmtSQLCloseWithoutCursor) {
154+
// Verify SQLFreeStmt(SQL_CLOSE) does not throw error with invalid cursor
155+
156+
ASSERT_EQ(SQL_SUCCESS, SQLFreeStmt(this->stmt, SQL_CLOSE));
157+
}
158+
159+
TYPED_TEST(StatementTest, TestSQLCloseCursorWithoutCursor) {
160+
ASSERT_EQ(SQL_ERROR, SQLCloseCursor(this->stmt));
161+
162+
// Verify invalid cursor error state is returned
163+
VerifyOdbcErrorState(SQL_HANDLE_STMT, this->stmt, kErrorState24000);
164+
}
165+
143166
} // namespace arrow::flight::sql::odbc

0 commit comments

Comments
 (0)