Warning, file /sdk/codevis/thirdparty/soci/src/core/soci-simple.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 //
0002 // Copyright (C) 2008 Maciej Sobczak
0003 // Distributed under the Boost Software License, Version 1.0.
0004 // (See accompanying file LICENSE_1_0.txt or copy at
0005 // http://www.boost.org/LICENSE_1_0.txt)
0006 //
0007 
0008 #define SOCI_SOURCE
0009 
0010 #include "soci/soci-simple.h"
0011 #include "soci/soci.h"
0012 
0013 #include <cstddef>
0014 #include <cstdio>
0015 #include <ctime>
0016 #include <exception>
0017 #include <map>
0018 #include <string>
0019 #include <vector>
0020 
0021 using namespace soci;
0022 
0023 namespace // unnamed
0024 {
0025 
0026 struct session_wrapper
0027 {
0028     session sql;
0029 
0030     bool is_ok;
0031     std::string error_message;
0032 };
0033 
0034 } // namespace unnamed
0035 
0036 
0037 SOCI_DECL session_handle soci_create_session(char const * connection_string)
0038 {
0039     session_wrapper * wrapper = NULL;
0040     try
0041     {
0042         wrapper = new session_wrapper();
0043     }
0044     catch (...)
0045     {
0046         return NULL;
0047     }
0048 
0049     try
0050     {
0051         wrapper->sql.open(connection_string);
0052         wrapper->is_ok = true;
0053     }
0054     catch (std::exception const & e)
0055     {
0056         wrapper->is_ok = false;
0057         wrapper->error_message = e.what();
0058     }
0059 
0060     return wrapper;
0061 }
0062 
0063 SOCI_DECL void soci_destroy_session(session_handle s)
0064 {
0065     session_wrapper * wrapper = static_cast<session_wrapper *>(s);
0066     delete wrapper;
0067 }
0068 
0069 SOCI_DECL void soci_begin(session_handle s)
0070 {
0071     session_wrapper * wrapper = static_cast<session_wrapper *>(s);
0072     try
0073     {
0074         wrapper->sql.begin();
0075         wrapper->is_ok = true;
0076     }
0077     catch (std::exception const & e)
0078     {
0079         wrapper->is_ok = false;
0080         wrapper->error_message = e.what();
0081     }
0082 }
0083 
0084 SOCI_DECL void soci_commit(session_handle s)
0085 {
0086     session_wrapper * wrapper = static_cast<session_wrapper *>(s);
0087     try
0088     {
0089         wrapper->sql.commit();
0090         wrapper->is_ok = true;
0091     }
0092     catch (std::exception const & e)
0093     {
0094         wrapper->is_ok = false;
0095         wrapper->error_message = e.what();
0096     }
0097 }
0098 
0099 SOCI_DECL void soci_rollback(session_handle s)
0100 {
0101     session_wrapper * wrapper = static_cast<session_wrapper *>(s);
0102     try
0103     {
0104         wrapper->sql.rollback();
0105         wrapper->is_ok = true;
0106     }
0107     catch (std::exception const & e)
0108     {
0109         wrapper->is_ok = false;
0110         wrapper->error_message = e.what();
0111     }
0112 }
0113 
0114 // this will not be needed until dynamic row is exposed
0115 // SOCI_DECL void soci_uppercase_column_names(session_handle s, bool forceToUpper)
0116 // {
0117 //     session_wrapper * wrapper = static_cast<session_wrapper *>(s);
0118 //     wrapper->sql.uppercase_column_names(forceToUpper);
0119 //     wrapper->is_ok = true;
0120 // }
0121 
0122 SOCI_DECL int soci_session_state(session_handle s)
0123 {
0124     session_wrapper * wrapper = static_cast<session_wrapper *>(s);
0125 
0126     return wrapper->is_ok ? 1 : 0;
0127 }
0128 
0129 SOCI_DECL char const * soci_session_error_message(session_handle s)
0130 {
0131     session_wrapper * wrapper = static_cast<session_wrapper *>(s);
0132 
0133     return wrapper->error_message.c_str();
0134 }
0135 
0136 
0137 // blob
0138 struct blob_wrapper
0139 {
0140     blob_wrapper(session &sql)
0141         : blob_(sql), is_ok(true) {}
0142 
0143     blob blob_;
0144     bool is_ok;
0145     std::string error_message;
0146 };
0147 
0148 blob_wrapper *soci_create_blob_session(soci::session &sql)
0149 {
0150     blob_wrapper *bw = NULL;
0151     try
0152     {
0153         bw = new blob_wrapper(sql);
0154     }
0155     catch (...)
0156     {
0157         delete bw;
0158         return NULL;
0159     }
0160 
0161     return bw;
0162 }
0163 
0164 SOCI_DECL blob_handle soci_create_blob(session_handle s)
0165 {
0166     session_wrapper * session = static_cast<session_wrapper *>(s);
0167     if (!session->is_ok)
0168         return NULL;
0169 
0170     return soci_create_blob_session(session->sql);
0171 }
0172 
0173 SOCI_DECL void soci_destroy_blob(blob_handle b)
0174 {
0175     blob_wrapper *blob = static_cast<blob_wrapper *>(b);
0176     try
0177     {
0178         delete blob;
0179     }
0180     catch (...)
0181     {}
0182 }
0183 
0184 SOCI_DECL int soci_blob_get_len(blob_handle b)
0185 {
0186     blob_wrapper *blob = static_cast<blob_wrapper *>(b);
0187     return static_cast<int>(blob->blob_.get_len());
0188 }
0189 
0190 SOCI_DECL int soci_blob_read(blob_handle b, int offset, char *buf, int toRead)
0191 {
0192     blob_wrapper *blob = static_cast<blob_wrapper *>(b);
0193     try
0194     {
0195         SOCI_ALLOW_DEPRECATED_BEGIN
0196         return static_cast<int>(blob->blob_.read(offset, buf, toRead));
0197         SOCI_ALLOW_DEPRECATED_END
0198     }
0199     catch (std::exception &e)
0200     {
0201         blob->is_ok = false;
0202         blob->error_message = e.what();
0203         return -1;
0204     }
0205     catch (...)
0206     {
0207         blob->is_ok = false;
0208         blob->error_message = "unknown exception";
0209         return -1;
0210     }
0211 }
0212 
0213 SOCI_DECL int soci_blob_read_from_start(blob_handle b, char *buf, int toRead, int offset)
0214 {
0215     blob_wrapper *blob = static_cast<blob_wrapper *>(b);
0216     try
0217     {
0218         return static_cast<int>(blob->blob_.read_from_start(buf, toRead, offset));
0219     }
0220     catch (std::exception &e)
0221     {
0222         blob->is_ok = false;
0223         blob->error_message = e.what();
0224         return -1;
0225     }
0226     catch (...)
0227     {
0228         blob->is_ok = false;
0229         blob->error_message = "unknown exception";
0230         return -1;
0231     }
0232 }
0233 
0234 SOCI_DECL int soci_blob_write(blob_handle b, int offset, char const *buf, int toWrite)
0235 {
0236     blob_wrapper *blob = static_cast<blob_wrapper *>(b);
0237     try
0238     {
0239         SOCI_ALLOW_DEPRECATED_BEGIN
0240         return static_cast<int>(blob->blob_.write(offset, buf, toWrite));
0241         SOCI_ALLOW_DEPRECATED_END
0242     }
0243     catch (std::exception &e)
0244     {
0245         blob->is_ok = false;
0246         blob->error_message = e.what();
0247         return -1;
0248     }
0249     catch (...)
0250     {
0251         blob->is_ok = false;
0252         blob->error_message = "unknown exception";
0253         return -1;
0254     }
0255 }
0256 
0257 SOCI_DECL int soci_blob_write_from_start(blob_handle b, char const *buf, int toWrite, int offset)
0258 {
0259     blob_wrapper *blob = static_cast<blob_wrapper *>(b);
0260     try
0261     {
0262         return static_cast<int>(blob->blob_.write_from_start(buf, toWrite, offset));
0263     }
0264     catch (std::exception &e)
0265     {
0266         blob->is_ok = false;
0267         blob->error_message = e.what();
0268         return -1;
0269     }
0270     catch (...)
0271     {
0272         blob->is_ok = false;
0273         blob->error_message = "unknown exception";
0274         return -1;
0275     }
0276 }
0277 
0278 SOCI_DECL int soci_blob_append(blob_handle b, char const *buf, int toWrite)
0279 {
0280     blob_wrapper *blob = static_cast<blob_wrapper *>(b);
0281     try
0282     {
0283         return static_cast<int>(blob->blob_.append(buf, toWrite));
0284     }
0285     catch (std::exception &e)
0286     {
0287         blob->is_ok = false;
0288         blob->error_message = e.what();
0289         return -1;
0290     }
0291     catch (...)
0292     {
0293         blob->is_ok = false;
0294         blob->error_message = "unknown exception";
0295         return -1;
0296     }
0297 }
0298 
0299 SOCI_DECL int soci_blob_trim(blob_handle b, int newLen)
0300 {
0301     blob_wrapper *blob = static_cast<blob_wrapper *>(b);
0302     try
0303     {
0304         blob->blob_.trim(newLen);
0305     }
0306     catch (std::exception &e)
0307     {
0308         blob->is_ok = false;
0309         blob->error_message = e.what();
0310         return -1;
0311     }
0312     catch (...)
0313     {
0314         blob->is_ok = false;
0315         blob->error_message = "unknown exception";
0316         return -1;
0317     }
0318 
0319     return 0;
0320 }
0321 
0322 SOCI_DECL int soci_blob_state(blob_handle b)
0323 {
0324     blob_wrapper *blob = static_cast<blob_wrapper *>(b);
0325     return (blob->is_ok ? 1 : 0);
0326 }
0327 
0328 SOCI_DECL char const * soci_blob_error_message(blob_handle b)
0329 {
0330     blob_wrapper *blob = static_cast<blob_wrapper *>(b);
0331     return blob->error_message.c_str();
0332 }
0333 
0334 // statement
0335 
0336 
0337 namespace // unnamed
0338 {
0339 
0340 struct statement_wrapper
0341 {
0342     statement_wrapper(session & _sql)
0343         : sql(_sql), st(sql), statement_state(clean), into_kind(empty), use_kind(empty),
0344           next_position(0), is_ok(true) {}
0345 
0346     ~statement_wrapper();
0347 
0348     session  &sql;
0349     statement st;
0350 
0351     enum state { clean, defining, executing } statement_state;
0352     enum kind { empty, single, bulk } into_kind, use_kind;
0353 
0354     // into elements
0355     int next_position;
0356     std::vector<data_type> into_types; // for both single and bulk
0357     std::vector<indicator> into_indicators;
0358     std::map<int, std::string> into_strings;
0359     std::map<int, int> into_ints;
0360     std::map<int, long long> into_longlongs;
0361     std::map<int, double> into_doubles;
0362     std::map<int, std::tm> into_dates;
0363     std::map<int, blob_wrapper *> into_blob;
0364 
0365     std::vector<std::vector<indicator> > into_indicators_v;
0366     std::map<int, std::vector<std::string> > into_strings_v;
0367     std::map<int, std::vector<int> > into_ints_v;
0368     std::map<int, std::vector<long long> > into_longlongs_v;
0369     std::map<int, std::vector<double> > into_doubles_v;
0370     std::map<int, std::vector<std::tm> > into_dates_v;
0371 
0372     // use elements
0373     std::map<std::string, indicator> use_indicators;
0374     std::map<std::string, std::string> use_strings;
0375     std::map<std::string, int> use_ints;
0376     std::map<std::string, long long> use_longlongs;
0377     std::map<std::string, double> use_doubles;
0378     std::map<std::string, std::tm> use_dates;
0379     std::map<std::string, blob_wrapper *> use_blob;
0380 
0381     std::map<std::string, std::vector<indicator> > use_indicators_v;
0382     std::map<std::string, std::vector<std::string> > use_strings_v;
0383     std::map<std::string, std::vector<int> > use_ints_v;
0384     std::map<std::string, std::vector<long long> > use_longlongs_v;
0385     std::map<std::string, std::vector<double> > use_doubles_v;
0386     std::map<std::string, std::vector<std::tm> > use_dates_v;
0387 
0388     // format is: "YYYY MM DD hh mm ss", but we make the buffer bigger to
0389     // avoid gcc -Wformat-truncation warnings as it considers that the output
0390     // could be up to 72 bytes if the integers had maximal values
0391     char date_formatted[80];
0392 
0393     bool is_ok;
0394     std::string error_message;
0395 
0396 private:
0397     SOCI_NOT_COPYABLE(statement_wrapper)
0398 };
0399 
0400 statement_wrapper::~statement_wrapper()
0401 {
0402     for (std::map<int, blob_wrapper *>::iterator iter = into_blob.begin(), last = into_blob.end();
0403          iter != last; ++iter)
0404     {
0405         soci_destroy_blob(iter->second);
0406     }
0407 
0408     for (std::map<std::string, blob_wrapper *>::iterator iter = use_blob.begin(), last = use_blob.end();
0409          iter != last; ++iter)
0410     {
0411         soci::indicator &ind = use_indicators[iter->first];
0412         blob_wrapper *&blob = iter->second;
0413         if (ind == i_null && blob != NULL)
0414             soci_destroy_blob(blob);
0415     }
0416 }
0417 
0418 // helper for checking if the attempt was made to add more into/use elements
0419 // after the statement was set for execution
0420 bool cannot_add_elements(statement_wrapper & wrapper, statement_wrapper::kind k, bool into)
0421 {
0422     if (wrapper.statement_state == statement_wrapper::executing)
0423     {
0424         wrapper.is_ok = false;
0425         wrapper.error_message = "Cannot add more data items.";
0426         return true;
0427     }
0428 
0429     if (into)
0430     {
0431         if (k == statement_wrapper::single && wrapper.into_kind == statement_wrapper::bulk)
0432         {
0433             wrapper.is_ok = false;
0434             wrapper.error_message = "Cannot add single into data items.";
0435             return true;
0436         }
0437         if (k == statement_wrapper::bulk && wrapper.into_kind == statement_wrapper::single)
0438         {
0439             wrapper.is_ok = false;
0440             wrapper.error_message = "Cannot add vector into data items.";
0441             return true;
0442         }
0443     }
0444     else
0445     {
0446         // trying to add use elements
0447         if (k == statement_wrapper::single && wrapper.use_kind == statement_wrapper::bulk)
0448         {
0449             wrapper.is_ok = false;
0450             wrapper.error_message = "Cannot add single use data items.";
0451             return true;
0452         }
0453         if (k == statement_wrapper::bulk && wrapper.use_kind == statement_wrapper::single)
0454         {
0455             wrapper.is_ok = false;
0456             wrapper.error_message = "Cannot add vector use data items.";
0457             return true;
0458         }
0459     }
0460 
0461     wrapper.is_ok = true;
0462     return false;
0463 }
0464 
0465 // helper for checking if the expected into element exists on the given position
0466 bool position_check_failed(statement_wrapper & wrapper, statement_wrapper::kind k,
0467     int position, data_type expected_type, char const * type_name)
0468 {
0469     if (position < 0 || position >= wrapper.next_position)
0470     {
0471         wrapper.is_ok = false;
0472         wrapper.error_message = "Invalid position.";
0473         return true;
0474     }
0475 
0476     if (wrapper.into_types[position] != expected_type)
0477     {
0478         wrapper.is_ok = false;
0479         wrapper.error_message = "No into ";
0480         if (k == statement_wrapper::bulk)
0481         {
0482             wrapper.error_message += "vector ";
0483         }
0484         wrapper.error_message += type_name;
0485         wrapper.error_message += " element at this position.";
0486         return true;
0487     }
0488 
0489     wrapper.is_ok = true;
0490     return false;
0491 }
0492 
0493 // helper for checking if the into element on the given position
0494 // is not null
0495 bool not_null_check_failed(statement_wrapper & wrapper, int position)
0496 {
0497     if (wrapper.into_indicators[position] == i_null)
0498     {
0499         wrapper.is_ok = false;
0500         wrapper.error_message = "Element is null.";
0501         return true;
0502     }
0503 
0504     wrapper.is_ok = true;
0505     return false;
0506 }
0507 
0508 // overloaded version for vectors
0509 bool not_null_check_failed(statement_wrapper & wrapper, int position, int index)
0510 {
0511     if (wrapper.into_indicators_v[position][index] == i_null)
0512     {
0513         wrapper.is_ok = false;
0514         wrapper.error_message = "Element is null.";
0515         return true;
0516     }
0517 
0518     wrapper.is_ok = true;
0519     return false;
0520 }
0521 
0522 // helper for checking the index value
0523 template <typename T>
0524 bool index_check_failed(std::vector<T> const & v,
0525     statement_wrapper & wrapper, int index)
0526 {
0527     if (index < 0 || index >= static_cast<int>(v.size()))
0528     {
0529         wrapper.is_ok = false;
0530         wrapper.error_message = "Invalid index.";
0531         return true;
0532     }
0533 
0534     wrapper.is_ok = true;
0535     return false;
0536 }
0537 
0538 // helper for checking the uniqueness of the use element's name
0539 bool name_unique_check_failed(statement_wrapper & wrapper,
0540     statement_wrapper::kind k, char const * name)
0541 {
0542     bool is_unique;
0543     if (k == statement_wrapper::single)
0544     {
0545         typedef std::map<std::string, indicator>::const_iterator iterator;
0546         iterator const it = wrapper.use_indicators.find(name);
0547         is_unique = it == wrapper.use_indicators.end();
0548     }
0549     else
0550     {
0551         // vector version
0552 
0553         typedef std::map
0554             <
0555                 std::string,
0556                 std::vector<indicator>
0557             >::const_iterator iterator;
0558 
0559         iterator const it = wrapper.use_indicators_v.find(name);
0560         is_unique = it == wrapper.use_indicators_v.end();
0561     }
0562 
0563     if (is_unique)
0564     {
0565         wrapper.is_ok = true;
0566         return false;
0567     }
0568     else
0569     {
0570         wrapper.is_ok = false;
0571         wrapper.error_message = "Name of use element should be unique.";
0572         return true;
0573     }
0574 }
0575 
0576 // helper for checking if the use element with the given name exists
0577 bool name_exists_check_failed(statement_wrapper & wrapper,
0578     char const * name, data_type expected_type,
0579     statement_wrapper::kind k, char const * type_name)
0580 {
0581     bool name_exists = false;
0582     if (k == statement_wrapper::single)
0583     {
0584         switch (expected_type)
0585         {
0586         case dt_string:
0587             {
0588                 typedef std::map
0589                     <
0590                         std::string,
0591                         std::string
0592                     >::const_iterator iterator;
0593                 iterator const it = wrapper.use_strings.find(name);
0594                 name_exists = (it != wrapper.use_strings.end());
0595             }
0596             break;
0597         case dt_integer:
0598             {
0599                 typedef std::map<std::string, int>::const_iterator iterator;
0600                 iterator const it = wrapper.use_ints.find(name);
0601                 name_exists = (it != wrapper.use_ints.end());
0602             }
0603             break;
0604         case dt_long_long:
0605         case dt_unsigned_long_long:
0606             {
0607                 typedef std::map<std::string, long long>::const_iterator
0608                     iterator;
0609                 iterator const it = wrapper.use_longlongs.find(name);
0610                 name_exists = (it != wrapper.use_longlongs.end());
0611             }
0612             break;
0613         case dt_double:
0614             {
0615                 typedef std::map<std::string, double>::const_iterator iterator;
0616                 iterator const it = wrapper.use_doubles.find(name);
0617                 name_exists = (it != wrapper.use_doubles.end());
0618             }
0619             break;
0620         case dt_date:
0621             {
0622                 typedef std::map<std::string, std::tm>::const_iterator iterator;
0623                 iterator const it = wrapper.use_dates.find(name);
0624                 name_exists = (it != wrapper.use_dates.end());
0625             }
0626             break;
0627         case dt_blob:
0628             {
0629                 typedef std::map<std::string, blob_wrapper *>::const_iterator iterator;
0630                 iterator const it = wrapper.use_blob.find(name);
0631                 name_exists = (it != wrapper.use_blob.end());
0632             }
0633         case dt_xml:
0634             // no support for xml
0635             break;
0636         }
0637     }
0638     else
0639     {
0640         // vector version
0641 
0642         switch (expected_type)
0643         {
0644         case dt_string:
0645             {
0646                 typedef std::map
0647                     <
0648                         std::string,
0649                         std::vector<std::string>
0650                     >::const_iterator iterator;
0651                 iterator const it = wrapper.use_strings_v.find(name);
0652                 name_exists = (it != wrapper.use_strings_v.end());
0653             }
0654             break;
0655         case dt_integer:
0656             {
0657                 typedef std::map
0658                     <
0659                         std::string,
0660                         std::vector<int>
0661                     >::const_iterator iterator;
0662                 iterator const it = wrapper.use_ints_v.find(name);
0663                 name_exists = (it != wrapper.use_ints_v.end());
0664             }
0665             break;
0666         case dt_long_long:
0667         case dt_unsigned_long_long:
0668             {
0669                 typedef std::map
0670                     <
0671                         std::string,
0672                         std::vector<long long>
0673                     >::const_iterator iterator;
0674                 iterator const it = wrapper.use_longlongs_v.find(name);
0675                 name_exists = (it != wrapper.use_longlongs_v.end());
0676             }
0677             break;
0678         case dt_double:
0679             {
0680                 typedef std::map<std::string,
0681                     std::vector<double> >::const_iterator iterator;
0682                 iterator const it = wrapper.use_doubles_v.find(name);
0683                 name_exists = (it != wrapper.use_doubles_v.end());
0684             }
0685             break;
0686         case dt_date:
0687             {
0688                 typedef std::map<std::string,
0689                         std::vector<std::tm> >::const_iterator iterator;
0690                 iterator const it = wrapper.use_dates_v.find(name);
0691                 name_exists = (it != wrapper.use_dates_v.end());
0692             }
0693             break;
0694         case dt_blob:
0695         case dt_xml:
0696             // no support for bulk and xml load
0697             break;
0698         }
0699     }
0700 
0701     if (name_exists)
0702     {
0703         wrapper.is_ok = true;
0704         return false;
0705     }
0706     else
0707     {
0708         wrapper.is_ok = false;
0709         wrapper.error_message = "No use ";
0710         wrapper.error_message += type_name;
0711         wrapper.error_message += " element with this name.";
0712         return true;
0713     }
0714 }
0715 
0716 // helper function for resizing all vectors<T> in the map
0717 template <typename T>
0718 void resize_in_map(std::map<std::string, std::vector<T> > & m, int new_size)
0719 {
0720     typedef typename std::map<std::string, std::vector<T> >::iterator iterator;
0721     iterator it = m.begin();
0722     iterator const end = m.end();
0723     for ( ; it != end; ++it)
0724     {
0725         std::vector<T> & v = it->second;
0726         v.resize(new_size);
0727     }
0728 }
0729 
0730 // helper for formatting date values
0731 char const * format_date(statement_wrapper & wrapper, std::tm const & d)
0732 {
0733     std::sprintf(wrapper.date_formatted, "%d %d %d %d %d %d",
0734         d.tm_year + 1900, d.tm_mon + 1, d.tm_mday,
0735         d.tm_hour, d.tm_min, d.tm_sec);
0736 
0737     return wrapper.date_formatted;
0738 }
0739 
0740 bool string_to_date(char const * val, std::tm & /* out */ dt,
0741     statement_wrapper & wrapper)
0742 {
0743     // format is: "YYYY MM DD hh mm ss"
0744     int year;
0745     int month;
0746     int day;
0747     int hour;
0748     int minute;
0749     int second;
0750     int const converted = std::sscanf(val, "%d %d %d %d %d %d",
0751         &year, &month, &day, &hour, &minute, &second);
0752     if (converted != 6)
0753     {
0754         wrapper.is_ok = false;
0755         wrapper.error_message = "Cannot convert date.";
0756         return false;
0757     }
0758 
0759     wrapper.is_ok = true;
0760 
0761     dt.tm_year = year - 1900;
0762     dt.tm_mon = month - 1;
0763     dt.tm_mday = day;
0764     dt.tm_hour = hour;
0765     dt.tm_min = minute;
0766     dt.tm_sec = second;
0767 
0768 return true;
0769 }
0770 
0771 } // namespace unnamed
0772 
0773 
0774 SOCI_DECL statement_handle soci_create_statement(session_handle s)
0775 {
0776     session_wrapper * session_w = static_cast<session_wrapper *>(s);
0777     try
0778     {
0779         statement_wrapper * statement_w = new statement_wrapper(session_w->sql);
0780         return statement_w;
0781     }
0782     catch (std::exception const & e)
0783     {
0784         session_w->is_ok = false;
0785         session_w->error_message = e.what();
0786         return NULL;
0787     }
0788 }
0789 
0790 SOCI_DECL void soci_destroy_statement(statement_handle st)
0791 {
0792     statement_wrapper * wrapper = static_cast<statement_wrapper *>(st);
0793     delete wrapper;
0794 }
0795 
0796 SOCI_DECL int soci_into_string(statement_handle st)
0797 {
0798     statement_wrapper * wrapper = static_cast<statement_wrapper *>(st);
0799 
0800     if (cannot_add_elements(*wrapper, statement_wrapper::single, true))
0801     {
0802         return -1;
0803     }
0804 
0805     wrapper->statement_state = statement_wrapper::defining;
0806     wrapper->into_kind = statement_wrapper::single;
0807 
0808     wrapper->into_types.push_back(dt_string);
0809     wrapper->into_indicators.push_back(i_ok);
0810     wrapper->into_strings[wrapper->next_position]; // create new entry
0811     return wrapper->next_position++;
0812 }
0813 
0814 SOCI_DECL int soci_into_int(statement_handle st)
0815 {
0816     statement_wrapper * wrapper = static_cast<statement_wrapper *>(st);
0817 
0818     if (cannot_add_elements(*wrapper, statement_wrapper::single, true))
0819     {
0820         return -1;
0821     }
0822 
0823     wrapper->statement_state = statement_wrapper::defining;
0824     wrapper->into_kind = statement_wrapper::single;
0825 
0826     wrapper->into_types.push_back(dt_integer);
0827     wrapper->into_indicators.push_back(i_ok);
0828     wrapper->into_ints[wrapper->next_position]; // create new entry
0829     return wrapper->next_position++;
0830 }
0831 
0832 SOCI_DECL int soci_into_long_long(statement_handle st)
0833 {
0834     statement_wrapper * wrapper = static_cast<statement_wrapper *>(st);
0835 
0836     if (cannot_add_elements(*wrapper, statement_wrapper::single, true))
0837     {
0838         return -1;
0839     }
0840 
0841     wrapper->statement_state = statement_wrapper::defining;
0842     wrapper->into_kind = statement_wrapper::single;
0843 
0844     wrapper->into_types.push_back(dt_long_long);
0845     wrapper->into_indicators.push_back(i_ok);
0846     wrapper->into_longlongs[wrapper->next_position]; // create new entry
0847     return wrapper->next_position++;
0848 }
0849 
0850 SOCI_DECL int soci_into_double(statement_handle st)
0851 {
0852     statement_wrapper * wrapper = static_cast<statement_wrapper *>(st);
0853 
0854     if (cannot_add_elements(*wrapper, statement_wrapper::single, true))
0855     {
0856         return -1;
0857     }
0858 
0859     wrapper->statement_state = statement_wrapper::defining;
0860     wrapper->into_kind = statement_wrapper::single;
0861 
0862     wrapper->into_types.push_back(dt_double);
0863     wrapper->into_indicators.push_back(i_ok);
0864     wrapper->into_doubles[wrapper->next_position]; // create new entry
0865     return wrapper->next_position++;
0866 }
0867 
0868 SOCI_DECL int soci_into_date(statement_handle st)
0869 {
0870     statement_wrapper * wrapper = static_cast<statement_wrapper *>(st);
0871 
0872     if (cannot_add_elements(*wrapper, statement_wrapper::single, true))
0873     {
0874         return -1;
0875     }
0876 
0877     wrapper->statement_state = statement_wrapper::defining;
0878     wrapper->into_kind = statement_wrapper::single;
0879 
0880     wrapper->into_types.push_back(dt_date);
0881     wrapper->into_indicators.push_back(i_ok);
0882     wrapper->into_dates[wrapper->next_position]; // create new entry
0883     return wrapper->next_position++;
0884 }
0885 
0886 SOCI_DECL int soci_into_blob(statement_handle st)
0887 {
0888     statement_wrapper * wrapper = static_cast<statement_wrapper *>(st);
0889 
0890     if (cannot_add_elements(*wrapper, statement_wrapper::single, true))
0891     {
0892         return -1;
0893     }
0894 
0895     wrapper->statement_state = statement_wrapper::defining;
0896     wrapper->into_kind = statement_wrapper::single;
0897 
0898     wrapper->into_types.push_back(dt_blob);
0899     wrapper->into_indicators.push_back(i_ok);
0900     wrapper->into_blob[wrapper->next_position] = soci_create_blob_session(wrapper->sql); // create new entry
0901     return wrapper->next_position++;
0902 }
0903 
0904 SOCI_DECL int soci_into_string_v(statement_handle st)
0905 {
0906     statement_wrapper * wrapper = static_cast<statement_wrapper *>(st);
0907 
0908     if (cannot_add_elements(*wrapper, statement_wrapper::bulk, true))
0909     {
0910         return -1;
0911     }
0912 
0913     wrapper->statement_state = statement_wrapper::defining;
0914     wrapper->into_kind = statement_wrapper::bulk;
0915 
0916     wrapper->into_types.push_back(dt_string);
0917     wrapper->into_indicators_v.push_back(std::vector<indicator>());
0918     wrapper->into_strings_v[wrapper->next_position];
0919     return wrapper->next_position++;
0920 }
0921 
0922 SOCI_DECL int soci_into_int_v(statement_handle st)
0923 {
0924     statement_wrapper * wrapper = static_cast<statement_wrapper *>(st);
0925 
0926     if (cannot_add_elements(*wrapper, statement_wrapper::bulk, true))
0927     {
0928         return -1;
0929     }
0930 
0931     wrapper->statement_state = statement_wrapper::defining;
0932     wrapper->into_kind = statement_wrapper::bulk;
0933 
0934     wrapper->into_types.push_back(dt_integer);
0935     wrapper->into_indicators_v.push_back(std::vector<indicator>());
0936     wrapper->into_ints_v[wrapper->next_position];
0937     return wrapper->next_position++;
0938 }
0939 
0940 SOCI_DECL int soci_into_long_long_v(statement_handle st)
0941 {
0942     statement_wrapper * wrapper = static_cast<statement_wrapper *>(st);
0943 
0944     if (cannot_add_elements(*wrapper, statement_wrapper::bulk, true))
0945     {
0946         return -1;
0947     }
0948 
0949     wrapper->statement_state = statement_wrapper::defining;
0950     wrapper->into_kind = statement_wrapper::bulk;
0951 
0952     wrapper->into_types.push_back(dt_long_long);
0953     wrapper->into_indicators_v.push_back(std::vector<indicator>());
0954     wrapper->into_longlongs_v[wrapper->next_position];
0955     return wrapper->next_position++;
0956 }
0957 
0958 SOCI_DECL int soci_into_double_v(statement_handle st)
0959 {
0960     statement_wrapper * wrapper = static_cast<statement_wrapper *>(st);
0961 
0962     if (cannot_add_elements(*wrapper, statement_wrapper::bulk, true))
0963     {
0964         return -1;
0965     }
0966 
0967     wrapper->statement_state = statement_wrapper::defining;
0968     wrapper->into_kind = statement_wrapper::bulk;
0969 
0970     wrapper->into_types.push_back(dt_double);
0971     wrapper->into_indicators_v.push_back(std::vector<indicator>());
0972     wrapper->into_doubles_v[wrapper->next_position];
0973     return wrapper->next_position++;
0974 }
0975 
0976 SOCI_DECL int soci_into_date_v(statement_handle st)
0977 {
0978     statement_wrapper * wrapper = static_cast<statement_wrapper *>(st);
0979 
0980     if (cannot_add_elements(*wrapper, statement_wrapper::bulk, true))
0981     {
0982         return -1;
0983     }
0984 
0985     wrapper->statement_state = statement_wrapper::defining;
0986     wrapper->into_kind = statement_wrapper::bulk;
0987 
0988     wrapper->into_types.push_back(dt_date);
0989     wrapper->into_indicators_v.push_back(std::vector<indicator>());
0990     wrapper->into_dates_v[wrapper->next_position];
0991     return wrapper->next_position++;
0992 }
0993 
0994 SOCI_DECL int soci_get_into_state(statement_handle st, int position)
0995 {
0996     statement_wrapper * wrapper = static_cast<statement_wrapper *>(st);
0997 
0998     if (position < 0 || position >= wrapper->next_position)
0999     {
1000         wrapper->is_ok = false;
1001         wrapper->error_message = "Invalid position.";
1002         return 0;
1003     }
1004 
1005     wrapper->is_ok = true;
1006     return wrapper->into_indicators[position] == i_ok ? 1 : 0;
1007 }
1008 
1009 SOCI_DECL char const * soci_get_into_string(statement_handle st, int position)
1010 {
1011     statement_wrapper * wrapper = static_cast<statement_wrapper *>(st);
1012 
1013     if (position_check_failed(*wrapper,
1014             statement_wrapper::single, position, dt_string, "string") ||
1015         not_null_check_failed(*wrapper, position))
1016     {
1017         return "";
1018     }
1019 
1020     return wrapper->into_strings[position].c_str();
1021 }
1022 
1023 SOCI_DECL int soci_get_into_int(statement_handle st, int position)
1024 {
1025     statement_wrapper * wrapper = static_cast<statement_wrapper *>(st);
1026 
1027     if (position_check_failed(*wrapper,
1028             statement_wrapper::single, position, dt_integer, "int") ||
1029         not_null_check_failed(*wrapper, position))
1030     {
1031         return 0;
1032     }
1033 
1034     return wrapper->into_ints[position];
1035 }
1036 
1037 SOCI_DECL long long soci_get_into_long_long(statement_handle st, int position)
1038 {
1039     statement_wrapper * wrapper = static_cast<statement_wrapper *>(st);
1040 
1041     if (position_check_failed(*wrapper,
1042             statement_wrapper::single, position, dt_long_long, "long long") ||
1043         not_null_check_failed(*wrapper, position))
1044     {
1045         return 0LL;
1046     }
1047 
1048     return wrapper->into_longlongs[position];
1049 }
1050 
1051 SOCI_DECL double soci_get_into_double(statement_handle st, int position)
1052 {
1053     statement_wrapper * wrapper = static_cast<statement_wrapper *>(st);
1054 
1055     if (position_check_failed(*wrapper,
1056             statement_wrapper::single, position, dt_double, "double") ||
1057         not_null_check_failed(*wrapper, position))
1058     {
1059         return 0.0;
1060     }
1061 
1062     return wrapper->into_doubles[position];
1063 }
1064 
1065 SOCI_DECL char const * soci_get_into_date(statement_handle st, int position)
1066 {
1067     statement_wrapper * wrapper = static_cast<statement_wrapper *>(st);
1068 
1069     if (position_check_failed(*wrapper,
1070             statement_wrapper::single, position, dt_date, "date") ||
1071         not_null_check_failed(*wrapper, position))
1072     {
1073         return "";
1074     }
1075 
1076     // format is: "YYYY MM DD hh mm ss"
1077     std::tm const & d = wrapper->into_dates[position];
1078     return format_date(*wrapper, d);
1079 }
1080 
1081 SOCI_DECL blob_handle soci_get_into_blob(statement_handle st, int position)
1082 {
1083     statement_wrapper * wrapper = static_cast<statement_wrapper *>(st);
1084 
1085     if (position_check_failed(*wrapper,
1086             statement_wrapper::single, position, dt_blob, "blob") ||
1087         not_null_check_failed(*wrapper, position))
1088     {
1089         return NULL;
1090     }
1091 
1092     return wrapper->into_blob[position];
1093 }
1094 
1095 SOCI_DECL int soci_into_get_size_v(statement_handle st)
1096 {
1097     statement_wrapper * wrapper = static_cast<statement_wrapper *>(st);
1098 
1099     if (wrapper->into_kind != statement_wrapper::bulk)
1100     {
1101         wrapper->is_ok = false;
1102         wrapper->error_message = "No vector into elements.";
1103         return -1;
1104     }
1105 
1106     return static_cast<int>(wrapper->into_indicators_v[0].size());
1107 }
1108 
1109 SOCI_DECL void soci_into_resize_v(statement_handle st, int new_size)
1110 {
1111     statement_wrapper * wrapper = static_cast<statement_wrapper *>(st);
1112 
1113     if (new_size <= 0)
1114     {
1115         wrapper->is_ok = false;
1116         wrapper->error_message = "Invalid size.";
1117         return;
1118     }
1119 
1120     if (wrapper->into_kind != statement_wrapper::bulk)
1121     {
1122         wrapper->is_ok = false;
1123         wrapper->error_message = "No vector into elements.";
1124         return;
1125     }
1126 
1127     for (int i = 0; i != wrapper->next_position; ++i)
1128     {
1129         wrapper->into_indicators_v[i].resize(new_size);
1130 
1131         switch (wrapper->into_types[i])
1132         {
1133         case dt_string:
1134             wrapper->into_strings_v[i].resize(new_size);
1135             break;
1136         case dt_integer:
1137             wrapper->into_ints_v[i].resize(new_size);
1138             break;
1139         case dt_long_long:
1140         case dt_unsigned_long_long:
1141             wrapper->into_longlongs_v[i].resize(new_size);
1142             break;
1143         case dt_double:
1144             wrapper->into_doubles_v[i].resize(new_size);
1145             break;
1146         case dt_date:
1147             wrapper->into_dates_v[i].resize(new_size);
1148             break;
1149         case dt_blob:
1150         case dt_xml:
1151             // no support for bulk blob
1152             break;
1153         }
1154     }
1155 
1156     wrapper->is_ok = true;
1157 }
1158 
1159 SOCI_DECL int soci_get_into_state_v(statement_handle st, int position, int index)
1160 {
1161     statement_wrapper * wrapper = static_cast<statement_wrapper *>(st);
1162 
1163     if (position < 0 || position >= wrapper->next_position)
1164     {
1165         wrapper->is_ok = false;
1166         wrapper->error_message = "Invalid position.";
1167         return 0;
1168     }
1169 
1170     std::vector<indicator> const & v = wrapper->into_indicators_v[position];
1171     if (index_check_failed(v, *wrapper, index))
1172     {
1173         return 0;
1174     }
1175 
1176     return v[index] == i_ok ? 1 : 0;
1177 }
1178 
1179 SOCI_DECL char const * soci_get_into_string_v(statement_handle st, int position, int index)
1180 {
1181     statement_wrapper * wrapper = static_cast<statement_wrapper *>(st);
1182 
1183     if (position_check_failed(*wrapper,
1184             statement_wrapper::bulk, position, dt_string, "string"))
1185     {
1186         return "";
1187     }
1188 
1189     std::vector<std::string> const & v = wrapper->into_strings_v[position];
1190     if (index_check_failed(v, *wrapper, index) ||
1191         not_null_check_failed(*wrapper, position, index))
1192     {
1193         return "";
1194     }
1195 
1196     return v[index].c_str();
1197 }
1198 
1199 SOCI_DECL int soci_get_into_int_v(statement_handle st, int position, int index)
1200 {
1201     statement_wrapper * wrapper = static_cast<statement_wrapper *>(st);
1202 
1203     if (position_check_failed(*wrapper,
1204             statement_wrapper::bulk, position, dt_integer, "int"))
1205     {
1206         return 0;
1207     }
1208 
1209     std::vector<int> const & v = wrapper->into_ints_v[position];
1210     if (index_check_failed(v, *wrapper, index) ||
1211         not_null_check_failed(*wrapper, position, index))
1212     {
1213         return 0;
1214     }
1215 
1216     return v[index];
1217 }
1218 
1219 SOCI_DECL long long soci_get_into_long_long_v(statement_handle st, int position, int index)
1220 {
1221     statement_wrapper * wrapper = static_cast<statement_wrapper *>(st);
1222 
1223     if (position_check_failed(*wrapper,
1224             statement_wrapper::bulk, position, dt_long_long, "long long"))
1225     {
1226         return 0;
1227     }
1228 
1229     std::vector<long long> const & v = wrapper->into_longlongs_v[position];
1230     if (index_check_failed(v, *wrapper, index) ||
1231         not_null_check_failed(*wrapper, position, index))
1232     {
1233         return 0;
1234     }
1235 
1236     return v[index];
1237 }
1238 
1239 SOCI_DECL double soci_get_into_double_v(statement_handle st, int position, int index)
1240 {
1241     statement_wrapper * wrapper = static_cast<statement_wrapper *>(st);
1242 
1243     if (position_check_failed(*wrapper,
1244             statement_wrapper::bulk, position, dt_double, "double"))
1245     {
1246         return 0.0;
1247     }
1248 
1249     std::vector<double> const & v = wrapper->into_doubles_v[position];
1250     if (index_check_failed(v, *wrapper, index) ||
1251         not_null_check_failed(*wrapper, position, index))
1252     {
1253         return 0.0;
1254     }
1255 
1256     return v[index];
1257 }
1258 
1259 SOCI_DECL char const * soci_get_into_date_v(statement_handle st, int position, int index)
1260 {
1261     statement_wrapper * wrapper = static_cast<statement_wrapper *>(st);
1262 
1263     if (position_check_failed(*wrapper,
1264             statement_wrapper::bulk, position, dt_date, "date"))
1265     {
1266         return "";
1267     }
1268 
1269     std::vector<std::tm> const & v = wrapper->into_dates_v[position];
1270     if (index_check_failed(v, *wrapper, index) ||
1271         not_null_check_failed(*wrapper, position, index))
1272     {
1273         return "";
1274     }
1275 
1276     return format_date(*wrapper, v[index]);
1277 }
1278 
1279 SOCI_DECL void soci_use_string(statement_handle st, char const * name)
1280 {
1281     statement_wrapper * wrapper = static_cast<statement_wrapper *>(st);
1282 
1283     if (cannot_add_elements(*wrapper, statement_wrapper::single, false) ||
1284         name_unique_check_failed(*wrapper, statement_wrapper::single, name))
1285     {
1286         return;
1287     }
1288 
1289     wrapper->statement_state = statement_wrapper::defining;
1290     wrapper->use_kind = statement_wrapper::single;
1291 
1292     wrapper->use_indicators[name] = i_ok; // create new entry
1293     wrapper->use_strings[name]; // create new entry
1294 }
1295 
1296 SOCI_DECL void soci_use_int(statement_handle st, char const * name)
1297 {
1298     statement_wrapper * wrapper = static_cast<statement_wrapper *>(st);
1299 
1300     if (cannot_add_elements(*wrapper, statement_wrapper::single, false) ||
1301         name_unique_check_failed(*wrapper, statement_wrapper::single, name))
1302     {
1303         return;
1304     }
1305 
1306     wrapper->statement_state = statement_wrapper::defining;
1307     wrapper->use_kind = statement_wrapper::single;
1308 
1309     wrapper->use_indicators[name] = i_ok; // create new entry
1310     wrapper->use_ints[name]; // create new entry
1311 }
1312 
1313 SOCI_DECL void soci_use_long_long(statement_handle st, char const * name)
1314 {
1315     statement_wrapper * wrapper = static_cast<statement_wrapper *>(st);
1316 
1317     if (cannot_add_elements(*wrapper, statement_wrapper::single, false) ||
1318         name_unique_check_failed(*wrapper, statement_wrapper::single, name))
1319     {
1320         return;
1321     }
1322 
1323     wrapper->statement_state = statement_wrapper::defining;
1324     wrapper->use_kind = statement_wrapper::single;
1325 
1326     wrapper->use_indicators[name] = i_ok; // create new entry
1327     wrapper->use_longlongs[name]; // create new entry
1328 }
1329 
1330 SOCI_DECL void soci_use_double(statement_handle st, char const * name)
1331 {
1332     statement_wrapper * wrapper = static_cast<statement_wrapper *>(st);
1333 
1334     if (cannot_add_elements(*wrapper, statement_wrapper::single, false) ||
1335         name_unique_check_failed(*wrapper, statement_wrapper::single, name))
1336     {
1337         return;
1338     }
1339 
1340     wrapper->statement_state = statement_wrapper::defining;
1341     wrapper->use_kind = statement_wrapper::single;
1342 
1343     wrapper->use_indicators[name] = i_ok; // create new entry
1344     wrapper->use_doubles[name]; // create new entry
1345 }
1346 
1347 SOCI_DECL void soci_use_date(statement_handle st, char const * name)
1348 {
1349     statement_wrapper * wrapper = static_cast<statement_wrapper *>(st);
1350 
1351     if (cannot_add_elements(*wrapper, statement_wrapper::single, false) ||
1352         name_unique_check_failed(*wrapper, statement_wrapper::single, name))
1353     {
1354         return;
1355     }
1356 
1357     wrapper->statement_state = statement_wrapper::defining;
1358     wrapper->use_kind = statement_wrapper::single;
1359 
1360     wrapper->use_indicators[name] = i_ok; // create new entry
1361     wrapper->use_dates[name]; // create new entry
1362 }
1363 
1364 SOCI_DECL void soci_use_blob(statement_handle st, char const * name)
1365 {
1366     statement_wrapper * wrapper = static_cast<statement_wrapper *>(st);
1367 
1368     if (cannot_add_elements(*wrapper, statement_wrapper::single, false) ||
1369         name_unique_check_failed(*wrapper, statement_wrapper::single, name))
1370     {
1371         return;
1372     }
1373 
1374     wrapper->statement_state = statement_wrapper::defining;
1375     wrapper->use_kind = statement_wrapper::single;
1376 
1377     wrapper->use_indicators[name] = i_null; // create new entry
1378     wrapper->use_blob[name] = soci_create_blob_session(wrapper->sql); // create new entry
1379 }
1380 
1381 SOCI_DECL void soci_use_string_v(statement_handle st, char const * name)
1382 {
1383     statement_wrapper * wrapper = static_cast<statement_wrapper *>(st);
1384 
1385     if (cannot_add_elements(*wrapper, statement_wrapper::bulk, false) ||
1386         name_unique_check_failed(*wrapper, statement_wrapper::bulk, name))
1387     {
1388         return;
1389     }
1390 
1391     wrapper->statement_state = statement_wrapper::defining;
1392     wrapper->use_kind = statement_wrapper::bulk;
1393 
1394     wrapper->use_indicators_v[name]; // create new entry
1395     wrapper->use_strings_v[name]; // create new entry
1396 }
1397 
1398 SOCI_DECL void soci_use_int_v(statement_handle st, char const * name)
1399 {
1400     statement_wrapper * wrapper = static_cast<statement_wrapper *>(st);
1401 
1402     if (cannot_add_elements(*wrapper, statement_wrapper::bulk, false) ||
1403         name_unique_check_failed(*wrapper, statement_wrapper::bulk, name))
1404     {
1405         return;
1406     }
1407 
1408     wrapper->statement_state = statement_wrapper::defining;
1409     wrapper->use_kind = statement_wrapper::bulk;
1410 
1411     wrapper->use_indicators_v[name]; // create new entry
1412     wrapper->use_ints_v[name]; // create new entry
1413 }
1414 
1415 SOCI_DECL void soci_use_long_long_v(statement_handle st, char const * name)
1416 {
1417     statement_wrapper * wrapper = static_cast<statement_wrapper *>(st);
1418 
1419     if (cannot_add_elements(*wrapper, statement_wrapper::bulk, false) ||
1420         name_unique_check_failed(*wrapper, statement_wrapper::bulk, name))
1421     {
1422         return;
1423     }
1424 
1425     wrapper->statement_state = statement_wrapper::defining;
1426     wrapper->use_kind = statement_wrapper::bulk;
1427 
1428     wrapper->use_indicators_v[name]; // create new entry
1429     wrapper->use_longlongs_v[name]; // create new entry
1430 }
1431 
1432 SOCI_DECL void soci_use_double_v(statement_handle st, char const * name)
1433 {
1434     statement_wrapper * wrapper = static_cast<statement_wrapper *>(st);
1435 
1436     if (cannot_add_elements(*wrapper, statement_wrapper::bulk, false) ||
1437         name_unique_check_failed(*wrapper, statement_wrapper::bulk, name))
1438     {
1439         return;
1440     }
1441 
1442     wrapper->statement_state = statement_wrapper::defining;
1443     wrapper->use_kind = statement_wrapper::bulk;
1444 
1445     wrapper->use_indicators_v[name]; // create new entry
1446     wrapper->use_doubles_v[name]; // create new entry
1447 }
1448 
1449 SOCI_DECL void soci_use_date_v(statement_handle st, char const * name)
1450 {
1451     statement_wrapper * wrapper = static_cast<statement_wrapper *>(st);
1452 
1453     if (cannot_add_elements(*wrapper, statement_wrapper::bulk, false) ||
1454         name_unique_check_failed(*wrapper, statement_wrapper::bulk, name))
1455     {
1456         return;
1457     }
1458 
1459     wrapper->statement_state = statement_wrapper::defining;
1460     wrapper->use_kind = statement_wrapper::bulk;
1461 
1462     wrapper->use_indicators_v[name]; // create new entry
1463     wrapper->use_dates_v[name]; // create new entry
1464 }
1465 
1466 SOCI_DECL void soci_set_use_state(statement_handle st, char const * name, int state)
1467 {
1468     statement_wrapper * wrapper = static_cast<statement_wrapper *>(st);
1469 
1470     typedef std::map<std::string, indicator>::const_iterator iterator;
1471     iterator const it = wrapper->use_indicators.find(name);
1472     if (it == wrapper->use_indicators.end())
1473     {
1474         wrapper->is_ok = false;
1475         wrapper->error_message = "Invalid name.";
1476         return;
1477     }
1478 
1479     wrapper->is_ok = true;
1480     wrapper->use_indicators[name] = (state != 0 ? i_ok : i_null);
1481 }
1482 
1483 SOCI_DECL void soci_set_use_string(statement_handle st, char const * name, char const * val)
1484 {
1485     statement_wrapper * wrapper = static_cast<statement_wrapper *>(st);
1486 
1487     if (name_exists_check_failed(*wrapper,
1488             name, dt_string, statement_wrapper::single, "string"))
1489     {
1490         return;
1491     }
1492 
1493     wrapper->use_indicators[name] = i_ok;
1494     wrapper->use_strings[name] = val;
1495 }
1496 
1497 SOCI_DECL void soci_set_use_int(statement_handle st, char const * name, int val)
1498 {
1499     statement_wrapper * wrapper = static_cast<statement_wrapper *>(st);
1500 
1501     if (name_exists_check_failed(*wrapper,
1502             name, dt_integer, statement_wrapper::single, "int"))
1503     {
1504         return;
1505     }
1506 
1507     wrapper->use_indicators[name] = i_ok;
1508     wrapper->use_ints[name] = val;
1509 }
1510 
1511 SOCI_DECL void soci_set_use_long_long(statement_handle st, char const * name, long long val)
1512 {
1513     statement_wrapper * wrapper = static_cast<statement_wrapper *>(st);
1514 
1515     if (name_exists_check_failed(*wrapper,
1516             name, dt_long_long, statement_wrapper::single, "long long"))
1517     {
1518         return;
1519     }
1520 
1521     wrapper->use_indicators[name] = i_ok;
1522     wrapper->use_longlongs[name] = val;
1523 }
1524 
1525 SOCI_DECL void soci_set_use_double(statement_handle st, char const * name, double val)
1526 {
1527     statement_wrapper * wrapper = static_cast<statement_wrapper *>(st);
1528 
1529     if (name_exists_check_failed(*wrapper,
1530             name, dt_double, statement_wrapper::single, "double"))
1531     {
1532         return;
1533     }
1534 
1535     wrapper->use_indicators[name] = i_ok;
1536     wrapper->use_doubles[name] = val;
1537 }
1538 
1539 SOCI_DECL void soci_set_use_date(statement_handle st, char const * name, char const * val)
1540 {
1541     statement_wrapper * wrapper = static_cast<statement_wrapper *>(st);
1542 
1543     if (name_exists_check_failed(*wrapper,
1544             name, dt_date, statement_wrapper::single, "date"))
1545     {
1546         return;
1547     }
1548 
1549     std::tm dt = std::tm();
1550     bool const converted = string_to_date(val, dt, *wrapper);
1551     if (converted == false)
1552     {
1553         return;
1554     }
1555 
1556     wrapper->use_indicators[name] = i_ok;
1557     wrapper->use_dates[name] = dt;
1558 }
1559 
1560 SOCI_DECL void soci_set_use_blob(statement_handle st, char const * name, blob_handle b)
1561 {
1562     statement_wrapper * wrapper = static_cast<statement_wrapper *>(st);
1563 
1564     if (name_exists_check_failed(*wrapper,
1565             name, dt_blob, statement_wrapper::single, "blob"))
1566     {
1567         return;
1568     }
1569 
1570     soci::indicator &ind = wrapper->use_indicators[name];
1571     blob_wrapper *&blob = wrapper->use_blob[name];
1572     if (ind == i_null && blob != NULL)
1573         soci_destroy_blob(blob);
1574 
1575     ind = i_ok;
1576     blob = static_cast<blob_wrapper *>(b);
1577 }
1578 
1579 SOCI_DECL int soci_use_get_size_v(statement_handle st)
1580 {
1581     statement_wrapper * wrapper = static_cast<statement_wrapper *>(st);
1582 
1583     if (wrapper->use_kind != statement_wrapper::bulk)
1584     {
1585         wrapper->is_ok = false;
1586         wrapper->error_message = "No vector use elements.";
1587         return -1;
1588     }
1589 
1590     if (wrapper->use_indicators_v.empty())
1591     {
1592         wrapper->is_ok = false;
1593         wrapper->error_message = "Empty indicators vector.";
1594         return -1;
1595     }
1596 
1597     return static_cast<int>(wrapper->use_indicators_v.begin()->second.size());
1598 }
1599 
1600 SOCI_DECL void soci_use_resize_v(statement_handle st, int new_size)
1601 {
1602     statement_wrapper * wrapper = static_cast<statement_wrapper *>(st);
1603 
1604     if (new_size <= 0)
1605     {
1606         wrapper->is_ok = false;
1607         wrapper->error_message = "Invalid size.";
1608         return;
1609     }
1610 
1611     if (wrapper->use_kind != statement_wrapper::bulk)
1612     {
1613         wrapper->is_ok = false;
1614         wrapper->error_message = "No vector use elements.";
1615         return;
1616     }
1617 
1618     resize_in_map(wrapper->use_indicators_v, new_size);
1619     resize_in_map(wrapper->use_strings_v, new_size);
1620     resize_in_map(wrapper->use_ints_v, new_size);
1621     resize_in_map(wrapper->use_longlongs_v, new_size);
1622     resize_in_map(wrapper->use_doubles_v, new_size);
1623     resize_in_map(wrapper->use_dates_v, new_size);
1624 
1625     wrapper->is_ok = true;
1626 }
1627 
1628 SOCI_DECL void soci_set_use_state_v(statement_handle st,
1629     char const * name, int index, int state)
1630 {
1631     statement_wrapper * wrapper = static_cast<statement_wrapper *>(st);
1632 
1633     typedef std::map<std::string, std::vector<indicator> >::iterator iterator;
1634     iterator const it = wrapper->use_indicators_v.find(name);
1635     if (it == wrapper->use_indicators_v.end())
1636     {
1637         wrapper->is_ok = false;
1638         wrapper->error_message = "Invalid name.";
1639         return;
1640     }
1641 
1642     std::vector<indicator> & v = it->second;
1643     if (index_check_failed(v, *wrapper, index))
1644     {
1645         return;
1646     }
1647 
1648     v[index] = (state != 0 ? i_ok : i_null);
1649 }
1650 
1651 SOCI_DECL void soci_set_use_string_v(statement_handle st,
1652     char const * name, int index, char const * val)
1653 {
1654     statement_wrapper * wrapper = static_cast<statement_wrapper *>(st);
1655 
1656     if (name_exists_check_failed(*wrapper,
1657             name, dt_string, statement_wrapper::bulk, "vector string"))
1658     {
1659         return;
1660     }
1661 
1662     std::vector<std::string> & v = wrapper->use_strings_v[name];
1663     if (index_check_failed(v, *wrapper, index))
1664     {
1665         return;
1666     }
1667 
1668     wrapper->use_indicators_v[name][index] = i_ok;
1669     v[index] = val;
1670 }
1671 
1672 SOCI_DECL void soci_set_use_int_v(statement_handle st,
1673     char const * name, int index, int val)
1674 {
1675     statement_wrapper * wrapper = static_cast<statement_wrapper *>(st);
1676 
1677     if (name_exists_check_failed(*wrapper,
1678             name, dt_integer, statement_wrapper::bulk, "vector int"))
1679     {
1680         return;
1681     }
1682 
1683     std::vector<int> & v = wrapper->use_ints_v[name];
1684     if (index_check_failed(v, *wrapper, index))
1685     {
1686         return;
1687     }
1688 
1689     wrapper->use_indicators_v[name][index] = i_ok;
1690     v[index] = val;
1691 }
1692 
1693 SOCI_DECL void soci_set_use_long_long_v(statement_handle st,
1694     char const * name, int index, long long val)
1695 {
1696     statement_wrapper * wrapper = static_cast<statement_wrapper *>(st);
1697 
1698     if (name_exists_check_failed(*wrapper,
1699             name, dt_long_long, statement_wrapper::bulk, "vector long long"))
1700     {
1701         return;
1702     }
1703 
1704     std::vector<long long> & v = wrapper->use_longlongs_v[name];
1705     if (index_check_failed(v, *wrapper, index))
1706     {
1707         return;
1708     }
1709 
1710     wrapper->use_indicators_v[name][index] = i_ok;
1711     v[index] = val;
1712 }
1713 
1714 SOCI_DECL void soci_set_use_double_v(statement_handle st,
1715     char const * name, int index, double val)
1716 {
1717     statement_wrapper * wrapper = static_cast<statement_wrapper *>(st);
1718 
1719     if (name_exists_check_failed(*wrapper,
1720             name, dt_double, statement_wrapper::bulk, "vector double"))
1721     {
1722         return;
1723     }
1724 
1725     std::vector<double> & v = wrapper->use_doubles_v[name];
1726     if (index_check_failed(v, *wrapper, index))
1727     {
1728         return;
1729     }
1730 
1731     wrapper->use_indicators_v[name][index] = i_ok;
1732     v[index] = val;
1733 }
1734 
1735 SOCI_DECL void soci_set_use_date_v(statement_handle st,
1736     char const * name, int index, char const * val)
1737 {
1738     statement_wrapper * wrapper = static_cast<statement_wrapper *>(st);
1739 
1740     if (name_exists_check_failed(*wrapper,
1741             name, dt_date, statement_wrapper::bulk, "vector date"))
1742     {
1743         return;
1744     }
1745 
1746     std::vector<std::tm> & v = wrapper->use_dates_v[name];
1747     if (index_check_failed(v, *wrapper, index))
1748     {
1749         return;
1750     }
1751 
1752     std::tm dt = std::tm();
1753     bool const converted = string_to_date(val, dt, *wrapper);
1754     if (converted == false)
1755     {
1756         return;
1757     }
1758 
1759     wrapper->use_indicators_v[name][index] = i_ok;
1760     v[index] = dt;
1761 }
1762 
1763 SOCI_DECL int soci_get_use_state(statement_handle st, char const * name)
1764 {
1765     statement_wrapper * wrapper = static_cast<statement_wrapper *>(st);
1766 
1767     typedef std::map<std::string, indicator>::const_iterator iterator;
1768     iterator const it = wrapper->use_indicators.find(name);
1769     if (it == wrapper->use_indicators.end())
1770     {
1771         wrapper->is_ok = false;
1772         wrapper->error_message = "Invalid name.";
1773         return 0;
1774     }
1775 
1776     wrapper->is_ok = true;
1777     return wrapper->use_indicators[name] == i_ok ? 1 : 0;
1778 }
1779 
1780 SOCI_DECL char const * soci_get_use_string(statement_handle st, char const * name)
1781 {
1782     statement_wrapper * wrapper = static_cast<statement_wrapper *>(st);
1783 
1784     if (name_exists_check_failed(*wrapper,
1785             name, dt_string, statement_wrapper::bulk, "string"))
1786     {
1787         return "";
1788     }
1789 
1790     return wrapper->use_strings[name].c_str();
1791 }
1792 
1793 SOCI_DECL int soci_get_use_int(statement_handle st, char const * name)
1794 {
1795     statement_wrapper * wrapper = static_cast<statement_wrapper *>(st);
1796 
1797     if (name_exists_check_failed(*wrapper,
1798             name, dt_integer, statement_wrapper::bulk, "int"))
1799     {
1800         return 0;
1801     }
1802 
1803     return wrapper->use_ints[name];
1804 }
1805 
1806 SOCI_DECL long long soci_get_use_long_long(statement_handle st, char const * name)
1807 {
1808     statement_wrapper * wrapper = static_cast<statement_wrapper *>(st);
1809 
1810     if (name_exists_check_failed(*wrapper,
1811             name, dt_long_long, statement_wrapper::bulk, "long long"))
1812     {
1813         return 0LL;
1814     }
1815 
1816     return wrapper->use_longlongs[name];
1817 }
1818 
1819 SOCI_DECL double soci_get_use_double(statement_handle st, char const * name)
1820 {
1821     statement_wrapper * wrapper = static_cast<statement_wrapper *>(st);
1822 
1823     if (name_exists_check_failed(*wrapper,
1824             name, dt_double, statement_wrapper::bulk, "double"))
1825     {
1826         return 0.0;
1827     }
1828 
1829     return wrapper->use_doubles[name];
1830 }
1831 
1832 SOCI_DECL char const * soci_get_use_date(statement_handle st, char const * name)
1833 {
1834     statement_wrapper * wrapper = static_cast<statement_wrapper *>(st);
1835 
1836     if (name_exists_check_failed(*wrapper,
1837             name, dt_date, statement_wrapper::bulk, "date"))
1838     {
1839         return "";
1840     }
1841 
1842     // format is: "YYYY MM DD hh mm ss"
1843     std::tm const & d = wrapper->use_dates[name];
1844     std::sprintf(wrapper->date_formatted, "%d %d %d %d %d %d",
1845         d.tm_year + 1900, d.tm_mon + 1, d.tm_mday,
1846         d.tm_hour, d.tm_min, d.tm_sec);
1847 
1848     return wrapper->date_formatted;
1849 }
1850 
1851 SOCI_DECL blob_handle soci_get_use_blob(statement_handle st, char const * name)
1852 {
1853     statement_wrapper * wrapper = static_cast<statement_wrapper *>(st);
1854 
1855     if (name_exists_check_failed(*wrapper,
1856             name, dt_blob, statement_wrapper::bulk, "blob"))
1857     {
1858         return NULL;
1859     }
1860 
1861     return wrapper->use_blob[name];
1862 }
1863 
1864 SOCI_DECL void soci_prepare(statement_handle st, char const * query)
1865 {
1866     statement_wrapper * wrapper = static_cast<statement_wrapper *>(st);
1867 
1868     try
1869     {
1870         wrapper->statement_state = statement_wrapper::executing;
1871 
1872         // bind all into elements
1873 
1874         int const into_elements = static_cast<int>(wrapper->into_types.size());
1875         if (wrapper->into_kind == statement_wrapper::single)
1876         {
1877             for (int i = 0; i != into_elements; ++i)
1878             {
1879                 switch (wrapper->into_types[i])
1880                 {
1881                 case dt_string:
1882                     wrapper->st.exchange(
1883                         into(wrapper->into_strings[i], wrapper->into_indicators[i]));
1884                     break;
1885                 case dt_integer:
1886                     wrapper->st.exchange(
1887                         into(wrapper->into_ints[i], wrapper->into_indicators[i]));
1888                     break;
1889                 case dt_long_long:
1890                 case dt_unsigned_long_long:
1891                     wrapper->st.exchange(
1892                         into(wrapper->into_longlongs[i], wrapper->into_indicators[i]));
1893                     break;
1894                 case dt_double:
1895                     wrapper->st.exchange(
1896                         into(wrapper->into_doubles[i], wrapper->into_indicators[i]));
1897                     break;
1898                 case dt_date:
1899                     wrapper->st.exchange(
1900                         into(wrapper->into_dates[i], wrapper->into_indicators[i]));
1901                     break;
1902                 case dt_blob:
1903                     wrapper->st.exchange(
1904                         into(wrapper->into_blob[i]->blob_, wrapper->into_indicators[i]));
1905                     break;
1906                 case dt_xml:
1907                     // no support for xml
1908                     break;
1909                 }
1910             }
1911         }
1912         else
1913         {
1914             // vector elements
1915             for (int i = 0; i != into_elements; ++i)
1916             {
1917                 switch (wrapper->into_types[i])
1918                 {
1919                 case dt_string:
1920                     wrapper->st.exchange(
1921                         into(wrapper->into_strings_v[i], wrapper->into_indicators_v[i]));
1922                     break;
1923                 case dt_integer:
1924                     wrapper->st.exchange(
1925                         into(wrapper->into_ints_v[i], wrapper->into_indicators_v[i]));
1926                     break;
1927                 case dt_long_long:
1928                 case dt_unsigned_long_long:
1929                     wrapper->st.exchange(
1930                         into(wrapper->into_longlongs_v[i], wrapper->into_indicators_v[i]));
1931                     break;
1932                 case dt_double:
1933                     wrapper->st.exchange(
1934                         into(wrapper->into_doubles_v[i], wrapper->into_indicators_v[i]));
1935                     break;
1936                 case dt_date:
1937                     wrapper->st.exchange(
1938                         into(wrapper->into_dates_v[i], wrapper->into_indicators_v[i]));
1939                     break;
1940                 case dt_blob:
1941                 case dt_xml:
1942                     // no support for bulk blob and xml
1943                     break;
1944                 }
1945             }
1946         }
1947 
1948         // bind all use elements
1949         {
1950             // strings
1951             typedef std::map<std::string, std::string>::iterator iterator;
1952             iterator uit = wrapper->use_strings.begin();
1953             iterator const uend = wrapper->use_strings.end();
1954             for ( ; uit != uend; ++uit)
1955             {
1956                 std::string const & use_name = uit->first;
1957                 std::string & use_string = uit->second;
1958                 indicator & use_ind = wrapper->use_indicators[use_name];
1959                 wrapper->st.exchange(use(use_string, use_ind, use_name));
1960             }
1961         }
1962         {
1963             // ints
1964             typedef std::map<std::string, int>::iterator iterator;
1965             iterator uit = wrapper->use_ints.begin();
1966             iterator const uend = wrapper->use_ints.end();
1967             for ( ; uit != uend; ++uit)
1968             {
1969                 std::string const & use_name = uit->first;
1970                 int & use_int = uit->second;
1971                 indicator & use_ind = wrapper->use_indicators[use_name];
1972                 wrapper->st.exchange(use(use_int, use_ind, use_name));
1973             }
1974         }
1975         {
1976             // longlongs
1977             typedef std::map<std::string, long long>::iterator iterator;
1978             iterator uit = wrapper->use_longlongs.begin();
1979             iterator const uend = wrapper->use_longlongs.end();
1980             for ( ; uit != uend; ++uit)
1981             {
1982                 std::string const & use_name = uit->first;
1983                 long long & use_longlong = uit->second;
1984                 indicator & use_ind = wrapper->use_indicators[use_name];
1985                 wrapper->st.exchange(use(use_longlong, use_ind, use_name));
1986             }
1987         }
1988         {
1989             // doubles
1990             typedef std::map<std::string, double>::iterator iterator;
1991             iterator uit = wrapper->use_doubles.begin();
1992             iterator const uend = wrapper->use_doubles.end();
1993             for ( ; uit != uend; ++uit)
1994             {
1995                 std::string const & use_name = uit->first;
1996                 double & use_double = uit->second;
1997                 indicator & use_ind = wrapper->use_indicators[use_name];
1998                 wrapper->st.exchange(use(use_double, use_ind, use_name));
1999             }
2000         }
2001         {
2002             // dates
2003             typedef std::map<std::string, std::tm>::iterator iterator;
2004             iterator uit = wrapper->use_dates.begin();
2005             iterator const uend = wrapper->use_dates.end();
2006             for ( ; uit != uend; ++uit)
2007             {
2008                 std::string const & use_name = uit->first;
2009                 std::tm & use_date = uit->second;
2010                 indicator & use_ind = wrapper->use_indicators[use_name];
2011                 wrapper->st.exchange(use(use_date, use_ind, use_name));
2012             }
2013         }
2014         {
2015             // blobs
2016             typedef std::map<std::string, blob_wrapper *>::iterator iterator;
2017             iterator uit = wrapper->use_blob.begin();
2018             iterator uend = wrapper->use_blob.end();
2019             for ( ; uit != uend; ++uit)
2020             {
2021                 std::string const & use_name = uit->first;
2022                 blob &use_blob = uit->second->blob_;
2023                 indicator & use_ind = wrapper->use_indicators[use_name];
2024                 wrapper->st.exchange(use(use_blob, use_ind, use_name));
2025             }
2026         }
2027 
2028         // bind all use vecctor elements
2029         {
2030             // strings
2031             typedef std::map<std::string,
2032                 std::vector<std::string> >::iterator iterator;
2033             iterator uit = wrapper->use_strings_v.begin();
2034             iterator const uend = wrapper->use_strings_v.end();
2035             for ( ; uit != uend; ++uit)
2036             {
2037                 std::string const & use_name = uit->first;
2038                 std::vector<std::string> & use_string = uit->second;
2039                 std::vector<indicator> & use_ind =
2040                     wrapper->use_indicators_v[use_name];
2041                 wrapper->st.exchange(use(use_string, use_ind, use_name));
2042             }
2043         }
2044         {
2045             // ints
2046             typedef std::map<std::string,
2047                 std::vector<int> >::iterator iterator;
2048             iterator uit = wrapper->use_ints_v.begin();
2049             iterator const uend = wrapper->use_ints_v.end();
2050             for ( ; uit != uend; ++uit)
2051             {
2052                 std::string const & use_name = uit->first;
2053                 std::vector<int> & use_int = uit->second;
2054                 std::vector<indicator> & use_ind =
2055                     wrapper->use_indicators_v[use_name];
2056                 wrapper->st.exchange(use(use_int, use_ind, use_name));
2057             }
2058         }
2059         {
2060             // longlongs
2061             typedef std::map<std::string,
2062                 std::vector<long long> >::iterator iterator;
2063             iterator uit = wrapper->use_longlongs_v.begin();
2064             iterator const uend = wrapper->use_longlongs_v.end();
2065             for ( ; uit != uend; ++uit)
2066             {
2067                 std::string const & use_name = uit->first;
2068                 std::vector<long long> & use_longlong = uit->second;
2069                 std::vector<indicator> & use_ind =
2070                     wrapper->use_indicators_v[use_name];
2071                 wrapper->st.exchange(use(use_longlong, use_ind, use_name));
2072             }
2073         }
2074         {
2075             // doubles
2076             typedef std::map<std::string,
2077                 std::vector<double> >::iterator iterator;
2078             iterator uit = wrapper->use_doubles_v.begin();
2079             iterator const uend = wrapper->use_doubles_v.end();
2080             for ( ; uit != uend; ++uit)
2081             {
2082                 std::string const & use_name = uit->first;
2083                 std::vector<double> & use_double = uit->second;
2084                 std::vector<indicator> & use_ind =
2085                     wrapper->use_indicators_v[use_name];
2086                 wrapper->st.exchange(use(use_double, use_ind, use_name));
2087             }
2088         }
2089         {
2090             // dates
2091             typedef std::map<std::string,
2092                 std::vector<std::tm> >::iterator iterator;
2093             iterator uit = wrapper->use_dates_v.begin();
2094             iterator const uend = wrapper->use_dates_v.end();
2095             for ( ; uit != uend; ++uit)
2096             {
2097                 std::string const & use_name = uit->first;
2098                 std::vector<std::tm> & use_date = uit->second;
2099                 std::vector<indicator> & use_ind =
2100                     wrapper->use_indicators_v[use_name];
2101                 wrapper->st.exchange(use(use_date, use_ind, use_name));
2102             }
2103         }
2104 
2105         wrapper->st.alloc();
2106         wrapper->st.prepare(query);
2107         wrapper->st.define_and_bind();
2108 
2109         wrapper->is_ok = true;
2110     }
2111     catch (std::exception const & e)
2112     {
2113         wrapper->is_ok = false;
2114         wrapper->error_message = e.what();
2115     }
2116 }
2117 
2118 SOCI_DECL int soci_execute(statement_handle st, int withDataExchange)
2119 {
2120     statement_wrapper * wrapper = static_cast<statement_wrapper *>(st);
2121 
2122     try
2123     {
2124         bool const gotData = wrapper->st.execute(withDataExchange != 0);
2125 
2126         wrapper->is_ok = true;
2127 
2128         return gotData ? 1 : 0;
2129     }
2130     catch (std::exception const & e)
2131     {
2132         wrapper->is_ok = false;
2133         wrapper->error_message = e.what();
2134 
2135         return 0;
2136     }
2137 }
2138 
2139 SOCI_DECL long long soci_get_affected_rows(statement_handle st)
2140 {
2141     statement_wrapper * wrapper = static_cast<statement_wrapper *>(st);
2142 
2143     return wrapper->st.get_affected_rows();
2144 }
2145 
2146 SOCI_DECL int soci_fetch(statement_handle st)
2147 {
2148     statement_wrapper * wrapper = static_cast<statement_wrapper *>(st);
2149 
2150     try
2151     {
2152         bool const gotData = wrapper->st.fetch();
2153 
2154         wrapper->is_ok = true;
2155 
2156         return gotData ? 1 : 0;
2157     }
2158     catch (std::exception const & e)
2159     {
2160         wrapper->is_ok = false;
2161         wrapper->error_message = e.what();
2162 
2163         return 0;
2164     }
2165 }
2166 
2167 SOCI_DECL int soci_got_data(statement_handle st)
2168 {
2169     statement_wrapper * wrapper = static_cast<statement_wrapper *>(st);
2170 
2171     return wrapper->st.got_data() ? 1 : 0;
2172 }
2173 
2174 SOCI_DECL int soci_statement_state(statement_handle st)
2175 {
2176     statement_wrapper * wrapper = static_cast<statement_wrapper *>(st);
2177 
2178     return wrapper->is_ok ? 1 : 0;
2179 }
2180 
2181 SOCI_DECL char const * soci_statement_error_message(statement_handle st)
2182 {
2183     statement_wrapper * wrapper = static_cast<statement_wrapper *>(st);
2184 
2185     return wrapper->error_message.c_str();
2186 }