Skip to content

Commit 70cbce0

Browse files
committed
cadcorp: Improve mapping of SQL integer types to C corresponding types
Porting nanodbc#370 Fine-grained mapping of SQL integer types to C corresponding types Add reading of missing C data types for integers Distinguish SQL_C_BIT data type for reading Prefer mapping of SQL_C_* types to fixed-width integer types Ensure SQL_C_SHORT and SQL_C_LONG are mapped to fixed-width variant types test: Catch up with improved integer types mapping Refine reading of SQL_C_TINYINT into int8_t instead of int16_t The int16_t may lead to numeric garbage for values at range boundaries. tests: Refine SQLite tests for integer types Fix size of output value read for SQL_C_BIT data
1 parent 9139ae0 commit 70cbce0

File tree

3 files changed

+49
-13
lines changed

3 files changed

+49
-13
lines changed

nanodbc/nanodbc.cpp

Lines changed: 45 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -614,6 +614,14 @@ struct sql_ctype
614614
{
615615
};
616616

617+
template <typename T>
618+
struct sql_ctype<
619+
T,
620+
typename std::enable_if<is_integral8<T>::value && std::is_signed<T>::value>::type>
621+
{
622+
static const SQLSMALLINT value = SQL_C_STINYINT;
623+
};
624+
617625
template <>
618626
struct sql_ctype<uint8_t>
619627
{
@@ -3814,9 +3822,21 @@ class result::result_impl
38143822
switch (col.sqltype_)
38153823
{
38163824
case SQL_BIT:
3825+
col.ctype_ = SQL_C_BIT;
3826+
col.clen_ = sizeof(int8_t);
3827+
break;
38173828
case SQL_TINYINT:
3829+
col.ctype_ = SQL_C_STINYINT;
3830+
col.clen_ = sizeof(int8_t);
3831+
break;
38183832
case SQL_SMALLINT:
3819-
case SQL_INTEGER:
3833+
col.ctype_ = SQL_C_SSHORT;
3834+
col.clen_ = sizeof(int16_t);
3835+
break;
3836+
case SQL_INTEGER: // TODO: Can be 32 or 64 bit? Then sizeof(SQLINTEGER)
3837+
col.ctype_ = SQL_C_SLONG;
3838+
col.clen_ = sizeof(int32_t);
3839+
break;
38203840
case SQL_BIGINT:
38213841
col.ctype_ = SQL_C_SBIGINT;
38223842
col.clen_ = sizeof(int64_t);
@@ -4159,6 +4179,7 @@ inline void result::result_impl::get_ref_impl(short column, T& result) const
41594179
}
41604180

41614181
case SQL_C_LONG:
4182+
case SQL_C_SLONG:
41624183
{
41634184
std::string buffer(column_size + 1, 0); // ensure terminating null
41644185
const int32_t data = *ensure_pdata<int32_t>(column);
@@ -4402,7 +4423,7 @@ inline void result::result_impl::get_ref_impl<_variant_t>(short column, _variant
44024423
}
44034424
case SQL_C_BIT:
44044425
{
4405-
auto const v = *(ensure_pdata<short>(column));
4426+
auto const v = *(ensure_pdata<int8_t>(column));
44064427
result = _variant_t(!!v ? VARIANT_TRUE : VARIANT_FALSE, VT_BOOL);
44074428
break;
44084429
}
@@ -4422,22 +4443,28 @@ inline void result::result_impl::get_ref_impl<_variant_t>(short column, _variant
44224443
}
44234444
case SQL_C_TINYINT:
44244445
case SQL_C_STINYINT:
4425-
result = (char)*(ensure_pdata<short>(column));
4446+
result = (char)*(ensure_pdata<int16_t>(column));
44264447
break;
44274448
case SQL_C_UTINYINT:
4428-
result = (unsigned char)*(ensure_pdata<unsigned short>(column));
4449+
result = (unsigned char)*(ensure_pdata<uint16_t>(column));
44294450
break;
44304451
case SQL_C_SHORT:
44314452
case SQL_C_SSHORT:
4432-
result = *(ensure_pdata<short>(column));
4453+
{
4454+
auto d = *(ensure_pdata<int16_t>(column));
4455+
result = _variant_t(d, VT_I2);
44334456
break;
4457+
}
44344458
case SQL_C_USHORT:
4435-
result = *(ensure_pdata<unsigned short>(column));
4459+
result = *(ensure_pdata<uint16_t>(column));
44364460
break;
44374461
case SQL_C_LONG:
44384462
case SQL_C_SLONG:
4439-
result = *(ensure_pdata<int32_t>(column));
4463+
{
4464+
long d = *(ensure_pdata<int32_t>(column));
4465+
result = _variant_t(d, VT_I4); // avoid VT_INT
44404466
break;
4467+
}
44414468
case SQL_C_ULONG:
44424469
result = *(ensure_pdata<uint32_t>(column));
44434470
break;
@@ -4666,15 +4693,24 @@ void result::result_impl::get_ref_impl(short column, T& result) const
46664693
using namespace std; // if int64_t is in std namespace (in c++11)
46674694
switch (col.ctype_)
46684695
{
4696+
case SQL_C_BIT:
4697+
result = (T) * (ensure_pdata<int8_t>(column));
4698+
return;
46694699
case SQL_C_CHAR:
46704700
case SQL_C_WCHAR:
46714701
get_ref_from_string_column(column, result);
46724702
return;
4703+
case SQL_C_TINYINT:
4704+
case SQL_C_STINYINT:
4705+
result = (T) * (ensure_pdata<int8_t>(column));
4706+
return;
4707+
case SQL_C_SHORT:
46734708
case SQL_C_SSHORT:
4674-
result = (T) * (ensure_pdata<short>(column));
4709+
result = (T) * (ensure_pdata<int16_t>(column));
46754710
return;
4711+
case SQL_C_UTINYINT:
46764712
case SQL_C_USHORT:
4677-
result = (T) * (ensure_pdata<unsigned short>(column));
4713+
result = (T) * (ensure_pdata<uint16_t>(column));
46784714
return;
46794715
case SQL_C_LONG:
46804716
case SQL_C_SLONG:

test/sqlite_test.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -296,7 +296,7 @@ TEST_CASE_METHOD(sqlite_fixture, "test_integral_boundary", "[sqlite][integral]")
296296
execute(
297297
connection,
298298
NANODBC_TEXT(
299-
"create table test_integral_boundary(i1 integer,i2 integer,i4 integer,i8 integer);"));
299+
"create table test_integral_boundary(i1 tinyint,i2 smallint,i4 integer,i8 bigint);"));
300300

301301
auto const sql =
302302
NANODBC_TEXT("insert into test_integral_boundary(i1,i2,i4,i8) values (?,?,?,?);");

test/test_case_fixture.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -866,12 +866,12 @@ struct test_case_fixture : public base_test_fixture
866866
REQUIRE(result.column_datatype(0) == SQL_INTEGER);
867867
if (vendor_ == database_vendor::sqlserver)
868868
{
869-
REQUIRE(result.column_c_datatype(0) == SQL_C_SBIGINT);
869+
REQUIRE(result.column_c_datatype(0) == SQL_C_SLONG);
870870
}
871871
else if (vendor_ == database_vendor::sqlite)
872872
{
873873
REQUIRE(result.column_datatype_name(0) == NANODBC_TEXT("int"));
874-
REQUIRE(result.column_c_datatype(0) == SQL_C_SBIGINT);
874+
REQUIRE(result.column_c_datatype(0) == SQL_C_SLONG);
875875
}
876876
REQUIRE(result.column_size(0) == 10);
877877
REQUIRE(result.column_decimal_digits(0) == 0);
@@ -2140,7 +2140,7 @@ struct test_case_fixture : public base_test_fixture
21402140
rs.next();
21412141
{
21422142
auto v = rs.get<_variant_t>(0);
2143-
REQUIRE(v.vt == VT_I8);
2143+
REQUIRE(v.vt == VT_I4);
21442144
REQUIRE(static_cast<int>(v) == i);
21452145
}
21462146
{

0 commit comments

Comments
 (0)