This is an automated email from the ASF dual-hosted git repository.
lidavidm pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow.git
The following commit(s) were added to refs/heads/main by this push:
new 0c694e7833 GH-47722: [C++][FlightRPC] ODBC Data Type Information
(#48051)
0c694e7833 is described below
commit 0c694e78331687e838c74d0d0aa73af350bdb66a
Author: Alina (Xi) Li <[email protected]>
AuthorDate: Mon Dec 29 17:19:57 2025 -0800
GH-47722: [C++][FlightRPC] ODBC Data Type Information (#48051)
### Rationale for this change
Implement ODBC to return information about data types supported by the data
source
### What changes are included in this PR?
- SQLGetTypeInfo & Tests
### Are these changes tested?
Tested locally on MSVC
### Are there any user-facing changes?
N/A
* GitHub Issue: #47722
Authored-by: Alina (Xi) Li <[email protected]>
Signed-off-by: David Li <[email protected]>
---
cpp/src/arrow/flight/sql/odbc/odbc_api.cc | 56 +-
.../flight_sql_statement_get_type_info.cc | 9 +-
cpp/src/arrow/flight/sql/odbc/odbc_impl/util.cc | 8 +
cpp/src/arrow/flight/sql/odbc/tests/CMakeLists.txt | 1 +
.../arrow/flight/sql/odbc/tests/type_info_test.cc | 1672 ++++++++++++++++++++
5 files changed, 1741 insertions(+), 5 deletions(-)
diff --git a/cpp/src/arrow/flight/sql/odbc/odbc_api.cc
b/cpp/src/arrow/flight/sql/odbc/odbc_api.cc
index 6ce248a4fa..4eec8dcbf2 100644
--- a/cpp/src/arrow/flight/sql/odbc/odbc_api.cc
+++ b/cpp/src/arrow/flight/sql/odbc/odbc_api.cc
@@ -1388,8 +1388,60 @@ SQLRETURN SQLGetTypeInfo(SQLHSTMT stmt, SQLSMALLINT
data_type) {
// appropriate data types in `SEARCHABLE` field
ARROW_LOG(DEBUG) << "SQLGetTypeInfoW called with stmt: " << stmt
<< " data_type: " << data_type;
- // GH-47722 TODO: Implement SQLGetTypeInfo
- return SQL_INVALID_HANDLE;
+
+ using ODBC::ODBCStatement;
+ return ODBC::ODBCStatement::ExecuteWithDiagnostics(stmt, SQL_ERROR, [=]() {
+ ODBCStatement* statement = reinterpret_cast<ODBCStatement*>(stmt);
+
+ switch (data_type) {
+ case SQL_ALL_TYPES:
+ case SQL_CHAR:
+ case SQL_VARCHAR:
+ case SQL_LONGVARCHAR:
+ case SQL_WCHAR:
+ case SQL_WVARCHAR:
+ case SQL_WLONGVARCHAR:
+ case SQL_BIT:
+ case SQL_BINARY:
+ case SQL_VARBINARY:
+ case SQL_LONGVARBINARY:
+ case SQL_TINYINT:
+ case SQL_SMALLINT:
+ case SQL_INTEGER:
+ case SQL_BIGINT:
+ case SQL_NUMERIC:
+ case SQL_DECIMAL:
+ case SQL_FLOAT:
+ case SQL_REAL:
+ case SQL_DOUBLE:
+ case SQL_GUID:
+ case SQL_DATE:
+ case SQL_TYPE_DATE:
+ case SQL_TIME:
+ case SQL_TYPE_TIME:
+ case SQL_TIMESTAMP:
+ case SQL_TYPE_TIMESTAMP:
+ case SQL_INTERVAL_DAY:
+ case SQL_INTERVAL_DAY_TO_HOUR:
+ case SQL_INTERVAL_DAY_TO_MINUTE:
+ case SQL_INTERVAL_DAY_TO_SECOND:
+ case SQL_INTERVAL_HOUR:
+ case SQL_INTERVAL_HOUR_TO_MINUTE:
+ case SQL_INTERVAL_HOUR_TO_SECOND:
+ case SQL_INTERVAL_MINUTE:
+ case SQL_INTERVAL_MINUTE_TO_SECOND:
+ case SQL_INTERVAL_SECOND:
+ case SQL_INTERVAL_YEAR:
+ case SQL_INTERVAL_YEAR_TO_MONTH:
+ case SQL_INTERVAL_MONTH:
+ statement->GetTypeInfo(data_type);
+ break;
+ default:
+ throw DriverException("Invalid SQL data type", "HY004");
+ }
+
+ return SQL_SUCCESS;
+ });
}
SQLRETURN SQLNativeSql(SQLHDBC conn, SQLWCHAR* in_statement_text,
diff --git
a/cpp/src/arrow/flight/sql/odbc/odbc_impl/flight_sql_statement_get_type_info.cc
b/cpp/src/arrow/flight/sql/odbc/odbc_impl/flight_sql_statement_get_type_info.cc
index e94378b7e0..3fd1494c0a 100644
---
a/cpp/src/arrow/flight/sql/odbc/odbc_impl/flight_sql_statement_get_type_info.cc
+++
b/cpp/src/arrow/flight/sql/odbc/odbc_impl/flight_sql_statement_get_type_info.cc
@@ -108,7 +108,8 @@ Result<std::shared_ptr<RecordBatch>> TransformInner(
data.literal_suffix = reader.GetLiteralSuffix();
const auto& create_params = reader.GetCreateParams();
- if (create_params) {
+ if (create_params && !create_params->empty()) {
+ // GH-48093 TODO: replace boost-algorithm with alternatives
data.create_params = boost::algorithm::join(*create_params, ",");
} else {
data.create_params = nullopt;
@@ -116,6 +117,8 @@ Result<std::shared_ptr<RecordBatch>> TransformInner(
data.nullable = reader.GetNullable() ? NULLABILITY_NULLABLE :
NULLABILITY_NO_NULLS;
data.case_sensitive = reader.GetCaseSensitive();
+ // GH-47237 return SEARCHABILITY_LIKE_ONLY and
SEARCHABILITY_ALL_EXPECT_LIKE for
+ // appropriate data types
data.searchable = reader.GetSearchable() ? SEARCHABILITY_ALL :
SEARCHABILITY_NONE;
data.unsigned_attribute = reader.GetUnsignedAttribute();
data.fixed_prec_scale = reader.GetFixedPrecScale();
@@ -123,9 +126,9 @@ Result<std::shared_ptr<RecordBatch>> TransformInner(
data.local_type_name = reader.GetLocalTypeName();
data.minimum_scale = reader.GetMinimumScale();
data.maximum_scale = reader.GetMaximumScale();
- data.sql_data_type =
+ data.sql_data_type = util::GetNonConciseDataType(
EnsureRightSqlCharType(static_cast<SqlDataType>(reader.GetSqlDataType()),
- metadata_settings_.use_wide_char);
+ metadata_settings_.use_wide_char));
data.sql_datetime_sub =
util::GetSqlDateTimeSubCode(static_cast<SqlDataType>(data.data_type));
data.num_prec_radix = reader.GetNumPrecRadix();
diff --git a/cpp/src/arrow/flight/sql/odbc/odbc_impl/util.cc
b/cpp/src/arrow/flight/sql/odbc/odbc_impl/util.cc
index f06f00845a..fa0a35274a 100644
--- a/cpp/src/arrow/flight/sql/odbc/odbc_impl/util.cc
+++ b/cpp/src/arrow/flight/sql/odbc/odbc_impl/util.cc
@@ -56,6 +56,9 @@ SqlDataType GetDefaultSqlCharType(bool use_wide_char) {
SqlDataType GetDefaultSqlVarcharType(bool use_wide_char) {
return use_wide_char ? SqlDataType_WVARCHAR : SqlDataType_VARCHAR;
}
+SqlDataType GetDefaultSqlLongVarcharType(bool use_wide_char) {
+ return use_wide_char ? SqlDataType_WLONGVARCHAR : SqlDataType_LONGVARCHAR;
+}
CDataType GetDefaultCCharType(bool use_wide_char) {
return use_wide_char ? CDataType_WCHAR : CDataType_CHAR;
}
@@ -147,6 +150,9 @@ SqlDataType EnsureRightSqlCharType(SqlDataType data_type,
bool use_wide_char) {
case SqlDataType_VARCHAR:
case SqlDataType_WVARCHAR:
return GetDefaultSqlVarcharType(use_wide_char);
+ case SqlDataType_LONGVARCHAR:
+ case SqlDataType_WLONGVARCHAR:
+ return GetDefaultSqlLongVarcharType(use_wide_char);
default:
return data_type;
}
@@ -748,10 +754,12 @@ bool NeedArrayConversion(Type::type original_type_id,
CDataType data_type) {
return data_type != CDataType_BINARY;
case Type::DECIMAL128:
return data_type != CDataType_NUMERIC;
+ case Type::DURATION:
case Type::LIST:
case Type::LARGE_LIST:
case Type::FIXED_SIZE_LIST:
case Type::MAP:
+ case Type::STRING_VIEW:
case Type::STRUCT:
return data_type == CDataType_CHAR || data_type == CDataType_WCHAR;
default:
diff --git a/cpp/src/arrow/flight/sql/odbc/tests/CMakeLists.txt
b/cpp/src/arrow/flight/sql/odbc/tests/CMakeLists.txt
index f4e90420a7..5485ef9b4d 100644
--- a/cpp/src/arrow/flight/sql/odbc/tests/CMakeLists.txt
+++ b/cpp/src/arrow/flight/sql/odbc/tests/CMakeLists.txt
@@ -43,6 +43,7 @@ add_arrow_test(flight_sql_odbc_test
statement_attr_test.cc
statement_test.cc
tables_test.cc
+ type_info_test.cc
# Enable Protobuf cleanup after test execution
# GH-46889: move protobuf_test_util to a more common location
../../../../engine/substrait/protobuf_test_util.cc
diff --git a/cpp/src/arrow/flight/sql/odbc/tests/type_info_test.cc
b/cpp/src/arrow/flight/sql/odbc/tests/type_info_test.cc
new file mode 100644
index 0000000000..ce05f8a70b
--- /dev/null
+++ b/cpp/src/arrow/flight/sql/odbc/tests/type_info_test.cc
@@ -0,0 +1,1672 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+#include "arrow/flight/sql/odbc/tests/odbc_test_suite.h"
+
+#include "arrow/flight/sql/odbc/odbc_impl/platform.h"
+
+#include <sql.h>
+#include <sqltypes.h>
+#include <sqlucode.h>
+
+#include <gtest/gtest.h>
+
+namespace arrow::flight::sql::odbc {
+
+using std::optional;
+
+template <typename T>
+class TypeInfoTest : public T {};
+
+class TypeInfoMockTest : public FlightSQLODBCMockTestBase {};
+using TestTypes = ::testing::Types<TypeInfoMockTest,
FlightSQLODBCRemoteTestBase>;
+TYPED_TEST_SUITE(TypeInfoTest, TestTypes);
+
+class TypeInfoOdbcV2MockTest : public FlightSQLOdbcV2MockTestBase {};
+
+namespace {
+// Helper Functions
+
+void CheckSQLGetTypeInfo(
+ SQLHSTMT stmt, const std::wstring& expected_type_name,
+ const SQLSMALLINT& expected_data_type, const SQLINTEGER&
expected_column_size,
+ const optional<std::wstring>& expected_literal_prefix,
+ const optional<std::wstring>& expected_literal_suffix,
+ const optional<std::wstring>& expected_create_params,
+ const SQLSMALLINT& expected_nullable, const SQLSMALLINT&
expected_case_sensitive,
+ const SQLSMALLINT& expected_searchable, const SQLSMALLINT&
expected_unsigned_attr,
+ const SQLSMALLINT& expected_fixed_prec_scale,
+ const SQLSMALLINT& expected_auto_unique_value,
+ const std::wstring& expected_local_type_name, const SQLSMALLINT&
expected_min_scale,
+ const SQLSMALLINT& expected_max_scale, const SQLSMALLINT&
expected_sql_data_type,
+ const SQLSMALLINT& expected_sql_datetime_sub,
+ const SQLINTEGER& expected_num_prec_radix, const SQLINTEGER&
expected_interval_prec) {
+ CheckStringColumnW(stmt, 1, expected_type_name); // type name
+ CheckSmallIntColumn(stmt, 2, expected_data_type); // data type
+ CheckIntColumn(stmt, 3, expected_column_size); // column size
+
+ if (expected_literal_prefix) { // literal prefix
+ CheckStringColumnW(stmt, 4, *expected_literal_prefix);
+ } else {
+ CheckNullColumnW(stmt, 4);
+ }
+
+ if (expected_literal_suffix) { // literal suffix
+ CheckStringColumnW(stmt, 5, *expected_literal_suffix);
+ } else {
+ CheckNullColumnW(stmt, 5);
+ }
+
+ if (expected_create_params) { // create params
+ CheckStringColumnW(stmt, 6, *expected_create_params);
+ } else {
+ CheckNullColumnW(stmt, 6);
+ }
+
+ CheckSmallIntColumn(stmt, 7, expected_nullable); // nullable
+ CheckSmallIntColumn(stmt, 8, expected_case_sensitive); // case sensitive
+ CheckSmallIntColumn(stmt, 9, expected_searchable); // searchable
+ CheckSmallIntColumn(stmt, 10, expected_unsigned_attr); // unsigned attr
+ CheckSmallIntColumn(stmt, 11, expected_fixed_prec_scale); // fixed prec
scale
+ CheckSmallIntColumn(stmt, 12, expected_auto_unique_value); // auto unique
value
+ CheckStringColumnW(stmt, 13, expected_local_type_name); // local type
name
+ CheckSmallIntColumn(stmt, 14, expected_min_scale); // min scale
+ CheckSmallIntColumn(stmt, 15, expected_max_scale); // max scale
+ CheckSmallIntColumn(stmt, 16, expected_sql_data_type); // sql data type
+ CheckSmallIntColumn(stmt, 17, expected_sql_datetime_sub); // sql datetime
sub
+ CheckIntColumn(stmt, 18, expected_num_prec_radix); // num prec radix
+ CheckIntColumn(stmt, 19, expected_interval_prec); // interval prec
+}
+} // namespace
+
+TEST_F(TypeInfoMockTest, TestSQLGetTypeInfoAllTypes) {
+ ASSERT_EQ(SQL_SUCCESS, SQLGetTypeInfo(this->stmt, SQL_ALL_TYPES));
+
+ // Check bit data type
+ ASSERT_EQ(SQL_SUCCESS, SQLFetch(this->stmt));
+
+ CheckSQLGetTypeInfo(this->stmt,
+ std::wstring(L"bit"), // expected_type_name
+ SQL_BIT, // expected_data_type
+ 1, // expected_column_size
+ std::nullopt, // expected_literal_prefix
+ std::nullopt, // expected_literal_suffix
+ std::nullopt, // expected_create_params
+ SQL_NULLABLE, // expected_nullable
+ SQL_FALSE, // expected_case_sensitive
+ SQL_SEARCHABLE, // expected_searchable
+ NULL, // expected_unsigned_attr
+ SQL_FALSE, // expected_fixed_prec_scale
+ NULL, // expected_auto_unique_value
+ std::wstring(L"bit"), // expected_local_type_name
+ NULL, // expected_min_scale
+ NULL, // expected_max_scale
+ SQL_BIT, // expected_sql_data_type
+ NULL, // expected_sql_datetime_sub
+ NULL, // expected_num_prec_radix
+ NULL); // expected_interval_prec
+
+ // Check tinyint data type
+ ASSERT_EQ(SQL_SUCCESS, SQLFetch(this->stmt));
+
+ CheckSQLGetTypeInfo(this->stmt,
+ std::wstring(L"tinyint"), // expected_type_name
+ SQL_TINYINT, // expected_data_type
+ 3, // expected_column_size
+ std::nullopt, // expected_literal_prefix
+ std::nullopt, // expected_literal_suffix
+ std::nullopt, // expected_create_params
+ SQL_NULLABLE, // expected_nullable
+ SQL_FALSE, // expected_case_sensitive
+ SQL_SEARCHABLE, // expected_searchable
+ SQL_FALSE, // expected_unsigned_attr
+ SQL_FALSE, // expected_fixed_prec_scale
+ NULL, // expected_auto_unique_value
+ std::wstring(L"tinyint"), // expected_local_type_name
+ NULL, // expected_min_scale
+ NULL, // expected_max_scale
+ SQL_TINYINT, // expected_sql_data_type
+ NULL, // expected_sql_datetime_sub
+ NULL, // expected_num_prec_radix
+ NULL); // expected_interval_prec
+
+ // Check bigint data type
+ ASSERT_EQ(SQL_SUCCESS, SQLFetch(this->stmt));
+
+ CheckSQLGetTypeInfo(this->stmt,
+ std::wstring(L"bigint"), // expected_type_name
+ SQL_BIGINT, // expected_data_type
+ 19, // expected_column_size
+ std::nullopt, // expected_literal_prefix
+ std::nullopt, // expected_literal_suffix
+ std::nullopt, // expected_create_params
+ SQL_NULLABLE, // expected_nullable
+ SQL_FALSE, // expected_case_sensitive
+ SQL_SEARCHABLE, // expected_searchable
+ SQL_FALSE, // expected_unsigned_attr
+ SQL_FALSE, // expected_fixed_prec_scale
+ NULL, // expected_auto_unique_value
+ std::wstring(L"bigint"), // expected_local_type_name
+ NULL, // expected_min_scale
+ NULL, // expected_max_scale
+ SQL_BIGINT, // expected_sql_data_type
+ NULL, // expected_sql_datetime_sub
+ NULL, // expected_num_prec_radix
+ NULL); // expected_interval_prec
+
+ // Check longvarbinary data type
+ ASSERT_EQ(SQL_SUCCESS, SQLFetch(this->stmt));
+
+ CheckSQLGetTypeInfo(this->stmt,
+ std::wstring(L"longvarbinary"), // expected_type_name
+ SQL_LONGVARBINARY, // expected_data_type
+ 65536, // expected_column_size
+ std::nullopt, //
expected_literal_prefix
+ std::nullopt, //
expected_literal_suffix
+ std::nullopt, //
expected_create_params
+ SQL_NULLABLE, // expected_nullable
+ SQL_FALSE, //
expected_case_sensitive
+ SQL_SEARCHABLE, // expected_searchable
+ NULL, //
expected_unsigned_attr
+ SQL_FALSE, //
expected_fixed_prec_scale
+ NULL, //
expected_auto_unique_value
+ std::wstring(L"longvarbinary"), //
expected_local_type_name
+ NULL, // expected_min_scale
+ NULL, // expected_max_scale
+ SQL_LONGVARBINARY, //
expected_sql_data_type
+ NULL, //
expected_sql_datetime_sub
+ NULL, //
expected_num_prec_radix
+ NULL); //
expected_interval_prec
+
+ // Check varbinary data type
+ ASSERT_EQ(SQL_SUCCESS, SQLFetch(this->stmt));
+
+ CheckSQLGetTypeInfo(this->stmt,
+ std::wstring(L"varbinary"), // expected_type_name
+ SQL_VARBINARY, // expected_data_type
+ 255, // expected_column_size
+ std::nullopt, // expected_literal_prefix
+ std::nullopt, // expected_literal_suffix
+ std::nullopt, // expected_create_params
+ SQL_NULLABLE, // expected_nullable
+ SQL_FALSE, // expected_case_sensitive
+ SQL_SEARCHABLE, // expected_searchable
+ NULL, // expected_unsigned_attr
+ SQL_FALSE, // expected_fixed_prec_scale
+ NULL, //
expected_auto_unique_value
+ std::wstring(L"varbinary"), // expected_local_type_name
+ NULL, // expected_min_scale
+ NULL, // expected_max_scale
+ SQL_VARBINARY, // expected_sql_data_type
+ NULL, // expected_sql_datetime_sub
+ NULL, // expected_num_prec_radix
+ NULL); // expected_interval_prec
+
+ // Check text data type
+ ASSERT_EQ(SQL_SUCCESS, SQLFetch(this->stmt));
+
+ // Driver returns SQL_WLONGVARCHAR since unicode is enabled
+ CheckSQLGetTypeInfo(this->stmt,
+ std::wstring(L"text"), // expected_type_name
+ SQL_WLONGVARCHAR, // expected_data_type
+ 65536, // expected_column_size
+ std::wstring(L"'"), // expected_literal_prefix
+ std::wstring(L"'"), // expected_literal_suffix
+ std::wstring(L"length"), // expected_create_params
+ SQL_NULLABLE, // expected_nullable
+ SQL_FALSE, // expected_case_sensitive
+ SQL_SEARCHABLE, // expected_searchable
+ NULL, // expected_unsigned_attr
+ SQL_FALSE, // expected_fixed_prec_scale
+ NULL, // expected_auto_unique_value
+ std::wstring(L"text"), // expected_local_type_name
+ NULL, // expected_min_scale
+ NULL, // expected_max_scale
+ SQL_WLONGVARCHAR, // expected_sql_data_type
+ NULL, // expected_sql_datetime_sub
+ NULL, // expected_num_prec_radix
+ NULL); // expected_interval_prec
+
+ // Check longvarchar data type
+ ASSERT_EQ(SQL_SUCCESS, SQLFetch(this->stmt));
+
+ CheckSQLGetTypeInfo(this->stmt,
+ std::wstring(L"longvarchar"), // expected_type_name
+ SQL_WLONGVARCHAR, // expected_data_type
+ 65536, // expected_column_size
+ std::wstring(L"'"), // expected_literal_prefix
+ std::wstring(L"'"), // expected_literal_suffix
+ std::wstring(L"length"), // expected_create_params
+ SQL_NULLABLE, // expected_nullable
+ SQL_FALSE, // expected_case_sensitive
+ SQL_SEARCHABLE, // expected_searchable
+ NULL, // expected_unsigned_attr
+ SQL_FALSE, //
expected_fixed_prec_scale
+ NULL, //
expected_auto_unique_value
+ std::wstring(L"longvarchar"), //
expected_local_type_name
+ NULL, // expected_min_scale
+ NULL, // expected_max_scale
+ SQL_WLONGVARCHAR, // expected_sql_data_type
+ NULL, //
expected_sql_datetime_sub
+ NULL, // expected_num_prec_radix
+ NULL); // expected_interval_prec
+
+ // Check char data type
+ ASSERT_EQ(SQL_SUCCESS, SQLFetch(this->stmt));
+
+ // Driver returns SQL_WCHAR since unicode is enabled
+ CheckSQLGetTypeInfo(this->stmt,
+ std::wstring(L"char"), // expected_type_name
+ SQL_WCHAR, // expected_data_type
+ 255, // expected_column_size
+ std::wstring(L"'"), // expected_literal_prefix
+ std::wstring(L"'"), // expected_literal_suffix
+ std::wstring(L"length"), // expected_create_params
+ SQL_NULLABLE, // expected_nullable
+ SQL_FALSE, // expected_case_sensitive
+ SQL_SEARCHABLE, // expected_searchable
+ NULL, // expected_unsigned_attr
+ SQL_FALSE, // expected_fixed_prec_scale
+ NULL, // expected_auto_unique_value
+ std::wstring(L"char"), // expected_local_type_name
+ NULL, // expected_min_scale
+ NULL, // expected_max_scale
+ SQL_WCHAR, // expected_sql_data_type
+ NULL, // expected_sql_datetime_sub
+ NULL, // expected_num_prec_radix
+ NULL); // expected_interval_prec
+
+ // Check integer data type
+ ASSERT_EQ(SQL_SUCCESS, SQLFetch(this->stmt));
+
+ CheckSQLGetTypeInfo(this->stmt,
+ std::wstring(L"integer"), // expected_type_name
+ SQL_INTEGER, // expected_data_type
+ 9, // expected_column_size
+ std::nullopt, // expected_literal_prefix
+ std::nullopt, // expected_literal_suffix
+ std::nullopt, // expected_create_params
+ SQL_NULLABLE, // expected_nullable
+ SQL_FALSE, // expected_case_sensitive
+ SQL_SEARCHABLE, // expected_searchable
+ SQL_FALSE, // expected_unsigned_attr
+ SQL_FALSE, // expected_fixed_prec_scale
+ NULL, // expected_auto_unique_value
+ std::wstring(L"integer"), // expected_local_type_name
+ NULL, // expected_min_scale
+ NULL, // expected_max_scale
+ SQL_INTEGER, // expected_sql_data_type
+ NULL, // expected_sql_datetime_sub
+ NULL, // expected_num_prec_radix
+ NULL); // expected_interval_prec
+
+ // Check smallint data type
+ ASSERT_EQ(SQL_SUCCESS, SQLFetch(this->stmt));
+
+ CheckSQLGetTypeInfo(this->stmt,
+ std::wstring(L"smallint"), // expected_type_name
+ SQL_SMALLINT, // expected_data_type
+ 5, // expected_column_size
+ std::nullopt, // expected_literal_prefix
+ std::nullopt, // expected_literal_suffix
+ std::nullopt, // expected_create_params
+ SQL_NULLABLE, // expected_nullable
+ SQL_FALSE, // expected_case_sensitive
+ SQL_SEARCHABLE, // expected_searchable
+ SQL_FALSE, // expected_unsigned_attr
+ SQL_FALSE, // expected_fixed_prec_scale
+ NULL, // expected_auto_unique_value
+ std::wstring(L"smallint"), // expected_local_type_name
+ NULL, // expected_min_scale
+ NULL, // expected_max_scale
+ SQL_SMALLINT, // expected_sql_data_type
+ NULL, // expected_sql_datetime_sub
+ NULL, // expected_num_prec_radix
+ NULL); // expected_interval_prec
+
+ // Check float data type
+ ASSERT_EQ(SQL_SUCCESS, SQLFetch(this->stmt));
+
+ CheckSQLGetTypeInfo(this->stmt,
+ std::wstring(L"float"), // expected_type_name
+ SQL_FLOAT, // expected_data_type
+ 7, // expected_column_size
+ std::nullopt, // expected_literal_prefix
+ std::nullopt, // expected_literal_suffix
+ std::nullopt, // expected_create_params
+ SQL_NULLABLE, // expected_nullable
+ SQL_FALSE, // expected_case_sensitive
+ SQL_SEARCHABLE, // expected_searchable
+ SQL_FALSE, // expected_unsigned_attr
+ SQL_FALSE, // expected_fixed_prec_scale
+ NULL, // expected_auto_unique_value
+ std::wstring(L"float"), // expected_local_type_name
+ NULL, // expected_min_scale
+ NULL, // expected_max_scale
+ SQL_FLOAT, // expected_sql_data_type
+ NULL, // expected_sql_datetime_sub
+ NULL, // expected_num_prec_radix
+ NULL); // expected_interval_prec
+
+ // Check double data type
+ ASSERT_EQ(SQL_SUCCESS, SQLFetch(this->stmt));
+
+ CheckSQLGetTypeInfo(this->stmt,
+ std::wstring(L"double"), // expected_type_name
+ SQL_DOUBLE, // expected_data_type
+ 15, // expected_column_size
+ std::nullopt, // expected_literal_prefix
+ std::nullopt, // expected_literal_suffix
+ std::nullopt, // expected_create_params
+ SQL_NULLABLE, // expected_nullable
+ SQL_FALSE, // expected_case_sensitive
+ SQL_SEARCHABLE, // expected_searchable
+ SQL_FALSE, // expected_unsigned_attr
+ SQL_FALSE, // expected_fixed_prec_scale
+ NULL, // expected_auto_unique_value
+ std::wstring(L"double"), // expected_local_type_name
+ NULL, // expected_min_scale
+ NULL, // expected_max_scale
+ SQL_DOUBLE, // expected_sql_data_type
+ NULL, // expected_sql_datetime_sub
+ NULL, // expected_num_prec_radix
+ NULL); // expected_interval_prec
+
+ // Check numeric data type
+ ASSERT_EQ(SQL_SUCCESS, SQLFetch(this->stmt));
+
+ // Mock server treats numeric data type as a double type
+ CheckSQLGetTypeInfo(this->stmt,
+ std::wstring(L"numeric"), // expected_type_name
+ SQL_DOUBLE, // expected_data_type
+ 15, // expected_column_size
+ std::nullopt, // expected_literal_prefix
+ std::nullopt, // expected_literal_suffix
+ std::nullopt, // expected_create_params
+ SQL_NULLABLE, // expected_nullable
+ SQL_FALSE, // expected_case_sensitive
+ SQL_SEARCHABLE, // expected_searchable
+ SQL_FALSE, // expected_unsigned_attr
+ SQL_FALSE, // expected_fixed_prec_scale
+ NULL, // expected_auto_unique_value
+ std::wstring(L"numeric"), // expected_local_type_name
+ NULL, // expected_min_scale
+ NULL, // expected_max_scale
+ SQL_DOUBLE, // expected_sql_data_type
+ NULL, // expected_sql_datetime_sub
+ NULL, // expected_num_prec_radix
+ NULL); // expected_interval_prec
+
+ // Check varchar data type
+ ASSERT_EQ(SQL_SUCCESS, SQLFetch(this->stmt));
+
+ // Driver returns SQL_WVARCHAR since unicode is enabled
+ CheckSQLGetTypeInfo(this->stmt,
+ std::wstring(L"varchar"), // expected_type_name
+ SQL_WVARCHAR, // expected_data_type
+ 255, // expected_column_size
+ std::wstring(L"'"), // expected_literal_prefix
+ std::wstring(L"'"), // expected_literal_suffix
+ std::wstring(L"length"), // expected_create_params
+ SQL_NULLABLE, // expected_nullable
+ SQL_FALSE, // expected_case_sensitive
+ SQL_SEARCHABLE, // expected_searchable
+ SQL_FALSE, // expected_unsigned_attr
+ SQL_FALSE, // expected_fixed_prec_scale
+ NULL, // expected_auto_unique_value
+ std::wstring(L"varchar"), // expected_local_type_name
+ NULL, // expected_min_scale
+ NULL, // expected_max_scale
+ SQL_WVARCHAR, // expected_sql_data_type
+ NULL, // expected_sql_datetime_sub
+ NULL, // expected_num_prec_radix
+ NULL); // expected_interval_prec
+
+ // Check date data type
+ ASSERT_EQ(SQL_SUCCESS, SQLFetch(this->stmt));
+
+ CheckSQLGetTypeInfo(this->stmt,
+ std::wstring(L"date"), // expected_type_name
+ SQL_TYPE_DATE, // expected_data_type
+ 10, // expected_column_size
+ std::wstring(L"'"), // expected_literal_prefix
+ std::wstring(L"'"), // expected_literal_suffix
+ std::nullopt, // expected_create_params
+ SQL_NULLABLE, // expected_nullable
+ SQL_FALSE, // expected_case_sensitive
+ SQL_SEARCHABLE, // expected_searchable
+ SQL_FALSE, // expected_unsigned_attr
+ SQL_FALSE, // expected_fixed_prec_scale
+ NULL, // expected_auto_unique_value
+ std::wstring(L"date"), // expected_local_type_name
+ NULL, // expected_min_scale
+ NULL, // expected_max_scale
+ SQL_DATETIME, // expected_sql_data_type
+ SQL_CODE_DATE, // expected_sql_datetime_sub
+ NULL, // expected_num_prec_radix
+ NULL); // expected_interval_prec
+
+ // Check time data type
+ ASSERT_EQ(SQL_SUCCESS, SQLFetch(this->stmt));
+
+ CheckSQLGetTypeInfo(this->stmt,
+ std::wstring(L"time"), // expected_type_name
+ SQL_TYPE_TIME, // expected_data_type
+ 8, // expected_column_size
+ std::wstring(L"'"), // expected_literal_prefix
+ std::wstring(L"'"), // expected_literal_suffix
+ std::nullopt, // expected_create_params
+ SQL_NULLABLE, // expected_nullable
+ SQL_FALSE, // expected_case_sensitive
+ SQL_SEARCHABLE, // expected_searchable
+ SQL_FALSE, // expected_unsigned_attr
+ SQL_FALSE, // expected_fixed_prec_scale
+ NULL, // expected_auto_unique_value
+ std::wstring(L"time"), // expected_local_type_name
+ NULL, // expected_min_scale
+ NULL, // expected_max_scale
+ SQL_DATETIME, // expected_sql_data_type
+ SQL_CODE_TIME, // expected_sql_datetime_sub
+ NULL, // expected_num_prec_radix
+ NULL); // expected_interval_prec
+
+ // Check timestamp data type
+ ASSERT_EQ(SQL_SUCCESS, SQLFetch(this->stmt));
+
+ CheckSQLGetTypeInfo(this->stmt,
+ std::wstring(L"timestamp"), // expected_type_name
+ SQL_TYPE_TIMESTAMP, // expected_data_type
+ 32, // expected_column_size
+ std::wstring(L"'"), // expected_literal_prefix
+ std::wstring(L"'"), // expected_literal_suffix
+ std::nullopt, // expected_create_params
+ SQL_NULLABLE, // expected_nullable
+ SQL_FALSE, // expected_case_sensitive
+ SQL_SEARCHABLE, // expected_searchable
+ SQL_FALSE, // expected_unsigned_attr
+ SQL_FALSE, // expected_fixed_prec_scale
+ NULL, //
expected_auto_unique_value
+ std::wstring(L"timestamp"), // expected_local_type_name
+ NULL, // expected_min_scale
+ NULL, // expected_max_scale
+ SQL_DATETIME, // expected_sql_data_type
+ SQL_CODE_TIMESTAMP, // expected_sql_datetime_sub
+ NULL, // expected_num_prec_radix
+ NULL); // expected_interval_prec
+}
+
+TEST_F(TypeInfoOdbcV2MockTest, TestSQLGetTypeInfoAllTypesODBCVer2) {
+ ASSERT_EQ(SQL_SUCCESS, SQLGetTypeInfo(this->stmt, SQL_ALL_TYPES));
+
+ // Check bit data type
+ ASSERT_EQ(SQL_SUCCESS, SQLFetch(this->stmt));
+
+ CheckSQLGetTypeInfo(this->stmt,
+ std::wstring(L"bit"), // expected_type_name
+ SQL_BIT, // expected_data_type
+ 1, // expected_column_size
+ std::nullopt, // expected_literal_prefix
+ std::nullopt, // expected_literal_suffix
+ std::nullopt, // expected_create_params
+ SQL_NULLABLE, // expected_nullable
+ SQL_FALSE, // expected_case_sensitive
+ SQL_SEARCHABLE, // expected_searchable
+ NULL, // expected_unsigned_attr
+ SQL_FALSE, // expected_fixed_prec_scale
+ NULL, // expected_auto_unique_value
+ std::wstring(L"bit"), // expected_local_type_name
+ NULL, // expected_min_scale
+ NULL, // expected_max_scale
+ SQL_BIT, // expected_sql_data_type
+ NULL, // expected_sql_datetime_sub
+ NULL, // expected_num_prec_radix
+ NULL); // expected_interval_prec
+
+ // Check tinyint data type
+ ASSERT_EQ(SQL_SUCCESS, SQLFetch(this->stmt));
+
+ CheckSQLGetTypeInfo(this->stmt,
+ std::wstring(L"tinyint"), // expected_type_name
+ SQL_TINYINT, // expected_data_type
+ 3, // expected_column_size
+ std::nullopt, // expected_literal_prefix
+ std::nullopt, // expected_literal_suffix
+ std::nullopt, // expected_create_params
+ SQL_NULLABLE, // expected_nullable
+ SQL_FALSE, // expected_case_sensitive
+ SQL_SEARCHABLE, // expected_searchable
+ SQL_FALSE, // expected_unsigned_attr
+ SQL_FALSE, // expected_fixed_prec_scale
+ NULL, // expected_auto_unique_value
+ std::wstring(L"tinyint"), // expected_local_type_name
+ NULL, // expected_min_scale
+ NULL, // expected_max_scale
+ SQL_TINYINT, // expected_sql_data_type
+ NULL, // expected_sql_datetime_sub
+ NULL, // expected_num_prec_radix
+ NULL); // expected_interval_prec
+
+ // Check bigint data type
+ ASSERT_EQ(SQL_SUCCESS, SQLFetch(this->stmt));
+
+ CheckSQLGetTypeInfo(this->stmt,
+ std::wstring(L"bigint"), // expected_type_name
+ SQL_BIGINT, // expected_data_type
+ 19, // expected_column_size
+ std::nullopt, // expected_literal_prefix
+ std::nullopt, // expected_literal_suffix
+ std::nullopt, // expected_create_params
+ SQL_NULLABLE, // expected_nullable
+ SQL_FALSE, // expected_case_sensitive
+ SQL_SEARCHABLE, // expected_searchable
+ SQL_FALSE, // expected_unsigned_attr
+ SQL_FALSE, // expected_fixed_prec_scale
+ NULL, // expected_auto_unique_value
+ std::wstring(L"bigint"), // expected_local_type_name
+ NULL, // expected_min_scale
+ NULL, // expected_max_scale
+ SQL_BIGINT, // expected_sql_data_type
+ NULL, // expected_sql_datetime_sub
+ NULL, // expected_num_prec_radix
+ NULL); // expected_interval_prec
+
+ // Check longvarbinary data type
+ ASSERT_EQ(SQL_SUCCESS, SQLFetch(this->stmt));
+
+ CheckSQLGetTypeInfo(this->stmt,
+ std::wstring(L"longvarbinary"), // expected_type_name
+ SQL_LONGVARBINARY, // expected_data_type
+ 65536, // expected_column_size
+ std::nullopt, //
expected_literal_prefix
+ std::nullopt, //
expected_literal_suffix
+ std::nullopt, //
expected_create_params
+ SQL_NULLABLE, // expected_nullable
+ SQL_FALSE, //
expected_case_sensitive
+ SQL_SEARCHABLE, // expected_searchable
+ NULL, //
expected_unsigned_attr
+ SQL_FALSE, //
expected_fixed_prec_scale
+ NULL, //
expected_auto_unique_value
+ std::wstring(L"longvarbinary"), //
expected_local_type_name
+ NULL, // expected_min_scale
+ NULL, // expected_max_scale
+ SQL_LONGVARBINARY, //
expected_sql_data_type
+ NULL, //
expected_sql_datetime_sub
+ NULL, //
expected_num_prec_radix
+ NULL); //
expected_interval_prec
+
+ // Check varbinary data type
+ ASSERT_EQ(SQL_SUCCESS, SQLFetch(this->stmt));
+
+ CheckSQLGetTypeInfo(this->stmt,
+ std::wstring(L"varbinary"), // expected_type_name
+ SQL_VARBINARY, // expected_data_type
+ 255, // expected_column_size
+ std::nullopt, // expected_literal_prefix
+ std::nullopt, // expected_literal_suffix
+ std::nullopt, // expected_create_params
+ SQL_NULLABLE, // expected_nullable
+ SQL_FALSE, // expected_case_sensitive
+ SQL_SEARCHABLE, // expected_searchable
+ NULL, // expected_unsigned_attr
+ SQL_FALSE, // expected_fixed_prec_scale
+ NULL, //
expected_auto_unique_value
+ std::wstring(L"varbinary"), // expected_local_type_name
+ NULL, // expected_min_scale
+ NULL, // expected_max_scale
+ SQL_VARBINARY, // expected_sql_data_type
+ NULL, // expected_sql_datetime_sub
+ NULL, // expected_num_prec_radix
+ NULL); // expected_interval_prec
+
+ // Check text data type
+ ASSERT_EQ(SQL_SUCCESS, SQLFetch(this->stmt));
+
+ // Driver returns SQL_WLONGVARCHAR since unicode is enabled
+ CheckSQLGetTypeInfo(this->stmt,
+ std::wstring(L"text"), // expected_type_name
+ SQL_WLONGVARCHAR, // expected_data_type
+ 65536, // expected_column_size
+ std::wstring(L"'"), // expected_literal_prefix
+ std::wstring(L"'"), // expected_literal_suffix
+ std::wstring(L"length"), // expected_create_params
+ SQL_NULLABLE, // expected_nullable
+ SQL_FALSE, // expected_case_sensitive
+ SQL_SEARCHABLE, // expected_searchable
+ NULL, // expected_unsigned_attr
+ SQL_FALSE, // expected_fixed_prec_scale
+ NULL, // expected_auto_unique_value
+ std::wstring(L"text"), // expected_local_type_name
+ NULL, // expected_min_scale
+ NULL, // expected_max_scale
+ SQL_WLONGVARCHAR, // expected_sql_data_type
+ NULL, // expected_sql_datetime_sub
+ NULL, // expected_num_prec_radix
+ NULL); // expected_interval_prec
+
+ // Check longvarchar data type
+ ASSERT_EQ(SQL_SUCCESS, SQLFetch(this->stmt));
+
+ CheckSQLGetTypeInfo(this->stmt,
+ std::wstring(L"longvarchar"), // expected_type_name
+ SQL_WLONGVARCHAR, // expected_data_type
+ 65536, // expected_column_size
+ std::wstring(L"'"), // expected_literal_prefix
+ std::wstring(L"'"), // expected_literal_suffix
+ std::wstring(L"length"), // expected_create_params
+ SQL_NULLABLE, // expected_nullable
+ SQL_FALSE, // expected_case_sensitive
+ SQL_SEARCHABLE, // expected_searchable
+ NULL, // expected_unsigned_attr
+ SQL_FALSE, //
expected_fixed_prec_scale
+ NULL, //
expected_auto_unique_value
+ std::wstring(L"longvarchar"), //
expected_local_type_name
+ NULL, // expected_min_scale
+ NULL, // expected_max_scale
+ SQL_WLONGVARCHAR, // expected_sql_data_type
+ NULL, //
expected_sql_datetime_sub
+ NULL, // expected_num_prec_radix
+ NULL); // expected_interval_prec
+
+ // Check char data type
+ ASSERT_EQ(SQL_SUCCESS, SQLFetch(this->stmt));
+
+ // Driver returns SQL_WCHAR since unicode is enabled
+ CheckSQLGetTypeInfo(this->stmt,
+ std::wstring(L"char"), // expected_type_name
+ SQL_WCHAR, // expected_data_type
+ 255, // expected_column_size
+ std::wstring(L"'"), // expected_literal_prefix
+ std::wstring(L"'"), // expected_literal_suffix
+ std::wstring(L"length"), // expected_create_params
+ SQL_NULLABLE, // expected_nullable
+ SQL_FALSE, // expected_case_sensitive
+ SQL_SEARCHABLE, // expected_searchable
+ NULL, // expected_unsigned_attr
+ SQL_FALSE, // expected_fixed_prec_scale
+ NULL, // expected_auto_unique_value
+ std::wstring(L"char"), // expected_local_type_name
+ NULL, // expected_min_scale
+ NULL, // expected_max_scale
+ SQL_WCHAR, // expected_sql_data_type
+ NULL, // expected_sql_datetime_sub
+ NULL, // expected_num_prec_radix
+ NULL); // expected_interval_prec
+
+ // Check integer data type
+ ASSERT_EQ(SQL_SUCCESS, SQLFetch(this->stmt));
+
+ CheckSQLGetTypeInfo(this->stmt,
+ std::wstring(L"integer"), // expected_type_name
+ SQL_INTEGER, // expected_data_type
+ 9, // expected_column_size
+ std::nullopt, // expected_literal_prefix
+ std::nullopt, // expected_literal_suffix
+ std::nullopt, // expected_create_params
+ SQL_NULLABLE, // expected_nullable
+ SQL_FALSE, // expected_case_sensitive
+ SQL_SEARCHABLE, // expected_searchable
+ SQL_FALSE, // expected_unsigned_attr
+ SQL_FALSE, // expected_fixed_prec_scale
+ NULL, // expected_auto_unique_value
+ std::wstring(L"integer"), // expected_local_type_name
+ NULL, // expected_min_scale
+ NULL, // expected_max_scale
+ SQL_INTEGER, // expected_sql_data_type
+ NULL, // expected_sql_datetime_sub
+ NULL, // expected_num_prec_radix
+ NULL); // expected_interval_prec
+
+ // Check smallint data type
+ ASSERT_EQ(SQL_SUCCESS, SQLFetch(this->stmt));
+
+ CheckSQLGetTypeInfo(this->stmt,
+ std::wstring(L"smallint"), // expected_type_name
+ SQL_SMALLINT, // expected_data_type
+ 5, // expected_column_size
+ std::nullopt, // expected_literal_prefix
+ std::nullopt, // expected_literal_suffix
+ std::nullopt, // expected_create_params
+ SQL_NULLABLE, // expected_nullable
+ SQL_FALSE, // expected_case_sensitive
+ SQL_SEARCHABLE, // expected_searchable
+ SQL_FALSE, // expected_unsigned_attr
+ SQL_FALSE, // expected_fixed_prec_scale
+ NULL, // expected_auto_unique_value
+ std::wstring(L"smallint"), // expected_local_type_name
+ NULL, // expected_min_scale
+ NULL, // expected_max_scale
+ SQL_SMALLINT, // expected_sql_data_type
+ NULL, // expected_sql_datetime_sub
+ NULL, // expected_num_prec_radix
+ NULL); // expected_interval_prec
+
+ // Check float data type
+ ASSERT_EQ(SQL_SUCCESS, SQLFetch(this->stmt));
+
+ CheckSQLGetTypeInfo(this->stmt,
+ std::wstring(L"float"), // expected_type_name
+ SQL_FLOAT, // expected_data_type
+ 7, // expected_column_size
+ std::nullopt, // expected_literal_prefix
+ std::nullopt, // expected_literal_suffix
+ std::nullopt, // expected_create_params
+ SQL_NULLABLE, // expected_nullable
+ SQL_FALSE, // expected_case_sensitive
+ SQL_SEARCHABLE, // expected_searchable
+ SQL_FALSE, // expected_unsigned_attr
+ SQL_FALSE, // expected_fixed_prec_scale
+ NULL, // expected_auto_unique_value
+ std::wstring(L"float"), // expected_local_type_name
+ NULL, // expected_min_scale
+ NULL, // expected_max_scale
+ SQL_FLOAT, // expected_sql_data_type
+ NULL, // expected_sql_datetime_sub
+ NULL, // expected_num_prec_radix
+ NULL); // expected_interval_prec
+
+ // Check double data type
+ ASSERT_EQ(SQL_SUCCESS, SQLFetch(this->stmt));
+
+ CheckSQLGetTypeInfo(this->stmt,
+ std::wstring(L"double"), // expected_type_name
+ SQL_DOUBLE, // expected_data_type
+ 15, // expected_column_size
+ std::nullopt, // expected_literal_prefix
+ std::nullopt, // expected_literal_suffix
+ std::nullopt, // expected_create_params
+ SQL_NULLABLE, // expected_nullable
+ SQL_FALSE, // expected_case_sensitive
+ SQL_SEARCHABLE, // expected_searchable
+ SQL_FALSE, // expected_unsigned_attr
+ SQL_FALSE, // expected_fixed_prec_scale
+ NULL, // expected_auto_unique_value
+ std::wstring(L"double"), // expected_local_type_name
+ NULL, // expected_min_scale
+ NULL, // expected_max_scale
+ SQL_DOUBLE, // expected_sql_data_type
+ NULL, // expected_sql_datetime_sub
+ NULL, // expected_num_prec_radix
+ NULL); // expected_interval_prec
+
+ // Check numeric data type
+ ASSERT_EQ(SQL_SUCCESS, SQLFetch(this->stmt));
+
+ // Mock server treats numeric data type as a double type
+ CheckSQLGetTypeInfo(this->stmt,
+ std::wstring(L"numeric"), // expected_type_name
+ SQL_DOUBLE, // expected_data_type
+ 15, // expected_column_size
+ std::nullopt, // expected_literal_prefix
+ std::nullopt, // expected_literal_suffix
+ std::nullopt, // expected_create_params
+ SQL_NULLABLE, // expected_nullable
+ SQL_FALSE, // expected_case_sensitive
+ SQL_SEARCHABLE, // expected_searchable
+ SQL_FALSE, // expected_unsigned_attr
+ SQL_FALSE, // expected_fixed_prec_scale
+ NULL, // expected_auto_unique_value
+ std::wstring(L"numeric"), // expected_local_type_name
+ NULL, // expected_min_scale
+ NULL, // expected_max_scale
+ SQL_DOUBLE, // expected_sql_data_type
+ NULL, // expected_sql_datetime_sub
+ NULL, // expected_num_prec_radix
+ NULL); // expected_interval_prec
+
+ // Check varchar data type
+ ASSERT_EQ(SQL_SUCCESS, SQLFetch(this->stmt));
+
+ // Driver returns SQL_WVARCHAR since unicode is enabled
+ CheckSQLGetTypeInfo(this->stmt,
+ std::wstring(L"varchar"), // expected_type_name
+ SQL_WVARCHAR, // expected_data_type
+ 255, // expected_column_size
+ std::wstring(L"'"), // expected_literal_prefix
+ std::wstring(L"'"), // expected_literal_suffix
+ std::wstring(L"length"), // expected_create_params
+ SQL_NULLABLE, // expected_nullable
+ SQL_FALSE, // expected_case_sensitive
+ SQL_SEARCHABLE, // expected_searchable
+ SQL_FALSE, // expected_unsigned_attr
+ SQL_FALSE, // expected_fixed_prec_scale
+ NULL, // expected_auto_unique_value
+ std::wstring(L"varchar"), // expected_local_type_name
+ NULL, // expected_min_scale
+ NULL, // expected_max_scale
+ SQL_WVARCHAR, // expected_sql_data_type
+ NULL, // expected_sql_datetime_sub
+ NULL, // expected_num_prec_radix
+ NULL); // expected_interval_prec
+
+ // Check date data type
+ ASSERT_EQ(SQL_SUCCESS, SQLFetch(this->stmt));
+
+ CheckSQLGetTypeInfo(this->stmt,
+ std::wstring(L"date"), // expected_type_name
+ SQL_DATE, // expected_data_type
+ 10, // expected_column_size
+ std::wstring(L"'"), // expected_literal_prefix
+ std::wstring(L"'"), // expected_literal_suffix
+ std::nullopt, // expected_create_params
+ SQL_NULLABLE, // expected_nullable
+ SQL_FALSE, // expected_case_sensitive
+ SQL_SEARCHABLE, // expected_searchable
+ SQL_FALSE, // expected_unsigned_attr
+ SQL_FALSE, // expected_fixed_prec_scale
+ NULL, // expected_auto_unique_value
+ std::wstring(L"date"), // expected_local_type_name
+ NULL, // expected_min_scale
+ NULL, // expected_max_scale
+ SQL_DATETIME, // expected_sql_data_type
+ NULL, // expected_sql_datetime_sub, driver returns
NULL for Ver2
+ NULL, // expected_num_prec_radix
+ NULL); // expected_interval_prec
+
+ // Check time data type
+ ASSERT_EQ(SQL_SUCCESS, SQLFetch(this->stmt));
+
+ CheckSQLGetTypeInfo(this->stmt,
+ std::wstring(L"time"), // expected_type_name
+ SQL_TIME, // expected_data_type
+ 8, // expected_column_size
+ std::wstring(L"'"), // expected_literal_prefix
+ std::wstring(L"'"), // expected_literal_suffix
+ std::nullopt, // expected_create_params
+ SQL_NULLABLE, // expected_nullable
+ SQL_FALSE, // expected_case_sensitive
+ SQL_SEARCHABLE, // expected_searchable
+ SQL_FALSE, // expected_unsigned_attr
+ SQL_FALSE, // expected_fixed_prec_scale
+ NULL, // expected_auto_unique_value
+ std::wstring(L"time"), // expected_local_type_name
+ NULL, // expected_min_scale
+ NULL, // expected_max_scale
+ SQL_DATETIME, // expected_sql_data_type
+ NULL, // expected_sql_datetime_sub, driver returns
NULL for Ver2
+ NULL, // expected_num_prec_radix
+ NULL); // expected_interval_prec
+
+ // Check timestamp data type
+ ASSERT_EQ(SQL_SUCCESS, SQLFetch(this->stmt));
+
+ CheckSQLGetTypeInfo(this->stmt,
+ std::wstring(L"timestamp"), // expected_type_name
+ SQL_TIMESTAMP, // expected_data_type
+ 32, // expected_column_size
+ std::wstring(L"'"), // expected_literal_prefix
+ std::wstring(L"'"), // expected_literal_suffix
+ std::nullopt, // expected_create_params
+ SQL_NULLABLE, // expected_nullable
+ SQL_FALSE, // expected_case_sensitive
+ SQL_SEARCHABLE, // expected_searchable
+ SQL_FALSE, // expected_unsigned_attr
+ SQL_FALSE, // expected_fixed_prec_scale
+ NULL, //
expected_auto_unique_value
+ std::wstring(L"timestamp"), // expected_local_type_name
+ NULL, // expected_min_scale
+ NULL, // expected_max_scale
+ SQL_DATETIME, // expected_sql_data_type
+ NULL, // expected_sql_datetime_sub, driver returns
NULL for Ver2
+ NULL, // expected_num_prec_radix
+ NULL); // expected_interval_prec
+}
+
+TEST_F(TypeInfoMockTest, TestSQLGetTypeInfoBit) {
+ ASSERT_EQ(SQL_SUCCESS, SQLGetTypeInfo(this->stmt, SQL_BIT));
+
+ // Check bit data type
+ ASSERT_EQ(SQL_SUCCESS, SQLFetch(this->stmt));
+
+ CheckSQLGetTypeInfo(this->stmt,
+ std::wstring(L"bit"), // expected_type_name
+ SQL_BIT, // expected_data_type
+ 1, // expected_column_size
+ std::nullopt, // expected_literal_prefix
+ std::nullopt, // expected_literal_suffix
+ std::nullopt, // expected_create_params
+ SQL_NULLABLE, // expected_nullable
+ SQL_FALSE, // expected_case_sensitive
+ SQL_SEARCHABLE, // expected_searchable
+ NULL, // expected_unsigned_attr
+ SQL_FALSE, // expected_fixed_prec_scale
+ NULL, // expected_auto_unique_value
+ std::wstring(L"bit"), // expected_local_type_name
+ NULL, // expected_min_scale
+ NULL, // expected_max_scale
+ SQL_BIT, // expected_sql_data_type
+ NULL, // expected_sql_datetime_sub
+ NULL, // expected_num_prec_radix
+ NULL); // expected_interval_prec
+
+ // No more data
+ ASSERT_EQ(SQL_NO_DATA, SQLFetch(this->stmt));
+}
+
+TEST_F(TypeInfoMockTest, TestSQLGetTypeInfoTinyInt) {
+ ASSERT_EQ(SQL_SUCCESS, SQLGetTypeInfo(this->stmt, SQL_TINYINT));
+
+ // Check tinyint data type
+ ASSERT_EQ(SQL_SUCCESS, SQLFetch(this->stmt));
+
+ CheckSQLGetTypeInfo(this->stmt,
+ std::wstring(L"tinyint"), // expected_type_name
+ SQL_TINYINT, // expected_data_type
+ 3, // expected_column_size
+ std::nullopt, // expected_literal_prefix
+ std::nullopt, // expected_literal_suffix
+ std::nullopt, // expected_create_params
+ SQL_NULLABLE, // expected_nullable
+ SQL_FALSE, // expected_case_sensitive
+ SQL_SEARCHABLE, // expected_searchable
+ SQL_FALSE, // expected_unsigned_attr
+ SQL_FALSE, // expected_fixed_prec_scale
+ NULL, // expected_auto_unique_value
+ std::wstring(L"tinyint"), // expected_local_type_name
+ NULL, // expected_min_scale
+ NULL, // expected_max_scale
+ SQL_TINYINT, // expected_sql_data_type
+ NULL, // expected_sql_datetime_sub
+ NULL, // expected_num_prec_radix
+ NULL); // expected_interval_prec
+
+ // No more data
+ ASSERT_EQ(SQL_NO_DATA, SQLFetch(this->stmt));
+}
+
+TEST_F(TypeInfoMockTest, TestSQLGetTypeInfoBigInt) {
+ ASSERT_EQ(SQL_SUCCESS, SQLGetTypeInfo(this->stmt, SQL_BIGINT));
+
+ // Check bigint data type
+ ASSERT_EQ(SQL_SUCCESS, SQLFetch(this->stmt));
+
+ CheckSQLGetTypeInfo(this->stmt,
+ std::wstring(L"bigint"), // expected_type_name
+ SQL_BIGINT, // expected_data_type
+ 19, // expected_column_size
+ std::nullopt, // expected_literal_prefix
+ std::nullopt, // expected_literal_suffix
+ std::nullopt, // expected_create_params
+ SQL_NULLABLE, // expected_nullable
+ SQL_FALSE, // expected_case_sensitive
+ SQL_SEARCHABLE, // expected_searchable
+ SQL_FALSE, // expected_unsigned_attr
+ SQL_FALSE, // expected_fixed_prec_scale
+ NULL, // expected_auto_unique_value
+ std::wstring(L"bigint"), // expected_local_type_name
+ NULL, // expected_min_scale
+ NULL, // expected_max_scale
+ SQL_BIGINT, // expected_sql_data_type
+ NULL, // expected_sql_datetime_sub
+ NULL, // expected_num_prec_radix
+ NULL); // expected_interval_prec
+
+ // No more data
+ ASSERT_EQ(SQL_NO_DATA, SQLFetch(this->stmt));
+}
+
+TEST_F(TypeInfoMockTest, TestSQLGetTypeInfoLongVarbinary) {
+ ASSERT_EQ(SQL_SUCCESS, SQLGetTypeInfo(this->stmt, SQL_LONGVARBINARY));
+
+ // Check longvarbinary data type
+ ASSERT_EQ(SQL_SUCCESS, SQLFetch(this->stmt));
+
+ CheckSQLGetTypeInfo(this->stmt,
+ std::wstring(L"longvarbinary"), // expected_type_name
+ SQL_LONGVARBINARY, // expected_data_type
+ 65536, // expected_column_size
+ std::nullopt, //
expected_literal_prefix
+ std::nullopt, //
expected_literal_suffix
+ std::nullopt, //
expected_create_params
+ SQL_NULLABLE, // expected_nullable
+ SQL_FALSE, //
expected_case_sensitive
+ SQL_SEARCHABLE, // expected_searchable
+ NULL, //
expected_unsigned_attr
+ SQL_FALSE, //
expected_fixed_prec_scale
+ NULL, //
expected_auto_unique_value
+ std::wstring(L"longvarbinary"), //
expected_local_type_name
+ NULL, // expected_min_scale
+ NULL, // expected_max_scale
+ SQL_LONGVARBINARY, //
expected_sql_data_type
+ NULL, //
expected_sql_datetime_sub
+ NULL, //
expected_num_prec_radix
+ NULL); //
expected_interval_prec
+
+ // No more data
+ ASSERT_EQ(SQL_NO_DATA, SQLFetch(this->stmt));
+}
+
+TEST_F(TypeInfoMockTest, TestSQLGetTypeInfoVarbinary) {
+ ASSERT_EQ(SQL_SUCCESS, SQLGetTypeInfo(this->stmt, SQL_VARBINARY));
+
+ // Check varbinary data type
+ ASSERT_EQ(SQL_SUCCESS, SQLFetch(this->stmt));
+
+ CheckSQLGetTypeInfo(this->stmt,
+ std::wstring(L"varbinary"), // expected_type_name
+ SQL_VARBINARY, // expected_data_type
+ 255, // expected_column_size
+ std::nullopt, // expected_literal_prefix
+ std::nullopt, // expected_literal_suffix
+ std::nullopt, // expected_create_params
+ SQL_NULLABLE, // expected_nullable
+ SQL_FALSE, // expected_case_sensitive
+ SQL_SEARCHABLE, // expected_searchable
+ NULL, // expected_unsigned_attr
+ SQL_FALSE, // expected_fixed_prec_scale
+ NULL, //
expected_auto_unique_value
+ std::wstring(L"varbinary"), // expected_local_type_name
+ NULL, // expected_min_scale
+ NULL, // expected_max_scale
+ SQL_VARBINARY, // expected_sql_data_type
+ NULL, // expected_sql_datetime_sub
+ NULL, // expected_num_prec_radix
+ NULL); // expected_interval_prec
+
+ // No more data
+ ASSERT_EQ(SQL_NO_DATA, SQLFetch(this->stmt));
+}
+
+TEST_F(TypeInfoMockTest, TestSQLGetTypeInfoLongVarchar) {
+ ASSERT_EQ(SQL_SUCCESS, SQLGetTypeInfo(this->stmt, SQL_WLONGVARCHAR));
+
+ // Check text data type
+ ASSERT_EQ(SQL_SUCCESS, SQLFetch(this->stmt));
+
+ // Driver returns SQL_WLONGVARCHAR since unicode is enabled
+ CheckSQLGetTypeInfo(this->stmt,
+ std::wstring(L"text"), // expected_type_name
+ SQL_WLONGVARCHAR, // expected_data_type
+ 65536, // expected_column_size
+ std::wstring(L"'"), // expected_literal_prefix
+ std::wstring(L"'"), // expected_literal_suffix
+ std::wstring(L"length"), // expected_create_params
+ SQL_NULLABLE, // expected_nullable
+ SQL_FALSE, // expected_case_sensitive
+ SQL_SEARCHABLE, // expected_searchable
+ NULL, // expected_unsigned_attr
+ SQL_FALSE, // expected_fixed_prec_scale
+ NULL, // expected_auto_unique_value
+ std::wstring(L"text"), // expected_local_type_name
+ NULL, // expected_min_scale
+ NULL, // expected_max_scale
+ SQL_WLONGVARCHAR, // expected_sql_data_type
+ NULL, // expected_sql_datetime_sub
+ NULL, // expected_num_prec_radix
+ NULL); // expected_interval_prec
+
+ // Check longvarchar data type
+ ASSERT_EQ(SQL_SUCCESS, SQLFetch(this->stmt));
+
+ CheckSQLGetTypeInfo(this->stmt,
+ std::wstring(L"longvarchar"), // expected_type_name
+ SQL_WLONGVARCHAR, // expected_data_type
+ 65536, // expected_column_size
+ std::wstring(L"'"), // expected_literal_prefix
+ std::wstring(L"'"), // expected_literal_suffix
+ std::wstring(L"length"), // expected_create_params
+ SQL_NULLABLE, // expected_nullable
+ SQL_FALSE, // expected_case_sensitive
+ SQL_SEARCHABLE, // expected_searchable
+ NULL, // expected_unsigned_attr
+ SQL_FALSE, //
expected_fixed_prec_scale
+ NULL, //
expected_auto_unique_value
+ std::wstring(L"longvarchar"), //
expected_local_type_name
+ NULL, // expected_min_scale
+ NULL, // expected_max_scale
+ SQL_WLONGVARCHAR, // expected_sql_data_type
+ NULL, //
expected_sql_datetime_sub
+ NULL, // expected_num_prec_radix
+ NULL); // expected_interval_prec
+
+ // No more data
+ ASSERT_EQ(SQL_NO_DATA, SQLFetch(this->stmt));
+}
+
+TEST_F(TypeInfoMockTest, TestSQLGetTypeInfoChar) {
+ ASSERT_EQ(SQL_SUCCESS, SQLGetTypeInfo(this->stmt, SQL_WCHAR));
+
+ // Check char data type
+ ASSERT_EQ(SQL_SUCCESS, SQLFetch(this->stmt));
+
+ // Driver returns SQL_WCHAR since unicode is enabled
+ CheckSQLGetTypeInfo(this->stmt,
+ std::wstring(L"char"), // expected_type_name
+ SQL_WCHAR, // expected_data_type
+ 255, // expected_column_size
+ std::wstring(L"'"), // expected_literal_prefix
+ std::wstring(L"'"), // expected_literal_suffix
+ std::wstring(L"length"), // expected_create_params
+ SQL_NULLABLE, // expected_nullable
+ SQL_FALSE, // expected_case_sensitive
+ SQL_SEARCHABLE, // expected_searchable
+ NULL, // expected_unsigned_attr
+ SQL_FALSE, // expected_fixed_prec_scale
+ NULL, // expected_auto_unique_value
+ std::wstring(L"char"), // expected_local_type_name
+ NULL, // expected_min_scale
+ NULL, // expected_max_scale
+ SQL_WCHAR, // expected_sql_data_type
+ NULL, // expected_sql_datetime_sub
+ NULL, // expected_num_prec_radix
+ NULL); // expected_interval_prec
+
+ // No more data
+ ASSERT_EQ(SQL_NO_DATA, SQLFetch(this->stmt));
+}
+
+TEST_F(TypeInfoMockTest, TestSQLGetTypeInfoInteger) {
+ ASSERT_EQ(SQL_SUCCESS, SQLGetTypeInfo(this->stmt, SQL_INTEGER));
+
+ // Check integer data type
+ ASSERT_EQ(SQL_SUCCESS, SQLFetch(this->stmt));
+
+ CheckSQLGetTypeInfo(this->stmt,
+ std::wstring(L"integer"), // expected_type_name
+ SQL_INTEGER, // expected_data_type
+ 9, // expected_column_size
+ std::nullopt, // expected_literal_prefix
+ std::nullopt, // expected_literal_suffix
+ std::nullopt, // expected_create_params
+ SQL_NULLABLE, // expected_nullable
+ SQL_FALSE, // expected_case_sensitive
+ SQL_SEARCHABLE, // expected_searchable
+ SQL_FALSE, // expected_unsigned_attr
+ SQL_FALSE, // expected_fixed_prec_scale
+ NULL, // expected_auto_unique_value
+ std::wstring(L"integer"), // expected_local_type_name
+ NULL, // expected_min_scale
+ NULL, // expected_max_scale
+ SQL_INTEGER, // expected_sql_data_type
+ NULL, // expected_sql_datetime_sub
+ NULL, // expected_num_prec_radix
+ NULL); // expected_interval_prec
+
+ // No more data
+ ASSERT_EQ(SQL_NO_DATA, SQLFetch(this->stmt));
+}
+
+TEST_F(TypeInfoMockTest, TestSQLGetTypeInfoSmallInt) {
+ ASSERT_EQ(SQL_SUCCESS, SQLGetTypeInfo(this->stmt, SQL_SMALLINT));
+
+ // Check smallint data type
+ ASSERT_EQ(SQL_SUCCESS, SQLFetch(this->stmt));
+
+ CheckSQLGetTypeInfo(this->stmt,
+ std::wstring(L"smallint"), // expected_type_name
+ SQL_SMALLINT, // expected_data_type
+ 5, // expected_column_size
+ std::nullopt, // expected_literal_prefix
+ std::nullopt, // expected_literal_suffix
+ std::nullopt, // expected_create_params
+ SQL_NULLABLE, // expected_nullable
+ SQL_FALSE, // expected_case_sensitive
+ SQL_SEARCHABLE, // expected_searchable
+ SQL_FALSE, // expected_unsigned_attr
+ SQL_FALSE, // expected_fixed_prec_scale
+ NULL, // expected_auto_unique_value
+ std::wstring(L"smallint"), // expected_local_type_name
+ NULL, // expected_min_scale
+ NULL, // expected_max_scale
+ SQL_SMALLINT, // expected_sql_data_type
+ NULL, // expected_sql_datetime_sub
+ NULL, // expected_num_prec_radix
+ NULL); // expected_interval_prec
+
+ // No more data
+ ASSERT_EQ(SQL_NO_DATA, SQLFetch(this->stmt));
+}
+
+TEST_F(TypeInfoMockTest, TestSQLGetTypeInfoFloat) {
+ ASSERT_EQ(SQL_SUCCESS, SQLGetTypeInfo(this->stmt, SQL_FLOAT));
+
+ // Check float data type
+ ASSERT_EQ(SQL_SUCCESS, SQLFetch(this->stmt));
+
+ CheckSQLGetTypeInfo(this->stmt,
+ std::wstring(L"float"), // expected_type_name
+ SQL_FLOAT, // expected_data_type
+ 7, // expected_column_size
+ std::nullopt, // expected_literal_prefix
+ std::nullopt, // expected_literal_suffix
+ std::nullopt, // expected_create_params
+ SQL_NULLABLE, // expected_nullable
+ SQL_FALSE, // expected_case_sensitive
+ SQL_SEARCHABLE, // expected_searchable
+ SQL_FALSE, // expected_unsigned_attr
+ SQL_FALSE, // expected_fixed_prec_scale
+ NULL, // expected_auto_unique_value
+ std::wstring(L"float"), // expected_local_type_name
+ NULL, // expected_min_scale
+ NULL, // expected_max_scale
+ SQL_FLOAT, // expected_sql_data_type
+ NULL, // expected_sql_datetime_sub
+ NULL, // expected_num_prec_radix
+ NULL); // expected_interval_prec
+
+ // No more data
+ ASSERT_EQ(SQL_NO_DATA, SQLFetch(this->stmt));
+}
+
+TEST_F(TypeInfoMockTest, TestSQLGetTypeInfoDouble) {
+ ASSERT_EQ(SQL_SUCCESS, SQLGetTypeInfo(this->stmt, SQL_DOUBLE));
+
+ // Check double data type
+ ASSERT_EQ(SQL_SUCCESS, SQLFetch(this->stmt));
+
+ CheckSQLGetTypeInfo(this->stmt,
+ std::wstring(L"double"), // expected_type_name
+ SQL_DOUBLE, // expected_data_type
+ 15, // expected_column_size
+ std::nullopt, // expected_literal_prefix
+ std::nullopt, // expected_literal_suffix
+ std::nullopt, // expected_create_params
+ SQL_NULLABLE, // expected_nullable
+ SQL_FALSE, // expected_case_sensitive
+ SQL_SEARCHABLE, // expected_searchable
+ SQL_FALSE, // expected_unsigned_attr
+ SQL_FALSE, // expected_fixed_prec_scale
+ NULL, // expected_auto_unique_value
+ std::wstring(L"double"), // expected_local_type_name
+ NULL, // expected_min_scale
+ NULL, // expected_max_scale
+ SQL_DOUBLE, // expected_sql_data_type
+ NULL, // expected_sql_datetime_sub
+ NULL, // expected_num_prec_radix
+ NULL); // expected_interval_prec
+
+ // Check numeric data type
+ ASSERT_EQ(SQL_SUCCESS, SQLFetch(this->stmt));
+
+ // Mock server treats numeric data type as a double type
+ CheckSQLGetTypeInfo(this->stmt,
+ std::wstring(L"numeric"), // expected_type_name
+ SQL_DOUBLE, // expected_data_type
+ 15, // expected_column_size
+ std::nullopt, // expected_literal_prefix
+ std::nullopt, // expected_literal_suffix
+ std::nullopt, // expected_create_params
+ SQL_NULLABLE, // expected_nullable
+ SQL_FALSE, // expected_case_sensitive
+ SQL_SEARCHABLE, // expected_searchable
+ SQL_FALSE, // expected_unsigned_attr
+ SQL_FALSE, // expected_fixed_prec_scale
+ NULL, // expected_auto_unique_value
+ std::wstring(L"numeric"), // expected_local_type_name
+ NULL, // expected_min_scale
+ NULL, // expected_max_scale
+ SQL_DOUBLE, // expected_sql_data_type
+ NULL, // expected_sql_datetime_sub
+ NULL, // expected_num_prec_radix
+ NULL); // expected_interval_prec
+
+ // No more data
+ ASSERT_EQ(SQL_NO_DATA, SQLFetch(this->stmt));
+}
+
+TEST_F(TypeInfoMockTest, TestSQLGetTypeInfoVarchar) {
+ ASSERT_EQ(SQL_SUCCESS, SQLGetTypeInfo(this->stmt, SQL_WVARCHAR));
+
+ // Check varchar data type
+ ASSERT_EQ(SQL_SUCCESS, SQLFetch(this->stmt));
+
+ // Driver returns SQL_WVARCHAR since unicode is enabled
+ CheckSQLGetTypeInfo(this->stmt,
+ std::wstring(L"varchar"), // expected_type_name
+ SQL_WVARCHAR, // expected_data_type
+ 255, // expected_column_size
+ std::wstring(L"'"), // expected_literal_prefix
+ std::wstring(L"'"), // expected_literal_suffix
+ std::wstring(L"length"), // expected_create_params
+ SQL_NULLABLE, // expected_nullable
+ SQL_FALSE, // expected_case_sensitive
+ SQL_SEARCHABLE, // expected_searchable
+ SQL_FALSE, // expected_unsigned_attr
+ SQL_FALSE, // expected_fixed_prec_scale
+ NULL, // expected_auto_unique_value
+ std::wstring(L"varchar"), // expected_local_type_name
+ NULL, // expected_min_scale
+ NULL, // expected_max_scale
+ SQL_WVARCHAR, // expected_sql_data_type
+ NULL, // expected_sql_datetime_sub
+ NULL, // expected_num_prec_radix
+ NULL); // expected_interval_prec
+
+ // No more data
+ ASSERT_EQ(SQL_NO_DATA, SQLFetch(this->stmt));
+}
+
+TEST_F(TypeInfoMockTest, TestSQLGetTypeInfoSQLTypeDate) {
+ ASSERT_EQ(SQL_SUCCESS, SQLGetTypeInfo(this->stmt, SQL_TYPE_DATE));
+
+ // Check date data type
+ ASSERT_EQ(SQL_SUCCESS, SQLFetch(this->stmt));
+
+ CheckSQLGetTypeInfo(this->stmt,
+ std::wstring(L"date"), // expected_type_name
+ SQL_TYPE_DATE, // expected_data_type
+ 10, // expected_column_size
+ std::wstring(L"'"), // expected_literal_prefix
+ std::wstring(L"'"), // expected_literal_suffix
+ std::nullopt, // expected_create_params
+ SQL_NULLABLE, // expected_nullable
+ SQL_FALSE, // expected_case_sensitive
+ SQL_SEARCHABLE, // expected_searchable
+ SQL_FALSE, // expected_unsigned_attr
+ SQL_FALSE, // expected_fixed_prec_scale
+ NULL, // expected_auto_unique_value
+ std::wstring(L"date"), // expected_local_type_name
+ NULL, // expected_min_scale
+ NULL, // expected_max_scale
+ SQL_DATETIME, // expected_sql_data_type
+ SQL_CODE_DATE, // expected_sql_datetime_sub
+ NULL, // expected_num_prec_radix
+ NULL); // expected_interval_prec
+
+ // No more data
+ ASSERT_EQ(SQL_NO_DATA, SQLFetch(this->stmt));
+}
+
+TEST_F(TypeInfoMockTest, TestSQLGetTypeInfoSQLDate) {
+ // Pass ODBC Ver 2 data type
+ ASSERT_EQ(SQL_SUCCESS, SQLGetTypeInfo(this->stmt, SQL_DATE));
+
+ // Check date data type
+ ASSERT_EQ(SQL_SUCCESS, SQLFetch(this->stmt));
+
+ CheckSQLGetTypeInfo(this->stmt,
+ std::wstring(L"date"), // expected_type_name
+ SQL_TYPE_DATE, // expected_data_type
+ 10, // expected_column_size
+ std::wstring(L"'"), // expected_literal_prefix
+ std::wstring(L"'"), // expected_literal_suffix
+ std::nullopt, // expected_create_params
+ SQL_NULLABLE, // expected_nullable
+ SQL_FALSE, // expected_case_sensitive
+ SQL_SEARCHABLE, // expected_searchable
+ SQL_FALSE, // expected_unsigned_attr
+ SQL_FALSE, // expected_fixed_prec_scale
+ NULL, // expected_auto_unique_value
+ std::wstring(L"date"), // expected_local_type_name
+ NULL, // expected_min_scale
+ NULL, // expected_max_scale
+ SQL_DATETIME, // expected_sql_data_type
+ SQL_CODE_DATE, // expected_sql_datetime_sub
+ NULL, // expected_num_prec_radix
+ NULL); // expected_interval_prec
+
+ // No more data
+ ASSERT_EQ(SQL_NO_DATA, SQLFetch(this->stmt));
+}
+
+TEST_F(TypeInfoOdbcV2MockTest, TestSQLGetTypeInfoDateODBCVer2) {
+ ASSERT_EQ(SQL_SUCCESS, SQLGetTypeInfo(this->stmt, SQL_DATE));
+
+ // Check date data type
+ ASSERT_EQ(SQL_SUCCESS, SQLFetch(this->stmt));
+
+ CheckSQLGetTypeInfo(this->stmt,
+ std::wstring(L"date"), // expected_type_name
+ SQL_DATE, // expected_data_type
+ 10, // expected_column_size
+ std::wstring(L"'"), // expected_literal_prefix
+ std::wstring(L"'"), // expected_literal_suffix
+ std::nullopt, // expected_create_params
+ SQL_NULLABLE, // expected_nullable
+ SQL_FALSE, // expected_case_sensitive
+ SQL_SEARCHABLE, // expected_searchable
+ SQL_FALSE, // expected_unsigned_attr
+ SQL_FALSE, // expected_fixed_prec_scale
+ NULL, // expected_auto_unique_value
+ std::wstring(L"date"), // expected_local_type_name
+ NULL, // expected_min_scale
+ NULL, // expected_max_scale
+ SQL_DATETIME, // expected_sql_data_type
+ NULL, // expected_sql_datetime_sub, driver returns
NULL for Ver2
+ NULL, // expected_num_prec_radix
+ NULL); // expected_interval_prec
+
+ // No more data
+ ASSERT_EQ(SQL_NO_DATA, SQLFetch(this->stmt));
+}
+
+TEST_F(TypeInfoOdbcV2MockTest, TestSQLGetTypeInfoSQLTypeDateODBCVer2) {
+ // Pass ODBC Ver 3 data type
+ ASSERT_EQ(SQL_ERROR, SQLGetTypeInfo(this->stmt, SQL_TYPE_DATE));
+
+ // Driver manager returns SQL data type out of range error state
+ VerifyOdbcErrorState(SQL_HANDLE_STMT, this->stmt, kErrorStateS1004);
+}
+
+TEST_F(TypeInfoMockTest, TestSQLGetTypeInfoSQLTypeTime) {
+ ASSERT_EQ(SQL_SUCCESS, SQLGetTypeInfo(this->stmt, SQL_TYPE_TIME));
+
+ // Check time data type
+ ASSERT_EQ(SQL_SUCCESS, SQLFetch(this->stmt));
+
+ CheckSQLGetTypeInfo(this->stmt,
+ std::wstring(L"time"), // expected_type_name
+ SQL_TYPE_TIME, // expected_data_type
+ 8, // expected_column_size
+ std::wstring(L"'"), // expected_literal_prefix
+ std::wstring(L"'"), // expected_literal_suffix
+ std::nullopt, // expected_create_params
+ SQL_NULLABLE, // expected_nullable
+ SQL_FALSE, // expected_case_sensitive
+ SQL_SEARCHABLE, // expected_searchable
+ SQL_FALSE, // expected_unsigned_attr
+ SQL_FALSE, // expected_fixed_prec_scale
+ NULL, // expected_auto_unique_value
+ std::wstring(L"time"), // expected_local_type_name
+ NULL, // expected_min_scale
+ NULL, // expected_max_scale
+ SQL_DATETIME, // expected_sql_data_type
+ SQL_CODE_TIME, // expected_sql_datetime_sub
+ NULL, // expected_num_prec_radix
+ NULL); // expected_interval_prec
+
+ // No more data
+ ASSERT_EQ(SQL_NO_DATA, SQLFetch(this->stmt));
+}
+
+TEST_F(TypeInfoMockTest, TestSQLGetTypeInfoSQLTime) {
+ // Pass ODBC Ver 2 data type
+ ASSERT_EQ(SQL_SUCCESS, SQLGetTypeInfo(this->stmt, SQL_TIME));
+
+ // Check time data type
+ ASSERT_EQ(SQL_SUCCESS, SQLFetch(this->stmt));
+
+ CheckSQLGetTypeInfo(this->stmt,
+ std::wstring(L"time"), // expected_type_name
+ SQL_TYPE_TIME, // expected_data_type
+ 8, // expected_column_size
+ std::wstring(L"'"), // expected_literal_prefix
+ std::wstring(L"'"), // expected_literal_suffix
+ std::nullopt, // expected_create_params
+ SQL_NULLABLE, // expected_nullable
+ SQL_FALSE, // expected_case_sensitive
+ SQL_SEARCHABLE, // expected_searchable
+ SQL_FALSE, // expected_unsigned_attr
+ SQL_FALSE, // expected_fixed_prec_scale
+ NULL, // expected_auto_unique_value
+ std::wstring(L"time"), // expected_local_type_name
+ NULL, // expected_min_scale
+ NULL, // expected_max_scale
+ SQL_DATETIME, // expected_sql_data_type
+ SQL_CODE_TIME, // expected_sql_datetime_sub
+ NULL, // expected_num_prec_radix
+ NULL); // expected_interval_prec
+
+ // No more data
+ ASSERT_EQ(SQL_NO_DATA, SQLFetch(this->stmt));
+}
+
+TEST_F(TypeInfoOdbcV2MockTest, TestSQLGetTypeInfoTimeODBCVer2) {
+ ASSERT_EQ(SQL_SUCCESS, SQLGetTypeInfo(this->stmt, SQL_TIME));
+
+ // Check time data type
+ ASSERT_EQ(SQL_SUCCESS, SQLFetch(this->stmt));
+
+ CheckSQLGetTypeInfo(this->stmt,
+ std::wstring(L"time"), // expected_type_name
+ SQL_TIME, // expected_data_type
+ 8, // expected_column_size
+ std::wstring(L"'"), // expected_literal_prefix
+ std::wstring(L"'"), // expected_literal_suffix
+ std::nullopt, // expected_create_params
+ SQL_NULLABLE, // expected_nullable
+ SQL_FALSE, // expected_case_sensitive
+ SQL_SEARCHABLE, // expected_searchable
+ SQL_FALSE, // expected_unsigned_attr
+ SQL_FALSE, // expected_fixed_prec_scale
+ NULL, // expected_auto_unique_value
+ std::wstring(L"time"), // expected_local_type_name
+ NULL, // expected_min_scale
+ NULL, // expected_max_scale
+ SQL_DATETIME, // expected_sql_data_type
+ NULL, // expected_sql_datetime_sub, driver returns
NULL for Ver2
+ NULL, // expected_num_prec_radix
+ NULL); // expected_interval_prec
+
+ // No more data
+ ASSERT_EQ(SQL_NO_DATA, SQLFetch(this->stmt));
+}
+
+TEST_F(TypeInfoOdbcV2MockTest, TestSQLGetTypeInfoSQLTypeTimeODBCVer2) {
+ // Pass ODBC Ver 3 data type
+ ASSERT_EQ(SQL_ERROR, SQLGetTypeInfo(this->stmt, SQL_TYPE_TIME));
+
+ // Driver manager returns SQL data type out of range error state
+ VerifyOdbcErrorState(SQL_HANDLE_STMT, this->stmt, kErrorStateS1004);
+}
+
+TEST_F(TypeInfoMockTest, TestSQLGetTypeInfoSQLTypeTimestamp) {
+ ASSERT_EQ(SQL_SUCCESS, SQLGetTypeInfo(this->stmt, SQL_TYPE_TIMESTAMP));
+
+ // Check timestamp data type
+ ASSERT_EQ(SQL_SUCCESS, SQLFetch(this->stmt));
+
+ CheckSQLGetTypeInfo(this->stmt,
+ std::wstring(L"timestamp"), // expected_type_name
+ SQL_TYPE_TIMESTAMP, // expected_data_type
+ 32, // expected_column_size
+ std::wstring(L"'"), // expected_literal_prefix
+ std::wstring(L"'"), // expected_literal_suffix
+ std::nullopt, // expected_create_params
+ SQL_NULLABLE, // expected_nullable
+ SQL_FALSE, // expected_case_sensitive
+ SQL_SEARCHABLE, // expected_searchable
+ SQL_FALSE, // expected_unsigned_attr
+ SQL_FALSE, // expected_fixed_prec_scale
+ NULL, //
expected_auto_unique_value
+ std::wstring(L"timestamp"), // expected_local_type_name
+ NULL, // expected_min_scale
+ NULL, // expected_max_scale
+ SQL_DATETIME, // expected_sql_data_type
+ SQL_CODE_TIMESTAMP, // expected_sql_datetime_sub
+ NULL, // expected_num_prec_radix
+ NULL); // expected_interval_prec
+
+ // No more data
+ ASSERT_EQ(SQL_NO_DATA, SQLFetch(this->stmt));
+}
+
+TEST_F(TypeInfoMockTest, TestSQLGetTypeInfoSQLTimestamp) {
+ // Pass ODBC Ver 2 data type
+ ASSERT_EQ(SQL_SUCCESS, SQLGetTypeInfo(this->stmt, SQL_TIMESTAMP));
+
+ // Check timestamp data type
+ ASSERT_EQ(SQL_SUCCESS, SQLFetch(this->stmt));
+
+ CheckSQLGetTypeInfo(this->stmt,
+ std::wstring(L"timestamp"), // expected_type_name
+ SQL_TYPE_TIMESTAMP, // expected_data_type
+ 32, // expected_column_size
+ std::wstring(L"'"), // expected_literal_prefix
+ std::wstring(L"'"), // expected_literal_suffix
+ std::nullopt, // expected_create_params
+ SQL_NULLABLE, // expected_nullable
+ SQL_FALSE, // expected_case_sensitive
+ SQL_SEARCHABLE, // expected_searchable
+ SQL_FALSE, // expected_unsigned_attr
+ SQL_FALSE, // expected_fixed_prec_scale
+ NULL, //
expected_auto_unique_value
+ std::wstring(L"timestamp"), // expected_local_type_name
+ NULL, // expected_min_scale
+ NULL, // expected_max_scale
+ SQL_DATETIME, // expected_sql_data_type
+ SQL_CODE_TIMESTAMP, // expected_sql_datetime_sub
+ NULL, // expected_num_prec_radix
+ NULL); // expected_interval_prec
+
+ // No more data
+ ASSERT_EQ(SQL_NO_DATA, SQLFetch(this->stmt));
+}
+
+TEST_F(TypeInfoOdbcV2MockTest, TestSQLGetTypeInfoSQLTimestampODBCVer2) {
+ ASSERT_EQ(SQL_SUCCESS, SQLGetTypeInfo(this->stmt, SQL_TIMESTAMP));
+
+ // Check timestamp data type
+ ASSERT_EQ(SQL_SUCCESS, SQLFetch(this->stmt));
+
+ CheckSQLGetTypeInfo(this->stmt,
+ std::wstring(L"timestamp"), // expected_type_name
+ SQL_TIMESTAMP, // expected_data_type
+ 32, // expected_column_size
+ std::wstring(L"'"), // expected_literal_prefix
+ std::wstring(L"'"), // expected_literal_suffix
+ std::nullopt, // expected_create_params
+ SQL_NULLABLE, // expected_nullable
+ SQL_FALSE, // expected_case_sensitive
+ SQL_SEARCHABLE, // expected_searchable
+ SQL_FALSE, // expected_unsigned_attr
+ SQL_FALSE, // expected_fixed_prec_scale
+ NULL, //
expected_auto_unique_value
+ std::wstring(L"timestamp"), // expected_local_type_name
+ NULL, // expected_min_scale
+ NULL, // expected_max_scale
+ SQL_DATETIME, // expected_sql_data_type
+ NULL, // expected_sql_datetime_sub, driver returns
NULL for Ver2
+ NULL, // expected_num_prec_radix
+ NULL); // expected_interval_prec
+
+ // No more data
+ ASSERT_EQ(SQL_NO_DATA, SQLFetch(this->stmt));
+}
+
+TEST_F(TypeInfoOdbcV2MockTest, TestSQLGetTypeInfoSQLTypeTimestampODBCVer2) {
+ // Pass ODBC Ver 3 data type
+ ASSERT_EQ(SQL_ERROR, SQLGetTypeInfo(this->stmt, SQL_TYPE_TIMESTAMP));
+
+ // Driver manager returns SQL data type out of range error state
+ VerifyOdbcErrorState(SQL_HANDLE_STMT, this->stmt, kErrorStateS1004);
+}
+
+TEST_F(TypeInfoMockTest, TestSQLGetTypeInfoInvalidDataType) {
+ SQLSMALLINT invalid_data_type = -114;
+ ASSERT_EQ(SQL_ERROR, SQLGetTypeInfo(this->stmt, invalid_data_type));
+ VerifyOdbcErrorState(SQL_HANDLE_STMT, this->stmt, kErrorStateHY004);
+}
+
+TYPED_TEST(TypeInfoTest, TestSQLGetTypeInfoUnsupportedDataType) {
+ // Assumes mock and remote server don't support GUID data type
+
+ ASSERT_EQ(SQL_SUCCESS, SQLGetTypeInfo(this->stmt, SQL_GUID));
+
+ // Result set is empty with valid data type that is unsupported by the server
+ ASSERT_EQ(SQL_NO_DATA, SQLFetch(this->stmt));
+}
+
+} // namespace arrow::flight::sql::odbc