Skip to content
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
19 changes: 6 additions & 13 deletions cpp/src/arrow/flight/sql/odbc/entry_points.cc
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,12 @@ SQLRETURN SQL_API SQLGetData(SQLHSTMT stmt, SQLUSMALLINT recordNumber, SQLSMALLI
indicatorPtr);
}

SQLRETURN SQL_API SQLPrepare(SQLHSTMT stmt, SQLWCHAR* queryText, SQLINTEGER textLength) {
return arrow::SQLPrepare(stmt, queryText, textLength);
}

SQLRETURN SQL_API SQLExecute(SQLHSTMT stmt) { return arrow::SQLExecute(stmt); }

SQLRETURN SQL_API SQLBindCol(SQLHSTMT statementHandle, SQLUSMALLINT columnNumber,
SQLSMALLINT targetType, SQLPOINTER targetValuePtr,
SQLLEN bufferLength, SQLLEN* strLen_or_IndPtr) {
Expand Down Expand Up @@ -208,11 +214,6 @@ SQLRETURN SQL_API SQLError(SQLHENV handleType, SQLHDBC handle, SQLHSTMT hstmt,
return SQL_ERROR;
}

SQLRETURN SQL_API SQLExecute(SQLHSTMT statementHandle) {
LOG_DEBUG("SQLExecute called with statementHandle: {}", statementHandle);
return SQL_ERROR;
}

SQLRETURN SQL_API SQLForeignKeys(SQLHSTMT statementHandle, SQLWCHAR* pKCatalogName,
SQLSMALLINT pKCatalogNameLength, SQLWCHAR* pKSchemaName,
SQLSMALLINT pKSchemaNameLength, SQLWCHAR* pKTableName,
Expand Down Expand Up @@ -265,14 +266,6 @@ SQLRETURN SQL_API SQLRowCount(SQLHSTMT stmt, SQLLEN* rowCountPtr) {
return arrow::SQLRowCount(stmt, rowCountPtr);
}

SQLRETURN SQL_API SQLPrepare(SQLHSTMT statementHandle, SQLWCHAR* statementText,
SQLINTEGER textLength) {
LOG_DEBUG(
"SQLPrepareW called with statementHandle: {}, statementText: {}, textLength: {}",
statementHandle, fmt::ptr(statementText), textLength);
return SQL_ERROR;
}

SQLRETURN SQL_API SQLPrimaryKeys(SQLHSTMT statementHandle, SQLWCHAR* catalogName,
SQLSMALLINT catalogNameLength, SQLWCHAR* schemaName,
SQLSMALLINT schemaNameLength, SQLWCHAR* tableName,
Expand Down
33 changes: 30 additions & 3 deletions cpp/src/arrow/flight/sql/odbc/odbc_api.cc
Original file line number Diff line number Diff line change
Expand Up @@ -314,7 +314,7 @@ SQLRETURN SQLGetDiagField(SQLSMALLINT handleType, SQLHANDLE handle, SQLSMALLINT
case SQL_DIAG_CURSOR_ROW_COUNT: {
if (handleType == SQL_HANDLE_STMT) {
if (diagInfoPtr) {
// Will always be 0 if only select supported
// Will always be 0 if only SELECT supported
*static_cast<SQLLEN*>(diagInfoPtr) = 0;
}

Expand Down Expand Up @@ -894,7 +894,7 @@ SQLRETURN SQLExecDirect(SQLHSTMT stmt, SQLWCHAR* queryText, SQLINTEGER textLengt
LOG_DEBUG("SQLExecDirectW called with stmt: {}, queryText: {}, textLength: {}", stmt,
fmt::ptr(queryText), textLength);
using ODBC::ODBCStatement;
// The driver is built to handle select statements only.
// The driver is built to handle SELECT statements only.
return ODBCStatement::ExecuteWithDiagnostics(stmt, SQL_ERROR, [=]() {
ODBCStatement* statement = reinterpret_cast<ODBCStatement*>(stmt);
std::string query = ODBC::SqlWcharToString(queryText, textLength);
Expand All @@ -906,6 +906,34 @@ SQLRETURN SQLExecDirect(SQLHSTMT stmt, SQLWCHAR* queryText, SQLINTEGER textLengt
});
}

SQLRETURN SQLPrepare(SQLHSTMT stmt, SQLWCHAR* queryText, SQLINTEGER textLength) {
LOG_DEBUG("SQLPrepareW called with stmt: {}, queryText: {}, textLength: {}", stmt,
fmt::ptr(queryText), textLength);
using ODBC::ODBCStatement;
// The driver is built to handle SELECT statements only.
return ODBCStatement::ExecuteWithDiagnostics(stmt, SQL_ERROR, [=]() {
ODBCStatement* statement = reinterpret_cast<ODBCStatement*>(stmt);
std::string query = ODBC::SqlWcharToString(queryText, textLength);

statement->Prepare(query);

return SQL_SUCCESS;
});
}

SQLRETURN SQLExecute(SQLHSTMT stmt) {
LOG_DEBUG("SQLExecute called with stmt: {}", stmt);
using ODBC::ODBCStatement;
// The driver is built to handle SELECT statements only.
return ODBCStatement::ExecuteWithDiagnostics(stmt, SQL_ERROR, [=]() {
ODBCStatement* statement = reinterpret_cast<ODBCStatement*>(stmt);

statement->ExecutePrepared();

return SQL_SUCCESS;
});
}

SQLRETURN SQLFetch(SQLHSTMT stmt) {
LOG_DEBUG("SQLFetch called with stmt: {}", stmt);
using ODBC::ODBCDescriptor;
Expand Down Expand Up @@ -976,5 +1004,4 @@ SQLRETURN SQL_API SQLRowCount(SQLHSTMT stmt, SQLLEN* rowCountPtr) {
return SQL_SUCCESS;
});
}

} // namespace arrow
2 changes: 2 additions & 0 deletions cpp/src/arrow/flight/sql/odbc/odbc_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ SQLRETURN SQLGetInfo(SQLHDBC conn, SQLUSMALLINT infoType, SQLPOINTER infoValuePt
SQLRETURN SQLGetStmtAttr(SQLHSTMT stmt, SQLINTEGER attribute, SQLPOINTER valuePtr,
SQLINTEGER bufferLength, SQLINTEGER* stringLengthPtr);
SQLRETURN SQLExecDirect(SQLHSTMT stmt, SQLWCHAR* queryText, SQLINTEGER textLength);
SQLRETURN SQLPrepare(SQLHSTMT stmt, SQLWCHAR* queryText, SQLINTEGER textLength);
SQLRETURN SQLExecute(SQLHSTMT stmt);
SQLRETURN SQLFetch(SQLHSTMT stmt);
SQLRETURN SQLGetData(SQLHSTMT stmt, SQLUSMALLINT recordNumber, SQLSMALLINT cType,
SQLPOINTER dataPtr, SQLLEN bufferLength, SQLLEN* indicatorPtr);
Expand Down
1 change: 1 addition & 0 deletions cpp/src/arrow/flight/sql/odbc/tests/odbc_test_suite.h
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@ static constexpr std::string_view error_state_22002 = "22002";
static constexpr std::string_view error_state_24000 = "24000";
static constexpr std::string_view error_state_28000 = "28000";
static constexpr std::string_view error_state_HY000 = "HY000";
static constexpr std::string_view error_state_HY010 = "HY010";
static constexpr std::string_view error_state_HY024 = "HY024";
static constexpr std::string_view error_state_HY092 = "HY092";
static constexpr std::string_view error_state_HYC00 = "HYC00";
Expand Down
56 changes: 56 additions & 0 deletions cpp/src/arrow/flight/sql/odbc/tests/statement_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,62 @@ TYPED_TEST(FlightSQLODBCTestBase, TestSQLExecDirectInvalidQuery) {
this->disconnect();
}

TYPED_TEST(FlightSQLODBCTestBase, TestSQLExecuteSimpleQuery) {
this->connect();

std::wstring wsql = L"SELECT 1;";
std::vector<SQLWCHAR> sql0(wsql.begin(), wsql.end());

SQLRETURN ret = SQLPrepare(this->stmt, &sql0[0], static_cast<SQLINTEGER>(sql0.size()));
EXPECT_EQ(ret, SQL_SUCCESS);

ret = SQLExecute(this->stmt);
EXPECT_EQ(ret, SQL_SUCCESS);

// Fetch data
ret = SQLFetch(this->stmt);
EXPECT_EQ(ret, SQL_SUCCESS);

SQLINTEGER val;

ret = SQLGetData(this->stmt, 1, SQL_C_LONG, &val, 0, 0);

EXPECT_EQ(ret, SQL_SUCCESS);
// Verify 1 is returned
EXPECT_EQ(val, 1);

ret = SQLFetch(this->stmt);

EXPECT_EQ(ret, SQL_NO_DATA);

ret = SQLGetData(this->stmt, 1, SQL_C_LONG, &val, 0, 0);

EXPECT_EQ(ret, SQL_ERROR);
// Invalid cursor state
VerifyOdbcErrorState(SQL_HANDLE_STMT, this->stmt, error_state_24000);

this->disconnect();
}

TYPED_TEST(FlightSQLODBCTestBase, TestSQLPrepareInvalidQuery) {
this->connect();

std::wstring wsql = L"SELECT;";
std::vector<SQLWCHAR> sql0(wsql.begin(), wsql.end());

SQLRETURN ret = SQLPrepare(this->stmt, &sql0[0], static_cast<SQLINTEGER>(sql0.size()));

EXPECT_EQ(ret, SQL_ERROR);
// ODBC provides generic error code HY000 to all statement errors
VerifyOdbcErrorState(SQL_HANDLE_STMT, this->stmt, error_state_HY000);

ret = SQLExecute(this->stmt);
// Verify function sequence error state is returned
VerifyOdbcErrorState(SQL_HANDLE_STMT, this->stmt, error_state_HY010);

this->disconnect();
}

TYPED_TEST(FlightSQLODBCTestBase, TestSQLExecDirectDataQuery) {
this->connect();

Expand Down
Loading