aGrUM  0.16.0
nanodbc.h
Go to the documentation of this file.
1 #ifndef DOXYGEN_SHOULD_SKIP_THIS
2 
3 #ifdef _ODBC // Enable Nanodbc only if an odbc driver was found
4 
6 
77 
78 #ifndef NANODBC_H
79 #define NANODBC_H
80 
81 #include <functional>
82 #include <memory>
83 #include <stdexcept>
84 #include <string>
85 #include <vector>
86 
87 #ifndef __clang__
88  #include <cstdint>
89 #endif
90 
93 namespace nanodbc
94 {
95 
96 // .d8888b. .d888 d8b 888 d8b
97 // d88P Y88b d88P" Y8P 888 Y8P
98 // 888 888 888 888
99 // 888 .d88b. 88888b. 888888 888 .d88b. 888 888 888d888 8888b. 888888 888 .d88b. 88888b.
100 // 888 d88""88b 888 "88b 888 888 d88P"88b 888 888 888P" "88b 888 888 d88""88b 888 "88b
101 // 888 888 888 888 888 888 888 888 888 888 888 888 888 .d888888 888 888 888 888 888 888
102 // Y88b d88P Y88..88P 888 888 888 888 Y88b 888 Y88b 888 888 888 888 Y88b. 888 Y88..88P 888 888
103 // "Y8888P" "Y88P" 888 888 888 888 "Y88888 "Y88888 888 "Y888888 "Y888 888 "Y88P" 888 888
104 // 888
105 // Y8b d88P
106 // "Y88P"
107 // MARK: Configuration -
108 
113 
114 #ifdef DOXYGEN
115  #define NANODBC_ASSERT(expression) assert(expression)
130 #endif
131 
133 
134 // You must explicitly request Unicode support by defining NANODBC_USE_UNICODE at compile time.
135 #ifndef DOXYGEN
136  #ifdef NANODBC_USE_UNICODE
137  #ifdef NANODBC_USE_IODBC_WIDE_STRINGS
138  typedef std::u32string string_type;
139  #else
140  typedef std::u16string string_type;
141  #endif
142  #else
143  typedef std::string string_type;
144  #endif // NANODBC_USE_UNICODE
145 
146  #if defined(_WIN64)
147  // LLP64 machine: Windows
148  typedef std::int64_t null_type;
149  #elif !defined(_WIN64) && defined(__LP64__)
150  // LP64 machine: OS X or Linux
151  typedef long null_type;
152  #else
153  // 32-bit machine
154  typedef long null_type;
155  #endif
156 #else
157  typedef unspecified-type string_type;
160  typedef unspecified-type null_type;
161 #endif // DOXYGEN
162 
163 #if defined(_MSC_VER) && _MSC_VER <= 1800
164  // These versions of Visual C++ do not yet support \c noexcept or \c std::move.
165  #define NANODBC_NOEXCEPT
166  #define NANODBC_NO_MOVE_CTOR
167 #else
168  #define NANODBC_NOEXCEPT noexcept
169 #endif
170 
171 // 8888888888 888 888 888 888 d8b
172 // 888 888 888 888 888 Y8P
173 // 888 888 888 888 888
174 // 8888888 888d888 888d888 .d88b. 888d888 8888888888 8888b. 88888b. .d88888 888 888 88888b. .d88b.
175 // 888 888P" 888P" d88""88b 888P" 888 888 "88b 888 "88b d88" 888 888 888 888 "88b d88P"88b
176 // 888 888 888 888 888 888 888 888 .d888888 888 888 888 888 888 888 888 888 888 888
177 // 888 888 888 Y88..88P 888 888 888 888 888 888 888 Y88b 888 888 888 888 888 Y88b 888
178 // 8888888888 888 888 "Y88P" 888 888 888 "Y888888 888 888 "Y88888 888 888 888 888 "Y88888
179 // 888
180 // Y8b d88P
181 // "Y88P"
182 // MARK: Error Handling -
183 
192 
195 class type_incompatible_error : public std::runtime_error
196 {
197 public:
198  type_incompatible_error();
199  const char* what() const NANODBC_NOEXCEPT;
200 };
201 
204 class null_access_error : public std::runtime_error
205 {
206 public:
207  null_access_error();
208  const char* what() const NANODBC_NOEXCEPT;
209 };
210 
213 class index_range_error : public std::runtime_error
214 {
215 public:
216  index_range_error();
217  const char* what() const NANODBC_NOEXCEPT;
218 };
219 
222 class programming_error : public std::runtime_error
223 {
224 public:
225  explicit programming_error(const std::string& info);
226  const char* what() const NANODBC_NOEXCEPT;
227 };
228 
231 class database_error : public std::runtime_error
232 {
233 public:
238  database_error(void* handle, short handle_type, const std::string& info = "");
239  const char* what() const NANODBC_NOEXCEPT;
240  const long native() const NANODBC_NOEXCEPT;
241  const std::string state() const NANODBC_NOEXCEPT;
242 private:
243  long native_error;
244  std::string sql_state;
245  std::string message;
246 };
247 
249 
250 // 888 888 888 d8b 888 d8b 888 d8b
251 // 888 888 888 Y8P 888 Y8P 888 Y8P
252 // 888 888 888 888 888
253 // 888 888 888888 888 888 888 888888 888 .d88b. .d8888b
254 // 888 888 888 888 888 888 888 888 d8P Y8b 88K
255 // 888 888 888 888 888 888 888 888 88888888 "Y8888b.
256 // Y88b. .d88P Y88b. 888 888 888 Y88b. 888 Y8b. X88
257 // "Y88888P" "Y888 888 888 888 "Y888 888 "Y8888 88888P'
258 // MARK: Utilities -
259 
264 
266 struct date
267 {
268  std::int16_t year;
269  std::int16_t month;
270  std::int16_t day;
271 };
272 
274 struct timestamp
275 {
276  std::int16_t year;
277  std::int16_t month;
278  std::int16_t day;
279  std::int16_t hour;
280  std::int16_t min;
281  std::int16_t sec;
282  std::int32_t fract;
283 };
284 
286 
291 
292 // 88888888888 888 d8b
293 // 888 888 Y8P
294 // 888 888
295 // 888 888d888 8888b. 88888b. .d8888b 8888b. .d8888b 888888 888 .d88b. 88888b.
296 // 888 888P" "88b 888 "88b 88K "88b d88P" 888 888 d88""88b 888 "88b
297 // 888 888 .d888888 888 888 "Y8888b. .d888888 888 888 888 888 888 888 888
298 // 888 888 888 888 888 888 X88 888 888 Y88b. Y88b. 888 Y88..88P 888 888
299 // 888 888 "Y888888 888 888 88888P' "Y888888 "Y8888P "Y888 888 "Y88P" 888 888
300 // MARK: Transaction -
301 
305 class transaction
306 {
307 public:
311  explicit transaction(const class connection& conn);
312 
314  transaction(const transaction& rhs);
315 
316  #ifndef NANODBC_NO_MOVE_CTOR
317  transaction(transaction&& rhs) NANODBC_NOEXCEPT;
319  #endif
320 
322  transaction& operator=(transaction rhs);
323 
325  void swap(transaction& rhs) NANODBC_NOEXCEPT;
326 
328  ~transaction() NANODBC_NOEXCEPT;
329 
332  void commit();
333 
335  void rollback() NANODBC_NOEXCEPT;
336 
338  class connection& connection();
339 
341  const class connection& connection() const;
342 
344  operator class connection&();
345 
347  operator const class connection&() const;
348 
349 private:
350  class transaction_impl;
351  friend class nanodbc::connection;
352 
353 private:
354  std::shared_ptr<transaction_impl> impl_;
355 };
356 
357 // .d8888b. 888 888 888
358 // d88P Y88b 888 888 888
359 // Y88b. 888 888 888
360 // "Y888b. 888888 8888b. 888888 .d88b. 88888b.d88b. .d88b. 88888b. 888888
361 // "Y88b. 888 "88b 888 d8P Y8b 888 "888 "88b d8P Y8b 888 "88b 888
362 // "888 888 .d888888 888 88888888 888 888 888 88888888 888 888 888
363 // Y88b d88P Y88b. 888 888 Y88b. Y8b. 888 888 888 Y8b. 888 888 Y88b.
364 // "Y8888P" "Y888 "Y888888 "Y888 "Y8888 888 888 888 "Y8888 888 888 "Y888
365 // MARK: Statement -
366 
368 class statement
369 {
370 public:
373  enum param_direction
374  {
375  PARAM_IN
376  , PARAM_OUT
377  , PARAM_INOUT
378  , PARAM_RETURN
379  };
380 
381 public:
384  statement();
385 
389  explicit statement(class connection& conn);
390 
396  statement(class connection& conn, const string_type& query, long timeout = 0);
397 
399  statement(const statement& rhs);
400 
401  #ifndef NANODBC_NO_MOVE_CTOR
402  statement(statement&& rhs) NANODBC_NOEXCEPT;
404  #endif
405 
407  statement& operator=(statement rhs);
408 
410  void swap(statement& rhs) NANODBC_NOEXCEPT;
411 
414  ~statement() NANODBC_NOEXCEPT;
415 
419  void open(class connection& conn);
420 
422  bool open() const;
423 
425  bool connected() const;
426 
428  class connection& connection();
429 
431  const class connection& connection() const;
432 
434  void* native_statement_handle() const;
435 
437  void close();
438 
441  void cancel();
442 
449  void prepare(class connection& conn, const string_type& query, long timeout = 0);
450 
457  void prepare(const string_type& query, long timeout = 0);
458 
461  void timeout(long timeout = 0);
462 
471  class result execute_direct(class connection& conn, const string_type& query, long batch_operations = 1, long timeout = 0);
472 
486  void async_execute_direct(class connection& conn, void* event_handle, const string_type& query, long batch_operations = 1, long timeout = 0);
487 
495  class result async_complete(long batch_operations = 1);
496 
506  void just_execute_direct(class connection& conn, const string_type& query, long batch_operations = 1, long timeout = 0);
507 
515  class result execute(long batch_operations = 1, long timeout = 0);
516 
524  void just_execute(long batch_operations = 1, long timeout = 0);
525 
533  class result procedure_columns(const string_type& catalog, const string_type& schema, const string_type& procedure, const string_type& column);
534 
537  long affected_rows() const;
538 
541  short columns() const;
542 
544  void reset_parameters() NANODBC_NOEXCEPT;
545 
547  unsigned long parameter_size(short param) const;
548 
553 
565  template<class T>
566  void bind(short param, const T* value, param_direction direction = PARAM_IN);
567 
585 
588  template<class T>
589  void bind(short param, const T* values, std::size_t elements, param_direction direction = PARAM_IN);
590 
593  template<class T>
594  void bind(short param, const T* values, std::size_t elements, const T* null_sentry, param_direction direction = PARAM_IN);
595 
598  template<class T>
599  void bind(short param, const T* values, std::size_t elements, const bool* nulls, param_direction direction = PARAM_IN);
600 
602 
621 
624  void bind_strings(
625  short param
626  , const string_type::value_type* values
627  , std::size_t length
628  , std::size_t elements
629  , param_direction direction = PARAM_IN);
630 
633  template<std::size_t N, std::size_t M>
634  void bind_strings(
635  short param
636  , const string_type::value_type(&values)[N][M]
637  , param_direction direction = PARAM_IN)
638  {
639  bind_strings(
640  param
641  , reinterpret_cast<const string_type::value_type*>(values)
642  , M
643  , N
644  , direction);
645  }
646 
649  void bind_strings(
650  short param
651  , const string_type::value_type* values
652  , std::size_t length
653  , std::size_t elements
654  , const string_type::value_type* null_sentry
655  , param_direction direction = PARAM_IN);
656 
659  template<std::size_t N, std::size_t M>
660  void bind_strings(
661  short param
662  , const string_type::value_type(&values)[N][M]
663  , const string_type::value_type* null_sentry
664  , param_direction direction = PARAM_IN)
665  {
666  bind_strings(
667  param
668  , reinterpret_cast<const string_type::value_type*>(values)
669  , M
670  , N
671  , null_sentry
672  , direction);
673  }
674 
677  void bind_strings(
678  short param
679  , const string_type::value_type* values
680  , std::size_t length
681  , std::size_t elements
682  , const bool* nulls
683  , param_direction direction = PARAM_IN);
684 
687  template<std::size_t N, std::size_t M>
688  void bind_strings(
689  short param
690  , const string_type::value_type(&values)[N][M]
691  , const bool* nulls
692  , param_direction direction = PARAM_IN)
693  {
694  bind_strings(
695  param
696  , reinterpret_cast<const string_type::value_type*>(values)
697  , M
698  , N
699  , nulls
700  , direction);
701  }
702 
704 
715  void bind_null(short param, std::size_t elements = 1);
716 
718 
719 private:
720  typedef std::function<bool (std::size_t)> null_predicate_type;
721 
722 private:
723  class statement_impl;
724  friend class nanodbc::result;
725 
726 private:
727  std::shared_ptr<statement_impl> impl_;
728 };
729 
730 // .d8888b. 888 d8b
731 // d88P Y88b 888 Y8P
732 // 888 888 888
733 // 888 .d88b. 88888b. 88888b. .d88b. .d8888b 888888 888 .d88b. 88888b.
734 // 888 d88""88b 888 "88b 888 "88b d8P Y8b d88P" 888 888 d88""88b 888 "88b
735 // 888 888 888 888 888 888 888 888 88888888 888 888 888 888 888 888 888
736 // Y88b d88P Y88..88P 888 888 888 888 Y8b. Y88b. Y88b. 888 Y88..88P 888 888
737 // "Y8888P" "Y88P" 888 888 888 888 "Y8888 "Y8888P "Y888 888 "Y88P" 888 888
738 // MARK: Connection -
739 
741 class connection
742 {
743 public:
745  connection();
746 
748  connection(const connection& rhs);
749 
750  #ifndef NANODBC_NO_MOVE_CTOR
751  connection(connection&& rhs) NANODBC_NOEXCEPT;
753  #endif
754 
756  connection& operator=(connection rhs);
757 
759  void swap(connection&) NANODBC_NOEXCEPT;
760 
768  connection(
769  const string_type& dsn
770  , const string_type& user
771  , const string_type& pass
772  , long timeout = 0);
773 
779  connection(const string_type& connection_string, long timeout = 0);
780 
785  ~connection() NANODBC_NOEXCEPT;
786 
794  void connect(
795  const string_type& dsn
796  , const string_type& user
797  , const string_type& pass
798  , long timeout = 0);
799 
805  void connect(const string_type& connection_string, long timeout = 0);
806 
820  void async_connect(
821  const string_type& dsn
822  , const string_type& user
823  , const string_type& pass
824  , void* event_handle
825  , long timeout = 0);
826 
838  void async_connect(const string_type& connection_string, void* event_handle, long timeout = 0);
839 
841  void async_complete();
842 
844  bool connected() const;
845 
847  void disconnect();
848 
850  std::size_t transactions() const;
851 
853  void* native_dbc_handle() const;
854 
856  void* native_env_handle() const;
857 
861  string_type dbms_name() const;
862 
866  string_type dbms_version() const;
867 
870  string_type driver_name() const;
871 
874  string_type database_name() const;
875 
878  string_type catalog_name() const;
879 
880 private:
881  std::size_t ref_transaction();
882  std::size_t unref_transaction();
883  bool rollback() const;
884  void rollback(bool onoff);
885 
886 private:
887  class connection_impl;
888  friend class nanodbc::transaction::transaction_impl;
889 
890 private:
891  std::shared_ptr<connection_impl> impl_;
892 };
893 
894 // 8888888b. 888 888
895 // 888 Y88b 888 888
896 // 888 888 888 888
897 // 888 d88P .d88b. .d8888b 888 888 888 888888
898 // 8888888P" d8P Y8b 88K 888 888 888 888
899 // 888 T88b 88888888 "Y8888b. 888 888 888 888
900 // 888 T88b Y8b. X88 Y88b 888 888 Y88b.
901 // 888 T88b "Y8888 88888P' "Y88888 888 "Y888
902 // MARK: Result -
903 
904 class catalog;
905 
910 class result
911 {
912 public:
914  result();
915 
917  ~result() NANODBC_NOEXCEPT;
918 
920  result(const result& rhs);
921 
922  #ifndef NANODBC_NO_MOVE_CTOR
923  result(result&& rhs) NANODBC_NOEXCEPT;
925  #endif
926 
928  result& operator=(result rhs);
929 
931  void swap(result& rhs) NANODBC_NOEXCEPT;
932 
934  void* native_statement_handle() const;
935 
937  long rowset_size() const NANODBC_NOEXCEPT;
938 
941  long affected_rows() const;
942 
944  long rows() const NANODBC_NOEXCEPT;
945 
948  short columns() const;
949 
953  bool first();
954 
958  bool last();
959 
963  bool next();
964 
968  bool prior();
969 
973  bool move(long row);
974 
978  bool skip(long rows);
979 
981  unsigned long position() const;
982 
984  bool end() const NANODBC_NOEXCEPT;
985 
992  template<class T>
993  void get_ref(short column, T& result) const;
994 
1003  template<class T>
1004  void get_ref(short column, const T& fallback, T& result) const;
1005 
1011  template<class T>
1012  void get_ref(const string_type& column_name, T& result) const;
1013 
1021  template<class T>
1022  void get_ref(const string_type& column_name, const T& fallback, T& result) const;
1023 
1029  template<class T>
1030  T get(short column) const;
1031 
1039  template<class T>
1040  T get(short column, const T& fallback) const;
1041 
1046  template<class T>
1047  T get(const string_type& column_name) const;
1048 
1055  template<class T>
1056  T get(const string_type& column_name, const T& fallback) const;
1057 
1070  bool is_null(short column) const;
1071 
1078  bool is_null(const string_type& column_name) const;
1079 
1085  string_type column_name(short column) const;
1086 
1092  long column_size(short column) const;
1093 
1099  short column(const string_type& column_name) const;
1100 
1102  int column_datatype(short column) const;
1103 
1105  int column_datatype(const string_type& column_name) const;
1106 
1108  int column_c_datatype(short column) const;
1109 
1111  int column_c_datatype(const string_type& column_name) const;
1112 
1114  bool next_result();
1115 
1117  explicit operator bool() const;
1118 
1119 private:
1120  result(statement statement, long rowset_size);
1121 
1122 private:
1123  class result_impl;
1124  friend class nanodbc::statement::statement_impl;
1125  friend class nanodbc::catalog;
1126 
1127 private:
1128  std::shared_ptr<result_impl> impl_;
1129 };
1130 
1131 
1132 //
1133 // .d8888b. 888 888
1134 // d88P Y88b 888 888
1135 // 888 888 888 888
1136 // 888 8888b. 888888 8888b. 888 .d88b. .d88b.
1137 // 888 "88b 888 "88b 888 d88""88b d88P"88b
1138 // 888 888 .d888888 888 .d888888 888 888 888 888 888
1139 // Y88b d88P 888 888 Y88b. 888 888 888 Y88..88P Y88b 888
1140 // "Y8888P" "Y888888 "Y888 "Y888888 888 "Y88P" "Y88888
1141 // 888
1142 // Y8b d88P
1143 // "Y88P"
1144 // MARK: Catalog -
1145 
1146 class catalog
1147 {
1148 public:
1149 
1150  class tables
1151  {
1152  public:
1153  bool next();
1154  string_type table_catalog() const;
1155  string_type table_schema() const;
1156  string_type table_name() const;
1157  string_type table_type() const;
1158  string_type table_remarks() const;
1159 
1160  private:
1161  friend class nanodbc::catalog;
1162  tables(result& find_result);
1163  result result_;
1164  };
1165 
1166  class columns
1167  {
1168  public:
1169 
1171  bool next();
1172 
1174  string_type table_catalog() const;
1175 
1177  string_type table_schema() const;
1178 
1180  string_type table_name() const;
1181 
1183  string_type column_name() const;
1184 
1186  short data_type() const;
1187 
1189  string_type type_name() const;
1190 
1192  long column_size() const;
1193 
1195  long buffer_length() const;
1196 
1198  short decimal_digits() const;
1199 
1201  short numeric_precision_radix() const;
1202 
1204  short nullable() const;
1205 
1207  string_type remarks() const;
1208 
1210  string_type column_default() const;
1211 
1213  short sql_data_type() const;
1214 
1216  short sql_datetime_subtype() const;
1217 
1219  long char_octed_length() const;
1220 
1224  long ordinal_position() const;
1225 
1228  string_type is_nullable() const;
1229 
1230  private:
1231  friend class nanodbc::catalog;
1232  columns(result& find_result);
1233  result result_;
1234  };
1235 
1236  class primary_keys
1237  {
1238  public:
1239  bool next();
1240  string_type table_catalog() const;
1241  string_type table_schema() const;
1242  string_type table_name() const;
1243  string_type column_name() const;
1244 
1247  short column_number() const;
1248 
1252  string_type primary_key_name() const;
1253 
1254  private:
1255  friend class nanodbc::catalog;
1256  primary_keys(result& find_result);
1257  result result_;
1258  };
1259 
1261  catalog(connection& conn);
1262 
1269  catalog::tables find_tables(
1270  const string_type& table = string_type()
1271  , const string_type& type = string_type()
1272  , const string_type& schema = string_type()
1273  , const string_type& catalog = string_type());
1274 
1281  catalog::columns find_columns(
1282  const string_type& column = string_type()
1283  , const string_type& table = string_type()
1284  , const string_type& schema = string_type()
1285  , const string_type& catalog = string_type());
1286 
1292  catalog::primary_keys find_primary_keys(
1293  const string_type& table
1294  , const string_type& schema = string_type()
1295  , const string_type& catalog = string_type());
1296 
1297 private:
1298  connection conn_;
1299 };
1300 
1302 
1303 // 8888888888 8888888888 888 d8b
1304 // 888 888 888 Y8P
1305 // 888 888 888
1306 // 8888888 888d888 .d88b. .d88b. 8888888 888 888 88888b. .d8888b 888888 888 .d88b. 88888b. .d8888b
1307 // 888 888P" d8P Y8b d8P Y8b 888 888 888 888 "88b d88P" 888 888 d88""88b 888 "88b 88K
1308 // 888 888 88888888 88888888 888 888 888 888 888 888 888 888 888 888 888 888 "Y8888b.
1309 // 888 888 Y8b. Y8b. 888 Y88b 888 888 888 Y88b. Y88b. 888 Y88..88P 888 888 X88
1310 // 888 888 "Y8888 "Y8888 888 "Y88888 888 888 "Y8888P "Y888 888 "Y88P" 888 888 88888P'
1311 // MARK: Free Functions -
1312 
1317 
1326 result execute(
1327  connection& conn
1328  , const string_type& query
1329  , long batch_operations = 1
1330  , long timeout = 0);
1331 
1340 void just_execute(
1341  connection& conn
1342  , const string_type& query
1343  , long batch_operations = 1
1344  , long timeout = 0);
1345 
1353 result execute(statement& stmt, long batch_operations = 1);
1354 
1362 void just_execute(statement& stmt, long batch_operations = 1);
1363 
1371 result transact(statement& stmt, long batch_operations);
1372 
1380 void just_transact(statement& stmt, long batch_operations);
1381 
1389 void prepare(statement& stmt, const string_type& query, long timeout = 0);
1390 
1392 
1393 } // namespace nanodbc
1394 
1395 #endif // NANODBC_H
1396 
1397 #endif // _ODBC
1398 
1399 #endif // DOXYGEN_SHOULD_SKIP_THIS
STL namespace.
void swap(HashTable< LpCol, double > *&a, HashTable< LpCol, double > *&b)
Swap the addresses of two pointers to hashTables.