Skip to content

Commit e7e471b

Browse files
alinaliBQrscales
andcommitted
Extract implementation of SQLDescribeCol
This PR depends on SQLColAttribute for descriptor fixes, SQLColumns, SQLTables, and SQLGetTypeInfo for tests Co-Authored-By: rscales <[email protected]>
1 parent cd848bc commit e7e471b

File tree

5 files changed

+2687
-2
lines changed

5 files changed

+2687
-2
lines changed

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

Lines changed: 104 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1295,8 +1295,110 @@ SQLRETURN SQLDescribeCol(SQLHSTMT stmt, SQLUSMALLINT column_number, SQLWCHAR* co
12951295
<< ", decimal_digits_ptr: "
12961296
<< static_cast<const void*>(decimal_digits_ptr)
12971297
<< ", nullable_ptr: " << static_cast<const void*>(nullable_ptr);
1298-
// GH-47724 TODO: Implement SQLDescribeCol
1299-
return SQL_INVALID_HANDLE;
1298+
1299+
using ODBC::ODBCDescriptor;
1300+
using ODBC::ODBCStatement;
1301+
1302+
return ODBCStatement::ExecuteWithDiagnostics(stmt, SQL_ERROR, [=]() {
1303+
ODBCStatement* statement = reinterpret_cast<ODBCStatement*>(stmt);
1304+
ODBCDescriptor* ird = statement->GetIRD();
1305+
SQLINTEGER output_length_int;
1306+
SQLSMALLINT sql_type;
1307+
1308+
// Column SQL Type
1309+
ird->GetField(column_number, SQL_DESC_CONCISE_TYPE, &sql_type, sizeof(SQLSMALLINT),
1310+
nullptr);
1311+
if (data_type_ptr) {
1312+
*data_type_ptr = sql_type;
1313+
}
1314+
1315+
// Column Name
1316+
if (column_name || name_length_ptr) {
1317+
ird->GetField(column_number, SQL_DESC_NAME, column_name, buffer_length,
1318+
&output_length_int);
1319+
if (name_length_ptr) {
1320+
// returned length should be in characters
1321+
*name_length_ptr =
1322+
static_cast<SQLSMALLINT>(output_length_int / GetSqlWCharSize());
1323+
}
1324+
}
1325+
1326+
// Column Size
1327+
if (column_size_ptr) {
1328+
switch (sql_type) {
1329+
// All numeric types
1330+
case SQL_DECIMAL:
1331+
case SQL_NUMERIC:
1332+
case SQL_TINYINT:
1333+
case SQL_SMALLINT:
1334+
case SQL_INTEGER:
1335+
case SQL_BIGINT:
1336+
case SQL_REAL:
1337+
case SQL_FLOAT:
1338+
case SQL_DOUBLE: {
1339+
ird->GetField(column_number, SQL_DESC_PRECISION, column_size_ptr,
1340+
sizeof(SQLULEN), nullptr);
1341+
break;
1342+
}
1343+
1344+
default: {
1345+
ird->GetField(column_number, SQL_DESC_LENGTH, column_size_ptr, sizeof(SQLULEN),
1346+
nullptr);
1347+
}
1348+
}
1349+
}
1350+
1351+
// Column Decimal Digits
1352+
if (decimal_digits_ptr) {
1353+
switch (sql_type) {
1354+
// All exact numeric types
1355+
case SQL_TINYINT:
1356+
case SQL_SMALLINT:
1357+
case SQL_INTEGER:
1358+
case SQL_BIGINT:
1359+
case SQL_DECIMAL:
1360+
case SQL_NUMERIC: {
1361+
ird->GetField(column_number, SQL_DESC_SCALE, decimal_digits_ptr,
1362+
sizeof(SQLULEN), nullptr);
1363+
break;
1364+
}
1365+
1366+
// All datetime types (ODBC 2)
1367+
case SQL_DATE:
1368+
case SQL_TIME:
1369+
case SQL_TIMESTAMP:
1370+
// All datetime types (ODBC 3)
1371+
case SQL_TYPE_DATE:
1372+
case SQL_TYPE_TIME:
1373+
case SQL_TYPE_TIMESTAMP:
1374+
// All interval types with a seconds component
1375+
case SQL_INTERVAL_SECOND:
1376+
case SQL_INTERVAL_MINUTE_TO_SECOND:
1377+
case SQL_INTERVAL_HOUR_TO_SECOND:
1378+
case SQL_INTERVAL_DAY_TO_SECOND: {
1379+
ird->GetField(column_number, SQL_DESC_PRECISION, decimal_digits_ptr,
1380+
sizeof(SQLULEN), nullptr);
1381+
break;
1382+
}
1383+
1384+
default: {
1385+
// All character and binary types
1386+
// SQL_BIT
1387+
// All approximate numeric types
1388+
// All interval types with no seconds component
1389+
*decimal_digits_ptr = static_cast<SQLSMALLINT>(0);
1390+
}
1391+
}
1392+
}
1393+
1394+
// Column Nullable
1395+
if (nullable_ptr) {
1396+
ird->GetField(column_number, SQL_DESC_NULLABLE, nullable_ptr, sizeof(SQLSMALLINT),
1397+
nullptr);
1398+
}
1399+
1400+
return SQL_SUCCESS;
1401+
});
13001402
}
13011403

13021404
} // namespace arrow::flight::sql::odbc

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,15 @@ add_arrow_test(flight_sql_odbc_test
3434
SOURCES
3535
odbc_test_suite.cc
3636
odbc_test_suite.h
37+
columns_test.cc
3738
connection_attr_test.cc
3839
connection_info_test.cc
3940
connection_test.cc
4041
errors_test.cc
4142
statement_attr_test.cc
4243
statement_test.cc
4344
tables_test.cc
45+
type_info_test.cc
4446
# Enable Protobuf cleanup after test execution
4547
# GH-46889: move protobuf_test_util to a more common location
4648
../../../../engine/substrait/protobuf_test_util.cc

0 commit comments

Comments
 (0)