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 }