Skip to content

Commit c701849

Browse files
committed
Extract SQLGetInfo implementation
Co-Authored-By: rscales <[email protected]> Create connection_info_test.cc Add SQLGetInfo tests Co-authored-by: justing-bq <[email protected]> Co-Authored-By: rscales <[email protected]> Address code review comments Co-authored-by: justing-bq <[email protected]> Work on code review comments Fix build issues with tests Use Utility getters for SQLGetInfo Remove `using List` * fix build issues Add truncation test
1 parent 5aa7dd1 commit c701849

File tree

6 files changed

+1322
-78
lines changed

6 files changed

+1322
-78
lines changed

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

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -898,7 +898,6 @@ SQLRETURN SQLGetInfo(SQLHDBC conn, SQLUSMALLINT info_type, SQLPOINTER info_value
898898
<< ", string_length_ptr: "
899899
<< static_cast<const void*>(string_length_ptr);
900900

901-
// GH-47709 TODO: Update SQLGetInfo implementation and add tests for SQLGetInfo
902901
using ODBC::ODBCConnection;
903902

904903
return ODBCConnection::ExecuteWithDiagnostics(conn, SQL_ERROR, [=]() {
@@ -911,9 +910,8 @@ SQLRETURN SQLGetInfo(SQLHDBC conn, SQLUSMALLINT info_type, SQLPOINTER info_value
911910
return static_cast<SQLRETURN>(SQL_ERROR);
912911
}
913912

914-
connection->GetInfo(info_type, info_value_ptr, buf_len, string_length_ptr,
915-
is_unicode);
916-
return static_cast<SQLRETURN>(SQL_SUCCESS);
913+
return connection->GetInfo(info_type, info_value_ptr, buf_len, string_length_ptr,
914+
is_unicode);
917915
});
918916
}
919917

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

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -913,21 +913,21 @@ bool GetInfoCache::LoadInfoFromServer() {
913913
break;
914914
}
915915
case SqlInfoOptions::SQL_SUPPORTED_RESULT_SET_TYPES:
916-
// Ignored. Warpdrive supports forward-only only.
916+
// Ignored. Arrow ODBC supports forward-only only.
917917
break;
918918
case SqlInfoOptions::SQL_SUPPORTED_CONCURRENCIES_FOR_RESULT_SET_UNSPECIFIED:
919-
// Ignored. Warpdrive supports forward-only only.
919+
// Ignored. Arrow ODBC supports forward-only only.
920920
break;
921921
case SqlInfoOptions::SQL_SUPPORTED_CONCURRENCIES_FOR_RESULT_SET_FORWARD_ONLY:
922-
// Ignored. Warpdrive supports forward-only only.
922+
// Ignored. Arrow ODBC supports forward-only only.
923923
break;
924924
case SqlInfoOptions::
925925
SQL_SUPPORTED_CONCURRENCIES_FOR_RESULT_SET_SCROLL_SENSITIVE:
926-
// Ignored. Warpdrive supports forward-only only.
926+
// Ignored. Arrow ODBC supports forward-only only.
927927
break;
928928
case SqlInfoOptions::
929929
SQL_SUPPORTED_CONCURRENCIES_FOR_RESULT_SET_SCROLL_INSENSITIVE:
930-
// Ignored. Warpdrive supports forward-only only.
930+
// Ignored. Arrow ODBC supports forward-only only.
931931
break;
932932

933933
// List<string> properties
@@ -1127,6 +1127,7 @@ void GetInfoCache::LoadDefaultsForMissingEntries() {
11271127
SetDefaultIfMissing(info_, SQL_CONVERT_DECIMAL, static_cast<uint32_t>(0));
11281128
SetDefaultIfMissing(info_, SQL_CONVERT_DOUBLE, static_cast<uint32_t>(0));
11291129
SetDefaultIfMissing(info_, SQL_CONVERT_FLOAT, static_cast<uint32_t>(0));
1130+
SetDefaultIfMissing(info_, SQL_CONVERT_FUNCTIONS, static_cast<uint32_t>(0));
11301131
SetDefaultIfMissing(info_, SQL_CONVERT_GUID, static_cast<uint32_t>(0));
11311132
SetDefaultIfMissing(info_, SQL_CONVERT_INTEGER, static_cast<uint32_t>(0));
11321133
SetDefaultIfMissing(info_, SQL_CONVERT_INTERVAL_YEAR_MONTH, static_cast<uint32_t>(0));
@@ -1205,6 +1206,7 @@ void GetInfoCache::LoadDefaultsForMissingEntries() {
12051206
SetDefaultIfMissing(info_, SQL_MAX_COLUMNS_IN_ORDER_BY, static_cast<uint16_t>(0));
12061207
SetDefaultIfMissing(info_, SQL_MAX_COLUMNS_IN_SELECT, static_cast<uint16_t>(0));
12071208
SetDefaultIfMissing(info_, SQL_MAX_COLUMNS_IN_TABLE, static_cast<uint16_t>(0));
1209+
SetDefaultIfMissing(info_, SQL_MAX_CONCURRENT_ACTIVITIES, static_cast<uint16_t>(0));
12081210
SetDefaultIfMissing(info_, SQL_MAX_CURSOR_NAME_LEN, static_cast<uint16_t>(0));
12091211
SetDefaultIfMissing(info_, SQL_MAX_DRIVER_CONNECTIONS, static_cast<uint16_t>(0));
12101212
SetDefaultIfMissing(info_, SQL_MAX_IDENTIFIER_LEN, static_cast<uint16_t>(65535));
@@ -1224,6 +1226,7 @@ void GetInfoCache::LoadDefaultsForMissingEntries() {
12241226
SetDefaultIfMissing(info_, SQL_OJ_CAPABILITIES,
12251227
static_cast<uint32_t>(SQL_OJ_LEFT | SQL_OJ_RIGHT | SQL_OJ_FULL));
12261228
SetDefaultIfMissing(info_, SQL_ORDER_BY_COLUMNS_IN_SELECT, "Y");
1229+
SetDefaultIfMissing(info_, SQL_OUTER_JOINS, "N");
12271230
SetDefaultIfMissing(info_, SQL_PROCEDURE_TERM, "");
12281231
SetDefaultIfMissing(info_, SQL_PROCEDURES, "N");
12291232
SetDefaultIfMissing(info_, SQL_QUOTED_IDENTIFIER_CASE,
@@ -1232,6 +1235,7 @@ void GetInfoCache::LoadDefaultsForMissingEntries() {
12321235
SetDefaultIfMissing(info_, SQL_SCHEMA_USAGE,
12331236
static_cast<uint32_t>(SQL_SU_DML_STATEMENTS));
12341237
SetDefaultIfMissing(info_, SQL_SEARCH_PATTERN_ESCAPE, "\\");
1238+
SetDefaultIfMissing(info_, SQL_SPECIAL_CHARACTERS, "");
12351239
SetDefaultIfMissing(
12361240
info_, SQL_SERVER_NAME,
12371241
"Arrow Flight SQL Server"); // This might actually need to be the hostname.
@@ -1286,6 +1290,16 @@ void GetInfoCache::LoadDefaultsForMissingEntries() {
12861290
SQL_FN_TSI_FRAC_SECOND | SQL_FN_TSI_SECOND | SQL_FN_TSI_MINUTE |
12871291
SQL_FN_TSI_HOUR | SQL_FN_TSI_DAY | SQL_FN_TSI_WEEK |
12881292
SQL_FN_TSI_MONTH | SQL_FN_TSI_QUARTER | SQL_FN_TSI_YEAR));
1293+
SetDefaultIfMissing(
1294+
info_, SQL_TIMEDATE_FUNCTIONS,
1295+
static_cast<uint32_t>(
1296+
SQL_FN_TD_CURRENT_DATE | SQL_FN_TD_CURRENT_TIME | SQL_FN_TD_CURRENT_TIMESTAMP |
1297+
SQL_FN_TD_CURDATE | SQL_FN_TD_CURTIME | SQL_FN_TD_DAYNAME |
1298+
SQL_FN_TD_DAYOFMONTH | SQL_FN_TD_DAYOFWEEK | SQL_FN_TD_DAYOFYEAR |
1299+
SQL_FN_TD_EXTRACT | SQL_FN_TD_HOUR | SQL_FN_TD_MINUTE | SQL_FN_TD_MONTH |
1300+
SQL_FN_TD_MONTHNAME | SQL_FN_TD_NOW | SQL_FN_TD_QUARTER | SQL_FN_TD_SECOND |
1301+
SQL_FN_TD_TIMESTAMPADD | SQL_FN_TD_TIMESTAMPDIFF | SQL_FN_TD_WEEK |
1302+
SQL_FN_TD_YEAR));
12891303
SetDefaultIfMissing(info_, SQL_UNION,
12901304
static_cast<uint32_t>(SQL_U_UNION | SQL_U_UNION_ALL));
12911305
SetDefaultIfMissing(info_, SQL_XOPEN_CLI_YEAR, "1995");

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

Lines changed: 59 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -87,152 +87,144 @@ void ODBCConnection::Connect(std::string dsn,
8787
attribute_tracking_statement_ = std::make_shared<ODBCStatement>(*this, spi_statement);
8888
}
8989

90-
void ODBCConnection::GetInfo(SQLUSMALLINT info_type, SQLPOINTER value,
91-
SQLSMALLINT buffer_length, SQLSMALLINT* output_length,
92-
bool is_unicode) {
90+
SQLRETURN ODBCConnection::GetInfo(SQLUSMALLINT info_type, SQLPOINTER value,
91+
SQLSMALLINT buffer_length, SQLSMALLINT* output_length,
92+
bool is_unicode) {
9393
switch (info_type) {
9494
case SQL_ACTIVE_ENVIRONMENTS:
9595
GetAttribute(static_cast<SQLUSMALLINT>(0), value, buffer_length, output_length);
96-
break;
96+
return SQL_SUCCESS;
9797
#ifdef SQL_ASYNC_DBC_FUNCTIONS
9898
case SQL_ASYNC_DBC_FUNCTIONS:
9999
GetAttribute(static_cast<SQLUINTEGER>(SQL_ASYNC_DBC_NOT_CAPABLE), value,
100100
buffer_length, output_length);
101-
break;
101+
return SQL_SUCCESS;
102102
#endif
103103
case SQL_ASYNC_MODE:
104104
GetAttribute(static_cast<SQLUINTEGER>(SQL_AM_NONE), value, buffer_length,
105105
output_length);
106-
break;
106+
return SQL_SUCCESS;
107107
#ifdef SQL_ASYNC_NOTIFICATION
108108
case SQL_ASYNC_NOTIFICATION:
109109
GetAttribute(static_cast<SQLUINTEGER>(SQL_ASYNC_NOTIFICATION_NOT_CAPABLE), value,
110110
buffer_length, output_length);
111-
break;
111+
return SQL_SUCCESS;
112112
#endif
113113
case SQL_BATCH_ROW_COUNT:
114114
GetAttribute(static_cast<SQLUINTEGER>(0), value, buffer_length, output_length);
115-
break;
115+
return SQL_SUCCESS;
116116
case SQL_BATCH_SUPPORT:
117117
GetAttribute(static_cast<SQLUINTEGER>(0), value, buffer_length, output_length);
118-
break;
118+
return SQL_SUCCESS;
119119
case SQL_DATA_SOURCE_NAME:
120-
GetStringAttribute(is_unicode, dsn_, true, value, buffer_length, output_length,
121-
GetDiagnostics());
122-
break;
120+
return GetStringAttribute(is_unicode, dsn_, true, value, buffer_length,
121+
output_length, GetDiagnostics());
123122
case SQL_DRIVER_ODBC_VER:
124-
GetStringAttribute(is_unicode, "03.80", true, value, buffer_length, output_length,
125-
GetDiagnostics());
126-
break;
123+
return GetStringAttribute(is_unicode, "03.80", true, value, buffer_length,
124+
output_length, GetDiagnostics());
127125
case SQL_DYNAMIC_CURSOR_ATTRIBUTES1:
128126
GetAttribute(static_cast<SQLUINTEGER>(0), value, buffer_length, output_length);
129-
break;
127+
return SQL_SUCCESS;
130128
case SQL_DYNAMIC_CURSOR_ATTRIBUTES2:
131129
GetAttribute(static_cast<SQLUINTEGER>(0), value, buffer_length, output_length);
132-
break;
130+
return SQL_SUCCESS;
133131
case SQL_FORWARD_ONLY_CURSOR_ATTRIBUTES1:
134132
GetAttribute(static_cast<SQLUINTEGER>(SQL_CA1_NEXT), value, buffer_length,
135133
output_length);
136-
break;
134+
return SQL_SUCCESS;
137135
case SQL_FORWARD_ONLY_CURSOR_ATTRIBUTES2:
138136
GetAttribute(static_cast<SQLUINTEGER>(SQL_CA2_READ_ONLY_CONCURRENCY), value,
139137
buffer_length, output_length);
140-
break;
138+
return SQL_SUCCESS;
141139
case SQL_FILE_USAGE:
142140
GetAttribute(static_cast<SQLUSMALLINT>(SQL_FILE_NOT_SUPPORTED), value,
143141
buffer_length, output_length);
144-
break;
142+
return SQL_SUCCESS;
145143
case SQL_KEYSET_CURSOR_ATTRIBUTES1:
146144
GetAttribute(static_cast<SQLUINTEGER>(0), value, buffer_length, output_length);
147-
break;
145+
return SQL_SUCCESS;
148146
case SQL_KEYSET_CURSOR_ATTRIBUTES2:
149147
GetAttribute(static_cast<SQLUINTEGER>(0), value, buffer_length, output_length);
150-
break;
148+
return SQL_SUCCESS;
151149
case SQL_MAX_ASYNC_CONCURRENT_STATEMENTS:
152150
GetAttribute(static_cast<SQLUINTEGER>(0), value, buffer_length, output_length);
153-
break;
151+
return SQL_SUCCESS;
154152
case SQL_ODBC_INTERFACE_CONFORMANCE:
155153
GetAttribute(static_cast<SQLUINTEGER>(SQL_OIC_CORE), value, buffer_length,
156154
output_length);
157-
break;
155+
return SQL_SUCCESS;
158156
// case SQL_ODBC_STANDARD_CLI_CONFORMANCE: - mentioned in SQLGetInfo spec with no
159157
// description and there is no constant for this.
160158
case SQL_PARAM_ARRAY_ROW_COUNTS:
161159
GetAttribute(static_cast<SQLUINTEGER>(SQL_PARC_NO_BATCH), value, buffer_length,
162160
output_length);
163-
break;
161+
return SQL_SUCCESS;
164162
case SQL_PARAM_ARRAY_SELECTS:
165163
GetAttribute(static_cast<SQLUINTEGER>(SQL_PAS_NO_SELECT), value, buffer_length,
166164
output_length);
167-
break;
165+
return SQL_SUCCESS;
168166
case SQL_ROW_UPDATES:
169-
GetStringAttribute(is_unicode, "N", true, value, buffer_length, output_length,
170-
GetDiagnostics());
171-
break;
167+
return GetStringAttribute(is_unicode, "N", true, value, buffer_length,
168+
output_length, GetDiagnostics());
172169
case SQL_SCROLL_OPTIONS:
173170
GetAttribute(static_cast<SQLUINTEGER>(SQL_SO_FORWARD_ONLY), value, buffer_length,
174171
output_length);
175-
break;
172+
return SQL_SUCCESS;
176173
case SQL_STATIC_CURSOR_ATTRIBUTES1:
177174
GetAttribute(static_cast<SQLUINTEGER>(0), value, buffer_length, output_length);
178-
break;
175+
return SQL_SUCCESS;
179176
case SQL_STATIC_CURSOR_ATTRIBUTES2:
180177
GetAttribute(static_cast<SQLUINTEGER>(0), value, buffer_length, output_length);
181-
break;
178+
return SQL_SUCCESS;
182179
case SQL_BOOKMARK_PERSISTENCE:
183180
GetAttribute(static_cast<SQLUINTEGER>(0), value, buffer_length, output_length);
184-
break;
181+
return SQL_SUCCESS;
185182
case SQL_DESCRIBE_PARAMETER:
186-
GetStringAttribute(is_unicode, "N", true, value, buffer_length, output_length,
187-
GetDiagnostics());
188-
break;
183+
return GetStringAttribute(is_unicode, "N", true, value, buffer_length,
184+
output_length, GetDiagnostics());
189185
case SQL_MULT_RESULT_SETS:
190-
GetStringAttribute(is_unicode, "N", true, value, buffer_length, output_length,
191-
GetDiagnostics());
192-
break;
186+
return GetStringAttribute(is_unicode, "N", true, value, buffer_length,
187+
output_length, GetDiagnostics());
193188
case SQL_MULTIPLE_ACTIVE_TXN:
194-
GetStringAttribute(is_unicode, "N", true, value, buffer_length, output_length,
195-
GetDiagnostics());
196-
break;
189+
return GetStringAttribute(is_unicode, "N", true, value, buffer_length,
190+
output_length, GetDiagnostics());
197191
case SQL_NEED_LONG_DATA_LEN:
198-
GetStringAttribute(is_unicode, "N", true, value, buffer_length, output_length,
199-
GetDiagnostics());
200-
break;
192+
return GetStringAttribute(is_unicode, "N", true, value, buffer_length,
193+
output_length, GetDiagnostics());
201194
case SQL_TXN_CAPABLE:
202195
GetAttribute(static_cast<SQLUSMALLINT>(SQL_TC_NONE), value, buffer_length,
203196
output_length);
204-
break;
197+
return SQL_SUCCESS;
205198
case SQL_TXN_ISOLATION_OPTION:
206199
GetAttribute(static_cast<SQLUINTEGER>(0), value, buffer_length, output_length);
207-
break;
200+
return SQL_SUCCESS;
208201
case SQL_TABLE_TERM:
209-
GetStringAttribute(is_unicode, "table", true, value, buffer_length, output_length,
210-
GetDiagnostics());
211-
break;
202+
return GetStringAttribute(is_unicode, "table", true, value, buffer_length,
203+
output_length, GetDiagnostics());
212204
// Deprecated ODBC 2.x fields required for backwards compatibility.
213205
case SQL_ODBC_API_CONFORMANCE:
214206
GetAttribute(static_cast<SQLUSMALLINT>(SQL_OAC_LEVEL1), value, buffer_length,
215207
output_length);
216-
break;
208+
return SQL_SUCCESS;
217209
case SQL_FETCH_DIRECTION:
218210
GetAttribute(static_cast<SQLINTEGER>(SQL_FETCH_NEXT), value, buffer_length,
219211
output_length);
220-
break;
212+
return SQL_SUCCESS;
221213
case SQL_LOCK_TYPES:
222214
GetAttribute(static_cast<SQLINTEGER>(0), value, buffer_length, output_length);
223-
break;
215+
return SQL_SUCCESS;
224216
case SQL_POS_OPERATIONS:
225217
GetAttribute(static_cast<SQLINTEGER>(0), value, buffer_length, output_length);
226-
break;
218+
return SQL_SUCCESS;
227219
case SQL_POSITIONED_STATEMENTS:
228220
GetAttribute(static_cast<SQLINTEGER>(0), value, buffer_length, output_length);
229-
break;
221+
return SQL_SUCCESS;
230222
case SQL_SCROLL_CONCURRENCY:
231223
GetAttribute(static_cast<SQLINTEGER>(0), value, buffer_length, output_length);
232-
break;
224+
return SQL_SUCCESS;
233225
case SQL_STATIC_SENSITIVITY:
234226
GetAttribute(static_cast<SQLINTEGER>(0), value, buffer_length, output_length);
235-
break;
227+
return SQL_SUCCESS;
236228

237229
// Driver-level string properties.
238230
case SQL_USER_NAME:
@@ -267,9 +259,8 @@ void ODBCConnection::GetInfo(SQLUSMALLINT info_type, SQLPOINTER value,
267259
case SQL_XOPEN_CLI_YEAR: {
268260
const auto& info = spi_connection_->GetInfo(info_type);
269261
const std::string& info_value = boost::get<std::string>(info);
270-
GetStringAttribute(is_unicode, info_value, true, value, buffer_length,
271-
output_length, GetDiagnostics());
272-
break;
262+
return GetStringAttribute(is_unicode, info_value, true, value, buffer_length,
263+
output_length, GetDiagnostics());
273264
}
274265

275266
// Driver-level 32-bit integer properties.
@@ -359,7 +350,7 @@ void ODBCConnection::GetInfo(SQLUSMALLINT info_type, SQLPOINTER value,
359350
const auto& info = spi_connection_->GetInfo(info_type);
360351
uint32_t info_value = boost::get<uint32_t>(info);
361352
GetAttribute(info_value, value, buffer_length, output_length);
362-
break;
353+
return SQL_SUCCESS;
363354
}
364355

365356
// Driver-level 16-bit integer properties.
@@ -394,7 +385,7 @@ void ODBCConnection::GetInfo(SQLUSMALLINT info_type, SQLPOINTER value,
394385
const auto& info = spi_connection_->GetInfo(info_type);
395386
uint16_t info_value = boost::get<uint16_t>(info);
396387
GetAttribute(info_value, value, buffer_length, output_length);
397-
break;
388+
return SQL_SUCCESS;
398389
}
399390

400391
// Special case - SQL_DATABASE_NAME is an alias for SQL_ATTR_CURRENT_CATALOG.
@@ -404,13 +395,15 @@ void ODBCConnection::GetInfo(SQLUSMALLINT info_type, SQLPOINTER value,
404395
throw DriverException("Optional feature not supported.", "HYC00");
405396
}
406397
const std::string& info_value = boost::get<std::string>(*attr);
407-
GetStringAttribute(is_unicode, info_value, true, value, buffer_length,
408-
output_length, GetDiagnostics());
409-
break;
398+
return GetStringAttribute(is_unicode, info_value, true, value, buffer_length,
399+
output_length, GetDiagnostics());
410400
}
411401
default:
412-
throw DriverException("Unknown SQLGetInfo type: " + std::to_string(info_type));
402+
throw DriverException("Unknown SQLGetInfo type: " + std::to_string(info_type),
403+
"HY096");
413404
}
405+
406+
return SQL_ERROR;
414407
}
415408

416409
void ODBCConnection::SetConnectAttr(SQLINTEGER attribute, SQLPOINTER value,

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,8 @@ class ODBCConnection : public ODBCHandle<ODBCConnection> {
5353
const arrow::flight::sql::odbc::Connection::ConnPropertyMap& properties,
5454
std::vector<std::string_view>& missing_properties);
5555

56-
void GetInfo(SQLUSMALLINT info_type, SQLPOINTER value, SQLSMALLINT buffer_length,
57-
SQLSMALLINT* output_length, bool is_unicode);
56+
SQLRETURN GetInfo(SQLUSMALLINT info_type, SQLPOINTER value, SQLSMALLINT buffer_length,
57+
SQLSMALLINT* output_length, bool is_unicode);
5858
void SetConnectAttr(SQLINTEGER attribute, SQLPOINTER value, SQLINTEGER string_length,
5959
bool isUnicode);
6060
void GetConnectAttr(SQLINTEGER attribute, SQLPOINTER value, SQLINTEGER buffer_length,

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,9 @@ add_arrow_test(flight_sql_odbc_test
3434
SOURCES
3535
odbc_test_suite.cc
3636
odbc_test_suite.h
37-
statement_attr_test.cc
37+
connection_info_test.cc
3838
connection_test.cc
39+
statement_attr_test.cc
3940
# Enable Protobuf cleanup after test execution
4041
# GH-46889: move protobuf_test_util to a more common location
4142
../../../../engine/substrait/protobuf_test_util.cc

0 commit comments

Comments
 (0)