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
01381
01382 if(info->f_size == 0) {
01383
01384 info->f_size = 8 * 1024;
01385 }
01386 if(info->f_target_type == SQL_C_WCHAR) {
01387 info->f_size += sizeof(SQLWCHAR);
01388 info->f_size &= -sizeof(SQLWCHAR);
01389 }
01390 else {
01391 info->f_size += sizeof(SQLCHAR);
01392 }
01393
01394
01395 info->f_data_buffer.reset(new buffer_char_t(info->f_size + sizeof(SQLWCHAR)));
01396 info->f_data = info->f_data_buffer->get();
01397 }
01398
01399 f_statement->check(SQLBindCol(
01400 f_statement->get_handle(),
01401 idx,
01402 info->f_target_type,
01403 info->f_data,
01404 info->f_size,
01405 &info->f_fetch_size));
01406 }
01407 }
01408
01409
01410
01411
01412 void record::finalize()
01413 {
01414 bind_info_col_map_t::iterator by_col(f_bind_by_col.begin());
01415 while(by_col != f_bind_by_col.end()) {
01416 finalize_info(by_col->second);
01417 ++by_col;
01418 }
01419
01420 bind_info_name_map_t::iterator by_name(f_bind_by_name.begin());
01421 while(by_name != f_bind_by_name.end()) {
01422 finalize_info(by_name->second);
01423 ++by_name;
01424 }
01425 }
01426
01427
01438 void record::finalize_info(bind_info_t *info)
01439 {
01440 if(info->f_is_null != 0) {
01441 *info->f_is_null = info->f_fetch_size == SQL_NULL_DATA;
01442 }
01443
01444
01445
01446 if(info->f_string != 0) {
01447 if(info->f_target_type == SQL_C_CHAR) {
01448 info->f_string->clear();
01449 }
01450 else if(info->f_target_type == SQL_C_WCHAR) {
01451
01452 info->f_wstring->clear();
01453 }
01454 }
01455
01456 if(info->f_data != 0
01457 && info->f_string != 0
01458 && info->f_size > 0
01459 && info->f_fetch_size != SQL_NULL_DATA) {
01460 if(info->f_target_type == SQL_C_CHAR) {
01461
01462
01463 char *s = reinterpret_cast<char *>(info->f_data);
01464 s[info->f_size] = '\0';
01465 *info->f_string = s;
01466 }
01467 else if(info->f_target_type == SQL_C_WCHAR) {
01468
01469
01470 SQLWCHAR *s = reinterpret_cast<SQLWCHAR *>(info->f_data);
01471 s[info->f_size / sizeof(SQLWCHAR)] = '\0';
01472 while(*s != static_cast<SQLWCHAR>(0)) {
01473
01474
01475 *info->f_wstring += static_cast<wchar_t>(*s++);
01476 }
01477 }
01478 }
01479 }
01480
01481
01482
01674 const std::string& dynamic_record::column_name(SQLSMALLINT col) const
01675 {
01676 return find_column(col, SQL_UNKNOWN_TYPE)->f_name;
01677 }
01678
01690 SQLSMALLINT dynamic_record::column_number(const std::string& name) const
01691 {
01692 return find_column(name, SQL_UNKNOWN_TYPE)->f_col;
01693 }
01694
01695
01696
01697 void dynamic_record::bind_impl()
01698 {
01699 SQLSMALLINT idx, max, name_length;
01700 SQLCHAR column_name[256];
01701
01702 max = static_cast<SQLSMALLINT>(f_statement->cols());
01703 for(idx = 1; idx <= max; ++idx) {
01704
01705 bind_info_t *info = new bind_info_t;
01706 info->f_col = idx;
01707
01708
01709 name_length = sizeof(column_name);
01710 f_statement->check(SQLDescribeCol(
01711 f_statement->get_handle(),
01712 idx,
01713 column_name,
01714 sizeof(column_name),
01715 &name_length,
01716 &info->f_target_type,
01717 &info->f_size,
01718 &info->f_decimal_digits,
01719 NULL));
01720
01721
01722 switch(info->f_target_type) {
01723 case SQL_VARCHAR:
01724 case SQL_LONGVARCHAR:
01725 case SQL_BINARY:
01726 case SQL_VARBINARY:
01727 case SQL_LONGVARBINARY:
01728 case SQL_GUID:
01729 case SQL_DECIMAL:
01730 info->f_bind_type = SQL_C_CHAR;
01731 info->f_size += sizeof(SQLCHAR);
01732 break;
01733
01734 case SQL_WLONGVARCHAR:
01735 case SQL_WVARCHAR:
01736 info->f_bind_type = SQL_C_WCHAR;
01737 info->f_size += sizeof(SQLWCHAR);
01738 break;
01739
01740 case SQL_CHAR:
01741 info->f_size += sizeof(SQLCHAR);
01742 info->f_bind_type = info->f_target_type;
01743 break;
01744
01745 case SQL_WCHAR:
01746 info->f_size += sizeof(SQLWCHAR);
01747 info->f_bind_type = info->f_target_type;
01748 break;
01749
01750 case SQL_BIGINT:
01751 info->f_bind_type = SQL_C_SBIGINT;
01752 break;
01753
01754 case SQL_FLOAT:
01755 info->f_bind_type = SQL_C_DOUBLE;
01756 break;
01757
01758 default:
01759 info->f_bind_type = info->f_target_type;
01760 break;
01761
01762 }
01763
01764
01765 if(name_length >= sizeof(column_name)) {
01766 name_length = sizeof(column_name) - 1;
01767 }
01768 column_name[name_length] = '\0';
01769 info->f_name = reinterpret_cast<char *>(column_name);
01770
01771 info->f_data.reset(new buffer_char_t(info->f_size));
01772
01773 f_statement->check(SQLBindCol(
01774 f_statement->get_handle(),
01775 idx,
01776 info->f_bind_type,
01777 info->f_data->get(),
01778 info->f_size,
01779 &info->f_fetch_size));
01780 if(!info->f_name.empty()) {
01781 f_bind_by_name.insert(bind_info_name_t(info->f_name, info));
01782 }
01783 f_bind_by_col.push_back(info);
01784 }
01785 }
01786
01801 bool dynamic_record::exists(const std::string& name)
01802 {
01803 bind_info_name_map_t::iterator itr;
01804
01805 itr = f_bind_by_name.find(name);
01806 return itr != f_bind_by_name.end();
01807 }
01808
01809
01838 const dynamic_record::bind_info_t *dynamic_record::find_column(const std::string& name, SQLSMALLINT target_type, bool except_null) const
01839 {
01840 const bind_info_t *info;
01841 bind_info_name_map_t::const_iterator itr;
01842
01843
01844 itr = f_bind_by_name.find(name);
01845 if(itr == f_bind_by_name.end()) {
01846 diagnostic d(odbcpp_error::ODBCPP_NOT_FOUND, "the column \"" + name + "\" was not found in this record");
01847 throw odbcpp_error(d);
01848 }
01849
01850
01851 return verify_column(itr->second, target_type, except_null);
01852 }
01853
01854
01855
01879 const dynamic_record::bind_info_t *dynamic_record::find_column(SQLSMALLINT col, SQLSMALLINT target_type, bool except_null) const
01880 {
01881 const bind_info_t *info;
01882
01883 --col;
01884 if(static_cast<SQLUSMALLINT>(col) >= f_bind_by_col.size()) {
01885 diagnostic d(odbcpp_error::ODBCPP_NOT_FOUND, std::string("there is not that many columns in this record"));
01886 throw odbcpp_error(d);
01887 }
01888
01889
01890 return verify_column(f_bind_by_col[col], target_type, except_null);
01891 }
01892
01893
01894
01910 const dynamic_record::bind_info_t *dynamic_record::verify_column(const bind_info_t *info, SQLSMALLINT target_type, bool except_null) const
01911 {
01912
01913 if(target_type != SQL_UNKNOWN_TYPE
01914 && info->f_bind_type != target_type) {
01915
01916 switch(target_type) {
01917 case SQL_C_CHAR:
01918 target_type = SQL_VARCHAR;
01919 break;
01920
01921 case SQL_C_DATE:
01922 target_type = SQL_TYPE_DATE;
01923 break;
01924
01925 case SQL_C_TIME:
01926 target_type = SQL_TYPE_TIME;
01927 break;
01928
01929 case SQL_C_TIMESTAMP:
01930 target_type = SQL_TYPE_TIMESTAMP;
01931 break;
01932
01933 }
01934 if(info->f_bind_type != target_type) {
01935 std::ostringstream err;
01936 err << "type mismatch for column \"" + info->f_name + "\"";
01937 err << " (expected " << info->f_bind_type << ", requested " << target_type << ")";
01938 diagnostic d(odbcpp_error::ODBCPP_TYPE_MISMATCH, err.str());
01939 throw odbcpp_error(d);
01940 }
01941 }
01942
01943 if(except_null && info->f_fetch_size == SQL_NULL_DATA) {
01944 diagnostic d(odbcpp_error::ODBCPP_NO_DATA, std::string("this column is NULL and cannot be retrieved"));
01945 throw odbcpp_error(d);
01946 }
01947
01948 return info;
01949 }
01950
01951
01952
01968 SQLSMALLINT dynamic_record::get_type(const std::string& name) const
01969 {
01970 return find_column(name, SQL_UNKNOWN_TYPE)->f_target_type;
01971 }
01972
01973
01992 SQLSMALLINT dynamic_record::get_type(SQLSMALLINT col) const
01993 {
01994 return find_column(col, SQL_UNKNOWN_TYPE)->f_target_type;
01995 }
01996
01997
02013 SQLSMALLINT dynamic_record::get_decimal_digits(const std::string& name) const
02014 {
02015 return find_column(name, SQL_UNKNOWN_TYPE)->f_decimal_digits;
02016 }
02017
02018
02037 SQLSMALLINT dynamic_record::get_decimal_digits(SQLSMALLINT col) const
02038 {
02039 return find_column(col, SQL_UNKNOWN_TYPE)->f_decimal_digits;
02040 }
02041
02042
02056 SQLSMALLINT dynamic_record::get_is_null(const std::string& name) const
02057 {
02058 return find_column(name, SQL_UNKNOWN_TYPE)->f_fetch_size == SQL_NULL_DATA;
02059 }
02060
02061
02078 SQLSMALLINT dynamic_record::get_is_null(SQLSMALLINT col) const
02079 {
02080 return find_column(col, SQL_UNKNOWN_TYPE)->f_fetch_size == SQL_NULL_DATA;
02081 }
02082
02083
02104 SQLLEN dynamic_record::get_size(const std::string& name) const
02105 {
02106 return find_column(name, SQL_UNKNOWN_TYPE)->f_fetch_size;
02107 }
02108
02109
02133 SQLLEN dynamic_record::get_size(SQLSMALLINT col) const
02134 {
02135 return find_column(col, SQL_UNKNOWN_TYPE)->f_fetch_size;
02136 }
02137
02138
02152 void dynamic_record::get(const std::string& name, std::string& str) const
02153 {
02154 str = reinterpret_cast<const char *>(find_column(name, SQL_C_CHAR, true)->f_data->get());
02155 }
02156
02157
02171 void dynamic_record::get(SQLSMALLINT col, std::string& str) const
02172 {
02173 str = reinterpret_cast<const char *>(find_column(col, SQL_C_CHAR, true)->f_data->get());
02174 }
02175
02176
02190 void dynamic_record::get(const std::string& name, std::wstring& str) const
02191 {
02192 const SQLWCHAR *s = reinterpret_cast<const SQLWCHAR *>(find_column(name, SQL_C_WCHAR, true)->f_data->get());
02193 str.clear();
02194 while(*s != '\0') {
02195 str += static_cast<wchar_t>(*s++);
02196 }
02197 }
02198
02199
02213 void dynamic_record::get(SQLSMALLINT col, std::wstring& str) const
02214 {
02215 const SQLWCHAR *s = reinterpret_cast<const SQLWCHAR *>(find_column(col, SQL_C_WCHAR, true)->f_data->get());
02216 str.clear();
02217 while(*s != '\0') {
02218 str += static_cast<wchar_t>(*s++);
02219 }
02220 }
02221
02222
02236 void dynamic_record::get(const std::string& name, SQLCHAR& tiny_int) const
02237 {
02238 tiny_int = *reinterpret_cast<SQLCHAR *>(find_column(name, SQL_C_UTINYINT, true)->f_data->get());
02239 }
02240
02241
02255 void dynamic_record::get(SQLSMALLINT col, SQLCHAR& tiny_int) const
02256 {
02257 tiny_int = *reinterpret_cast<SQLCHAR *>(find_column(col, SQL_C_UTINYINT, true)->f_data->get());
02258 }
02259
02260
02274 void dynamic_record::get(const std::string& name, SQLSCHAR& tiny_int) const
02275 {
02276 tiny_int = *reinterpret_cast<SQLSCHAR *>(find_column(name, SQL_C_TINYINT, true)->f_data->get());
02277 }
02278
02279
02293 void dynamic_record::get(SQLSMALLINT col, SQLSCHAR& tiny_int) const
02294 {
02295 tiny_int = *reinterpret_cast<SQLSCHAR *>(find_column(col, SQL_C_TINYINT, true)->f_data->get());
02296 }
02297
02298
02312 void dynamic_record::get(const std::string& name, SQLSMALLINT& small_int) const
02313 {
02314 small_int = *reinterpret_cast<SQLSMALLINT *>(find_column(name, SQL_C_SHORT, true)->f_data->get());
02315 }
02316
02317
02331 void dynamic_record::get(SQLSMALLINT col, SQLSMALLINT& small_int) const
02332 {
02333 small_int = *reinterpret_cast<SQLSMALLINT *>(find_column(col, SQL_C_SHORT, true)->f_data->get());
02334 }
02335
02336
02350 void dynamic_record::get(const std::string& name, SQLUSMALLINT& small_int) const
02351 {
02352 small_int = *reinterpret_cast<SQLUSMALLINT *>(find_column(name, SQL_C_USHORT, true)->f_data->get());
02353 }
02354
02355
02369 void dynamic_record::get(SQLSMALLINT col, SQLUSMALLINT& small_int) const
02370 {
02371 small_int = *reinterpret_cast<SQLUSMALLINT *>(find_column(col, SQL_C_USHORT, true)->f_data->get());
02372 }
02373
02374
02388 void dynamic_record::get(const std::string& name, SQLINTEGER& integer) const
02389 {
02390 integer = *reinterpret_cast<SQLINTEGER *>(find_column(name, SQL_C_LONG, true)->f_data->get());
02391 }
02392
02393
02407 void dynamic_record::get(SQLSMALLINT col, SQLINTEGER& integer) const
02408 {
02409 integer = *reinterpret_cast<SQLUINTEGER *>(find_column(col, SQL_C_LONG, true)->f_data->get());
02410 }
02411
02412
02426 void dynamic_record::get(const std::string& name, SQLUINTEGER& integer) const
02427 {
02428 integer = *reinterpret_cast<SQLUINTEGER *>(find_column(name, SQL_C_ULONG, true)->f_data->get());
02429 }
02430
02431
02445 void dynamic_record::get(SQLSMALLINT col, SQLUINTEGER& integer) const
02446 {
02447 integer = *reinterpret_cast<SQLUINTEGER *>(find_column(col, SQL_C_ULONG, true)->f_data->get());
02448 }
02449
02450
02464 void dynamic_record::get(const std::string& name, SQLBIGINT& big_int) const
02465 {
02466 big_int = *reinterpret_cast<SQLBIGINT *>(find_column(name, SQL_C_SBIGINT, true)->f_data->get());
02467 }
02468
02469
02483 void dynamic_record::get(SQLSMALLINT col, SQLBIGINT& big_int) const
02484 {
02485 big_int = *reinterpret_cast<SQLBIGINT *>(find_column(col, SQL_C_SBIGINT, true)->f_data->get());
02486 }
02487
02488
02502 void dynamic_record::get(const std::string& name, SQLUBIGINT& big_int) const
02503 {
02504 big_int = *reinterpret_cast<SQLUBIGINT *>(find_column(name, SQL_C_UBIGINT, true)->f_data->get());
02505 }
02506
02507
02521 void dynamic_record::get(SQLSMALLINT col, SQLUBIGINT& big_int) const
02522 {
02523 big_int = *reinterpret_cast<SQLUBIGINT *>(find_column(col, SQL_C_UBIGINT, true)->f_data->get());
02524 }
02525
02526
02540 void dynamic_record::get(const std::string& name, SQLREAL& real) const
02541 {
02542 real = *reinterpret_cast<SQLREAL *>(find_column(name, SQL_C_FLOAT, true)->f_data->get());
02543 }
02544
02545
02559 void dynamic_record::get(SQLSMALLINT col, SQLREAL& real) const
02560 {
02561 real = *reinterpret_cast<SQLREAL *>(find_column(col, SQL_C_FLOAT, true)->f_data->get());
02562 }
02563
02564
02578 void dynamic_record::get(const std::string& name, SQLFLOAT& dbl) const
02579 {
02580 dbl = *reinterpret_cast<SQLFLOAT *>(find_column(name, SQL_C_DOUBLE, true)->f_data->get());
02581 }
02582
02583
02597 void dynamic_record::get(SQLSMALLINT col, SQLFLOAT& dbl) const
02598 {
02599 dbl = *reinterpret_cast<SQLFLOAT *>(find_column(col, SQL_C_DOUBLE, true)->f_data->get());
02600 }
02601
02602
02624 SQLULEN dynamic_record::get(const std::string& name, SQLCHAR *binary, SQLLEN length) const
02625 {
02626 if(length < 0) {
02627 diagnostic d(odbcpp_error::ODBCPP_INCORRECT_USE, std::string("a binary buffer cannot have a negative size"));
02628 throw odbcpp_error(d);
02629 }
02630 if(binary == 0) {
02631 diagnostic d(odbcpp_error::ODBCPP_INCORRECT_USE, std::string("a binary buffer cannot be a NULL pointer"));
02632 throw odbcpp_error(d);
02633 }
02634
02635 const bind_info_t *info = find_column(name, SQL_UNKNOWN_TYPE, true);
02636
02637 SQLLEN size = static_cast<SQLUINTEGER>(length) < info->f_fetch_size ? length : info->f_size;
02638
02639 memcpy(binary, info->f_data->get(), size);
02640
02641 return size;
02642 }
02643
02644
02666 SQLULEN dynamic_record::get(SQLSMALLINT col, SQLCHAR *binary, SQLLEN length) const
02667 {
02668 if(length < 0) {
02669 diagnostic d(odbcpp_error::ODBCPP_INCORRECT_USE, std::string("a binary buffer cannot have a negative size"));
02670 throw odbcpp_error(d);
02671 }
02672 if(binary == 0) {
02673 diagnostic d(odbcpp_error::ODBCPP_INCORRECT_USE, std::string("a binary buffer cannot be a NULL pointer"));
02674 throw odbcpp_error(d);
02675 }
02676
02677 const bind_info_t *info = find_column(col, SQL_UNKNOWN_TYPE, true);
02678
02679 SQLLEN size = static_cast<SQLUINTEGER>(length) < info->f_fetch_size ? length : info->f_size;
02680
02681 memcpy(binary, info->f_data->get(), size);
02682
02683 return size;
02684 }
02685
02686
02700 void dynamic_record::get(const std::string& name, SQL_DATE_STRUCT& date) const
02701 {
02702 date = *reinterpret_cast<SQL_DATE_STRUCT *>(find_column(name, SQL_C_DATE, true)->f_data->get());
02703 }
02704
02705
02719 void dynamic_record::get(SQLSMALLINT col, SQL_DATE_STRUCT& date) const
02720 {
02721 date = *reinterpret_cast<SQL_DATE_STRUCT *>(find_column(col, SQL_C_DATE, true)->f_data->get());
02722 }
02723
02724
02738 void dynamic_record::get(const std::string& name, SQL_TIME_STRUCT& time) const
02739 {
02740 time = *reinterpret_cast<SQL_TIME_STRUCT *>(find_column(name, SQL_C_TIME, true)->f_data->get());
02741 }
02742
02743
02757 void dynamic_record::get(SQLSMALLINT col, SQL_TIME_STRUCT& time) const
02758 {
02759 time = *reinterpret_cast<SQL_TIME_STRUCT *>(find_column(col, SQL_C_TIME, true)->f_data->get());
02760 }
02761
02762
02776 void dynamic_record::get(const std::string& name, SQL_TIMESTAMP_STRUCT& timestamp) const
02777 {
02778 timestamp = *reinterpret_cast<SQL_TIMESTAMP_STRUCT *>(find_column(name, SQL_C_TIMESTAMP, true)->f_data->get());
02779 }
02780
02781
02795 void dynamic_record::get(SQLSMALLINT col, SQL_TIMESTAMP_STRUCT& timestamp) const
02796 {
02797 timestamp = *reinterpret_cast<SQL_TIMESTAMP_STRUCT *>(find_column(col, SQL_C_TIMESTAMP, true)->f_data->get());
02798 }
02799
02800
02814 void dynamic_record::get(const std::string& name, SQL_NUMERIC_STRUCT& numeric) const
02815 {
02816 numeric = *reinterpret_cast<SQL_NUMERIC_STRUCT *>(find_column(name, SQL_C_NUMERIC, true)->f_data->get());
02817 }
02818
02819
02833 void dynamic_record::get(SQLSMALLINT col, SQL_NUMERIC_STRUCT& numeric) const
02834 {
02835 numeric = *reinterpret_cast<SQL_NUMERIC_STRUCT *>(find_column(col, SQL_C_NUMERIC, true)->f_data->get());
02836 }
02837
02838
02852 void dynamic_record::get(const std::string& name, SQLGUID& guid) const
02853 {
02854 guid = *reinterpret_cast<SQLGUID *>(find_column(name, SQL_C_GUID, true)->f_data->get());
02855 }
02856
02857
02871 void dynamic_record::get(SQLSMALLINT col, SQLGUID& guid) const
02872 {
02873 guid = *reinterpret_cast<SQLGUID *>(find_column(col, SQL_C_GUID, true)->f_data->get());
02874 }
02875
02876
02877
02878
02879
02880
02989 }