nanodbc
A small C++ wrapper for the native C ODBC API
Loading...
Searching...
No Matches
nanodbc.h
Go to the documentation of this file.
1
2
76
77#ifndef NANODBC_NANODBC_H
78#define NANODBC_NANODBC_H
79
80#include <any>
81#include <cstddef>
82#include <cstdint>
83#include <exception>
84#include <functional>
85#include <iterator>
86#include <list>
87#include <memory>
88#include <optional>
89#include <stdexcept>
90#include <string>
91#include <string_view>
92#include <type_traits>
93#include <utility>
94#include <variant>
95#include <vector>
96
97// nanodbc requires C++17, so these always hold. They are still defined, so that code
98// written against an earlier release and asking whether the feature is there keeps
99// compiling; new code has no reason to ask.
100#define NANODBC_HAS_STD_STRING_VIEW
101#define NANODBC_HAS_STD_OPTIONAL
102#define NANODBC_HAS_STD_VARIANT
103#define NANODBC_HAS_STD_ANY
104
111namespace nanodbc
112{
113
114// clang-format off
115// .d8888b. .d888 d8b 888 d8b
116// d88P Y88b d88P" Y8P 888 Y8P
117// 888 888 888 888
118// 888 .d88b. 88888b. 888888 888 .d88b. 888 888 888d888 8888b. 888888 888 .d88b. 88888b.
119// 888 d88""88b 888 "88b 888 888 d88P"88b 888 888 888P" "88b 888 888 d88""88b 888 "88b
120// 888 888 888 888 888 888 888 888 888 888 888 888 888 .d888888 888 888 888 888 888 888
121// Y88b d88P Y88..88P 888 888 888 888 Y88b 888 Y88b 888 888 888 888 Y88b. 888 Y88..88P 888 888
122// "Y8888P" "Y88P" 888 888 888 888 "Y88888 "Y88888 888 "Y888888 "Y888 888 "Y88P" 888 888
123// 888
124// Y8b d88P
125// "Y88P"
126// MARK: Configuration -
127// clang-format on
128
133#ifdef DOXYGEN
134
140#define NANODBC_THROW_NO_SOURCE_LOCATION 1
141
156#define NANODBC_ASSERT(expression) assert(expression)
157
158#endif
160
161// You must explicitly request Unicode support by defining NANODBC_ENABLE_UNICODE at compile time.
162// NANODBC_ENABLE_UTF8 keeps string narrow, holding UTF-8, and calls the wide ODBC functions.
163#if defined(NANODBC_ENABLE_UNICODE) && defined(NANODBC_ENABLE_UTF8)
164#error "NANODBC_ENABLE_UNICODE and NANODBC_ENABLE_UTF8 are alternatives; define one"
165#endif
166#ifndef DOXYGEN
167#ifdef NANODBC_ENABLE_UNICODE
168#ifdef NANODBC_USE_IODBC_WIDE_STRINGS
169#define NANODBC_TEXT(s) U##s
170using string = std::u32string;
171using string_view = std::u32string_view;
172#else
173#ifdef _MSC_VER
174using string = std::wstring;
175using string_view = std::wstring_view;
176#define NANODBC_TEXT(s) L##s
177#else
178using string = std::u16string;
179using string_view = std::u16string_view;
180#define NANODBC_TEXT(s) u##s
181#endif
182#endif
183#else
184using string = std::string;
185using string_view = std::string_view;
186#define NANODBC_TEXT(s) s
187#endif
188
189#ifdef NANODBC_USE_IODBC_WIDE_STRINGS
190using wide_string = std::u32string;
191using wide_string_view = std::u32string_view;
192#else
193#ifdef _MSC_VER
194using wide_string = std::wstring;
195using wide_string_view = std::wstring_view;
196#else
197using wide_string = std::u16string;
198using wide_string_view = std::u16string_view;
199#endif
200#endif
201
202using wide_char_t = wide_string::value_type;
203
204#if defined(_WIN64)
205// LLP64 machine: Windows
206using null_type = std::int64_t;
207#elif !defined(_WIN64) && defined(__LP64__)
208// LP64 machine: OS X or Linux
209using null_type = long;
210#else
211// 32-bit machine
212using null_type = long;
213#endif
214#else
224#define NANODBC_TEXT(s) s
225
230typedef unspecified - type string;
232typedef unspecified - type null_type;
233#endif
234
237#define NANODBC_DEPRECATED [[deprecated]]
238
239// forward declare
240#ifndef NANODBC_DISABLE_MSSQL_TVP
241class table_valued_parameter;
242#endif
243class statement;
244class connection;
245class transaction;
246class catalog;
247class result;
248
249// clang-format off
250// 8888888888 888 888 888 888 d8b
251// 888 888 888 888 888 Y8P
252// 888 888 888 888 888
253// 8888888 888d888 888d888 .d88b. 888d888 8888888888 8888b. 88888b. .d88888 888 888 88888b. .d88b.
254// 888 888P" 888P" d88""88b 888P" 888 888 "88b 888 "88b d88" 888 888 888 888 "88b d88P"88b
255// 888 888 888 888 888 888 888 888 .d888888 888 888 888 888 888 888 888 888 888 888
256// 888 888 888 Y88..88P 888 888 888 888 888 888 888 Y88b 888 888 888 888 888 Y88b 888
257// 8888888888 888 888 "Y88P" 888 888 888 "Y888888 888 888 "Y88888 888 888 888 888 "Y88888
258// 888
259// Y8b d88P
260// "Y88P"
261// MARK: Error Handling -
262// clang-format on
263
273
276class type_incompatible_error : public std::runtime_error
277{
278public:
280
282 char const* what() const noexcept override;
283};
284
287class null_access_error : public std::runtime_error
288{
289public:
291
293 char const* what() const noexcept override;
294};
295
298class index_range_error : public std::runtime_error
299{
300public:
302
304 char const* what() const noexcept override;
305};
306
309class programming_error : public std::runtime_error
310{
311public:
314 explicit programming_error(std::string const& info);
315
317 char const* what() const noexcept override;
318};
319
322class database_error : public std::runtime_error
323{
324public:
329 database_error(void* handle, short handle_type, std::string const& info = "");
330
332 char const* what() const noexcept override;
333
335 long native() const noexcept;
336
338 std::string const& state() const noexcept;
339
340private:
341 long native_error;
342 std::string sql_state;
343 std::string message;
344};
345
347
348// clang-format off
349// 888 888 888 d8b 888 d8b 888 d8b
350// 888 888 888 Y8P 888 Y8P 888 Y8P
351// 888 888 888 888 888
352// 888 888 888888 888 888 888 888888 888 .d88b. .d8888b
353// 888 888 888 888 888 888 888 888 d8P Y8b 88K
354// 888 888 888 888 888 888 888 888 88888888 "Y8888b.
355// Y88b. .d88P Y88b. 888 888 888 Y88b. 888 Y8b. X88
356// "Y88888P" "Y888 888 888 888 "Y888 888 "Y8888 88888P'
357// MARK: Utilities -
358// clang-format on
359
364
368{
369 long parameter_array_length{-1};
370 long rowset_size{-1};
371
373 batch_ops() = default;
374
377 batch_ops(const long all_length) noexcept
378 : parameter_array_length(all_length)
379 , rowset_size(all_length) {};
380};
381
383struct date
384{
385 std::int16_t year;
386 std::int16_t month;
387 std::int16_t day;
388};
389
391struct time
392{
393 std::int16_t hour;
394 std::int16_t min;
395 std::int16_t sec;
396};
397
400{
401 std::int16_t year;
402 std::int16_t month;
403 std::int16_t day;
404 std::int16_t hour;
405 std::int16_t min;
406 std::int16_t sec;
407 std::int32_t fract;
408};
409
412{
414 std::int16_t offset_hour;
415 std::int16_t offset_minute;
416};
417
422// `SQLSetConnectAttr`, or `SQLSetStmtAttr`. The second is the StringLength,
423// and the third is used to inform the ValuePtr argument. This argument,
430{
431public:
432#ifdef NANODBC_ENABLE_UNICODE
433 using variant =
434 std::variant<std::vector<uint8_t>, string, std::string, std::intptr_t, std::uintptr_t>;
435#else
436 using variant = std::variant<std::vector<uint8_t>, string, std::intptr_t, std::uintptr_t>;
437#endif
438 attribute() = delete;
439 attribute& operator=(attribute const&) = delete;
440
442 attribute(attribute const& other) noexcept;
443
448 attribute(long const& attribute, long const& string_length, variant resource) noexcept;
449
450protected:
455 void extractValuePtr() noexcept;
456
457 long attribute_;
458 long string_length_;
459 variant resource_;
460 void* value_ptr_{};
461};
462
465template <typename T>
466using is_string = std::bool_constant<
467 std::is_same_v<std::decay_t<T>, std::string> || std::is_same_v<std::decay_t<T>, wide_string> ||
468 std::is_same_v<std::decay_t<T>, std::string_view> ||
469 std::is_same_v<std::decay_t<T>, wide_string_view>>;
470
472template <typename T>
473inline constexpr bool is_string_v = is_string<T>::value;
474
479template <typename T>
480using is_owning_string = std::bool_constant<
481 std::is_same_v<std::decay_t<T>, std::string> || std::is_same_v<std::decay_t<T>, wide_string>>;
482
484template <typename T>
486
489template <typename T>
490using is_character = std::bool_constant<
491 std::is_same_v<std::decay_t<T>, std::string::value_type> ||
492 std::is_same_v<std::decay_t<T>, wide_char_t>>;
493
495template <typename T>
497
499template <typename T>
500using enable_if_string = std::enable_if_t<is_string_v<T>>;
501
503template <typename T>
504using enable_if_character = std::enable_if_t<is_character_v<T>>;
505
506namespace detail
507{
508
517template <class T>
518std::unique_ptr<bool[]>
519split_optional(std::vector<std::optional<T>> const& values, std::vector<T>& column)
520{
521 auto nulls = std::make_unique<bool[]>(values.size());
522 column.reserve(values.size());
523 std::size_t i = 0;
524 for (auto const& value : values)
525 {
526 nulls[i++] = !value.has_value();
527 column.push_back(value ? *value : T());
528 }
529 return nulls;
530}
531
532} // namespace detail
533
535
540
541// clang-format off
542// 88888888888 888 d8b
543// 888 888 Y8P
544// 888 888
545// 888 888d888 8888b. 88888b. .d8888b 8888b. .d8888b 888888 888 .d88b. 88888b.
546// 888 888P" "88b 888 "88b 88K "88b d88P" 888 888 d88""88b 888 "88b
547// 888 888 .d888888 888 888 "Y8888b. .d888888 888 888 888 888 888 888 888
548// 888 888 888 888 888 888 X88 888 888 Y88b. Y88b. 888 Y88..88P 888 888
549// 888 888 "Y888888 888 888 88888P' "Y888888 "Y8888P "Y888 888 "Y88P" 888 888
550// MARK: Transaction -
551// clang-format on
552
560{
561public:
565 explicit transaction(const class connection& conn);
566
568 void swap(transaction& rhs) noexcept;
569
572 void commit();
573
575 void rollback() noexcept;
576
578 class connection& connection() noexcept;
579
581 const class connection& connection() const noexcept;
582
584 operator class connection &() noexcept;
585
587 operator const class connection &() const noexcept;
588
589private:
590 class transaction_impl;
591 friend class nanodbc::connection;
592
593private:
594 std::shared_ptr<transaction_impl> impl_;
595};
596
597// clang-format off
598// 888b d888 .d8888b. .d8888b. .d88888b. 888 88888888888 888 888 8888888b.
599// 8888b d8888 d88P Y88b d88P Y88b d88P" "Y88b 888 888 888 888 888 Y88b
600// 88888b.d88888 Y88b. Y88b. 888 888 888 888 888 888 888 888
601// 888Y88888P888 "Y888b. "Y888b. 888 888 888 888 Y88b d88P 888 d88P
602// 888 Y888P 888 "Y88b. "Y88b. 888 888 888 888 Y88b d88P 8888888P"
603// 888 Y8P 888 "888 "888 888 Y8b 888 888 888888 888 Y88o88P 888
604// 888 " 888 Y88b d88P Y88b d88P Y88b.Y8b88P 888 888 Y888P 888
605// 888 888 "Y8888P" "Y8888P" "Y888888" 88888888 888 Y8P 888
606// Y8b
607// MARK: MSSQL - TVP (Table Valued Parameters) -
608// clang-format on
609#ifndef NANODBC_DISABLE_MSSQL_TVP
612{
613public:
616
619 void operator=(const table_valued_parameter&) = delete;
620 void operator=(table_valued_parameter&&) = delete;
621
624 table_valued_parameter(statement& stmt, short param_index, size_t row_count);
625
635 void open(statement& stmt, short param_index, std::size_t row_count);
636
639 void close();
640
660
663 template <class T>
664 void bind(short param_index, T const* values, std::size_t batch_size);
665
668 template <class T>
669 void bind(short param_index, T const* values, std::size_t batch_size, T const* null_sentry);
670
673 template <class T>
674 void bind(short param_index, T const* values, std::size_t batch_size, bool const* nulls);
675
678 void bind(short param_index, std::vector<std::vector<uint8_t>> const& values);
679
682 void
683 bind(short param_index, std::vector<std::vector<uint8_t>> const& values, bool const* nulls);
684
693 short param_index,
694 std::vector<std::vector<uint8_t>> const& values,
695 uint8_t const* null_sentry);
696
699 void bind(
700 short param_index,
701 std::vector<std::vector<uint8_t>> const& values,
702 std::vector<uint8_t> const& null_sentry);
703
705
725
728 template <class T, typename = enable_if_character<T>>
730 short param_index,
731 T const* values,
732 std::size_t value_size,
733 std::size_t batch_size);
734
741 template <class T, typename = enable_if_string<T>>
742 void bind_strings(short param_index, std::vector<T> const& values);
743
746 template <
747 std::size_t BatchSize,
748 std::size_t ValueSize,
749 class T,
750 typename = enable_if_character<T>>
751 void bind_strings(short param_index, T const (&values)[BatchSize][ValueSize])
752 {
753 auto param_values = reinterpret_cast<T const*>(values);
754 bind_strings(param_index, param_values, ValueSize, BatchSize);
755 }
756
759 template <class T, typename = enable_if_character<T>>
761 short param_index,
762 T const* values,
763 std::size_t value_size,
764 std::size_t batch_size,
765 T const* null_sentry);
766
769 template <class T, typename = enable_if_string<T>>
771 short param_index,
772 std::vector<T> const& values,
773 typename T::value_type const* null_sentry);
774
777 template <
778 std::size_t BatchSize,
779 std::size_t ValueSize,
780 class T,
781 typename = enable_if_character<T>>
782 void
783 bind_strings(short param_index, T const (&values)[BatchSize][ValueSize], T const* null_sentry)
784 {
785 auto param_values = reinterpret_cast<T const*>(values);
786 bind_strings(param_index, param_values, ValueSize, BatchSize, nullptr, null_sentry);
787 }
788
791 template <class T, typename = enable_if_character<T>>
793 short param_index,
794 T const* values,
795 std::size_t value_size,
796 std::size_t batch_size,
797 bool const* nulls);
798
801 template <class T, typename = enable_if_string<T>>
802 void bind_strings(short param_index, std::vector<T> const& values, bool const* nulls);
803
806 template <
807 std::size_t BatchSize,
808 std::size_t ValueSize,
809 class T,
810 typename = enable_if_character<T>>
811 void bind_strings(short param_index, T const (&values)[BatchSize][ValueSize], bool const* nulls)
812 {
813 auto param_values = reinterpret_cast<T const*>(values);
814 bind_strings(param_index, param_values, ValueSize, BatchSize, nulls);
815 }
816
818
822 void bind_null(short param_index);
823
835 const std::vector<short>& idx,
836 const std::vector<short>& type,
837 const std::vector<unsigned long>& size,
838 const std::vector<short>& scale);
839
841 short parameters() const noexcept;
842
844 unsigned long parameter_size(short param_index) const;
845
847 short parameter_scale(short param_index) const;
848
850 short parameter_type(short param_index) const;
851
852private:
853 class table_valued_parameter_impl;
854 friend class statement;
855
856private:
857 std::shared_ptr<table_valued_parameter_impl> impl_;
858};
859#endif // NANODBC_DISABLE_MSSQL_TVP
860
861// clang-format off
862// .d8888b. 888 888 888
863// d88P Y88b 888 888 888
864// Y88b. 888 888 888
865// "Y888b. 888888 8888b. 888888 .d88b. 88888b.d88b. .d88b. 88888b. 888888
866// "Y88b. 888 "88b 888 d8P Y8b 888 "888 "88b d8P Y8b 888 "88b 888
867// "888 888 .d888888 888 88888888 888 888 888 88888888 888 888 888
868// Y88b d88P Y88b. 888 888 Y88b. Y8b. 888 888 888 Y8b. 888 888 Y88b.
869// "Y8888P" "Y888 "Y888888 "Y888 "Y8888 888 888 888 "Y8888 888 888 "Y888
870// MARK: Statement -
871// clang-format on
872
875{
876
877private:
878 class statement_impl;
879
880public:
882 {
883 public:
884 attribute(
885 long const& attribute,
886 long const& string_length,
887 variant const& resource) noexcept
888 : nanodbc::attribute(attribute, string_length, resource) {};
889
890 private:
891 friend class nanodbc::statement::statement_impl;
892 };
893
894public:
907
908public:
912
916 explicit statement(class connection& conn);
917
923 explicit statement(class connection& conn, std::list<attribute> const& attributes);
924
930 statement(class connection& conn, string const& query, long timeout = 0);
931
933 void swap(statement& rhs) noexcept;
934
938 void open(class connection& conn);
939
941 [[nodiscard]] bool open() const noexcept;
942
944 [[nodiscard]] bool connected() const noexcept;
945
947 class connection& connection() noexcept;
948
950 const class connection& connection() const noexcept;
951
953 [[nodiscard]] void* native_statement_handle() const noexcept;
954
956 void close();
957
960 void cancel();
961
968 void prepare(class connection& conn, string const& query, long timeout = 0);
969
977 void prepare(string const& query, long timeout = 0);
978
981 void timeout(long timeout = 0);
982
993 class result execute_direct(
994 class connection& conn,
995 string const& query,
996 long batch_operations = 1,
997 long timeout = 0);
998
1009 class result execute_direct(
1010 class connection& conn,
1011 string const& query,
1012 batch_ops const& array_sizes,
1013 long timeout = 0);
1014
1015#if !defined(NANODBC_DISABLE_ASYNC)
1032 bool async_prepare(string const& query, void* event_handle, long timeout = 0);
1033
1046
1067 class connection& conn,
1068 void* event_handle,
1069 string const& query,
1070 long batch_operations = 1,
1071 long timeout = 0);
1072
1090 bool async_execute(void* event_handle, long batch_operations = 1, long timeout = 0);
1091
1105 class result complete_execute(long batch_operations = 1);
1106
1108 void enable_async(void* event_handle);
1109
1111 void disable_async() const;
1112#endif
1113
1124 class connection& conn,
1125 string const& query,
1126 long batch_operations = 1,
1127 long timeout = 0);
1128
1137 class result execute(long batch_operations = 1, long timeout = 0);
1138
1153 class result execute(batch_ops const& array_sizes, long timeout = 0);
1154
1162 void just_execute(long batch_operations = 1, long timeout = 0);
1163
1171 class result procedure_columns(
1172 string const& catalog,
1173 string const& schema,
1174 string const& procedure,
1175 string const& column);
1176
1179 [[nodiscard]] long affected_rows() const;
1180
1183 [[nodiscard]] short columns() const;
1184
1186 void reset_parameters() noexcept;
1187
1190 short parameters() const;
1191
1193 unsigned long parameter_size(short param_index) const;
1194
1196 short parameter_scale(short param_index) const;
1197
1199 short parameter_type(short param_index) const;
1200
1212 bool parameter_is_null(short param_index, std::size_t batch_index = 0) const;
1213
1236
1249 template <class T>
1250 void bind(short param_index, T const* value, param_direction direction = PARAM_IN);
1251
1268 template <class T>
1269 void
1270 bind(short param_index, std::optional<T> const& value, param_direction direction = PARAM_IN)
1271 {
1272 if (!value.has_value())
1273 {
1274 bind_null(param_index, 1);
1275 return;
1276 }
1277 if constexpr (is_owning_string_v<T>)
1278 bind(param_index, value->c_str(), direction);
1279 else
1280 bind(param_index, &*value, direction);
1281 }
1282
1301
1304 template <class T>
1305 void bind(
1306 short param_index,
1307 T const* values,
1308 std::size_t batch_size,
1309 param_direction direction = PARAM_IN);
1310
1313 template <class T>
1314 void bind(
1315 short param_index,
1316 T const* values,
1317 std::size_t batch_size,
1318 T const* null_sentry,
1319 param_direction direction = PARAM_IN);
1320
1323 template <class T>
1324 void bind(
1325 short param_index,
1326 T const* values,
1327 std::size_t batch_size,
1328 bool const* nulls,
1329 param_direction direction = PARAM_IN);
1330
1333 void bind(
1334 short param_index,
1335 std::vector<std::vector<uint8_t>> const& values,
1336 param_direction direction = PARAM_IN);
1337
1340 void bind(
1341 short param_index,
1342 std::vector<std::vector<uint8_t>> const& values,
1343 bool const* nulls,
1344 param_direction direction = PARAM_IN);
1345
1354 short param_index,
1355 std::vector<std::vector<uint8_t>> const& values,
1356 uint8_t const* null_sentry,
1357 param_direction direction = PARAM_IN);
1358
1361 void bind(
1362 short param_index,
1363 std::vector<std::vector<uint8_t>> const& values,
1364 std::vector<uint8_t> const& null_sentry,
1365 param_direction direction = PARAM_IN);
1366
1373 template <class T>
1374 void
1375 bind(short param_index, std::vector<T> const& values, param_direction direction = PARAM_IN);
1376
1379 template <class T>
1380 void bind(
1381 short param_index,
1382 std::vector<T> const& values,
1383 bool const* nulls,
1384 param_direction direction = PARAM_IN);
1385
1402 template <class T>
1403 void bind(
1404 short param_index,
1405 std::vector<std::optional<T>> const& values,
1406 param_direction direction = PARAM_IN)
1407 {
1408 std::vector<T> column;
1409 auto const nulls = detail::split_optional(values, column);
1410 bind(param_index, column, nulls.get(), direction);
1411 }
1412
1414
1435
1438 template <class T, typename = enable_if_character<T>>
1440 short param_index,
1441 T const* values,
1442 std::size_t value_size,
1443 std::size_t batch_size,
1444 param_direction direction = PARAM_IN);
1445
1452 template <class T, typename = enable_if_string<T>>
1454 short param_index,
1455 std::vector<T> const& values,
1456 param_direction direction = PARAM_IN);
1457
1460 template <
1461 std::size_t BatchSize,
1462 std::size_t ValueSize,
1463 class T,
1464 typename = enable_if_character<T>>
1466 short param_index,
1467 T const (&values)[BatchSize][ValueSize],
1468 param_direction direction = PARAM_IN)
1469 {
1470 auto param_values = reinterpret_cast<T const*>(values);
1471 bind_strings(param_index, param_values, ValueSize, BatchSize, direction);
1472 }
1473
1476 template <class T, typename = enable_if_character<T>>
1478 short param_index,
1479 T const* values,
1480 std::size_t value_size,
1481 std::size_t batch_size,
1482 T const* null_sentry,
1483 param_direction direction = PARAM_IN);
1484
1487 template <class T, typename = enable_if_string<T>>
1489 short param_index,
1490 std::vector<T> const& values,
1491 typename T::value_type const* null_sentry,
1492 param_direction direction = PARAM_IN);
1493
1496 template <
1497 std::size_t BatchSize,
1498 std::size_t ValueSize,
1499 class T,
1500 typename = enable_if_character<T>>
1502 short param_index,
1503 T const (&values)[BatchSize][ValueSize],
1504 T const* null_sentry,
1505 param_direction direction = PARAM_IN)
1506 {
1507 auto param_values = reinterpret_cast<T const*>(values);
1508 bind_strings(param_index, param_values, ValueSize, BatchSize, null_sentry, direction);
1509 }
1510
1513 template <class T, typename = enable_if_character<T>>
1515 short param_index,
1516 T const* values,
1517 std::size_t value_size,
1518 std::size_t batch_size,
1519 bool const* nulls,
1520 param_direction direction = PARAM_IN);
1521
1524 template <class T, typename = enable_if_string<T>>
1526 short param_index,
1527 std::vector<T> const& values,
1528 bool const* nulls,
1529 param_direction direction = PARAM_IN);
1530
1533 template <
1534 std::size_t BatchSize,
1535 std::size_t ValueSize,
1536 class T,
1537 typename = enable_if_character<T>>
1539 short param_index,
1540 T const (&values)[BatchSize][ValueSize],
1541 bool const* nulls,
1542 param_direction direction = PARAM_IN)
1543 {
1544 auto param_values = reinterpret_cast<T const*>(values);
1545 bind_strings(param_index, param_values, ValueSize, BatchSize, nulls, direction);
1546 }
1547
1565 template <class T, typename = enable_if_string<T>>
1567 short param_index,
1568 std::vector<std::optional<T>> const& values,
1569 param_direction direction = PARAM_IN)
1570 {
1571 std::vector<T> column;
1572 auto const nulls = detail::split_optional(values, column);
1573 bind_strings(param_index, column, nulls.get(), direction);
1574 }
1575
1577
1589 void bind_null(short param_index, std::size_t batch_size = 1);
1590
1592
1611 const std::vector<short>& idx,
1612 const std::vector<short>& type,
1613 const std::vector<unsigned long>& size,
1614 const std::vector<short>& scale);
1615
1616private:
1617 using null_predicate_type = std::function<bool(std::size_t)>;
1618 friend class nanodbc::result;
1619#ifndef NANODBC_DISABLE_MSSQL_TVP
1620 friend class nanodbc::table_valued_parameter::table_valued_parameter_impl;
1621#endif
1622
1623private:
1624 std::shared_ptr<statement_impl> impl_;
1625};
1626
1627// clang-format off
1628// .d8888b. 888 d8b
1629// d88P Y88b 888 Y8P
1630// 888 888 888
1631// 888 .d88b. 88888b. 88888b. .d88b. .d8888b 888888 888 .d88b. 88888b.
1632// 888 d88""88b 888 "88b 888 "88b d8P Y8b d88P" 888 888 d88""88b 888 "88b
1633// 888 888 888 888 888 888 888 888 88888888 888 888 888 888 888 888 888
1634// Y88b d88P Y88..88P 888 888 888 888 Y8b. Y88b. Y88b. 888 Y88..88P 888 888
1635// "Y8888P" "Y88P" 888 888 888 888 "Y8888 "Y8888P "Y888 888 "Y88P" 888 888
1636// MARK: Connection -
1637// clang-format on
1638
1641{
1642
1643private:
1644 class connection_impl;
1645 friend class nanodbc::transaction::transaction_impl;
1646
1647public:
1649 {
1650 public:
1651 attribute(
1652 long const& attribute,
1653 long const& string_length,
1654 variant const& resource) noexcept
1655 : nanodbc::attribute(attribute, string_length, resource) {};
1656
1657 private:
1658 friend class nanodbc::connection::connection_impl;
1659 };
1660
1661public:
1664
1666 void swap(connection&) noexcept;
1667
1678 connection(string const& dsn, string const& user, string const& pass, long timeout = 0);
1679
1689 explicit connection(string const& connection_string, long timeout = 0);
1690
1703
1705 string const& dsn,
1706 string const& user,
1707 string const& pass,
1708 std::list<attribute> const& attributes);
1719 connection(string const& connection_string, std::list<attribute> const& attributes);
1720
1729 void allocate();
1730
1734
1742 void connect(string const& dsn, string const& user, string const& pass, long timeout = 0);
1743
1749 void connect(string const& connection_string, long timeout = 0);
1750
1760 string const& dsn,
1761 string const& user,
1762 string const& pass,
1763 std::list<attribute> const& attributes);
1764
1771 void connect(string const& connection_string, std::list<attribute> const& attributes);
1772
1789 string browse_connect(string const& connection_string, bool& more_wanted);
1790#if !defined(NANODBC_DISABLE_ASYNC)
1809 string const& dsn,
1810 string const& user,
1811 string const& pass,
1812 void* event_handle,
1813 long timeout = 0);
1814
1830 bool async_connect(string const& connection_string, void* event_handle, long timeout = 0);
1831
1837#endif
1838
1844 [[nodiscard]] bool connected() const noexcept;
1845
1847 void disconnect();
1848
1850 [[nodiscard]] std::size_t transactions() const noexcept;
1851
1853 [[nodiscard]] void* native_dbc_handle() const noexcept;
1854
1856 [[nodiscard]] void* native_env_handle() const noexcept;
1857
1861 template <class T>
1862 T get_info(short info_type) const;
1863
1867 string dbms_name() const;
1868
1872 string dbms_version() const;
1873
1876 string driver_name() const;
1877
1880 string driver_version() const;
1881
1884 string database_name() const;
1885
1888 string catalog_name() const;
1889
1890private:
1891 std::size_t ref_transaction() noexcept;
1892 std::size_t unref_transaction() noexcept;
1893 bool rollback() const noexcept;
1894 void rollback(bool onoff) noexcept;
1895 bool restore_autocommit() const noexcept;
1896 void restore_autocommit(bool onoff) noexcept;
1897
1898private:
1899 std::shared_ptr<connection_impl> impl_;
1900};
1901
1902// clang-format off
1903// 8888888b. 888 888
1904// 888 Y88b 888 888
1905// 888 888 888 888
1906// 888 d88P .d88b. .d8888b 888 888 888 888888
1907// 8888888P" d8P Y8b 88K 888 888 888 888
1908// 888 T88b 88888888 "Y8888b. 888 888 888 888
1909// 888 T88b Y8b. X88 Y88b 888 888 Y88b.
1910// 888 T88b "Y8888 88888P' "Y88888 888 "Y888
1911// MARK: Result -
1912// clang-format on
1913
1914class catalog;
1915class variant_row_cached_result;
1916
1922{
1923public:
1925 result() = default;
1926
1928 void swap(result& rhs) noexcept;
1929
1931 [[nodiscard]] void* native_statement_handle() const noexcept;
1932
1934 [[nodiscard]] long rowset_size() const noexcept;
1935
1938 [[nodiscard]] long affected_rows() const;
1939
1948 bool has_affected_rows() const;
1949
1951 [[nodiscard]] long rows() const noexcept;
1952
1955 [[nodiscard]] short columns() const;
1956
1960 [[nodiscard]] bool first();
1961
1965 [[nodiscard]] bool last();
1966
1970 [[nodiscard]] bool next();
1971
1972#if !defined(NANODBC_DISABLE_ASYNC)
1977 bool async_next(void* event_handle);
1978
1983#endif
1984
1988 [[nodiscard]] bool prior();
1989
1997 [[nodiscard]] bool move(long row);
1998
2002 [[nodiscard]] bool skip(long rows);
2003
2005 unsigned long position() const;
2006
2008 bool at_end() const noexcept;
2009
2015 void unbind();
2016
2024 void unbind(string const& column_name);
2025
2041 void unbind(short column);
2042
2059
2069 template <class T>
2070 void get_ref(short column, T& result) const;
2071
2083 template <class T>
2084 void get_ref(short column, T const& fallback, T& result) const;
2085
2094 template <class T>
2095 void get_ref(string const& column_name, T& result) const;
2096
2107 template <class T>
2108 void get_ref(string const& column_name, T const& fallback, T& result) const;
2109
2122 template <class T>
2123 [[nodiscard]] T get(short column) const;
2124
2135 template <class T>
2136 [[nodiscard]] T get(short column, T const& fallback) const;
2137
2157 template <class T>
2158 [[nodiscard]] T get_as(short column) const;
2159
2162 template <class T>
2163 [[nodiscard]] T get_as(string const& column_name) const;
2164
2172 template <class T>
2173 [[nodiscard]] T get(string const& column_name) const;
2174
2184 template <class T>
2185 [[nodiscard]] T get(string const& column_name, T const& fallback) const;
2186
2188
2206 template <class T>
2207 bool get_chunks(
2208 short column,
2209 std::function<void(T const&)> const& callback,
2210 std::size_t chunk_size = 65536) const;
2211
2214 template <class T>
2215 bool get_chunks(
2216 string const& column_name,
2217 std::function<void(T const&)> const& callback,
2218 std::size_t chunk_size = 65536) const;
2219
2241 [[nodiscard]] bool is_null(short column) const;
2242
2250 [[nodiscard]] bool is_null(string const& column_name) const;
2251
2262 bool is_bound(short column) const;
2263
2270 bool is_bound(string const& column_name) const;
2271
2277 [[nodiscard]] short column(string const& column_name) const;
2278
2284 [[nodiscard]] string column_name(short column) const;
2285
2291 [[nodiscard]] long column_size(short column) const;
2292
2294 [[nodiscard]] long column_size(string const& column_name) const;
2295
2304 int column_decimal_digits(short column) const;
2305
2307 int column_decimal_digits(string const& column_name) const;
2308
2310 [[nodiscard]] int column_datatype(short column) const;
2311
2313 [[nodiscard]] int column_datatype(string const& column_name) const;
2314
2322 string column_datatype_name(short column) const;
2323
2331 string column_datatype_name(string const& column_name) const;
2332
2334 int column_c_datatype(short column) const;
2335
2337 int column_c_datatype(string const& column_name) const;
2338
2346 bool column_unsigned(short column) const;
2347
2350 bool column_unsigned(string const& column_name) const;
2351
2353 bool next_result();
2354
2356 [[nodiscard]] explicit operator bool() const noexcept;
2357
2358private:
2359 result(statement statement, long rowset_size);
2360
2361 class result_impl;
2362 friend class nanodbc::statement::statement_impl;
2363 friend class nanodbc::catalog;
2364#ifdef _MSC_VER
2365 friend class nanodbc::variant_row_cached_result;
2366#endif
2367
2368private:
2369 std::shared_ptr<result_impl> impl_;
2370};
2371
2374{
2375public:
2376 using iterator_category = std::input_iterator_tag;
2378 using pointer = result*;
2380 using difference_type = std::ptrdiff_t;
2381
2383 result_iterator() = default;
2384
2387 : result_{r}
2388 {
2389 ++*this;
2390 }
2391
2393 reference operator*() const noexcept { return result_; }
2394
2397 {
2398 if (!result_)
2399 throw std::runtime_error("result is empty");
2400 return &operator*();
2401 }
2402
2405 {
2406 try
2407 {
2408 if (!result_.next())
2409 result_ = {};
2410 }
2411 catch (...)
2412 {
2413 result_ = {};
2414 }
2415 return *this;
2416 }
2417
2423 void operator++(int) { ++*this; }
2424
2426 bool operator==(result_iterator const& rhs) const noexcept
2427 {
2428 if (result_ && rhs.result_)
2429 return result_.native_statement_handle() == rhs.result_.native_statement_handle();
2430 else
2431 return !result_ && !rhs.result_;
2432 }
2433
2435 bool operator!=(result_iterator const& rhs) const noexcept { return !(*this == rhs); }
2436
2437private:
2438 mutable result result_;
2439};
2440
2443{
2444 return result_iterator(r);
2445}
2446
2453inline result_iterator end(result& /*r*/) noexcept
2454{
2455 return {};
2456}
2457
2458// clang-format off
2459// 8888888b. d8b 888
2460// 888 "Y88b Y8P 888
2461// 888 888 888
2462// 888 888 .d88b. .d8888b .d8888b 888d888 888 88888b. 888888 .d88b. 888d888 .d8888b
2463// 888 888 d8P Y8b 88K d88P" 888P" 888 888 "88b 888 d88""88b 888P" 88K
2464// 888 888 88888888 "Y8888b. 888 888 888 888 888 888 888 888 888 "Y8888b.
2465// 888 .d88P Y8b. X88 Y88b. 888 888 888 d88P Y88b. Y88..88P 888 X88
2466// 8888888P" "Y8888 88888P' "Y8888P 888 888 88888P" "Y888 "Y88P" 888 88888P'
2467// 888
2468// 888
2469// 888
2470// MARK: Descriptors -
2471// clang-format on
2472
2479{
2480public:
2483
2496
2498 auto alloc_type() const -> short;
2499
2501 auto count() const noexcept -> short;
2502
2503 // Descriptor record fields (records) accessors
2504
2506 auto auto_unique_value(short record) const -> bool;
2507
2509 auto base_column_name(short record) const -> string;
2510
2512 auto base_table_name(short record) const -> string;
2513
2515 auto case_sensitive(short record) const -> bool;
2516
2518 auto catalog_name(short record) const -> string;
2519
2521 auto concise_type(short record) const -> short;
2522
2524 auto display_size(short record) const -> std::int64_t;
2525
2527 auto fixed_prec_scale(short record) const -> short;
2528
2530 auto label(short record) const -> string;
2531
2533 auto length(short record) const -> std::uint64_t;
2534
2536 auto local_type_name(short record) const -> string;
2537
2539 auto name(short record) const -> string;
2540
2544 auto nullable(short record) const -> short;
2545
2547 auto num_prec_radix(short record) const -> short;
2548
2550 auto octet_length(short record) const -> std::int64_t;
2551
2553 auto precision(short record) const -> short;
2554
2556 auto rowver(short record) const -> short;
2557
2559 auto scale(short record) const -> short;
2560
2562 auto schema_name(short record) const -> string;
2563
2568 auto searchable(short record) const -> short;
2569
2571 auto table_name(short record) const -> string;
2572
2574 auto type(short record) const -> short;
2575
2577 auto type_name(short record) const -> string;
2578
2580 auto unnamed(short record) const -> bool;
2581
2583 auto unsigned_(short record) const -> bool;
2584
2589 auto updatable(short record) const -> short;
2590
2591private:
2592 // Convenience wrapper for SQLGetDescrField accesor.
2593 struct sql_get_descr_field
2594 {
2595 sql_get_descr_field(
2597 short record,
2598 std::uint16_t field_identifier) noexcept;
2599 operator std::int64_t() const;
2600 operator std::uint64_t() const;
2601 operator string() const;
2602
2604 short record_;
2605 std::uint16_t field_identifier_;
2606 };
2607 friend sql_get_descr_field;
2608
2609 void initialize_descriptor();
2610 void throw_if_record_is_out_of_range(short record) const;
2611
2612 void* statement_handle_{nullptr};
2613 short statement_columns_count_{0};
2614 void* descriptor_handle_{nullptr};
2615 short descriptor_records_count_{0};
2616};
2617
2618// clang-format off
2619//
2620// .d8888b. 888 888
2621// d88P Y88b 888 888
2622// 888 888 888 888
2623// 888 8888b. 888888 8888b. 888 .d88b. .d88b.
2624// 888 "88b 888 "88b 888 d88""88b d88P"88b
2625// 888 888 .d888888 888 .d888888 888 888 888 888 888
2626// Y88b d88P 888 888 Y88b. 888 888 888 Y88..88P Y88b 888
2627// "Y8888P" "Y888888 "Y888 "Y888888 888 "Y88P" "Y88888
2628// 888
2629// Y8b d88P
2630// "Y88P"
2631// MARK: Catalog -
2632// clang-format on
2633
2640{
2641public:
2644 {
2645 public:
2646 [[nodiscard]] bool next();
2647 string table_catalog() const;
2648 string table_schema() const;
2649 string table_name() const;
2650 string table_type() const;
2651 string table_remarks() const;
2652
2653 private:
2654 friend class nanodbc::catalog;
2655 explicit tables(result& find_result) noexcept;
2656 result result_;
2657 };
2658
2661 {
2662 public:
2663 [[nodiscard]] bool next();
2664 string table_catalog() const;
2665 string table_schema() const;
2666 string table_name() const;
2667 string column_name() const;
2668 short data_type() const;
2669 string type_name() const;
2670 long column_size() const;
2671 long buffer_length() const;
2672 short decimal_digits() const;
2674 short nullable() const;
2675 string remarks() const;
2676 string column_default() const;
2677 short sql_data_type() const;
2678 short sql_datetime_subtype() const;
2679 long char_octet_length() const;
2680
2684 long ordinal_position() const;
2685
2691 string is_nullable() const;
2692
2693 private:
2694 friend class nanodbc::catalog;
2695 explicit columns(result& find_result) noexcept;
2696 result result_;
2697 };
2698
2701 {
2702 public:
2703 [[nodiscard]] bool next();
2704 string table_catalog() const;
2705 string table_schema() const;
2706 string table_name() const;
2707 string column_name() const;
2708
2711 short column_number() const;
2712
2716 string primary_key_name() const;
2717
2718 private:
2719 friend class nanodbc::catalog;
2720 explicit primary_keys(result& find_result) noexcept;
2721 result result_;
2722 };
2723
2726 {
2727 public:
2728 [[nodiscard]] bool next();
2729 string table_catalog() const;
2730 string table_schema() const;
2731 string table_name() const;
2732 string grantor() const;
2733 string grantee() const;
2734 string privilege() const;
2736 string is_grantable() const;
2737
2738 private:
2739 friend class nanodbc::catalog;
2740 explicit table_privileges(result& find_result) noexcept;
2741 result result_;
2742 };
2743
2746 {
2747 public:
2748 [[nodiscard]] bool next();
2749 string procedure_catalog() const;
2750 string procedure_schema() const;
2751 string procedure_name() const;
2752 string procedure_remarks() const;
2753 short procedure_type() const;
2754
2755 private:
2756 friend class nanodbc::catalog;
2757 explicit procedures(result& find_result) noexcept;
2758 result result_;
2759 };
2760
2763 {
2764 public:
2765 [[nodiscard]] bool next();
2766 string procedure_catalog() const;
2767 string procedure_schema() const;
2768 string procedure_name() const;
2769 string column_name() const;
2770 short column_type() const;
2771 short data_type() const;
2772 string type_name() const;
2773 long column_size() const;
2774 long buffer_length() const;
2775 short decimal_digits() const;
2777 short nullable() const;
2778 string remarks() const;
2779 string column_default() const;
2780 short sql_data_type() const;
2781 short sql_datetime_subtype() const;
2782 long char_octet_length() const;
2783
2787 long ordinal_position() const;
2788
2794 string is_nullable() const;
2795
2796 private:
2797 friend class nanodbc::catalog;
2798 explicit procedure_columns(result& find_result) noexcept;
2799 result result_;
2800 };
2801
2803 explicit catalog(connection& conn) noexcept;
2804
2815 string const& table = {},
2816 string const& type = {},
2817 string const& schema = {},
2818 string const& catalog = {});
2819
2834 string const& catalog,
2835 string const& table = {},
2836 string const& schema = {});
2837
2848 string const& column = {},
2849 string const& table = {},
2850 string const& schema = {},
2851 string const& catalog = {});
2852
2861 catalog::primary_keys
2862 find_primary_keys(string const& table, string const& schema = {}, string const& catalog = {});
2863
2873
2875 string const& procedure = {},
2876 string const& schema = {},
2877 string const& catalog = {});
2878
2890 string const& column = {},
2891 string const& procedure = {},
2892 string const& schema = {},
2893 string const& catalog = {});
2894
2898 std::list<string> list_catalogs();
2899
2903 std::list<string> list_schemas();
2904
2909 std::list<string> list_table_types();
2910
2911private:
2912 connection conn_;
2913};
2914
2916
2917// clang-format off
2918// 8888888888 8888888888 888 d8b
2919// 888 888 888 Y8P
2920// 888 888 888
2921// 8888888 888d888 .d88b. .d88b. 8888888 888 888 88888b. .d8888b 888888 888 .d88b. 88888b. .d8888b
2922// 888 888P" d8P Y8b d8P Y8b 888 888 888 888 "88b d88P" 888 888 d88""88b 888 "88b 88K
2923// 888 888 88888888 88888888 888 888 888 888 888 888 888 888 888 888 888 888 "Y8888b.
2924// 888 888 Y8b. Y8b. 888 Y88b 888 888 888 Y88b. Y88b. 888 Y88..88P 888 888 X88
2925// 888 888 "Y8888 "Y8888 888 "Y88888 888 888 "Y8888P "Y888 888 "Y88P" 888 888 88888P'
2927namespace detail
2928{
2929
2930// Moves what a column held, which get<std::any>() worked out from the type the driver
2931// reports, into whatever the caller asked to hold it.
2932template <class T>
2933struct hold_column_value;
2934
2935template <>
2936struct hold_column_value<std::any>
2937{
2938 static std::any from(std::any value) noexcept { return value; }
2939};
2940
2941template <class Alternative, class Variant>
2942inline bool hold_alternative(Variant& variant, std::any const& value)
2943{
2944 if (auto const* held = std::any_cast<Alternative>(&value))
2945 {
2946 variant = *held;
2947 return true;
2948 }
2949 return false;
2950}
2951
2952template <class... Ts>
2953struct hold_column_value<std::variant<Ts...>>
2954{
2955 static std::variant<Ts...> from(std::any const& value)
2956 {
2957 std::variant<Ts...> variant;
2958 if (!value.has_value())
2959 return variant; // the first alternative, which is what monostate is for
2960
2961 // A disjunction fold, which stops at the first alternative able to hold it.
2962 bool const held = (hold_alternative<Ts>(variant, value) || ...);
2963
2964 // The column holds something none of the alternatives can, which the compiler
2965 // cannot catch: what a column holds is only known once the driver has said.
2966 if (!held)
2967 throw type_incompatible_error();
2968
2969 return variant;
2970 }
2971};
2972
2973} // namespace detail
2974
2975template <class T>
2976T result::get_as(short column) const
2977{
2978 return detail::hold_column_value<T>::from(get<std::any>(column));
2979}
2980
2981template <class T>
2982T result::get_as(string const& column_name) const
2983{
2984 return get_as<T>(this->column(column_name));
2985}
2986
2987// MARK: Free Functions -
2988// clang-format on
2989
2994
2997{
3004
3006 std::list<attribute> attributes;
3007};
3008
3015
3017std::list<driver> list_drivers();
3018
3020std::list<datasource> list_datasources();
3021
3032result execute(connection& conn, string const& query, long batch_operations = 1, long timeout = 0);
3033
3043 connection& conn,
3044 string const& query,
3045 long batch_operations = 1,
3046 long timeout = 0);
3047
3049namespace detail
3050{
3051
3053template <class Row, class Member, class Class>
3054Member const& read_field(Row const& row, Member Class::* field)
3055{
3056 return row.*field;
3057}
3058
3060template <class Row, class Accessor>
3061auto read_field(Row const& row, Accessor const& accessor) -> decltype(accessor(row))
3062{
3063 return accessor(row);
3064}
3065
3067template <class Row, class Accessor>
3069{
3070 using type = std::decay_t<
3071 decltype(read_field(std::declval<Row const&>(), std::declval<Accessor const&>()))>;
3072};
3073
3074template <class T>
3075struct is_optional : std::false_type
3076{
3077};
3078
3079template <class T>
3080struct is_optional<std::optional<T>> : std::true_type
3081{
3082};
3083
3084template <class T>
3085inline constexpr bool is_optional_v = is_optional<T>::value;
3086
3087// Four ways to bind a column, told apart by what the accessor yields.
3089{
3090};
3092{
3093};
3095{
3096};
3098{
3099};
3100
3101template <class T, bool IsOptional = is_optional_v<T>>
3103{
3104 using type = std::conditional_t<is_owning_string_v<T>, bind_as_string, bind_as_value>;
3105};
3106
3107template <class T>
3108struct bind_kind<T, true>
3109{
3110 using type = std::conditional_t<
3111 is_owning_string_v<typename T::value_type>,
3114};
3115
3116template <class Rows, class Accessor>
3117void bind_column(
3118 statement& stmt,
3119 short param_index,
3120 Rows const& rows,
3121 Accessor const& accessor,
3123{
3124 using value_type = typename field_type<typename Rows::value_type, Accessor>::type;
3125 std::vector<value_type> column;
3126 column.reserve(rows.size());
3127 for (auto const& row : rows)
3128 column.push_back(read_field(row, accessor));
3129 stmt.bind(param_index, column);
3130}
3131
3132template <class Rows, class Accessor>
3133void bind_column(
3134 statement& stmt,
3135 short param_index,
3136 Rows const& rows,
3137 Accessor const& accessor,
3138 bind_as_string)
3139{
3140 using value_type = typename field_type<typename Rows::value_type, Accessor>::type;
3141 std::vector<value_type> column;
3142 column.reserve(rows.size());
3143 for (auto const& row : rows)
3144 column.push_back(read_field(row, accessor));
3145 stmt.bind_strings(param_index, column);
3146}
3147
3148// An absent value still occupies its place in the column, so that the values line up with
3149// the flags marking which of them are null.
3150template <class Rows, class Accessor, class Column>
3151std::unique_ptr<bool[]> gather_optional(Rows const& rows, Accessor const& accessor, Column& column)
3152{
3153 auto nulls = std::make_unique<bool[]>(rows.size());
3154 std::size_t i = 0;
3155 for (auto const& row : rows)
3156 {
3157 auto const& value = read_field(row, accessor);
3158 nulls[i++] = !value.has_value();
3159 column.push_back(value ? *value : typename Column::value_type());
3160 }
3161 return nulls;
3162}
3163
3164template <class Rows, class Accessor>
3165void bind_column(
3166 statement& stmt,
3167 short param_index,
3168 Rows const& rows,
3169 Accessor const& accessor,
3170 bind_as_optional_value)
3171{
3172 using optional_type = typename field_type<typename Rows::value_type, Accessor>::type;
3173 std::vector<typename optional_type::value_type> column;
3174 column.reserve(rows.size());
3175 auto const nulls = gather_optional(rows, accessor, column);
3176 stmt.bind(param_index, column, nulls.get());
3177}
3178
3179template <class Rows, class Accessor>
3180void bind_column(
3181 statement& stmt,
3182 short param_index,
3183 Rows const& rows,
3184 Accessor const& accessor,
3185 bind_as_optional_string)
3186{
3187 using optional_type = typename field_type<typename Rows::value_type, Accessor>::type;
3188 std::vector<typename optional_type::value_type> column;
3189 column.reserve(rows.size());
3190 auto const nulls = gather_optional(rows, accessor, column);
3191 stmt.bind_strings(param_index, column, nulls.get());
3192}
3193
3194template <class Rows, class Accessor>
3195void bind_one(statement& stmt, short param_index, Rows const& rows, Accessor const& accessor)
3196{
3197 using value_type = typename field_type<typename Rows::value_type, Accessor>::type;
3198 bind_column(stmt, param_index, rows, accessor, typename bind_kind<value_type>::type());
3199}
3200
3201} // namespace detail
3202
3233template <class Rows, class... Accessors>
3234void bind_rows(statement& stmt, Rows const& rows, Accessors const&... accessors)
3235{
3236 short param_index = 0;
3237 // A comma fold, which is ordered left to right, so the accessors line up with the
3238 // parameter markers in the order they were named.
3239 (detail::bind_one(stmt, param_index++, rows, accessors), ...);
3240}
3241
3250result execute(statement& stmt, long batch_operations = 1);
3251
3259void just_execute(statement& stmt, long batch_operations = 1);
3260
3269result transact(statement& stmt, long batch_operations);
3270
3278void just_transact(statement& stmt, long batch_operations);
3279
3289void prepare(statement& stmt, string const& query, long timeout = 0);
3290
3292
3293} // namespace nanodbc
3294
3295#endif
A class representing a connection or a statement attribute.
Definition nanodbc.h:430
attribute(attribute const &other) noexcept
Copy constructor.
void extractValuePtr() noexcept
Points value_ptr_ at the resource, according to which type it holds.
attribute(long const &attribute, long const &string_length, variant resource) noexcept
Creates an attribute from the three arguments the ODBC call takes.
Result set for a list of columns in one or more tables.
Definition nanodbc.h:2661
string remarks() const
Fetch column remarks.
short sql_data_type() const
Fetch column's SQL data type.
string table_catalog() const
Fetch table catalog.
short numeric_precision_radix() const
Fetch numeric precission.
string column_default() const
Fetch column's default.
string table_schema() const
Fetch table schema.
string type_name() const
Fetch column type name.
short sql_datetime_subtype() const
Fetch datetime subtype of column.
bool next()
Move to the next result in the result set.
short nullable() const
True iff column is nullable.
string column_name() const
Fetch column name.
string table_name() const
Fetch table name.
long column_size() const
Fetch column size.
short decimal_digits() const
Fetch decimal digits.
long char_octet_length() const
Fetch char octet length.
long ordinal_position() const
Ordinal position of the column in the table.
string is_nullable() const
Fetch column is-nullable information.
long buffer_length() const
Fetch buffer length.
short data_type() const
Fetch column data type.
Result set for a list of columns that compose the primary key of a single table.
Definition nanodbc.h:2701
bool next()
Move to the next result in the result set.
string column_name() const
Fetch column name.
short column_number() const
Column sequence number in the key (starting with 1).
string table_name() const
Fetch table name.
string primary_key_name() const
Primary key name.
string table_schema() const
Fetch table schema.
string table_catalog() const
Fetch table catalog.
Result set for a list of procedures in the data source.
Definition nanodbc.h:2763
string column_default() const
Fetch column's default.
string type_name() const
Fetch column type name.
long ordinal_position() const
Ordinal position of the column in the table.
bool next()
Move to the next result in the result set.
short decimal_digits() const
Fetch decimal digits.
long column_size() const
Fetch column size.
short sql_datetime_subtype() const
Fetch datetime subtype of column.
string remarks() const
Fetch column remarks.
long char_octet_length() const
Fetch char octet length.
string procedure_schema() const
Fetch procedure schema.
string procedure_catalog() const
Fetch procedure catalog.
short sql_data_type() const
Fetch column's SQL data type.
short column_type() const
Fetch column type.
short numeric_precision_radix() const
Fetch numeric precission.
string is_nullable() const
Fetch column is-nullable information.
long buffer_length() const
Fetch buffer length.
short nullable() const
True iff column is nullable.
string column_name() const
Fetch column name.
string procedure_name() const
Fetch procedure name.
short data_type() const
Fetch column data type.
Result set for a list of procedures in the data source.
Definition nanodbc.h:2746
string procedure_name() const
Fetch procedure name.
short procedure_type() const
Fetch procedure type.
string procedure_schema() const
Fetch procedure schema.
string procedure_catalog() const
Fetch procedure catalog.
string procedure_remarks() const
Fetch procedure remarks.
bool next()
Move to the next result in the result set.
Result set for a list of tables and the privileges associated with each table.
Definition nanodbc.h:2726
string privilege() const
Fetch the table privilege.
string grantor() const
Fetch name of user who granted the privilege.
bool next()
Move to the next result in the result set.
string table_schema() const
Fetch table schema.
string table_catalog() const
Fetch table catalog.
string table_name() const
Fetch table name.
string grantee() const
Fetch name of user whom the privilege was granted.
string is_grantable() const
Fetch indicator whether the grantee is permitted to grant the privilege to other users.
Result set for a list of tables in the data source.
Definition nanodbc.h:2644
string table_name() const
Fetch table name.
string table_catalog() const
Fetch table catalog.
bool next()
Move to the next result in the result set.
string table_remarks() const
Fetch table remarks.
string table_type() const
Fetch table type.
string table_schema() const
Fetch table schema.
A resource for get catalog information from connected data source.
Definition nanodbc.h:2640
std::list< string > list_schemas()
Returns names of all schemas available in connected data source.
std::list< string > list_catalogs()
Returns names of all catalogs (or databases) available in connected data source.
catalog(connection &conn) noexcept
Creates catalog operating on database accessible through the specified connection.
catalog::columns find_columns(string const &column={}, string const &table={}, string const &schema={}, string const &catalog={})
Creates result set with columns in one or more tables.
std::list< string > list_table_types()
Returns all available table types in the connected data source.
catalog::procedure_columns find_procedure_columns(string const &column={}, string const &procedure={}, string const &schema={}, string const &catalog={})
Creates result set with columns in one or more procedures.
catalog::procedures find_procedures(string const &procedure={}, string const &schema={}, string const &catalog={})
Creates result set with catalog, schema, procedure, and procedure types.
catalog::tables find_tables(string const &table={}, string const &type={}, string const &schema={}, string const &catalog={})
Creates result set with catalogs, schemas, tables, or table types.
catalog::primary_keys find_primary_keys(string const &table, string const &schema={}, string const &catalog={})
Creates result set with columns that compose the primary key of a single table.
catalog::table_privileges find_table_privileges(string const &catalog, string const &table={}, string const &schema={})
Creates result set with tables and the privileges associated with each table.
Definition nanodbc.h:1649
Manages and encapsulates ODBC resources such as the connection and environment handles.
Definition nanodbc.h:1641
void connect(string const &connection_string, std::list< attribute > const &attributes)
Set the connection attributes passed by the user, and connect to the given connection string.
connection(string const &dsn, string const &user, string const &pass, std::list< attribute > const &attributes)
Create new connection object, set the connection attributes passed as arguments and connect to the gi...
bool async_connect(string const &connection_string, void *event_handle, long timeout=0)
Initiate an asynchronous connection operation using the given connection string.
bool connected() const noexcept
Returns true if connected to the database.
void async_complete()
Completes a previously initiated asynchronous connection operation.
void connect(string const &dsn, string const &user, string const &pass, std::list< attribute > const &attributes)
Set the connection attributes passed by the user, and connect to the given data source.
void deallocate()
Release environment and connection handles.
void connect(string const &connection_string, long timeout=0)
Connect using the given connection string.
connection(string const &connection_string, std::list< attribute > const &attributes)
Create new connection object, set the connection attributes passed as arguments and connect to the gi...
connection(string const &dsn, string const &user, string const &pass, long timeout=0)
Create new connection object and immediately connect to the given data source.
connection()
Create new connection object, initially not connected.
bool async_connect(string const &dsn, string const &user, string const &pass, void *event_handle, long timeout=0)
Initiate an asynchronous connection operation to the given data source.
string browse_connect(string const &connection_string, bool &more_wanted)
Asks the driver what it needs in order to connect.
void swap(connection &) noexcept
Member swap.
void allocate()
Allocate environment and connection handles.
void connect(string const &dsn, string const &user, string const &pass, long timeout=0)
Connect to the given data source.
connection(string const &connection_string, long timeout=0)
Create new connection object and immediately connect using the given connection string.
General database error.
Definition nanodbc.h:323
char const * what() const noexcept override
Returns the full message, including the driver's own text.
database_error(void *handle, short handle_type, std::string const &info="")
Creates runtime_error with message about last ODBC error.
Provides access to metadata in the Implementation Row Descriptor (IRD) implicitly allocated for a pre...
Definition nanodbc.h:2479
implementation_row_descriptor(statement const &statement)
Initializes IRD access from prepared or executed statement.
implementation_row_descriptor(result const &result)
Initializes IRD access from statement of executed result set.
auto alloc_type() const -> short
Value of the header field SQL_DESC_ALLOC_AUTO.
Index out of range.
Definition nanodbc.h:299
char const * what() const noexcept override
Returns the message describing the out of range index.
Accessed null data.
Definition nanodbc.h:288
char const * what() const noexcept override
Returns the message describing the null access.
Programming logic error.
Definition nanodbc.h:310
programming_error(std::string const &info)
Creates a programming error with the given message.
char const * what() const noexcept override
Returns the message describing the error.
Single pass input iterator that accesses successive rows in the attached result set.
Definition nanodbc.h:2374
reference operator*() const noexcept
Dereference.
Definition nanodbc.h:2393
pointer operator->() const
Access through dereference.
Definition nanodbc.h:2396
result_iterator()=default
Default iterator; an empty result set.
bool operator!=(result_iterator const &rhs) const noexcept
Iterators are not equal if they have different native statemnt handles.
Definition nanodbc.h:2435
std::ptrdiff_t difference_type
Iterator difference.
Definition nanodbc.h:2380
std::input_iterator_tag iterator_category
Category of iterator.
Definition nanodbc.h:2376
void operator++(int)
Iteration.
Definition nanodbc.h:2423
bool operator==(result_iterator const &rhs) const noexcept
Iterators are equal if they a tied to the same native statemnt handle, or both empty.
Definition nanodbc.h:2426
result_iterator & operator++()
Iteration.
Definition nanodbc.h:2404
result_iterator(result &r)
Create result iterator for a given result set.
Definition nanodbc.h:2386
A resource for managing result sets from statement execution.
Definition nanodbc.h:1922
bool complete_next()
Completes a previously-initiated async fetch for next row in the current result set.
unsigned long position() const
Returns the row position in the current result set.
result()=default
Empty result set.
bool move(long row)
Moves to and fetches the specified row in the current result set.
void * native_statement_handle() const noexcept
Returns the native ODBC statement handle.
bool async_next(void *event_handle)
Initiates an asynchronous fetch of the next row in the current result set.
void swap(result &rhs) noexcept
Member swap.
bool at_end() const noexcept
Returns true if there are no more results in the current result set.
bool skip(long rows)
Skips a number of rows and then fetches the resulting row in the current result set.
bool prior()
Fetches the prior row in the current result set.
Definition nanodbc.h:882
Represents a statement on the database.
Definition nanodbc.h:875
statement(class connection &conn, std::list< attribute > const &attributes)
Constructs a statement object and associates it to the given connection, applying the given ODBC stat...
void just_execute_direct(class connection &conn, string const &query, long batch_operations=1, long timeout=0)
Execute the previously prepared query now without constructing result object.
bool open() const noexcept
Returns true if connection is open.
void complete_prepare()
Completes a previously initiated asynchronous query preparation.
void open(class connection &conn)
Creates a statement for the given connection.
param_direction
Provides support for retrieving output/return parameters.
Definition nanodbc.h:898
@ PARAM_OUT
Binding an output parameter.
Definition nanodbc.h:900
@ PARAM_INOUT
Binding an input/output parameter.
Definition nanodbc.h:901
@ PARAM_IN
Binding an input parameter.
Definition nanodbc.h:899
bool async_prepare(string const &query, void *event_handle, long timeout=0)
Prepare the given statement, in asynchronous mode.
short columns() const
Returns the number of columns in a result set.
void disable_async() const
undocumented - for internal use only (used from result_impl)
bool async_execute_direct(class connection &conn, void *event_handle, string const &query, long batch_operations=1, long timeout=0)
Opens, prepares, and executes query directly on the given connection, in async mode.
void describe_parameters(const std::vector< short > &idx, const std::vector< short > &type, const std::vector< unsigned long > &size, const std::vector< short > &scale)
Sets descriptions for parameters in the prepared statement.
statement(class connection &conn)
Constructs a statement object and associates it to the given connection.
void swap(statement &rhs) noexcept
Member swap.
bool async_execute(void *event_handle, long batch_operations=1, long timeout=0)
Execute the previously prepared query now, in asynchronous mode.
statement()
Creates a new un-prepared statement.
void enable_async(void *event_handle)
undocumented - for internal use only (used from result_impl)
statement(class connection &conn, string const &query, long timeout=0)
Constructs and prepares a statement using the given connection and query.
void reset_parameters() noexcept
Resets all currently bound parameters.
void just_execute(long batch_operations=1, long timeout=0)
Execute the previously prepared query now without constructing result object.
long affected_rows() const
Returns rows affected by the request or -1 if affected rows is not available.
Support for table-valued parameter.
Definition nanodbc.h:612
table_valued_parameter(statement &stmt, short param_index, size_t row_count)
Creates a table-valued parameter and opens it on the given statement.
void open(statement &stmt, short param_index, std::size_t row_count)
Opens the parameter on a statement, ready for values to be bound to it.
void bind_null(short param_index)
Binds a null value to the given column of every row.
void close()
Finishes the parameter, so the statement can be executed or bound further.
short parameters() const noexcept
Returns the number of columns in the table valued parameter.
table_valued_parameter()
Creates a table-valued parameter that is not yet open.
void describe_parameters(const std::vector< short > &idx, const std::vector< short > &type, const std::vector< unsigned long > &size, const std::vector< short > &scale)
Sets descriptions for columns of the table-valued parameter.
A resource for managing transaction commits and rollbacks.
Definition nanodbc.h:560
void rollback() noexcept
Marks this transaction for rollback.
transaction(const class connection &conn)
Begin a transaction on the given connection object.
void commit()
Commits transaction immediately.
void swap(transaction &rhs) noexcept
Member swap.
Type incompatible.
Definition nanodbc.h:277
char const * what() const noexcept override
Returns the message describing the incompatibility.
void bind(short param_index, T const *values, std::size_t batch_size, T const *null_sentry)
Binds multiple values.
void bind(short param_index, std::vector< std::vector< uint8_t > > const &values, std::vector< uint8_t > const &null_sentry)
Binds multiple values, those equal to the sentry, in size and bytes, as null.
void bind(short param_index, std::vector< std::vector< uint8_t > > const &values)
Binds multiple values.
void bind(short param_index, std::vector< std::vector< uint8_t > > const &values, bool const *nulls)
Binds multiple values.
void bind(short param_index, T const *values, std::size_t batch_size, param_direction direction=PARAM_IN)
Binds multiple values.
void bind(short param_index, T const *values, std::size_t batch_size, bool const *nulls)
Binds multiple values.
NANODBC_DEPRECATED void bind(short param_index, std::vector< std::vector< uint8_t > > const &values, uint8_t const *null_sentry, param_direction direction=PARAM_IN)
Binds multiple values.
void bind(short param_index, std::vector< std::vector< uint8_t > > const &values, bool const *nulls, param_direction direction=PARAM_IN)
Binds multiple values.
void bind(short param_index, std::vector< std::optional< T > > const &values, param_direction direction=PARAM_IN)
Binds a batch of values, any of which may be absent and bound as null.
Definition nanodbc.h:1403
void bind(short param_index, T const *values, std::size_t batch_size)
Binds multiple values.
void bind(short param_index, std::vector< T > const &values, param_direction direction=PARAM_IN)
Binds multiple values, holding a copy of them.
void bind(short param_index, T const *values, std::size_t batch_size, bool const *nulls, param_direction direction=PARAM_IN)
Binds multiple values.
void bind(short param_index, std::vector< std::vector< uint8_t > > const &values, param_direction direction=PARAM_IN)
Binds multiple values.
void bind(short param_index, std::vector< std::vector< uint8_t > > const &values, std::vector< uint8_t > const &null_sentry, param_direction direction=PARAM_IN)
Binds multiple values, those equal to the sentry, in size and bytes, as null.
void bind(short param_index, T const *values, std::size_t batch_size, T const *null_sentry, param_direction direction=PARAM_IN)
Binds multiple values.
void bind(short param_index, std::vector< T > const &values, bool const *nulls, param_direction direction=PARAM_IN)
Binds multiple values, holding a copy of them.
NANODBC_DEPRECATED void bind(short param_index, std::vector< std::vector< uint8_t > > const &values, uint8_t const *null_sentry)
Binds multiple values.
void bind_strings(short param_index, T const (&values)[BatchSize][ValueSize], bool const *nulls, param_direction direction=PARAM_IN)
Binds multiple string values.
Definition nanodbc.h:1538
void bind_strings(short param_index, T const (&values)[BatchSize][ValueSize], bool const *nulls)
Binds multiple string values.
Definition nanodbc.h:811
void bind_strings(short param_index, T const *values, std::size_t value_size, std::size_t batch_size, T const *null_sentry)
Binds multiple string values.
void bind_strings(short param_index, std::vector< std::optional< T > > const &values, param_direction direction=PARAM_IN)
Binds a batch of strings, any of which may be absent and bound as null.
Definition nanodbc.h:1566
void bind_strings(short param_index, std::vector< T > const &values, bool const *nulls)
Binds multiple string values.
void bind_strings(short param_index, std::vector< T > const &values, typename T::value_type const *null_sentry)
Binds multiple string values.
void bind_strings(short param_index, std::vector< T > const &values, bool const *nulls, param_direction direction=PARAM_IN)
Binds multiple string values.
void bind_strings(short param_index, T const (&values)[BatchSize][ValueSize])
Binds multiple string values.
Definition nanodbc.h:751
void bind_strings(short param_index, T const *values, std::size_t value_size, std::size_t batch_size, param_direction direction=PARAM_IN)
Binds multiple string values.
void bind_strings(short param_index, T const (&values)[BatchSize][ValueSize], T const *null_sentry)
Binds multiple string values.
Definition nanodbc.h:783
void bind_strings(short param_index, T const (&values)[BatchSize][ValueSize], param_direction direction=PARAM_IN)
Binds multiple string values.
Definition nanodbc.h:1465
void bind_strings(short param_index, T const *values, std::size_t value_size, std::size_t batch_size, T const *null_sentry, param_direction direction=PARAM_IN)
Binds multiple string values.
void bind_strings(short param_index, T const *values, std::size_t value_size, std::size_t batch_size, bool const *nulls)
Binds multiple string values.
void bind_strings(short param_index, std::vector< T > const &values, typename T::value_type const *null_sentry, param_direction direction=PARAM_IN)
Binds multiple string values.
void bind_strings(short param_index, T const *values, std::size_t value_size, std::size_t batch_size)
Binds multiple string values.
void bind_strings(short param_index, T const *values, std::size_t value_size, std::size_t batch_size, bool const *nulls, param_direction direction=PARAM_IN)
Binds multiple string values.
void bind_strings(short param_index, T const (&values)[BatchSize][ValueSize], T const *null_sentry, param_direction direction=PARAM_IN)
Binds multiple string values.
Definition nanodbc.h:1501
void bind_strings(short param_index, std::vector< T > const &values, param_direction direction=PARAM_IN)
Binds multiple string values.
void bind_strings(short param_index, std::vector< T > const &values)
Binds multiple string values.
void bind_null(short param_index, std::size_t batch_size=1)
Binds null values to the parameter placeholder number in the prepared statement.
void bind(short param_index, T const *value, param_direction direction=PARAM_IN)
Binds given value to given parameter placeholder number in the prepared statement.
result_iterator end(result &) noexcept
Returns an iterator to the end of a result set.
Definition nanodbc.h:2453
result_iterator begin(result &r)
Returns an iterator to the beginning of the given result set.
Definition nanodbc.h:2442
void prepare(statement &stmt, string const &query, long timeout=0)
Prepares the given statement to execute on it associated connection.
void bind_rows(statement &stmt, Rows const &rows, Accessors const &... accessors)
Binds a range of rows, a parameter at a time.
Definition nanodbc.h:3234
result execute(connection &conn, string const &query, long batch_operations=1, long timeout=0)
Immediately opens, prepares, and executes the given query directly on the given connection.
void just_transact(statement &stmt, long batch_operations)
Execute the previously prepared query now and without creating result object.
result transact(statement &stmt, long batch_operations)
Execute the previously prepared query now.
std::list< driver > list_drivers()
Returns a list of ODBC drivers on your system.
std::list< datasource > list_datasources()
Returns a list of ODBC data sources on your system.
void just_execute(connection &conn, string const &query, long batch_operations=1, long timeout=0)
Opens, prepares, and executes query directly without creating result object.
std::enable_if_t< is_character_v< T > > enable_if_character
Enables an overload only for the character types nanodbc binds as strings.
Definition nanodbc.h:504
constexpr bool is_owning_string_v
Whether a type is a string owning the characters it holds.
Definition nanodbc.h:485
std::bool_constant< std::is_same_v< std::decay_t< T >, std::string >||std::is_same_v< std::decay_t< T >, wide_string > > is_owning_string
A type trait for testing if a type is a string owning the characters it holds.
Definition nanodbc.h:481
constexpr bool is_string_v
Whether a type is a string compatible with the current nanodbc configuration.
Definition nanodbc.h:473
std::bool_constant< std::is_same_v< std::decay_t< T >, std::string >||std::is_same_v< std::decay_t< T >, wide_string >||std::is_same_v< std::decay_t< T >, std::string_view >||std::is_same_v< std::decay_t< T >, wide_string_view > > is_string
A type trait for testing if a type is a std::basic_string compatible with the current nanodbc configu...
Definition nanodbc.h:469
constexpr bool is_character_v
Whether a type is a character compatible with the current nanodbc configuration.
Definition nanodbc.h:496
std::enable_if_t< is_string_v< T > > enable_if_string
Enables an overload only for the string types nanodbc binds as strings.
Definition nanodbc.h:500
std::bool_constant< std::is_same_v< std::decay_t< T >, std::string::value_type >||std::is_same_v< std::decay_t< T >, wide_char_t > > is_character
A type trait for testing if a type is a character compatible with the current nanodbc configuration.
Definition nanodbc.h:492
Member const & read_field(Row const &row, Member Class::*field)
Reads a member through a pointer to it.
Definition nanodbc.h:3054
std::unique_ptr< bool[]> split_optional(std::vector< std::optional< T > > const &values, std::vector< T > &column)
Splits optionals into the values themselves and flags saying which are null.
Definition nanodbc.h:519
The entirety of nanodbc can be found within this one namespace.
Definition nanodbc.h:112
unspecified type string
string will be std::u16string or std::32string if NANODBC_ENABLE_UNICODE defined.
Definition nanodbc.h:230
unspecified type null_type
null_type will be int64_t for 64-bit compilations, otherwise long.
Definition nanodbc.h:232
#define NANODBC_DEPRECATED
Marks a declaration as deprecated.
Definition nanodbc.h:237
A type capturing parameter array length as well as number of rows in a rowset of a result.
Definition nanodbc.h:368
batch_ops()=default
Creates lengths of -1, meaning neither has been chosen.
batch_ops(const long all_length) noexcept
Creates both lengths with the same value.
Definition nanodbc.h:377
A data source name registered with the driver manager.
Definition nanodbc.h:3011
nanodbc::string driver
Driver description.
Definition nanodbc.h:3013
nanodbc::string name
DSN name.
Definition nanodbc.h:3012
A type for representing date data.
Definition nanodbc.h:384
std::int16_t month
Month of the year [1-12].
Definition nanodbc.h:386
std::int16_t day
Day of the month [1-31].
Definition nanodbc.h:387
std::int16_t year
Year [0-inf).
Definition nanodbc.h:385
Definition nanodbc.h:3092
Definition nanodbc.h:3089
Definition nanodbc.h:3103
The type an accessor yields for a row, stripped of reference and const.
Definition nanodbc.h:3069
Definition nanodbc.h:3076
Driver attributes.
Definition nanodbc.h:3000
nanodbc::string keyword
Driver keyword attribute.
Definition nanodbc.h:3001
nanodbc::string value
Driver attribute value.
Definition nanodbc.h:3002
Information on a configured ODBC driver.
Definition nanodbc.h:2997
nanodbc::string name
Driver name.
Definition nanodbc.h:3005
std::list< attribute > attributes
List of driver attributes.
Definition nanodbc.h:3006
A type for representing time data.
Definition nanodbc.h:392
std::int16_t hour
Hours since midnight [0-23].
Definition nanodbc.h:393
std::int16_t min
Minutes after the hour [0-59].
Definition nanodbc.h:394
std::int16_t sec
Seconds after the minute.
Definition nanodbc.h:395
A type for representing timestamp data.
Definition nanodbc.h:400
std::int16_t hour
Hours since midnight [0-23].
Definition nanodbc.h:404
std::int16_t sec
Seconds after the minute.
Definition nanodbc.h:406
std::int16_t day
Day of the month [1-31].
Definition nanodbc.h:403
std::int16_t year
Year [0-inf).
Definition nanodbc.h:401
std::int16_t min
Minutes after the hour [0-59].
Definition nanodbc.h:405
std::int32_t fract
Fractional seconds.
Definition nanodbc.h:407
std::int16_t month
Month of the year [1-12].
Definition nanodbc.h:402
A type for representing timestamp+offset data.
Definition nanodbc.h:412
std::int16_t offset_minute
Minutes part of time zome offset.
Definition nanodbc.h:415
timestamp stamp
Date and time, in the offset's local terms.
Definition nanodbc.h:413
std::int16_t offset_hour
Whole hour part of time zone offset.
Definition nanodbc.h:414