forked from lexicalunit/nanodbc
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathnanodbc.h
executable file
·908 lines (763 loc) · 36 KB
/
nanodbc.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
//! \file nanodbc.h The entirety of nanodbc can be found within this file and nanodbc.cpp.
//! \mainpage
//!
//! \section synopsis Synopsis
//! This library provides a wrapper API for the native ODBC API. It aims to do everything ODBC does, but with a \b much nicer interface.
//! Anything it doesn't (yet) do can be done by retrieving the native ODBC handles and dropping down to straight ODBC C API code.
//! For more propaganda, please see the <a href="http://lexicalunit.github.com/nanodbc/">project homepage</a>.
//!
//! \section toc Table of Contents
//! - \ref license "License"
//! - \ref credits "Credits"
//! - \ref examples "Examples"
//! - Source level documentation:
//! - \ref nanodbc "nanodbc namespace"
//! - \ref exceptions
//! - \ref utility
//! - \ref main
//! - \ref binding
//! - \ref bind_multi
//! - \ref bind_strings
//!
//! \section license License
//! Copyright (C) 2013 lexicalunit <amy@lexicalunit.com>
//!
//! The MIT License
//!
//! Permission is hereby granted, free of charge, to any person obtaining a copy
//! of this software and associated documentation files (the "Software"), to deal
//! in the Software without restriction, including without limitation the rights
//! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//! copies of the Software, and to permit persons to whom the Software is
//! furnished to do so, subject to the following conditions:
//!
//! The above copyright notice and this permission notice shall be included in
//! all copies or substantial portions of the Software.
//!
//! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
//! THE SOFTWARE.
//!
//! \section credits Credits
//! Much of the code in this file was originally derived from TinyODBC.<br />
//! TinyODBC is hosted at http://code.google.com/p/tiodbc/<br />
//! Copyright (C) 2008 SqUe squarious@gmail.com<br />
//! License: The MIT License<br />
//!
//! Transaction support was based on the implementation in SimpleDB: C++ ODBC database API.<br/>
//! SimpleDB is hosted at http://simpledb.sourceforge.net<br/>
//! Copyright (C) 2006 Eminence Technology Pty Ltd<br/>
//! Copyright (C) 2008-2010,2012 Russell Kliese russell@kliese.id.au<br/>
//! License: GNU Lesser General Public version 2.1<br/>
//!
//! Some improvements and features are based on The Python ODBC Library.<br/>
//! The Python ODBC Library is hosted at http://code.google.com/p/pyodbc/<br/>
//! License: The MIT License<br/>
//!
//! Implementation of column binding inspired by Nick E. Geht's source code posted to on CodeGuru.<br />
//! GSODBC hosted at http://www.codeguru.com/mfc_database/gsodbc.html<br />
//! Copyright (C) 2002 Nick E. Geht<br />
//! License: Perpetual license to reproduce, distribute, adapt, perform, display, and sublicense.<br/>
//! See http://www.codeguru.com/submission-guidelines.php for details.<br />
//! \page examples Example Usage
//! \brief Example library usage.
//! \include example.cpp
#ifndef NANODBC_H
#define NANODBC_H
#include <functional>
#include <stdexcept>
#include <string>
#include <vector>
// Define NANODBC_HAS_TR1_NAMESPACE if your compiler's standard library implementation
// has a std::tr1 namespace, otherwise we try to detect automatically.
#ifndef NANODBC_HAS_TR1_NAMESPACE
#if defined(_LIBCPP_VERSION) // libc++
#define NANODBC_HAS_TR1_NAMESPACE 0
#elif defined(__GLIBCXX__) // stdlibc++
#define NANODBC_HAS_TR1_NAMESPACE 1
#include <tr1/functional>
#endif
#endif
#ifdef NANODBC_USE_BOOST
#define NANODBC_TR1_STD std::
#include <boost/smart_ptr.hpp>
#include <boost/cstdint.hpp>
namespace std
{
using namespace boost;
}
#else
// You must explicitly request C++11 support by defining NANODBC_USE_CPP11 at compile time
// , otherwise nanodbc will assume it must use tr1 instead.
#ifndef NANODBC_USE_CPP11
#if NANODBC_HAS_TR1_NAMESPACE
#include <tr1/cstdint>
#include <tr1/memory>
#define NANODBC_TR1_STD std::tr1::
#else
#include <cstdint>
#include <memory>
#define NANODBC_TR1_STD std::
#endif
#else
#include <cstdint>
#include <memory>
#define NANODBC_TR1_STD std::
#endif
#endif
#ifndef DOXYGEN
namespace detail
{
// Safe Bool idiom from http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Safe_bool#Solution_and_Sample_Code
// Creative Commons Attribution/Share-Alike License: http://creativecommons.org/licenses/by-sa/3.0/
// In C++11 and on we can simply use explicit conversion operators instead of all this boilerplate
class safe_bool_base
{
public:
typedef void (safe_bool_base::*bool_type)() const;
void this_type_does_not_support_comparisons() const {}
protected:
safe_bool_base() {}
safe_bool_base(const safe_bool_base&) {}
safe_bool_base& operator=(const safe_bool_base&) {return *this;}
~safe_bool_base() {}
};
template <typename T=void>
class safe_bool : private safe_bool_base
{
// private or protected inheritance is very important here as it triggers the
// access control violation in main.
public:
operator bool_type() const
{
return (static_cast<const T*>(this))->boolean_test() ? &safe_bool_base::this_type_does_not_support_comparisons : 0;
}
protected:
~safe_bool() {}
};
} // namespace detail
#endif // DOXYGEN
//! \brief The entirety of nanodbc can be found within this one namespace.
//! \note This library does not make any exception safety guarantees, but should work just fine with a threading enabled ODBC driver. If you want to use nanodbc objects in threads I recommend each thread keep their own connection to the database. Otherwise you must synchronize any access to nanodbc objects.
namespace nanodbc
{
// You must explicitly request Unicode support by defining NANODBC_USE_UNICODE at compile time.
#ifndef DOXYGEN
#ifdef NANODBC_USE_UNICODE
typedef std::wstring string_type;
#else
typedef std::string string_type;
#endif // NANODBC_USE_UNICODE
#if defined(_WIN64)
// LLP64 machine, Windows
typedef NANODBC_TR1_STD int64_t null_type;
#elif !defined(_WIN64) && defined(__LP64__)
// LP64 machine, OS X or Linux
typedef long null_type;
#else
// 32-bit machine
typedef long null_type;
#endif
#else
//! string_type will be std::wstring if NANODBC_USE_UNICODE is defined, otherwise std::string.
typedef unspecified-type string_type;
//! null_type will be int64_t for 64-bit compilations, otherwise long.
typedef unspecified-type null_type;
#endif // DOXYGEN
//! \addtogroup exceptions Exception types
//! \brief Possible error conditions.
//!
//! Specific errors such as type_incompatible_error, null_access_error, and index_range_error can arise
//! from improper use of the nanodbc library. The general database_error is for all other situations
//! in which the ODBC driver or C API reports an error condition. The explanatory string for database_error
//! will, if possible, contain a diagnostic message obtained from SQLGetDiagRec().
//! @{
//! \brief Type incompatible.
//! \see exceptions
class type_incompatible_error : public std::runtime_error
{
public:
type_incompatible_error();
const char* what() const throw();
};
//! \brief Accessed null data.
//! \see exceptions
class null_access_error : public std::runtime_error
{
public:
null_access_error();
const char* what() const throw();
};
//! \brief Index out of range.
//! \see exceptions
class index_range_error : public std::runtime_error
{
public:
index_range_error();
const char* what() const throw();
};
//! \brief Programming logic error.
//! \see exceptions
class programming_error : public std::runtime_error
{
public:
explicit programming_error(const std::string& info);
const char* what() const throw();
};
//! \brief General database error.
//! \see exceptions
class database_error : public std::runtime_error
{
public:
//! \brief Creates a runtime_error with a message describing the last ODBC error generated for the given handle and handle_type.
//! \param handle The native ODBC statement or connection handle.
//! \param handle_type The native ODBC handle type code for the given handle.
//! \param info Additional information that will be appended to the beginning of the error message.
database_error(void* handle, short handle_type, const std::string& info = "");
const char* what() const throw();
};
//! @}
//! \addtogroup utility Utilities
//! \brief Additional nanodbc utility classes and functions.
//!
//! \{
//! \brief A type for representing date data.
struct date
{
NANODBC_TR1_STD int16_t year; //!< Year [0-inf).
NANODBC_TR1_STD int16_t month; //!< Month of the year [1-12].
NANODBC_TR1_STD int16_t day; //!< Day of the month [1-31].
};
//! \brief A type for representing timestamp data.
struct timestamp
{
NANODBC_TR1_STD int16_t year; //!< Year [0-inf).
NANODBC_TR1_STD int16_t month; //!< Month of the year [1-12].
NANODBC_TR1_STD int16_t day; //!< Day of the month [1-31].
NANODBC_TR1_STD int16_t hour; //!< Hours since midnight [0-23].
NANODBC_TR1_STD int16_t min; //!< Minutes after the hour [0-59].
NANODBC_TR1_STD int16_t sec; //!< Seconds after the minute.
NANODBC_TR1_STD int32_t fract; //!< Fractional seconds.
};
//! \}
//! \addtogroup main Main classes
//! \brief Main nanodbc classes.
//!
//! @{
//! \brief A resource for managing transaction commits and rollbacks.
//!
//! \attention You will want to use transactions if you are doing batch operations because it will prevent auto commits from occurring after each individual operation is executed.
class transaction
{
public:
//! \brief Begin a transaction on the given connection object.
//! \post Operations that modify the database must now be committed before taking effect.
//! \throws database_error
explicit transaction(const class connection& conn);
//! Copy constructor.
transaction(const transaction& rhs);
//! Assignment.
transaction& operator=(transaction rhs);
//! Member swap.
void swap(transaction& rhs) throw();
//! \brief If this transaction has not been committed, will will rollback any modifying operations.
~transaction() throw();
//! \brief Marks this transaction for commit.
//! \throws database_error
void commit();
//! \brief Marks this transaction for rollback.
void rollback() throw();
//! Returns the connection object.
class connection& connection();
//! Returns the connection object.
const class connection& connection() const;
//! Returns the connection object.
operator class connection&();
//! Returns the connection object.
operator const class connection&() const;
private:
class transaction_impl;
friend class nanodbc::connection;
private:
NANODBC_TR1_STD shared_ptr<transaction_impl> impl_;
};
//! \brief Represents a statement on the database.
class statement
{
public:
//! \brief Provides support for retrieving output/return parameters.
//! \see binding
enum param_direction
{
PARAM_IN //!< Binding an input parameter.
, PARAM_OUT //!< Binding an output parameter.
, PARAM_INOUT //!< Binding an input/output parameter.
, PARAM_RETURN //!< Binding a return parameter.
};
public:
//! \brief Creates a new un-prepared statement.
//! \see execute(), execute_direct(), open(), prepare()
statement();
//! \brief Constructs a statement object and associates it to the given connection.
//! \param conn The connection to use.
//! \see open(), prepare()
explicit statement(class connection& conn);
//! \brief Constructs and prepares a statement using the given connection and query.
//! \param conn The connection to use.
//! \param query The SQL query statement.
//! \param timeout The number in seconds before query timeout. Default is 0 indicating no timeout.
//! \see execute(), execute_direct(), open(), prepare()
statement(class connection& conn, const string_type& query, long timeout = 0);
//! Copy constructor.
statement(const statement& rhs);
//! Assignment.
statement& operator=(statement rhs);
//! Member swap.
void swap(statement& rhs) throw();
//! \brief Closes the statement.
//! \see close()
~statement() throw();
//! \brief Creates a statement for the given connection.
//! \param conn The connection where the statement will be executed.
//! \throws database_error
void open(class connection& conn);
//! \brief Returns true if connection is open.
bool open() const;
//! \brief Returns true if connected to the database.
bool connected() const;
//! \brief Returns the associated connection object if any.
class connection& connection();
//! \brief Returns the associated connection object if any.
const class connection& connection() const;
//! \brief Returns the native ODBC statement handle.
void* native_statement_handle() const;
//! \brief Closes the statement and frees all associated resources.
void close();
//! \brief Cancels execution of the statement.
//! \throws database_error
void cancel();
//! \brief Opens and prepares the given statement to execute on the given connection.
//! \param conn The connection where the statement will be executed.
//! \param query The SQL query that will be executed.
//! \param timeout The number in seconds before query timeout. Default is 0 indicating no timeout.
//! \see open()
//! \throws database_error
void prepare(class connection& conn, const string_type& query, long timeout = 0);
//! \brief Prepares the given statement to execute its associated connection.
//! If the statement is not open throws programming_error.
//! \param query The SQL query that will be executed.
//! \param timeout The number in seconds before query timeout. Default is 0 indicating no timeout.
//! \see open()
//! \throws database_error, programming_error
void prepare(const string_type& query, long timeout = 0);
//! \brief Sets the number in seconds before query timeout. Default is 0 indicating no timeout.
//! \throws database_error
void timeout(long timeout = 0);
//! \brief Immediately opens, prepares, and executes the given query directly on the given connection.
//! \param conn The connection where the statement will be executed.
//! \param query The SQL query that will be executed.
//! \param batch_operations Numbers of rows to fetch per rowset, or the number of batch parameters to process.
//! \param timeout The number in seconds before query timeout. Default is 0 indicating no timeout.
//! \return A result set object.
//! \attention You will want to use transactions if you are doing batch operations because it will prevent auto commits from occurring after each individual operation is executed.
//! \see open(), prepare(), execute(), result, transaction
class result execute_direct(class connection& conn, const string_type& query, long batch_operations = 1, long timeout = 0);
//! \brief Execute the previously prepared query now.
//! \param batch_operations Numbers of rows to fetch per rowset, or the number of batch parameters to process.
//! \param timeout The number in seconds before query timeout. Default is 0 indicating no timeout.
//! \throws database_error
//! \return A result set object.
//! \attention You will want to use transactions if you are doing batch operations because it will prevent auto commits from occurring after each individual operation is executed.
//! \see open(), prepare(), execute(), result, transaction
class result execute(long batch_operations = 1, long timeout = 0);
//! \brief Returns the number of rows affected by the request or –1 if the number of affected rows is not available.
//! \throws database_error
long affected_rows() const;
//! \brief Returns the number of columns in a result set.
//! \throws database_error
short columns() const;
//! \brief Resets all currently bound parameters.
void reset_parameters() throw();
//! \brief Returns the parameter size for the indicated parameter placeholder within a prepared statement.
unsigned long parameter_size(short param) const;
//! \addtogroup binding Binding parameters
//! \brief These functions are used to bind values to ODBC parameters.
//!
//! @{
//! \brief Binds the given value to the given parameter placeholder number in the prepared statement.
//!
//! If your prepared SQL query has any ? placeholders, this is how you bind values to them.
//! Placeholder numbers count from left to right and are 0-indexed.
//!
//! It is NOT possible to use these functions for bulk operations as number of elements is not specified here.
//!
//! \param param Placeholder position.
//! \param value Value to substitute into placeholder.
//! \param param_direciton ODBC parameter direction.
//! \throws database_error
template<class T>
void bind(short param, const T* value, param_direction direction = PARAM_IN);
//! \addtogroup bind_multi Binding multiple non-string values
//! \brief Binds the given values to the given parameter placeholder number in the prepared statement.
//!
//! If your prepared SQL query has any ? placeholders, this is how you bind values to them.
//! Placeholder numbers count from left to right and are 0-indexed.
//!
//! It is possible to use these functions for bulk operations.
//!
//! \param param Placeholder position.
//! \param values Values to substitute into placeholder.
//! \param elements The number of elements being bound.
//! \param null_sentry Value which should represent a null value.
//! \param nulls Flags for values that should be set to a null value.
//! \param param_direciton ODBC parameter direction.
//! \throws database_error
//!
//! @{
//! \brief Binds multiple values.
//! \see bind_multi
template<class T>
void bind(short param, const T* values, std::size_t elements, param_direction direction = PARAM_IN);
//! \brief Binds multiple values.
//! \see bind_multi
template<class T>
void bind(short param, const T* values, std::size_t elements, const T* null_sentry, param_direction direction = PARAM_IN);
//! \brief Binds multiple values.
//! \see bind_multi
template<class T>
void bind(short param, const T* values, std::size_t elements, const bool* nulls, param_direction direction = PARAM_IN);
//! @}
//! \addtogroup bind_strings Binding multiple string values
//! \brief Binds the given string values to the given parameter placeholder number in the prepared statement.
//!
//! If your prepared SQL query has any ? placeholders, this is how you bind values to them.
//! Placeholder numbers count from left to right and are 0-indexed.
//!
//! It is possible to use these functions for bulk operations.
//!
//! \param param Placeholder position.
//! \param values Values to substitute into placeholder.
//! \param length Maximum length of string elements.
//! \param elements The number of elements being bound. Otherwise the value N is taken as the number of elements.
//! \param null_sentry Value which should represent a null value.
//! \param nulls Flags for values that should be set to a null value.
//! \param param_direciton ODBC parameter direction.
//! \throws database_error
//!
//! @{
//! \brief Binds multiple string values.
//! \see bind_strings
void bind_strings(short param, const string_type::value_type* values, std::size_t length, std::size_t elements, param_direction direction = PARAM_IN);
//! \brief Binds multiple string values.
//! \see bind_strings
template<std::size_t N, std::size_t M>
void bind_strings(short param, const string_type::value_type(&values)[N][M], param_direction direction = PARAM_IN)
{
bind_strings(param, reinterpret_cast<const string_type::value_type*>(values), M, N, direction);
}
//! \brief Binds multiple string values.
//! \see bind_strings
void bind_strings(short param, const string_type::value_type* values, std::size_t length, std::size_t elements, const string_type::value_type* null_sentry, param_direction direction = PARAM_IN);
//! \brief Binds multiple string values.
//! \see bind_strings
template<std::size_t N, std::size_t M>
void bind_strings(short param, const string_type::value_type(&values)[N][M], const string_type::value_type* null_sentry, param_direction direction = PARAM_IN)
{
bind_strings(param, reinterpret_cast<const string_type::value_type*>(values), M, N, null_sentry, direction);
}
//! \brief Binds multiple string values.
//! \see bind_strings
void bind_strings(short param, const string_type::value_type* values, std::size_t length, std::size_t elements, const bool* nulls, param_direction direction = PARAM_IN);
//! \brief Binds multiple string values.
//! \see bind_strings
template<std::size_t N, std::size_t M>
void bind_strings(short param, const string_type::value_type(&values)[N][M], const bool* nulls, param_direction direction = PARAM_IN)
{
bind_strings(param, reinterpret_cast<const string_type::value_type*>(values), M, N, nulls, direction);
}
//! @}
//! \brief Binds null values to the given parameter placeholder number in the prepared statement.
//!
//! If your prepared SQL query has any ? placeholders, this is how you bind values to them.
//! Placeholder numbers count from left to right and are 0-indexed.
//!
//! It is possible to use this function for bulk operations.
//!
//! \param param Placeholder position.
//! \param elements The number of elements being bound.
//! \throws database_error
void bind_null(short param, std::size_t elements = 1);
//! @}
private:
typedef NANODBC_TR1_STD function<bool (std::size_t)> null_predicate_type;
private:
class statement_impl;
friend class nanodbc::result;
private:
NANODBC_TR1_STD shared_ptr<statement_impl> impl_;
};
//! \brief Manages and encapsulates ODBC resources such as the connection and environment handles.
class connection
{
public:
//! \brief Create new connection object, initially not connected.
connection();
//! Copy constructor.
connection(const connection& rhs);
//! Assignment.
connection& operator=(connection rhs);
//! Member swap.
void swap(connection&) throw();
//! \brief Create new connection object and immediately connect to the given data source.
//! \param dsn The name of the data source.
//! \param user The username for authenticating to the data source.
//! \param pass The password for authenticating to the data source.
//! \param timeout The number in seconds before connection timeout. Default is 0 indicating no timeout.
//! \throws database_error
//! \see connected(), connect()
connection(const string_type& dsn, const string_type& user, const string_type& pass, long timeout = 0);
//! \brief Create new connection object and immediately connect using the given connection string.
//! \param connection_string The connection string for establishing a connection.
//! \param timeout The number in seconds before connection timeout. Default is 0 indicating no timeout.
//! \throws database_error
//! \see connected(), connect()
connection(const string_type& connection_string, long timeout = 0);
//! \brief Automatically disconnects from the database and frees all associated resources.
//!
//! Will not throw even if disconnecting causes some kind of error and raises an exception.
//! If you explicitly need to know if disconnect() succeeds, call it directly.
~connection() throw();
//! \brief Create new connection object and immediately connect to the given data source.
//! \param dsn The name of the data source.
//! \param user The username for authenticating to the data source.
//! \param pass The password for authenticating to the data source.
//! \param timeout The number in seconds before connection timeout. Default is 0 indicating no timeout.
//! \throws database_error
//! \see connected()
void connect(const string_type& dsn, const string_type& user, const string_type& pass, long timeout = 0);
//! \brief Create new connection object and immediately connect using the given connection string.
//! \param connection_string The connection string for establishing a connection.
//! \param timeout The number in seconds before connection timeout. Default is 0 indicating no timeout.
//! \throws database_error
//! \see connected()
void connect(const string_type& connection_string, long timeout = 0);
//! \brief Returns true if connected to the database.
bool connected() const;
//! \brief Disconnects from the database, but maintains environment and handle resources.
void disconnect();
//! \brief Returns the number of transactions currently held for this connection.
std::size_t transactions() const;
//! \brief Returns the native ODBC database connection handle.
void* native_dbc_handle() const;
//! \brief Returns the native ODBC environment handle.
void* native_env_handle() const;
//! \brief Returns the name of the ODBC driver.
//! \throws database_error
string_type driver_name() const;
private:
std::size_t ref_transaction();
std::size_t unref_transaction();
bool rollback() const;
void rollback(bool onoff);
private:
class connection_impl;
friend class nanodbc::transaction::transaction_impl;
private:
NANODBC_TR1_STD shared_ptr<connection_impl> impl_;
};
#ifndef DOXYGEN
#ifdef NANODBC_USE_CPP11
class result
#else
class result : public detail::safe_bool<result>
#endif
#else
//! \brief A resource for managing result sets from statement execution.
//!
//! \see statement::execute(), statement::execute_direct()
//! \note result objects may be copied, however all copies will refer to the same underlying ODBC result set.
class result
#endif // doxygen
{
public:
//! Empty result set.
result();
//! Free result set.
~result() throw();
//! Copy constructor.
result(const result& rhs);
//! Assignment.
result& operator=(result rhs);
//! Member swap.
void swap(result& rhs) throw();
//! \brief Returns the native ODBC statement handle.
void* native_statement_handle() const;
//! \brief The rowset size for this result set.
long rowset_size() const throw();
//! \brief Returns the number of rows affected by the request or –1 if the number of affected rows is not available.
//! \throws database_error
long affected_rows() const;
//! \brief Returns the number of rows in the current rowset or 0 if the number of rows is not available.
long rows() const throw();
//! \brief Returns the number of columns in a result set.
//! \throws database_error
short columns() const;
//! \brief Fetches the first row in the current result set.
//! \return true if there are more results or false otherwise.
//! \throws database_error
bool first();
//! \brief Fetches the last row in the current result set.
//! \return true if there are more results or false otherwise.
//! \throws database_error
bool last();
//! \brief Fetches the next row in the current result set.
//! \return true if there are more results or false otherwise.
//! \throws database_error
bool next();
//! \brief Fetches the prior row in the current result set.
//! \return true if there are more results or false otherwise.
//! \throws database_error
bool prior();
//! \brief Moves to and fetches the specified row in the current result set.
//! \return true if there are results or false otherwise.
//! \throws database_error
bool move(long row);
//! \brief Skips a number of rows and then fetches the resulting row in the current result set.
//! \return true if there are results or false otherwise.
//! \throws database_error
bool skip(long rows);
//! \brief Returns the row position in the current result set.
unsigned long position() const;
//! \brief Returns true if there are no more results in the current result set.
bool end() const throw();
//! \brief Gets data from the given column of the current rowset.
//!
//! Columns are numbered from left to right and 0-indexed.
//! \param column position.
//! \throws database_error, index_range_error, type_incompatible_error, null_access_error
template<class T>
T get(short column) const;
//! \brief Gets data from the given column of the current rowset.
//! If the data is null, fallback is returned instead.
//!
//! Columns are numbered from left to right and 0-indexed.
//! \param column position.
//! \param fallback if value is null, return fallback instead.
//! \throws database_error, index_range_error, type_incompatible_error
template<class T>
T get(short column, const T& fallback) const;
//! \brief Gets data from the given column by name of the current rowset.
//!
//! \param column column's name.
//! \param row If there are multiple rows in this rowset, get from the specified row.
//! \throws database_error, index_range_error, type_incompatible_error, null_access_error
template<class T>
T get(const string_type& column_name) const;
//! \brief Gets data from the given column by name of the current rowset.
//! If the data is null, fallback is returned instead.
//!
//! \param column_name column's name.
//! \param fallback if value is null, return fallback instead.
//! \throws database_error, index_range_error, type_incompatible_error
template<class T>
T get(const string_type& column_name, const T& fallback) const;
//! \brief Returns true if and only if the given column of the current rowset is null.
//!
//! Columns are numbered from left to right and 0-indexed.
//! \param column position.
//! \throws database_error, index_range_error
bool is_null(short column) const;
//! \brief Returns true if and only if the given column by name of the current rowset is null.
//!
//! \param column column's name.
//! \throws database_error, index_range_error
bool is_null(const string_type& column_name) const;
//! \brief Returns the name of the specified column.
//!
//! Columns are numbered from left to right and 0-indexed.
//! \param column position.
//! \throws index_range_error
string_type column_name(short column) const;
//! \brief Returns the size of the specified column.
//!
//! Columns are numbered from left to right and 0-indexed.
//! \param Column position.
//! \throws index_range_error
long column_size(short column) const;
//! \brief Returns the column number of the specified column name.
//!
//! Columns are numbered from left to right and 0-indexed.
//! \param column column's name.
//! \throws index_range_error
short column(const string_type& column_name) const;
//! Returns a identifying integer value representing the C type of this column.
int column_datatype(short column) const;
//! Returns a identifying integer value representing the C type of this column by name.
int column_datatype(const string_type& column_name) const;
//! Returns the next result, for example when stored procedure returns multiple result sets.
bool next_result() const;
#ifndef DOXYGEN
#ifdef NANODBC_USE_CPP11
explicit operator bool() const;
#else
bool boolean_test() const;
#endif // NANODBC_USE_CPP11
#else
//! If and only if result object is valid, returns true.
//! \note A safe-bool idiom is used if NANODBC_USE_CPP11 is not defined, otherwise an explicit conversion operator is used.
operator bool() const;
#endif // DOXYGEN
private:
result(statement statement, long rowset_size);
private:
class result_impl;
friend class nanodbc::statement::statement_impl;
private:
NANODBC_TR1_STD shared_ptr<result_impl> impl_;
};
//! @}
//! \addtogroup main Free Functions
//! \brief Convenience functions.
//!
//! @{
//! \brief Immediately opens, prepares, and executes the given query directly on the given connection.
//! \param conn The connection where the statement will be executed.
//! \param query The SQL query that will be executed.
//! \param batch_operations Numbers of rows to fetch per rowset, or the number of batch parameters to process.
//! \param timeout The number in seconds before query timeout. Default is 0 indicating no timeout.
//! \return A result set object.
//! \attention You will want to use transactions if you are doing batch operations because it will prevent auto commits from occurring after each individual operation is executed.
//! \see open(), prepare(), execute(), result, transaction
result execute(connection& conn, const string_type& query, long batch_operations = 1, long timeout = 0);
//! \brief Execute the previously prepared query now.
//! \param stmt The prepared statement that will be executed.
//! \param batch_operations Numbers of rows to fetch per rowset, or the number of batch parameters to process.
//! \throws database_error
//! \return A result set object.
//! \attention You will want to use transactions if you are doing batch operations because it will prevent auto commits from occurring after each individual operation is executed.
//! \see open(), prepare(), execute(), result
result execute(statement& stmt, long batch_operations = 1);
//! \brief Execute the previously prepared query now.
//! Executes within the context of a transaction object and commits the transaction directly after execution.
//! \param stmt The prepared statement that will be executed in batch.
//! \param batch_operations Numbers of rows to fetch per rowset, or the number of batch parameters to process.
//! \throws database_error
//! \return A result set object.
//! \see open(), prepare(), execute(), result, transaction
result transact(statement& stmt, long batch_operations);
//! \brief Prepares the given statement to execute on it associated connection.
//! If the statement is not open throws programming_error.
//! \param conn The connection where the statement will be executed.
//! \param query The SQL query that will be executed.
//! \param timeout The number in seconds before query timeout. Default is 0 indicating no timeout.
//! \see open()
//! \throws database_error, programming_error
void prepare(statement& stmt, const string_type& query, long timeout = 0);
//! @}
} // namespace nanodbc
#undef NANODBC_TR1_STD
#endif // NANODBC_H