Skip to content

Commit 1cf04e2

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 4fc9f9e commit 1cf04e2

File tree

5 files changed

+2641
-2
lines changed

5 files changed

+2641
-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
@@ -1330,8 +1330,110 @@ SQLRETURN SQLDescribeCol(SQLHSTMT stmt, SQLUSMALLINT column_number, SQLWCHAR* co
13301330
<< ", decimal_digits_ptr: "
13311331
<< static_cast<const void*>(decimal_digits_ptr)
13321332
<< ", nullable_ptr: " << static_cast<const void*>(nullable_ptr);
1333-
// GH-47724 TODO: Implement SQLDescribeCol
1334-
return SQL_INVALID_HANDLE;
1333+
1334+
using ODBC::ODBCDescriptor;
1335+
using ODBC::ODBCStatement;
1336+
1337+
return ODBCStatement::ExecuteWithDiagnostics(stmt, SQL_ERROR, [=]() {
1338+
ODBCStatement* statement = reinterpret_cast<ODBCStatement*>(stmt);
1339+
ODBCDescriptor* ird = statement->GetIRD();
1340+
SQLINTEGER output_length_int;
1341+
SQLSMALLINT sql_type;
1342+
1343+
// Column SQL Type
1344+
ird->GetField(column_number, SQL_DESC_CONCISE_TYPE, &sql_type, sizeof(SQLSMALLINT),
1345+
nullptr);
1346+
if (data_type_ptr) {
1347+
*data_type_ptr = sql_type;
1348+
}
1349+
1350+
// Column Name
1351+
if (column_name || name_length_ptr) {
1352+
ird->GetField(column_number, SQL_DESC_NAME, column_name, buffer_length,
1353+
&output_length_int);
1354+
if (name_length_ptr) {
1355+
// returned length should be in characters
1356+
*name_length_ptr =
1357+
static_cast<SQLSMALLINT>(output_length_int / GetSqlWCharSize());
1358+
}
1359+
}
1360+
1361+
// Column Size
1362+
if (column_size_ptr) {
1363+
switch (sql_type) {
1364+
// All numeric types
1365+
case SQL_DECIMAL:
1366+
case SQL_NUMERIC:
1367+
case SQL_TINYINT:
1368+
case SQL_SMALLINT:
1369+
case SQL_INTEGER:
1370+
case SQL_BIGINT:
1371+
case SQL_REAL:
1372+
case SQL_FLOAT:
1373+
case SQL_DOUBLE: {
1374+
ird->GetField(column_number, SQL_DESC_PRECISION, column_size_ptr,
1375+
sizeof(SQLULEN), nullptr);
1376+
break;
1377+
}
1378+
1379+
default: {
1380+
ird->GetField(column_number, SQL_DESC_LENGTH, column_size_ptr, sizeof(SQLULEN),
1381+
nullptr);
1382+
}
1383+
}
1384+
}
1385+
1386+
// Column Decimal Digits
1387+
if (decimal_digits_ptr) {
1388+
switch (sql_type) {
1389+
// All exact numeric types
1390+
case SQL_TINYINT:
1391+
case SQL_SMALLINT:
1392+
case SQL_INTEGER:
1393+
case SQL_BIGINT:
1394+
case SQL_DECIMAL:
1395+
case SQL_NUMERIC: {
1396+
ird->GetField(column_number, SQL_DESC_SCALE, decimal_digits_ptr,
1397+
sizeof(SQLULEN), nullptr);
1398+
break;
1399+
}
1400+
1401+
// All datetime types (ODBC 2)
1402+
case SQL_DATE:
1403+
case SQL_TIME:
1404+
case SQL_TIMESTAMP:
1405+
// All datetime types (ODBC 3)
1406+
case SQL_TYPE_DATE:
1407+
case SQL_TYPE_TIME:
1408+
case SQL_TYPE_TIMESTAMP:
1409+
// All interval types with a seconds component
1410+
case SQL_INTERVAL_SECOND:
1411+
case SQL_INTERVAL_MINUTE_TO_SECOND:
1412+
case SQL_INTERVAL_HOUR_TO_SECOND:
1413+
case SQL_INTERVAL_DAY_TO_SECOND: {
1414+
ird->GetField(column_number, SQL_DESC_PRECISION, decimal_digits_ptr,
1415+
sizeof(SQLULEN), nullptr);
1416+
break;
1417+
}
1418+
1419+
default: {
1420+
// All character and binary types
1421+
// SQL_BIT
1422+
// All approximate numeric types
1423+
// All interval types with no seconds component
1424+
*decimal_digits_ptr = static_cast<SQLSMALLINT>(0);
1425+
}
1426+
}
1427+
}
1428+
1429+
// Column Nullable
1430+
if (nullable_ptr) {
1431+
ird->GetField(column_number, SQL_DESC_NULLABLE, nullable_ptr, sizeof(SQLSMALLINT),
1432+
nullptr);
1433+
}
1434+
1435+
return SQL_SUCCESS;
1436+
});
13351437
}
13361438

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

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ add_arrow_test(flight_sql_odbc_test
4242
statement_attr_test.cc
4343
statement_test.cc
4444
tables_test.cc
45+
type_info_test.cc
4546
# Enable Protobuf cleanup after test execution
4647
# GH-46889: move protobuf_test_util to a more common location
4748
../../../../engine/substrait/protobuf_test_util.cc

0 commit comments

Comments
 (0)