@@ -85,6 +85,8 @@ History: PJN / 24-09-2011 1. Initial creation
85
85
PJN / 12-05-2023 1. Updated copyright details
86
86
2. Updated modules to indicate that it needs to be compiled using /std:c++17. Thanks to Martin Richter
87
87
for reporting this issue.
88
+ PJN / 15-12-2023 1. Updated module to remove usage of _if_exists by now using ODBCVER and _ATL_MODULES
89
+ preprocessor macro checks along with SFINAE.
88
90
89
91
Copyright (c) 2011 - 2023 by PJ Naughter (Web: www.naughter.com, Email: [email protected] )
90
92
@@ -107,7 +109,7 @@ to maintain a single distribution point for the source code.
107
109
108
110
#if _MSVC_LANG < 201703
109
111
#error ODBCWrappers requires a minimum C++ language standard of /std:c++17
110
- #endif // #if __cplusplus < 201703
112
+ #endif // #if _MSVC_LANG < 201703
111
113
112
114
#ifndef __ODBCWRAPPERS_H__
113
115
#define __ODBCWRAPPERS_H__
@@ -539,7 +541,7 @@ namespace CODBC
539
541
}
540
542
}
541
543
542
- _NODISCARD operator SQLHANDLE () const noexcept
544
+ [[nodiscard]] operator SQLHANDLE () const noexcept
543
545
{
544
546
return m_h;
545
547
}
@@ -581,7 +583,7 @@ namespace CODBC
581
583
return SQLGetDiagRec (m_Type, m_h, iRecord, szSqlState, pfNativeError, szErrorMsg, cchErrorMsgMax, pcchErrorMsg);
582
584
}
583
585
584
- void GetDiagRecords (_Out_ std::vector<String>& records)
586
+ void GetDiagRecords (_Out_ std::vector<String>& records) const
585
587
{
586
588
// clear the vector
587
589
records.clear ();
@@ -609,29 +611,27 @@ namespace CODBC
609
611
}
610
612
}
611
613
612
- __if_exists (SQLCompleteAsync)
614
+ #if (ODBCVER >= 0x0380)
615
+ SQLRETURN CancelHandle () noexcept
613
616
{
614
- SQLRETURN CancelHandle () noexcept
615
- {
616
- // Validate our parameters
617
+ // Validate our parameters
617
618
#pragma warning(suppress: 26477)
618
- ATLASSERT (m_h != SQL_NULL_HANDLE);
619
+ ATLASSERT (m_h != SQL_NULL_HANDLE);
619
620
620
- return SQLCancelHandle (m_Type, m_h);
621
- }
622
- } // __if_exists(SQLCompleteAsync )
621
+ return SQLCancelHandle (m_Type, m_h);
622
+ }
623
+ # endif // #if (ODBCVER >= 0x0380 )
623
624
624
- __if_exists (SQLCompleteAsync)
625
+ #if (ODBCVER >= 0x0380)
626
+ SQLRETURN CompleteAsync (_Out_ RETCODE* AsyncRetCodePtr) noexcept
625
627
{
626
- SQLRETURN CompleteAsync (_Out_ RETCODE* AsyncRetCodePtr) noexcept
627
- {
628
- // Validate our parameters
628
+ // Validate our parameters
629
629
#pragma warning(suppress: 26477)
630
- ATLASSERT (m_h != SQL_NULL_HANDLE);
630
+ ATLASSERT (m_h != SQL_NULL_HANDLE);
631
631
632
- return SQLCompleteAsync (m_Type, m_h, AsyncRetCodePtr);
633
- }
634
- } // __if_exists(SQLCompleteAsync )
632
+ return SQLCompleteAsync (m_Type, m_h, AsyncRetCodePtr);
633
+ }
634
+ # endif // #if (ODBCVER >= 0x0380 )
635
635
636
636
#pragma warning(suppress: 26440)
637
637
void ValidateReturnValue (_In_ SQLRETURN nRet) const
@@ -1883,7 +1883,56 @@ namespace CODBC
1883
1883
};
1884
1884
1885
1885
1886
- // The base class which accessor classes derive from. T is the class that contains the data that will be accessed
1886
+ #ifdef _ATL_MODULES
1887
+
1888
+ template <typename , typename T>
1889
+ struct _Has_GetBindParametersEntries
1890
+ {
1891
+ static_assert (std::integral_constant<T, false >::value, " Second template parameter needs to be of function type." );
1892
+ };
1893
+
1894
+ template <typename C, typename Ret, typename ... Args>
1895
+ struct _Has_GetBindParametersEntries <C, Ret(Args...)>
1896
+ {
1897
+ private:
1898
+ template <typename T>
1899
+ static constexpr auto check (T*) -> typename std::is_same<decltype(std::declval<T>()._GetBindParametersEntries(std::declval<Args>()...)), Ret>::type;
1900
+
1901
+ template <typename >
1902
+ static constexpr std::false_type check (...);
1903
+
1904
+ using type = decltype(check<C>(nullptr ));
1905
+
1906
+ public:
1907
+ static constexpr bool value = type::value;
1908
+ };
1909
+
1910
+ template <typename , typename T>
1911
+ struct _Has_GetBindColumnEntries
1912
+ {
1913
+ static_assert (std::integral_constant<T, false >::value, " Second template parameter needs to be of function type." );
1914
+ };
1915
+
1916
+ template <typename C, typename Ret, typename ... Args>
1917
+ struct _Has_GetBindColumnEntries <C, Ret(Args...)>
1918
+ {
1919
+ private:
1920
+ template <typename T>
1921
+ static constexpr auto check (T*) -> typename std::is_same<decltype(std::declval<T>()._GetBindColumnEntries(std::declval<Args>()...)), Ret>::type;
1922
+
1923
+ template <typename >
1924
+ static constexpr std::false_type check (...);
1925
+
1926
+ using type = decltype(check<C>(nullptr ));
1927
+
1928
+ public:
1929
+ static constexpr bool value = type::value;
1930
+ };
1931
+
1932
+ #endif // #ifdef _ATL_MODULES
1933
+
1934
+
1935
+ // The base class which accessor classes derive from. T is the class that contains the data that will be accessed.
1887
1936
template <class T >
1888
1937
class CAccessor : public T
1889
1938
{
@@ -1898,7 +1947,11 @@ namespace CODBC
1898
1947
#pragma warning(suppress: 26496)
1899
1948
SQLRETURN nRet{ SQL_SUCCESS };
1900
1949
1950
+ #ifdef _ATL_MODULES
1951
+ if constexpr (_Has_GetBindColumnEntries<T, SQLRETURN (const CODBC::CStatement*, int *, std::vector<SQLLEN>*)>::value)
1952
+ #else
1901
1953
__if_exists (T::_GetBindColumnEntries)
1954
+ #endif // #ifdef _ATL_MODULES
1902
1955
{
1903
1956
// Work out the number of bound columns we have
1904
1957
int nColumns{ 0 };
@@ -1916,15 +1969,19 @@ namespace CODBC
1916
1969
return nRet;
1917
1970
}
1918
1971
1919
- #pragma warning(suppress: 26434)
1972
+ #pragma warning(suppress: 26434 26440 26460 )
1920
1973
SQLRETURN BindParameters (_In_ CStatement& statement)
1921
1974
{
1922
1975
UNREFERENCED_PARAMETER (statement);
1923
1976
1924
1977
// What will be the return value from this method
1925
1978
SQLRETURN nRet{ SQL_SUCCESS };
1926
1979
1980
+ #ifdef _ATL_MODULES
1981
+ if constexpr (_Has_GetBindParametersEntries<T, SQLRETURN (CODBC::CStatement*, int *, std::vector<SQLLEN>*)>::value)
1982
+ #else
1927
1983
__if_exists (T::_GetBindParametersEntries)
1984
+ #endif // #ifdef _ATL_MODULES
1928
1985
{
1929
1986
// Work out the number of bound parameters we have
1930
1987
int nColumns{ 0 };
@@ -2136,32 +2193,32 @@ namespace CODBC
2136
2193
return nRet;
2137
2194
}
2138
2195
2139
- _NODISCARD String GetColumnName (_In_ SQLSMALLINT nColumn) const
2196
+ [[nodiscard]] String GetColumnName (_In_ SQLSMALLINT nColumn) const
2140
2197
{
2141
2198
return this ->m_ColumnNames [nColumn - 1 ]; // nColumn is 1 based
2142
2199
}
2143
2200
2144
- _NODISCARD SQLSMALLINT GetColumnType (_In_ SQLSMALLINT nColumn) const
2201
+ [[nodiscard]] SQLSMALLINT GetColumnType (_In_ SQLSMALLINT nColumn) const
2145
2202
{
2146
2203
return this ->m_ColumnDataTypes [nColumn - 1 ]; // nColumn is 1 based
2147
2204
}
2148
2205
2149
- _NODISCARD SQLULEN GetColumnSize (_In_ SQLSMALLINT nColumn) const
2206
+ [[nodiscard]] SQLULEN GetColumnSize (_In_ SQLSMALLINT nColumn) const
2150
2207
{
2151
2208
return this ->m_ColumnSizes [nColumn - 1 ]; // nColumn is 1 based
2152
2209
}
2153
2210
2154
- _NODISCARD SQLSMALLINT GetColumnDecimalDigits (_In_ SQLSMALLINT nColumn) const
2211
+ [[nodiscard]] SQLSMALLINT GetColumnDecimalDigits (_In_ SQLSMALLINT nColumn) const
2155
2212
{
2156
2213
return this ->m_ColumnDecimalDigits [nColumn - 1 ]; // nColumn is 1 based
2157
2214
}
2158
2215
2159
- _NODISCARD SQLSMALLINT GetColumnNullables (_In_ SQLSMALLINT nColumn) const
2216
+ [[nodiscard]] SQLSMALLINT GetColumnNullables (_In_ SQLSMALLINT nColumn) const
2160
2217
{
2161
2218
return this ->m_ColumnNullables [nColumn - 1 ]; // nColumn is 1 based
2162
2219
}
2163
2220
2164
- _NODISCARD SQLSMALLINT GetColumnNo (_In_z_ LPCTSTR pszColumnName) const
2221
+ [[nodiscard]] SQLSMALLINT GetColumnNo (_In_z_ LPCTSTR pszColumnName) const
2165
2222
{
2166
2223
#pragma warning(suppress: 26489)
2167
2224
const auto iter{ std::find_if (this ->m_ColumnNames .begin (), this ->m_ColumnNames .end (), [pszColumnName](const String& element)
0 commit comments