00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "odbcpp/record.h"
00025 #include <sqlucode.h>
00026 #include <sstream>
00027 #include <iostream>
00028
00029 #ifdef _MSC_VER
00030 #pragma warning(disable: 4146)
00031 #endif
00032
00033
00034 namespace odbcpp
00035 {
00036
00037
00057 record_base::record_base()
00058
00059 {
00060 }
00061
00072 record_base::record_base(const record_base& rec)
00073
00074 {
00075
00076 (void) &rec;
00077 }
00078
00110 record_base& record_base::operator = (const record_base& rec)
00111 {
00112 unbind();
00113
00114
00115 (void) &rec;
00116
00117 return *this;
00118 }
00119
00154 void record_base::bind(statement& stmt)
00155 {
00156
00157 if(f_statement == stmt) {
00158 return;
00159 }
00160
00161
00162 if(f_statement) {
00163 diagnostic d(odbcpp_error::ODBCPP_INCORRECT_USE, std::string("records can be used with at most one statement"));
00164 throw odbcpp_error(d);
00165 }
00166
00167 f_statement = &stmt;
00168
00169
00170 bind_impl();
00171 }
00172
00173
00174
00375 void record::bind(const std::string& name, std::string& str, bool *is_null)
00376 {
00377 bind_info_t *bi = new bind_info_t;
00378
00379 bi->f_name = name;
00380
00381 bi->f_target_type = SQL_C_CHAR;
00382
00383
00384
00385 bi->f_is_null = is_null;
00386
00387 bi->f_string = &str;
00388 f_bind_by_name.insert(bind_info_name_t(name, bi));
00389 }
00390
00391
00401 void record::bind(SQLSMALLINT col, std::string& str, bool *is_null)
00402 {
00403 bind_info_t *bi = new bind_info_t;
00404
00405
00406 bi->f_col = col;
00407 bi->f_target_type = SQL_C_CHAR;
00408
00409
00410
00411 bi->f_is_null = is_null;
00412
00413 bi->f_string = &str;
00414 f_bind_by_col.insert(bind_info_col_t(col, bi));
00415 }
00416
00417
00427 void record::bind(const std::string& name, std::wstring& str, bool *is_null)
00428 {
00429 bind_info_t *bi = new bind_info_t;
00430
00431 bi->f_name = name;
00432
00433 bi->f_target_type = SQL_C_WCHAR;
00434
00435
00436
00437 bi->f_is_null = is_null;
00438
00439 bi->f_wstring = &str;
00440 f_bind_by_name.insert(bind_info_name_t(name, bi));
00441 }
00442
00443
00453 void record::bind(SQLSMALLINT col, std::wstring& str, bool *is_null)
00454 {
00455 bind_info_t *bi = new bind_info_t;
00456
00457
00458 bi->f_col = col;
00459 bi->f_target_type = SQL_C_WCHAR;
00460
00461
00462
00463 bi->f_is_null = is_null;
00464
00465 bi->f_wstring = &str;
00466 f_bind_by_col.insert(bind_info_col_t(col, bi));
00467 }
00468
00469
00479 void record::bind(const std::string& name, SQLCHAR& tiny_int, bool *is_null)
00480 {
00481 bind_info_t *bi = new bind_info_t;
00482
00483 bi->f_name = name;
00484
00485 bi->f_target_type = SQL_C_TINYINT;
00486 bi->f_data = &tiny_int;
00487 bi->f_size = sizeof(SQLSCHAR);
00488
00489 bi->f_is_null = is_null;
00490
00491
00492 f_bind_by_name.insert(bind_info_name_t(name, bi));
00493 }
00494
00495
00505 void record::bind(SQLSMALLINT col, SQLCHAR& tiny_int, bool *is_null)
00506 {
00507 bind_info_t *bi = new bind_info_t;
00508
00509
00510 bi->f_col = col;
00511 bi->f_target_type = SQL_C_TINYINT;
00512 bi->f_data = &tiny_int;
00513 bi->f_size = sizeof(SQLSCHAR);
00514
00515 bi->f_is_null = is_null;
00516
00517
00518 f_bind_by_col.insert(bind_info_col_t(col, bi));
00519 }
00520
00521
00531 void record::bind(const std::string& name, SQLSCHAR& tiny_int, bool *is_null)
00532 {
00533 bind_info_t *bi = new bind_info_t;
00534
00535 bi->f_name = name;
00536
00537 bi->f_target_type = SQL_C_TINYINT;
00538 bi->f_data = &tiny_int;
00539 bi->f_size = sizeof(SQLSCHAR);
00540
00541 bi->f_is_null = is_null;
00542
00543
00544 f_bind_by_name.insert(bind_info_name_t(name, bi));
00545 }
00546
00547
00557 void record::bind(SQLSMALLINT col, SQLSCHAR& tiny_int, bool *is_null)
00558 {
00559 bind_info_t *bi = new bind_info_t;
00560
00561
00562 bi->f_col = col;
00563 bi->f_target_type = SQL_C_TINYINT;
00564 bi->f_data = &tiny_int;
00565 bi->f_size = sizeof(SQLSCHAR);
00566
00567 bi->f_is_null = is_null;
00568
00569
00570 f_bind_by_col.insert(bind_info_col_t(col, bi));
00571 }
00572
00573
00583 void record::bind(const std::string& name, SQLSMALLINT& small_int, bool *is_null)
00584 {
00585 bind_info_t *bi = new bind_info_t;
00586
00587 bi->f_name = name;
00588
00589 bi->f_target_type = SQL_C_SHORT;
00590 bi->f_data = &small_int;
00591 bi->f_size = sizeof(SQLSMALLINT);
00592
00593 bi->f_is_null = is_null;
00594
00595
00596 f_bind_by_name.insert(bind_info_name_t(name, bi));
00597 }
00598
00599
00609 void record::bind(SQLSMALLINT col, SQLSMALLINT& small_int, bool *is_null)
00610 {
00611 bind_info_t *bi = new bind_info_t;
00612
00613
00614 bi->f_col = col;
00615 bi->f_target_type = SQL_C_SHORT;
00616 bi->f_data = &small_int;
00617 bi->f_size = sizeof(SQLSMALLINT);
00618
00619 bi->f_is_null = is_null;
00620
00621
00622 f_bind_by_col.insert(bind_info_col_t(col, bi));
00623 }
00624
00625
00635 void record::bind(const std::string& name, SQLUSMALLINT& small_int, bool *is_null)
00636 {
00637 bind_info_t *bi = new bind_info_t;
00638
00639 bi->f_name = name;
00640
00641 bi->f_target_type = SQL_C_USHORT;
00642 bi->f_data = &small_int;
00643 bi->f_size = sizeof(SQLUSMALLINT);
00644
00645 bi->f_is_null = is_null;
00646
00647
00648 f_bind_by_name.insert(bind_info_name_t(name, bi));
00649 }
00650
00651
00661 void record::bind(SQLSMALLINT col, SQLUSMALLINT& small_int, bool *is_null)
00662 {
00663 bind_info_t *bi = new bind_info_t;
00664
00665
00666 bi->f_col = col;
00667 bi->f_target_type = SQL_C_USHORT;
00668 bi->f_data = &small_int;
00669 bi->f_size = sizeof(SQLUSMALLINT);
00670
00671 bi->f_is_null = is_null;
00672
00673
00674 f_bind_by_col.insert(bind_info_col_t(col, bi));
00675 }
00676
00677
00687 void record::bind(const std::string& name, SQLINTEGER& integer, bool *is_null)
00688 {
00689 bind_info_t *bi = new bind_info_t;
00690
00691 bi->f_name = name;
00692
00693 bi->f_target_type = SQL_C_LONG;
00694 bi->f_data = &integer;
00695 bi->f_size = sizeof(SQLINTEGER);
00696
00697 bi->f_is_null = is_null;
00698
00699
00700 f_bind_by_name.insert(bind_info_name_t(name, bi));
00701 }
00702
00703
00713 void record::bind(SQLSMALLINT col, SQLINTEGER& integer, bool *is_null)
00714 {
00715 bind_info_t *bi = new bind_info_t;
00716
00717
00718 bi->f_col = col;
00719 bi->f_target_type = SQL_C_LONG;
00720 bi->f_data = &integer;
00721 bi->f_size = sizeof(SQLINTEGER);
00722
00723 bi->f_is_null = is_null;
00724
00725
00726 f_bind_by_col.insert(bind_info_col_t(col, bi));
00727 }
00728
00729
00739 void record::bind(const std::string& name, SQLUINTEGER& integer, bool *is_null)
00740 {
00741 bind_info_t *bi = new bind_info_t;
00742
00743 bi->f_name = name;
00744
00745 bi->f_target_type = SQL_C_ULONG;
00746 bi->f_data = &integer;
00747 bi->f_size = sizeof(SQLUINTEGER);
00748
00749 bi->f_is_null = is_null;
00750
00751
00752 f_bind_by_name.insert(bind_info_name_t(name, bi));
00753 }
00754
00755
00765 void record::bind(SQLSMALLINT col, SQLUINTEGER& integer, bool *is_null)
00766 {
00767 bind_info_t *bi = new bind_info_t;
00768
00769
00770 bi->f_col = col;
00771 bi->f_target_type = SQL_C_ULONG;
00772 bi->f_data = &integer;
00773 bi->f_size = sizeof(SQLUINTEGER);
00774
00775 bi->f_is_null = is_null;
00776
00777
00778 f_bind_by_col.insert(bind_info_col_t(col, bi));
00779 }
00780
00781
00791 void record::bind(const std::string& name, SQLBIGINT& big_int, bool *is_null)
00792 {
00793 bind_info_t *bi = new bind_info_t;
00794
00795 bi->f_name = name;
00796
00797 bi->f_target_type = SQL_C_SBIGINT;
00798 bi->f_data = &big_int;
00799 bi->f_size = sizeof(SQLBIGINT);
00800
00801 bi->f_is_null = is_null;
00802
00803
00804 f_bind_by_name.insert(bind_info_name_t(name, bi));
00805 }
00806
00807
00817 void record::bind(SQLSMALLINT col, SQLBIGINT& big_int, bool *is_null)
00818 {
00819 bind_info_t *bi = new bind_info_t;
00820
00821
00822 bi->f_col = col;
00823 bi->f_target_type = SQL_C_SBIGINT;
00824 bi->f_data = &big_int;
00825 bi->f_size = sizeof(SQLBIGINT);
00826
00827 bi->f_is_null = is_null;
00828
00829
00830 f_bind_by_col.insert(bind_info_col_t(col, bi));
00831 }
00832
00833
00843 void record::bind(const std::string& name, SQLUBIGINT& big_int, bool *is_null)
00844 {
00845 bind_info_t *bi = new bind_info_t;
00846
00847 bi->f_name = name;
00848
00849 bi->f_target_type = SQL_C_UBIGINT;
00850 bi->f_data = &big_int;
00851 bi->f_size = sizeof(SQLUBIGINT);
00852
00853 bi->f_is_null = is_null;
00854
00855
00856 f_bind_by_name.insert(bind_info_name_t(name, bi));
00857 }
00858
00859
00869 void record::bind(SQLSMALLINT col, SQLUBIGINT& big_int, bool *is_null)
00870 {
00871 bind_info_t *bi = new bind_info_t;
00872
00873
00874 bi->f_col = col;
00875 bi->f_target_type = SQL_C_UBIGINT;
00876 bi->f_data = &big_int;
00877 bi->f_size = sizeof(SQLUBIGINT);
00878
00879 bi->f_is_null = is_null;
00880
00881
00882 f_bind_by_col.insert(bind_info_col_t(col, bi));
00883 }
00884
00885
00898 void record::bind(const std::string& name, SQLREAL& real, bool *is_null)
00899 {
00900 bind_info_t *bi = new bind_info_t;
00901
00902 bi->f_name = name;
00903
00904 bi->f_target_type = SQL_C_FLOAT;
00905 bi->f_data = ℜ
00906 bi->f_size = sizeof(SQLREAL);
00907
00908 bi->f_is_null = is_null;
00909
00910
00911 f_bind_by_name.insert(bind_info_name_t(name, bi));
00912 }
00913
00914
00927 void record::bind(SQLSMALLINT col, SQLREAL& real, bool *is_null)
00928 {
00929 bind_info_t *bi = new bind_info_t;
00930
00931
00932 bi->f_col = col;
00933 bi->f_target_type = SQL_C_FLOAT;
00934 bi->f_data = ℜ
00935 bi->f_size = sizeof(SQLREAL);
00936
00937 bi->f_is_null = is_null;
00938
00939
00940 f_bind_by_col.insert(bind_info_col_t(col, bi));
00941 }
00942
00943
00956 void record::bind(const std::string& name, SQLFLOAT& dbl, bool *is_null)
00957 {
00958 bind_info_t *bi = new bind_info_t;
00959
00960 bi->f_name = name;
00961
00962 bi->f_target_type = SQL_C_DOUBLE;
00963 bi->f_data = &dbl;
00964 bi->f_size = sizeof(SQLFLOAT);
00965
00966 bi->f_is_null = is_null;
00967
00968
00969 f_bind_by_name.insert(bind_info_name_t(name, bi));
00970 }
00971
00972
00985 void record::bind(SQLSMALLINT col, SQLFLOAT& dbl, bool *is_null)
00986 {
00987 bind_info_t *bi = new bind_info_t;
00988
00989
00990 bi->f_col = col;
00991 bi->f_target_type = SQL_C_DOUBLE;
00992 bi->f_data = &dbl;
00993 bi->f_size = sizeof(SQLFLOAT);
00994
00995 bi->f_is_null = is_null;
00996
00997
00998 f_bind_by_col.insert(bind_info_col_t(col, bi));
00999 }
01000
01001
01012 void record::bind(const std::string& name, SQLCHAR *binary, SQLLEN length, bool *is_null)
01013 {
01014 bind_info_t *bi = new bind_info_t;
01015
01016 bi->f_name = name;
01017
01018 bi->f_target_type = SQL_C_BINARY;
01019 bi->f_data = binary;
01020 bi->f_size = length;
01021
01022 bi->f_is_null = is_null;
01023
01024
01025 f_bind_by_name.insert(bind_info_name_t(name, bi));
01026 }
01027
01028
01039 void record::bind(SQLSMALLINT col, SQLCHAR *binary, SQLLEN length, bool *is_null)
01040 {
01041 bind_info_t *bi = new bind_info_t;
01042
01043
01044 bi->f_col = col;
01045 bi->f_target_type = SQL_C_BINARY;
01046 bi->f_data = binary;
01047 bi->f_size = length;
01048
01049 bi->f_is_null = is_null;
01050
01051
01052 f_bind_by_col.insert(bind_info_col_t(col, bi));
01053 }
01054
01055
01065 void record::bind(const std::string& name, SQL_DATE_STRUCT& date, bool *is_null)
01066 {
01067 bind_info_t *bi = new bind_info_t;
01068
01069 bi->f_name = name;
01070
01071 bi->f_target_type = SQL_C_DATE;
01072 bi->f_data = &date;
01073 bi->f_size = sizeof(SQL_DATE_STRUCT);
01074
01075 bi->f_is_null = is_null;
01076
01077
01078 f_bind_by_name.insert(bind_info_name_t(name, bi));
01079 }
01080
01081
01091 void record::bind(SQLSMALLINT col, SQL_DATE_STRUCT& date, bool *is_null)
01092 {
01093 bind_info_t *bi = new bind_info_t;
01094
01095
01096 bi->f_col = col;
01097 bi->f_target_type = SQL_C_DATE;
01098 bi->f_data = &date;
01099 bi->f_size = sizeof(SQL_DATE_STRUCT);
01100
01101 bi->f_is_null = is_null;
01102
01103
01104 f_bind_by_col.insert(bind_info_col_t(col, bi));
01105 }
01106
01107
01117 void record::bind(const std::string& name, SQL_TIME_STRUCT& time, bool *is_null)
01118 {
01119 bind_info_t *bi = new bind_info_t;
01120
01121 bi->f_name = name;
01122
01123 bi->f_target_type = SQL_C_TIME;
01124 bi->f_data = &time;
01125 bi->f_size = sizeof(SQL_TIME_STRUCT);
01126
01127 bi->f_is_null = is_null;
01128
01129
01130 f_bind_by_name.insert(bind_info_name_t(name, bi));
01131 }
01132
01133
01143 void record::bind(SQLSMALLINT col, SQL_TIME_STRUCT& time, bool *is_null)
01144 {
01145 bind_info_t *bi = new bind_info_t;
01146
01147
01148 bi->f_col = col;
01149 bi->f_target_type = SQL_C_TIME;
01150 bi->f_data = &time;
01151 bi->f_size = sizeof(SQL_TIME_STRUCT);
01152
01153 bi->f_is_null = is_null;
01154
01155
01156 f_bind_by_col.insert(bind_info_col_t(col, bi));
01157 }
01158
01159
01169 void record::bind(const std::string& name, SQL_TIMESTAMP_STRUCT& timestamp, bool *is_null)
01170 {
01171 bind_info_t *bi = new bind_info_t;
01172
01173 bi->f_name = name;
01174
01175 bi->f_target_type = SQL_C_TIMESTAMP;
01176 bi->f_data = ×tamp;
01177 bi->f_size = sizeof(SQL_TIMESTAMP_STRUCT);
01178
01179 bi->f_is_null = is_null;
01180
01181
01182 f_bind_by_name.insert(bind_info_name_t(name, bi));
01183 }
01184
01185
01195 void record::bind(SQLSMALLINT col, SQL_TIMESTAMP_STRUCT& timestamp, bool *is_null)
01196 {
01197 bind_info_t *bi = new bind_info_t;
01198
01199
01200 bi->f_col = col;
01201 bi->f_target_type = SQL_C_TIMESTAMP;
01202 bi->f_data = ×tamp;
01203 bi->f_size = sizeof(SQL_TIMESTAMP_STRUCT);
01204
01205 bi->f_is_null = is_null;
01206
01207
01208 f_bind_by_col.insert(bind_info_col_t(col, bi));
01209 }
01210
01211
01221 void record::bind(const std::string& name, SQL_NUMERIC_STRUCT& numeric, bool *is_null)
01222 {
01223 bind_info_t *bi = new bind_info_t;
01224
01225 bi->f_name = name;
01226
01227 bi->f_target_type = SQL_C_NUMERIC;
01228 bi->f_data = &numeric;
01229 bi->f_size = sizeof(SQL_NUMERIC_STRUCT);
01230
01231 bi->f_is_null = is_null;
01232
01233
01234 f_bind_by_name.insert(bind_info_name_t(name, bi));
01235 }
01236
01237
01247 void record::bind(SQLSMALLINT col, SQL_NUMERIC_STRUCT& numeric, bool *is_null)
01248 {
01249 bind_info_t *bi = new bind_info_t;
01250
01251
01252 bi->f_col = col;
01253 bi->f_target_type = SQL_C_NUMERIC;
01254 bi->f_data = &numeric;
01255 bi->f_size = sizeof(SQL_NUMERIC_STRUCT);
01256
01257 bi->f_is_null = is_null;
01258
01259
01260 f_bind_by_col.insert(bind_info_col_t(col, bi));
01261 }
01262
01263
01273 void record::bind(const std::string& name, SQLGUID& guid, bool *is_null)
01274 {
01275 bind_info_t *bi = new bind_info_t;
01276
01277 bi->f_name = name;
01278
01279 bi->f_target_type = SQL_C_GUID;
01280 bi->f_data = &guid;
01281 bi->f_size = sizeof(SQLGUID);
01282
01283 bi->f_is_null = is_null;
01284
01285
01286 f_bind_by_name.insert(bind_info_name_t(name, bi));
01287 }
01288
01289
01299 void record::bind(SQLSMALLINT col, SQLGUID& guid, bool *is_null)
01300 {
01301 bind_info_t *bi = new bind_info_t;
01302
01303
01304 bi->f_col = col;
01305 bi->f_target_type = SQL_C_GUID;
01306 bi->f_data = &guid;
01307 bi->f_size = sizeof(SQLGUID);
01308
01309 bi->f_is_null = is_null;
01310
01311
01312 f_bind_by_col.insert(bind_info_col_t(col, bi));
01313 }
01314
01315
01316
01317 void record::bind_impl()
01318 {
01319 SQLSMALLINT idx, max, type, name_length;
01320 SQLULEN size;
01321 SQLCHAR column_name[256];
01322 bind_info_t *info;
01323
01324
01325
01326
01327 max = static_cast<SQLSMALLINT>(f_statement->cols());
01328 for(idx = 1; idx <= max; ++idx) {
01329
01330
01331 bind_info_col_map_t::iterator by_col;
01332 by_col = f_bind_by_col.find(idx);
01333 if(by_col == f_bind_by_col.end()) {
01334
01335 name_length = sizeof(column_name);
01336 f_statement->check(SQLDescribeCol(
01337 f_statement->get_handle(),
01338 idx,
01339 column_name,
01340 sizeof(column_name),
01341 &name_length,
01342 &type,
01343 &size,
01344 NULL,
01345 NULL));
01346
01347
01348 column_name[sizeof(column_name) - 1] = '\0';
01349 bind_info_name_map_t::iterator by_name;
01350 by_name = f_bind_by_name.find(reinterpret_cast<char *>(column_name));
01351 if(by_name == f_bind_by_name.end()) {
01352
01353 continue;
01354 }
01355 info = by_name->second;
01356 }
01357 else {
01358 info = by_col->second;
01359 size = 0;
01360 }
01361
01362
01363 if(info->f_target_type == SQL_C_CHAR
01364 || info->f_target_type == SQL_C_WCHAR) {
01365 if(size == 0) {
01366 f_statement->check(SQLDescribeCol(
01367 f_statement->get_handle(),
01368 idx,
01369 NULL,
01370 0,
01371 NULL,
01372 NULL,
01373 &info->f_size,
01374 NULL,
01375 NULL));
01376 }
01377 else {
01378 info->f_size = size;
01379 }
01380 if(info->f_size == 0) {
01381
01382 info->f_size = 8 * 1024;
01383 }
01384 if(info->f_target_type == SQL_C_WCHAR) {
01385
01386
01387 info->f_size = (info->f_size + 1) * sizeof(SQLWCHAR);
01388 }
01389 else {
01390 info->f_size += sizeof(SQLCHAR);
01391 }
01392
01393
01394 info->f_data_buffer.reset(new buffer_char_t(info->f_size + sizeof(SQLWCHAR)));
01395 info->f_data = info->f_data_buffer->get();
01396 }
01397
01398 f_statement->check(SQLBindCol(
01399 f_statement->get_handle(),
01400 idx,
01401 info->f_target_type,
01402 info->f_data,
01403 info->f_size,
01404 &info->f_fetch_size));
01405 }
01406 }
01407
01408
01409
01410
01411 void record::finalize()
01412 {
01413 bind_info_col_map_t::iterator by_col(f_bind_by_col.begin());
01414 while(by_col != f_bind_by_col.end()) {
01415 finalize_info(by_col->second);
01416 ++by_col;
01417 }
01418
01419 bind_info_name_map_t::iterator by_name(f_bind_by_name.begin());
01420 while(by_name != f_bind_by_name.end()) {
01421 finalize_info(by_name->second);
01422 ++by_name;
01423 }
01424 }
01425
01426
01437 void record::finalize_info(bind_info_t *info)
01438 {
01439 if(info->f_is_null != 0) {
01440 *info->f_is_null = info->f_fetch_size == SQL_NULL_DATA;
01441 }
01442
01443
01444
01445 if(info->f_string != 0) {
01446 if(info->f_target_type == SQL_C_CHAR) {
01447 info->f_string->clear();
01448 }
01449 else if(info->f_target_type == SQL_C_WCHAR) {
01450
01451 info->f_wstring->clear();
01452 }
01453 }
01454
01455 if(info->f_data != 0
01456 && info->f_string != 0
01457 && info->f_size > 0
01458 && info->f_fetch_size != SQL_NULL_DATA) {
01459 if(info->f_target_type == SQL_C_CHAR) {
01460
01461
01462 char *s = reinterpret_cast<char *>(info->f_data);
01463 s[info->f_size] = '\0';
01464 *info->f_string = s;
01465 }
01466 else if(info->f_target_type == SQL_C_WCHAR) {
01467
01468
01469 SQLWCHAR *s = reinterpret_cast<SQLWCHAR *>(info->f_data);
01470 s[info->f_size / sizeof(SQLWCHAR)] = '\0';
01471 while(*s != static_cast<SQLWCHAR>(0)) {
01472
01473
01474 *info->f_wstring += static_cast<wchar_t>(*s++);
01475 }
01476 }
01477 }
01478 }
01479
01480
01481
01673 const std::string& dynamic_record::column_name(SQLSMALLINT col) const
01674 {
01675 return find_column(col, SQL_UNKNOWN_TYPE)->f_name;
01676 }
01677
01689 SQLSMALLINT dynamic_record::column_number(const std::string& name) const
01690 {
01691 return find_column(name, SQL_UNKNOWN_TYPE)->f_col;
01692 }
01693
01694
01695
01696 void dynamic_record::bind_impl()
01697 {
01698 SQLSMALLINT idx, max, name_length;
01699 SQLCHAR column_name[256];
01700
01701 max = static_cast<SQLSMALLINT>(f_statement->cols());
01702 for(idx = 1; idx <= max; ++idx) {
01703
01704 bind_info_t *info = new bind_info_t;
01705 info->f_col = idx;
01706
01707
01708 name_length = sizeof(column_name);
01709 f_statement->check(SQLDescribeCol(
01710 f_statement->get_handle(),
01711 idx,
01712 column_name,
01713 sizeof(column_name),
01714 &name_length,
01715 &info->f_target_type,
01716 &info->f_size,
01717 &info->f_decimal_digits,
01718 NULL));
01719
01720
01721 switch(info->f_target_type) {
01722 case SQL_VARCHAR:
01723 case SQL_LONGVARCHAR:
01724 case SQL_BINARY:
01725 case SQL_VARBINARY:
01726 case SQL_LONGVARBINARY:
01727 case SQL_GUID:
01728 case SQL_DECIMAL:
01729 info->f_bind_type = SQL_C_CHAR;
01730 info->f_size += sizeof(SQLCHAR);
01731 break;
01732
01733 case SQL_WLONGVARCHAR:
01734 case SQL_WVARCHAR:
01735 info->f_bind_type = SQL_C_WCHAR;
01736 info->f_size = (info->f_size + 1) * sizeof(SQLWCHAR);
01737 break;
01738
01739 case SQL_CHAR:
01740 info->f_bind_type = info->f_target_type;
01741 info->f_size += sizeof(SQLCHAR);
01742 break;
01743
01744 case SQL_WCHAR:
01745 info->f_bind_type = info->f_target_type;
01746 info->f_size = (info->f_size + 1) * sizeof(SQLWCHAR);
01747 break;
01748
01749 case SQL_BIGINT:
01750 info->f_bind_type = SQL_C_SBIGINT;
01751 break;
01752
01753 case SQL_FLOAT:
01754 info->f_bind_type = SQL_C_DOUBLE;
01755 break;
01756
01757 default:
01758 info->f_bind_type = info->f_target_type;
01759 break;
01760
01761 }
01762
01763
01764 if(name_length >= sizeof(column_name)) {
01765 name_length = sizeof(column_name) - 1;
01766 }
01767 column_name[name_length] = '\0';
01768 info->f_name = reinterpret_cast<char *>(column_name);
01769
01770
01771
01772 info->f_data.reset(new buffer_char_t(info->f_size));
01773
01774 f_statement->check(SQLBindCol(
01775 f_statement->get_handle(),
01776 idx,
01777 info->f_bind_type,
01778 info->f_data->get(),
01779 info->f_size,
01780 &info->f_fetch_size));
01781 if(!info->f_name.empty()) {
01782 f_bind_by_name.insert(bind_info_name_t(info->f_name, info));
01783 }
01784 f_bind_by_col.push_back(info);
01785 }
01786 }
01787
01802 bool dynamic_record::exists(const std::string& name)
01803 {
01804 bind_info_name_map_t::iterator itr;
01805
01806 itr = f_bind_by_name.find(name);
01807 return itr != f_bind_by_name.end();
01808 }
01809
01810
01839 const dynamic_record::bind_info_t *dynamic_record::find_column(const std::string& name, SQLSMALLINT target_type, bool except_null) const
01840 {
01841 const bind_info_t *info;
01842 bind_info_name_map_t::const_iterator itr;
01843
01844
01845 itr = f_bind_by_name.find(name);
01846 if(itr == f_bind_by_name.end()) {
01847 diagnostic d(odbcpp_error::ODBCPP_NOT_FOUND, "the column \"" + name + "\" was not found in this record");
01848 throw odbcpp_error(d);
01849 }
01850
01851
01852 return verify_column(itr->second, target_type, except_null);
01853 }
01854
01855
01856
01880 const dynamic_record::bind_info_t *dynamic_record::find_column(SQLSMALLINT col, SQLSMALLINT target_type, bool except_null) const
01881 {
01882 const bind_info_t *info;
01883
01884 --col;
01885 if(static_cast<SQLUSMALLINT>(col) >= f_bind_by_col.size()) {
01886 diagnostic d(odbcpp_error::ODBCPP_NOT_FOUND, std::string("there is not that many columns in this record"));
01887 throw odbcpp_error(d);
01888 }
01889
01890
01891 return verify_column(f_bind_by_col[col], target_type, except_null);
01892 }
01893
01894
01895
01911 const dynamic_record::bind_info_t *dynamic_record::verify_column(const bind_info_t *info, SQLSMALLINT target_type, bool except_null) const
01912 {
01913
01914 if(target_type != SQL_UNKNOWN_TYPE
01915 && info->f_bind_type != target_type) {
01916
01917 switch(target_type) {
01918 case SQL_C_CHAR:
01919 target_type = SQL_VARCHAR;
01920 break;
01921
01922 case SQL_C_DATE:
01923 target_type = SQL_TYPE_DATE;
01924 break;
01925
01926 case SQL_C_TIME:
01927 target_type = SQL_TYPE_TIME;
01928 break;
01929
01930 case SQL_C_TIMESTAMP:
01931 target_type = SQL_TYPE_TIMESTAMP;
01932 break;
01933
01934 }
01935 if(info->f_bind_type != target_type) {
01936 std::ostringstream err;
01937 err << "type mismatch for column \"" + info->f_name + "\"";
01938 err << " (expected " << info->f_bind_type << ", requested " << target_type << ")";
01939 diagnostic d(odbcpp_error::ODBCPP_TYPE_MISMATCH, err.str());
01940 throw odbcpp_error(d);
01941 }
01942 }
01943
01944 if(except_null && info->f_fetch_size == SQL_NULL_DATA) {
01945 diagnostic d(odbcpp_error::ODBCPP_NO_DATA, std::string("this column is NULL and cannot be retrieved"));
01946 throw odbcpp_error(d);
01947 }
01948
01949 return info;
01950 }
01951
01952
01953
01969 SQLSMALLINT dynamic_record::get_type(const std::string& name) const
01970 {
01971 return find_column(name, SQL_UNKNOWN_TYPE)->f_target_type;
01972 }
01973
01974
01993 SQLSMALLINT dynamic_record::get_type(SQLSMALLINT col) const
01994 {
01995 return find_column(col, SQL_UNKNOWN_TYPE)->f_target_type;
01996 }
01997
01998
02014 SQLSMALLINT dynamic_record::get_decimal_digits(const std::string& name) const
02015 {
02016 return find_column(name, SQL_UNKNOWN_TYPE)->f_decimal_digits;
02017 }
02018
02019
02038 SQLSMALLINT dynamic_record::get_decimal_digits(SQLSMALLINT col) const
02039 {
02040 return find_column(col, SQL_UNKNOWN_TYPE)->f_decimal_digits;
02041 }
02042
02043
02057 SQLSMALLINT dynamic_record::get_is_null(const std::string& name) const
02058 {
02059 return find_column(name, SQL_UNKNOWN_TYPE)->f_fetch_size == SQL_NULL_DATA;
02060 }
02061
02062
02079 SQLSMALLINT dynamic_record::get_is_null(SQLSMALLINT col) const
02080 {
02081 return find_column(col, SQL_UNKNOWN_TYPE)->f_fetch_size == SQL_NULL_DATA;
02082 }
02083
02084
02105 SQLLEN dynamic_record::get_size(const std::string& name) const
02106 {
02107 return find_column(name, SQL_UNKNOWN_TYPE)->f_fetch_size;
02108 }
02109
02110
02134 SQLLEN dynamic_record::get_size(SQLSMALLINT col) const
02135 {
02136 return find_column(col, SQL_UNKNOWN_TYPE)->f_fetch_size;
02137 }
02138
02139
02153 void dynamic_record::get(const std::string& name, std::string& str) const
02154 {
02155 str = reinterpret_cast<const char *>(find_column(name, SQL_C_CHAR, true)->f_data->get());
02156 }
02157
02158
02172 void dynamic_record::get(SQLSMALLINT col, std::string& str) const
02173 {
02174 str = reinterpret_cast<const char *>(find_column(col, SQL_C_CHAR, true)->f_data->get());
02175 }
02176
02177
02191 void dynamic_record::get(const std::string& name, std::wstring& str) const
02192 {
02193 const SQLWCHAR *s = reinterpret_cast<const SQLWCHAR *>(find_column(name, SQL_C_WCHAR, true)->f_data->get());
02194 str.clear();
02195 while(*s != '\0') {
02196 str += static_cast<wchar_t>(*s++);
02197 }
02198 }
02199
02200
02214 void dynamic_record::get(SQLSMALLINT col, std::wstring& str) const
02215 {
02216 const SQLWCHAR *s = reinterpret_cast<const SQLWCHAR *>(find_column(col, SQL_C_WCHAR, true)->f_data->get());
02217 str.clear();
02218 while(*s != '\0') {
02219 str += static_cast<wchar_t>(*s++);
02220 }
02221 }
02222
02223
02237 void dynamic_record::get(const std::string& name, SQLCHAR& tiny_int) const
02238 {
02239 tiny_int = *reinterpret_cast<SQLCHAR *>(find_column(name, SQL_C_UTINYINT, true)->f_data->get());
02240 }
02241
02242
02256 void dynamic_record::get(SQLSMALLINT col, SQLCHAR& tiny_int) const
02257 {
02258 tiny_int = *reinterpret_cast<SQLCHAR *>(find_column(col, SQL_C_UTINYINT, true)->f_data->get());
02259 }
02260
02261
02275 void dynamic_record::get(const std::string& name, SQLSCHAR& tiny_int) const
02276 {
02277 tiny_int = *reinterpret_cast<SQLSCHAR *>(find_column(name, SQL_C_TINYINT, true)->f_data->get());
02278 }
02279
02280
02294 void dynamic_record::get(SQLSMALLINT col, SQLSCHAR& tiny_int) const
02295 {
02296 tiny_int = *reinterpret_cast<SQLSCHAR *>(find_column(col, SQL_C_TINYINT, true)->f_data->get());
02297 }
02298
02299
02313 void dynamic_record::get(const std::string& name, SQLSMALLINT& small_int) const
02314 {
02315 small_int = *reinterpret_cast<SQLSMALLINT *>(find_column(name, SQL_C_SHORT, true)->f_data->get());
02316 }
02317
02318
02332 void dynamic_record::get(SQLSMALLINT col, SQLSMALLINT& small_int) const
02333 {
02334 small_int = *reinterpret_cast<SQLSMALLINT *>(find_column(col, SQL_C_SHORT, true)->f_data->get());
02335 }
02336
02337
02351 void dynamic_record::get(const std::string& name, SQLUSMALLINT& small_int) const
02352 {
02353 small_int = *reinterpret_cast<SQLUSMALLINT *>(find_column(name, SQL_C_USHORT, true)->f_data->get());
02354 }
02355
02356
02370 void dynamic_record::get(SQLSMALLINT col, SQLUSMALLINT& small_int) const
02371 {
02372 small_int = *reinterpret_cast<SQLUSMALLINT *>(find_column(col, SQL_C_USHORT, true)->f_data->get());
02373 }
02374
02375
02389 void dynamic_record::get(const std::string& name, SQLINTEGER& integer) const
02390 {
02391 integer = *reinterpret_cast<SQLINTEGER *>(find_column(name, SQL_C_LONG, true)->f_data->get());
02392 }
02393
02394
02408 void dynamic_record::get(SQLSMALLINT col, SQLINTEGER& integer) const
02409 {
02410 integer = *reinterpret_cast<SQLUINTEGER *>(find_column(col, SQL_C_LONG, true)->f_data->get());
02411 }
02412
02413
02427 void dynamic_record::get(const std::string& name, SQLUINTEGER& integer) const
02428 {
02429 integer = *reinterpret_cast<SQLUINTEGER *>(find_column(name, SQL_C_ULONG, true)->f_data->get());
02430 }
02431
02432
02446 void dynamic_record::get(SQLSMALLINT col, SQLUINTEGER& integer) const
02447 {
02448 integer = *reinterpret_cast<SQLUINTEGER *>(find_column(col, SQL_C_ULONG, true)->f_data->get());
02449 }
02450
02451
02465 void dynamic_record::get(const std::string& name, SQLBIGINT& big_int) const
02466 {
02467 big_int = *reinterpret_cast<SQLBIGINT *>(find_column(name, SQL_C_SBIGINT, true)->f_data->get());
02468 }
02469
02470
02484 void dynamic_record::get(SQLSMALLINT col, SQLBIGINT& big_int) const
02485 {
02486 big_int = *reinterpret_cast<SQLBIGINT *>(find_column(col, SQL_C_SBIGINT, true)->f_data->get());
02487 }
02488
02489
02503 void dynamic_record::get(const std::string& name, SQLUBIGINT& big_int) const
02504 {
02505 big_int = *reinterpret_cast<SQLUBIGINT *>(find_column(name, SQL_C_UBIGINT, true)->f_data->get());
02506 }
02507
02508
02522 void dynamic_record::get(SQLSMALLINT col, SQLUBIGINT& big_int) const
02523 {
02524 big_int = *reinterpret_cast<SQLUBIGINT *>(find_column(col, SQL_C_UBIGINT, true)->f_data->get());
02525 }
02526
02527
02541 void dynamic_record::get(const std::string& name, SQLREAL& real) const
02542 {
02543 real = *reinterpret_cast<SQLREAL *>(find_column(name, SQL_C_FLOAT, true)->f_data->get());
02544 }
02545
02546
02560 void dynamic_record::get(SQLSMALLINT col, SQLREAL& real) const
02561 {
02562 real = *reinterpret_cast<SQLREAL *>(find_column(col, SQL_C_FLOAT, true)->f_data->get());
02563 }
02564
02565
02579 void dynamic_record::get(const std::string& name, SQLFLOAT& dbl) const
02580 {
02581 dbl = *reinterpret_cast<SQLFLOAT *>(find_column(name, SQL_C_DOUBLE, true)->f_data->get());
02582 }
02583
02584
02598 void dynamic_record::get(SQLSMALLINT col, SQLFLOAT& dbl) const
02599 {
02600 dbl = *reinterpret_cast<SQLFLOAT *>(find_column(col, SQL_C_DOUBLE, true)->f_data->get());
02601 }
02602
02603
02625 SQLULEN dynamic_record::get(const std::string& name, SQLCHAR *binary, SQLLEN length) const
02626 {
02627 if(length < 0) {
02628 diagnostic d(odbcpp_error::ODBCPP_INCORRECT_USE, std::string("a binary buffer cannot have a negative size"));
02629 throw odbcpp_error(d);
02630 }
02631 if(binary == 0) {
02632 diagnostic d(odbcpp_error::ODBCPP_INCORRECT_USE, std::string("a binary buffer cannot be a NULL pointer"));
02633 throw odbcpp_error(d);
02634 }
02635
02636 const bind_info_t *info = find_column(name, SQL_UNKNOWN_TYPE, true);
02637
02638 SQLLEN size = static_cast<SQLUINTEGER>(length) < info->f_fetch_size ? length : info->f_size;
02639
02640 memcpy(binary, info->f_data->get(), size);
02641
02642 return size;
02643 }
02644
02645
02667 SQLULEN dynamic_record::get(SQLSMALLINT col, SQLCHAR *binary, SQLLEN length) const
02668 {
02669 if(length < 0) {
02670 diagnostic d(odbcpp_error::ODBCPP_INCORRECT_USE, std::string("a binary buffer cannot have a negative size"));
02671 throw odbcpp_error(d);
02672 }
02673 if(binary == 0) {
02674 diagnostic d(odbcpp_error::ODBCPP_INCORRECT_USE, std::string("a binary buffer cannot be a NULL pointer"));
02675 throw odbcpp_error(d);
02676 }
02677
02678 const bind_info_t *info = find_column(col, SQL_UNKNOWN_TYPE, true);
02679
02680 SQLLEN size = static_cast<SQLUINTEGER>(length) < info->f_fetch_size ? length : info->f_size;
02681
02682 memcpy(binary, info->f_data->get(), size);
02683
02684 return size;
02685 }
02686
02687
02701 void dynamic_record::get(const std::string& name, SQL_DATE_STRUCT& date) const
02702 {
02703 date = *reinterpret_cast<SQL_DATE_STRUCT *>(find_column(name, SQL_C_DATE, true)->f_data->get());
02704 }
02705
02706
02720 void dynamic_record::get(SQLSMALLINT col, SQL_DATE_STRUCT& date) const
02721 {
02722 date = *reinterpret_cast<SQL_DATE_STRUCT *>(find_column(col, SQL_C_DATE, true)->f_data->get());
02723 }
02724
02725
02739 void dynamic_record::get(const std::string& name, SQL_TIME_STRUCT& time) const
02740 {
02741 time = *reinterpret_cast<SQL_TIME_STRUCT *>(find_column(name, SQL_C_TIME, true)->f_data->get());
02742 }
02743
02744
02758 void dynamic_record::get(SQLSMALLINT col, SQL_TIME_STRUCT& time) const
02759 {
02760 time = *reinterpret_cast<SQL_TIME_STRUCT *>(find_column(col, SQL_C_TIME, true)->f_data->get());
02761 }
02762
02763
02777 void dynamic_record::get(const std::string& name, SQL_TIMESTAMP_STRUCT& timestamp) const
02778 {
02779 timestamp = *reinterpret_cast<SQL_TIMESTAMP_STRUCT *>(find_column(name, SQL_C_TIMESTAMP, true)->f_data->get());
02780 }
02781
02782
02796 void dynamic_record::get(SQLSMALLINT col, SQL_TIMESTAMP_STRUCT& timestamp) const
02797 {
02798 timestamp = *reinterpret_cast<SQL_TIMESTAMP_STRUCT *>(find_column(col, SQL_C_TIMESTAMP, true)->f_data->get());
02799 }
02800
02801
02815 void dynamic_record::get(const std::string& name, SQL_NUMERIC_STRUCT& numeric) const
02816 {
02817 numeric = *reinterpret_cast<SQL_NUMERIC_STRUCT *>(find_column(name, SQL_C_NUMERIC, true)->f_data->get());
02818 }
02819
02820
02834 void dynamic_record::get(SQLSMALLINT col, SQL_NUMERIC_STRUCT& numeric) const
02835 {
02836 numeric = *reinterpret_cast<SQL_NUMERIC_STRUCT *>(find_column(col, SQL_C_NUMERIC, true)->f_data->get());
02837 }
02838
02839
02853 void dynamic_record::get(const std::string& name, SQLGUID& guid) const
02854 {
02855 guid = *reinterpret_cast<SQLGUID *>(find_column(name, SQL_C_GUID, true)->f_data->get());
02856 }
02857
02858
02872 void dynamic_record::get(SQLSMALLINT col, SQLGUID& guid) const
02873 {
02874 guid = *reinterpret_cast<SQLGUID *>(find_column(col, SQL_C_GUID, true)->f_data->get());
02875 }
02876
02877
02878
02879
02880
02881
02990 }