00001 // 00002 // Copyright (C) 2004-2006 Maciej Sobczak, Stephen Hutton, David Courtney 00003 // Distributed under the Boost Software License, Version 1.0. 00004 // (See accompanying file LICENSE_1_0.txt or copy at 00005 // http://www.boost.org/LICENSE_1_0.txt) 00006 // 00007 00008 00009 #include "soci-sqlite3.h" 00010 #include "common.h" 00011 #include <limits> 00012 #include <cstdio> 00013 #include <sstream> 00014 #include <cstring> 00015 00016 #ifdef _MSC_VER 00017 #pragma warning(disable:4355 4996) 00018 #define snprintf _snprintf 00019 #endif 00020 00021 using namespace soci; 00022 using namespace soci::details; 00023 using namespace soci::details::sqlite3; 00024 00025 void sqlite3_vector_use_type_backend::bind_by_pos(int & position, 00026 void * data, 00027 exchange_type type) 00028 { 00029 if (statement_.boundByName_) 00030 { 00031 throw soci_error( 00032 "Binding for use elements must be either by position or by name."); 00033 } 00034 00035 data_ = data; 00036 type_ = type; 00037 position_ = position++; 00038 00039 statement_.boundByPos_ = true; 00040 } 00041 00042 void sqlite3_vector_use_type_backend::bind_by_name(std::string const & name, 00043 void * data, 00044 exchange_type type) 00045 { 00046 if (statement_.boundByPos_) 00047 { 00048 throw soci_error( 00049 "Binding for use elements must be either by position or by name."); 00050 } 00051 00052 data_ = data; 00053 type_ = type; 00054 name_ = ":" + name; 00055 00056 statement_.resetIfNeeded(); 00057 position_ = sqlite3_bind_parameter_index(statement_.stmt_, name_.c_str()); 00058 00059 if (0 == position_) 00060 { 00061 std::ostringstream ss; 00062 ss << "Cannot bind (by name) to " << name_; 00063 throw soci_error(ss.str()); 00064 } 00065 statement_.boundByName_ = true; 00066 } 00067 00068 void sqlite3_vector_use_type_backend::pre_use(indicator const * ind) 00069 { 00070 std::size_t const vsize = size(); 00071 00072 // make sure that useData can hold enough rows 00073 if (statement_.useData_.size() != vsize) 00074 { 00075 statement_.useData_.resize(vsize); 00076 } 00077 00078 int pos = position_ - 1; 00079 00080 for (size_t i = 0; i != vsize; ++i) 00081 { 00082 char *buf = 0; 00083 00084 // make sure that each row can accomodate the number of columns 00085 if (statement_.useData_[i].size() < 00086 static_cast<std::size_t>(position_)) 00087 { 00088 statement_.useData_[i].resize(position_); 00089 } 00090 00091 // the data in vector can be either i_ok or i_null 00092 if (ind != NULL && ind[i] == i_null) 00093 { 00094 statement_.useData_[i][pos].isNull_ = true; 00095 statement_.useData_[i][pos].data_ = ""; 00096 statement_.useData_[i][pos].blobBuf_ = 0; 00097 statement_.useData_[i][pos].blobSize_ = 0; 00098 } 00099 else 00100 { 00101 // allocate and fill the buffer with text-formatted client data 00102 switch (type_) 00103 { 00104 case x_char: 00105 { 00106 std::vector<char> *pv 00107 = static_cast<std::vector<char> *>(data_); 00108 std::vector<char> &v = *pv; 00109 00110 buf = new char[2]; 00111 buf[0] = v[i]; 00112 buf[1] = '\0'; 00113 } 00114 break; 00115 case x_stdstring: 00116 { 00117 std::vector<std::string> *pv 00118 = static_cast<std::vector<std::string> *>(data_); 00119 std::vector<std::string> &v = *pv; 00120 00121 buf = new char[v[i].size() + 1]; 00122 std::strcpy(buf, v[i].c_str()); 00123 } 00124 break; 00125 case x_short: 00126 { 00127 std::vector<short> *pv 00128 = static_cast<std::vector<short> *>(data_); 00129 std::vector<short> &v = *pv; 00130 00131 std::size_t const bufSize 00132 = std::numeric_limits<short>::digits10 + 3; 00133 buf = new char[bufSize]; 00134 snprintf(buf, bufSize, "%d", static_cast<int>(v[i])); 00135 } 00136 break; 00137 case x_integer: 00138 { 00139 std::vector<int> *pv 00140 = static_cast<std::vector<int> *>(data_); 00141 std::vector<int> &v = *pv; 00142 00143 std::size_t const bufSize 00144 = std::numeric_limits<int>::digits10 + 3; 00145 buf = new char[bufSize]; 00146 snprintf(buf, bufSize, "%d", v[i]); 00147 } 00148 break; 00149 case x_unsigned_long: 00150 { 00151 std::vector<unsigned long> *pv 00152 = static_cast<std::vector<unsigned long> *>(data_); 00153 std::vector<unsigned long> &v = *pv; 00154 00155 std::size_t const bufSize 00156 = std::numeric_limits<unsigned long>::digits10 + 2; 00157 buf = new char[bufSize]; 00158 snprintf(buf, bufSize, "%lu", v[i]); 00159 } 00160 break; 00161 case x_long_long: 00162 { 00163 std::vector<long long> *pv 00164 = static_cast<std::vector<long long> *>(data_); 00165 std::vector<long long> &v = *pv; 00166 00167 std::size_t const bufSize 00168 = std::numeric_limits<long long>::digits10 + 3; 00169 buf = new char[bufSize]; 00170 snprintf(buf, bufSize, "%lld", v[i]); 00171 } 00172 break; 00173 case x_double: 00174 { 00175 // no need to overengineer it (KISS)... 00176 00177 std::vector<double> *pv 00178 = static_cast<std::vector<double> *>(data_); 00179 std::vector<double> &v = *pv; 00180 00181 std::size_t const bufSize = 100; 00182 buf = new char[bufSize]; 00183 00184 snprintf(buf, bufSize, "%.20g", v[i]); 00185 } 00186 break; 00187 case x_stdtm: 00188 { 00189 std::vector<std::tm> *pv 00190 = static_cast<std::vector<std::tm> *>(data_); 00191 std::vector<std::tm> &v = *pv; 00192 00193 std::size_t const bufSize = 20; 00194 buf = new char[bufSize]; 00195 00196 snprintf(buf, bufSize, "%d-%02d-%02d %02d:%02d:%02d", 00197 v[i].tm_year + 1900, v[i].tm_mon + 1, v[i].tm_mday, 00198 v[i].tm_hour, v[i].tm_min, v[i].tm_sec); 00199 } 00200 break; 00201 00202 default: 00203 throw soci_error( 00204 "Use vector element used with non-supported type."); 00205 } 00206 00207 statement_.useData_[i][pos].isNull_ = false; 00208 statement_.useData_[i][pos].data_ = buf; 00209 statement_.useData_[i][pos].blobBuf_ = 0; 00210 statement_.useData_[i][pos].blobSize_ = 0; 00211 } 00212 00213 if (buf) 00214 { 00215 delete [] buf; 00216 } 00217 } 00218 } 00219 00220 std::size_t sqlite3_vector_use_type_backend::size() 00221 { 00222 std::size_t sz = 0; // dummy initialization to please the compiler 00223 switch (type_) 00224 { 00225 // simple cases 00226 case x_char: sz = getVectorSize<char> (data_); break; 00227 case x_short: sz = getVectorSize<short> (data_); break; 00228 case x_integer: sz = getVectorSize<int> (data_); break; 00229 case x_unsigned_long: sz = getVectorSize<unsigned long>(data_); break; 00230 case x_long_long: sz = getVectorSize<long long> (data_); break; 00231 case x_double: sz = getVectorSize<double> (data_); break; 00232 case x_stdstring: sz = getVectorSize<std::string> (data_); break; 00233 case x_stdtm: sz = getVectorSize<std::tm> (data_); break; 00234 00235 default: 00236 throw soci_error("Use vector element used with non-supported type."); 00237 } 00238 00239 return sz; 00240 } 00241 00242 void sqlite3_vector_use_type_backend::clean_up() 00243 { 00244 // ... 00245 }
Generated on Sun Oct 3 2010 17:42:16 for EXTRAS-SOCI by Doxygen 1.7.1