Skip to content

Commit 19caeb8

Browse files
committed
Extract SQLCloseCursor implementation
Co-Authored-By: alinalibq <[email protected]>
1 parent 42f27ab commit 19caeb8

File tree

4 files changed

+75
-3
lines changed

4 files changed

+75
-3
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
@@ -863,8 +863,16 @@ SQLRETURN SQLBindCol(SQLHSTMT stmt, SQLUSMALLINT record_number, SQLSMALLINT c_ty
863863

864864
SQLRETURN SQLCloseCursor(SQLHSTMT stmt) {
865865
ARROW_LOG(DEBUG) << "SQLCloseCursor called with stmt: " << stmt;
866-
// GH-47717 TODO: Implement SQLCloseCursor
867-
return SQL_INVALID_HANDLE;
866+
867+
using ODBC::ODBCStatement;
868+
return ODBCStatement::ExecuteWithDiagnostics(stmt, SQL_ERROR, [=]() {
869+
ODBCStatement* statement = reinterpret_cast<ODBCStatement*>(stmt);
870+
871+
// Close cursor with suppressErrors set to false
872+
statement->CloseCursor(false);
873+
874+
return SQL_SUCCESS;
875+
});
868876
}
869877

870878
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
@@ -677,7 +677,7 @@ void ODBCStatement::RevertAppDescriptor(bool isApd) {
677677

678678
void ODBCStatement::CloseCursor(bool suppress_errors) {
679679
if (!suppress_errors && !current_result_) {
680-
throw DriverException("Invalid cursor state", "28000");
680+
throw DriverException("Invalid cursor state", "24000");
681681
}
682682

683683
if (current_result_) {

cpp/src/arrow/flight/sql/odbc/tests/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ add_arrow_test(flight_sql_odbc_test
3535
odbc_test_suite.cc
3636
odbc_test_suite.h
3737
connection_test.cc
38+
statement_test.cc
3839
# Enable Protobuf cleanup after test execution
3940
# GH-46889: move protobuf_test_util to a more common location
4041
../../../../engine/substrait/protobuf_test_util.cc
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
// Licensed to the Apache Software Foundation (ASF) under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. The ASF licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// "License"); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
#include "arrow/flight/sql/odbc/tests/odbc_test_suite.h"
18+
19+
#include "arrow/flight/sql/odbc/odbc_impl/platform.h"
20+
21+
#include <sql.h>
22+
#include <sqltypes.h>
23+
#include <sqlucode.h>
24+
25+
#include <limits>
26+
27+
#include <gmock/gmock.h>
28+
#include <gtest/gtest.h>
29+
30+
namespace arrow::flight::sql::odbc {
31+
32+
template <typename T>
33+
class StatementTest : public T {};
34+
35+
class StatementMockTest : public FlightSQLODBCMockTestBase {};
36+
class StatementRemoteTest : public FlightSQLODBCRemoteTestBase {};
37+
using TestTypes = ::testing::Types<StatementMockTest, StatementRemoteTest>;
38+
TYPED_TEST_SUITE(StatementTest, TestTypes);
39+
40+
TYPED_TEST(StatementTest, TestSQLCloseCursor) {
41+
std::wstring wsql = L"SELECT 1;";
42+
std::vector<SQLWCHAR> sql0(wsql.begin(), wsql.end());
43+
44+
ASSERT_EQ(SQL_SUCCESS,
45+
SQLExecDirect(this->stmt, &sql0[0], static_cast<SQLINTEGER>(sql0.size())));
46+
47+
ASSERT_EQ(SQL_SUCCESS, SQLCloseCursor(this->stmt));
48+
}
49+
50+
TYPED_TEST(StatementTest, TestSQLFreeStmtSQLCloseWithoutCursor) {
51+
// SQLFreeStmt(SQL_CLOSE) does not throw error with invalid cursor
52+
53+
ASSERT_EQ(SQL_SUCCESS, SQLFreeStmt(this->stmt, SQL_CLOSE));
54+
}
55+
56+
TYPED_TEST(StatementTest, TestSQLCloseCursorWithoutCursor) {
57+
ASSERT_EQ(SQL_ERROR, SQLCloseCursor(this->stmt));
58+
59+
// Verify invalid cursor error state is returned
60+
VerifyOdbcErrorState(SQL_HANDLE_STMT, this->stmt, kErrorState24000);
61+
}
62+
63+
} // namespace arrow::flight::sql::odbc

0 commit comments

Comments
 (0)