db2/vector-use-type.cpp
Go to the documentation of this file.
1 //
2 // Copyright (C) 2011-2013 Denis Chapligin
3 // Copyright (C) 2004-2006 Maciej Sobczak, Stephen Hutton, David Courtney
4 // Distributed under the Boost Software License, Version 1.0.
5 // (See accompanying file LICENSE_1_0.txt or copy at
6 // http://www.boost.org/LICENSE_1_0.txt)
7 //
8 
9 #define SOCI_DB2_SOURCE
10 #include "soci-db2.h"
11 #include <cctype>
12 #include <cstdio>
13 #include <cstring>
14 #include <ctime>
15 #include <sstream>
16 
17 #ifdef _MSC_VER
18 // disables the warning about converting int to void*. This is a 64 bit compatibility
19 // warning, but odbc requires the value to be converted on this line
20 // SQLSetStmtAttr(statement_.hstmt_, SQL_ATTR_PARAMSET_SIZE, (SQLPOINTER)arraySize, 0);
21 #pragma warning(disable:4312)
22 #endif
23 
24 
25 using namespace soci;
26 using namespace soci::details;
27 
29 {
30  if (size == 0)
31  {
32  throw soci_error("Vectors of size 0 are not allowed.");
33  }
34 
35  indVec.resize(size);
36  indptr = &indVec[0];
37 }
38 
39 void db2_vector_use_type_backend::prepare_for_bind(void *&data, SQLUINTEGER &size,
40  SQLSMALLINT &sqlType, SQLSMALLINT &cType)
41 {
42  switch (type)
43  { // simple cases
44  case x_short:
45  {
46  sqlType = SQL_SMALLINT;
47  cType = SQL_C_SSHORT;
48  size = sizeof(short);
49  std::vector<short> *vp = static_cast<std::vector<short> *>(data);
50  std::vector<short> &v(*vp);
51  prepare_indicators(v.size());
52  data = &v[0];
53  }
54  break;
55  case x_integer:
56  {
57  sqlType = SQL_INTEGER;
58  cType = SQL_C_SLONG;
59  size = sizeof(int);
60  std::vector<int> *vp = static_cast<std::vector<int> *>(data);
61  std::vector<int> &v(*vp);
62  prepare_indicators(v.size());
63  data = &v[0];
64  }
65  break;
66  case x_long_long:
67  {
68  sqlType = SQL_BIGINT;
69  cType = SQL_C_SBIGINT;
70  size = sizeof(long long);
71  std::vector<long long> *vp
72  = static_cast<std::vector<long long> *>(data);
73  std::vector<long long> &v(*vp);
74  prepare_indicators(v.size());
75  data = &v[0];
76  }
77  break;
79  {
80  sqlType = SQL_BIGINT;
81  cType = SQL_C_UBIGINT;
82  size = sizeof(unsigned long long);
83  std::vector<unsigned long long> *vp
84  = static_cast<std::vector<unsigned long long> *>(data);
85  std::vector<unsigned long long> &v(*vp);
86  prepare_indicators(v.size());
87  data = &v[0];
88  }
89  break;
90  case x_double:
91  {
92  sqlType = SQL_DOUBLE;
93  cType = SQL_C_DOUBLE;
94  size = sizeof(double);
95  std::vector<double> *vp = static_cast<std::vector<double> *>(data);
96  std::vector<double> &v(*vp);
97  prepare_indicators(v.size());
98  data = &v[0];
99  }
100  break;
101 
102  // cases that require adjustments and buffer management
103  case x_char:
104  {
105  std::vector<char> *vp
106  = static_cast<std::vector<char> *>(data);
107  std::size_t const vsize = vp->size();
108 
109  prepare_indicators(vsize);
110 
111  size = sizeof(char) * 2;
112  buf = new char[size * vsize];
113 
114  char *pos = buf;
115 
116  for (std::size_t i = 0; i != vsize; ++i)
117  {
118  *pos++ = (*vp)[i];
119  *pos++ = 0;
120  }
121 
122  sqlType = SQL_CHAR;
123  cType = SQL_C_CHAR;
124  data = buf;
125  }
126  break;
127  case x_stdstring:
128  {
129  sqlType = SQL_CHAR;
130  cType = SQL_C_CHAR;
131 
132  std::vector<std::string> *vp
133  = static_cast<std::vector<std::string> *>(data);
134  std::vector<std::string> &v(*vp);
135 
136  std::size_t maxSize = 0;
137  std::size_t const vecSize = v.size();
138  prepare_indicators(vecSize);
139  for (std::size_t i = 0; i != vecSize; ++i)
140  {
141  std::size_t sz = v[i].length() + 1; // add one for null
142  indVec[i] = static_cast<long>(sz);
143  maxSize = sz > maxSize ? sz : maxSize;
144  }
145 
146  buf = new char[maxSize * vecSize];
147  memset(buf, 0, maxSize * vecSize);
148 
149  char *pos = buf;
150  for (std::size_t i = 0; i != vecSize; ++i)
151  {
152  strncpy(pos, v[i].c_str(), v[i].length());
153  pos += maxSize;
154  }
155 
156  data = buf;
157  size = static_cast<SQLINTEGER>(maxSize);
158  }
159  break;
160  case x_stdtm:
161  {
162  std::vector<std::tm> *vp
163  = static_cast<std::vector<std::tm> *>(data);
164 
165  prepare_indicators(vp->size());
166 
167  buf = new char[sizeof(TIMESTAMP_STRUCT) * vp->size()];
168 
169  sqlType = SQL_TYPE_TIMESTAMP;
170  cType = SQL_C_TYPE_TIMESTAMP;
171  data = buf;
172  size = 19; // This number is not the size in bytes, but the number
173  // of characters in the date if it was written out
174  // yyyy-mm-dd hh:mm:ss
175  }
176  break;
177 
178  case x_statement: break; // not supported
179  case x_rowid: break; // not supported
180  case x_blob: break; // not supported
181  }
182 
183  colSize = size;
184 }
185 
187 {
188  this->data = data; // for future reference
189  this->type = type; // for future reference
190 
191  SQLSMALLINT sqlType;
192  SQLSMALLINT cType;
193  SQLUINTEGER size;
194 
195  prepare_for_bind(data, size, sqlType, cType);
196 
197  SQLINTEGER arraySize = (SQLINTEGER)indVec.size();
198  SQLSetStmtAttr(statement_.hStmt, SQL_ATTR_PARAMSET_SIZE, (SQLPOINTER)arraySize, 0);
199 
200  SQLRETURN cliRC = SQLBindParameter(statement_.hStmt, static_cast<SQLUSMALLINT>(position++),
201  SQL_PARAM_INPUT, cType, sqlType, size, 0,
202  static_cast<SQLPOINTER>(data), size, indptr);
203 
204  if ( cliRC != SQL_SUCCESS )
205  {
206  throw db2_soci_error("Error while binding value to column", cliRC);
207  }
208 }
209 
211  void *data, exchange_type type)
212 {
213  if (statement_.use_binding_method_ == details::db2::BOUND_BY_NAME)
214  {
215  throw soci_error("Binding for use elements must be either by position or by name.");
216  }
217  statement_.use_binding_method_ = details::db2::BOUND_BY_POSITION;
218 
219  bind_helper(position, data, type);
220 }
221 
223  std::string const &name, void *data, exchange_type type)
224 {
225  int position = -1;
226  int count = 1;
227 
228  if (statement_.use_binding_method_ == details::db2::BOUND_BY_POSITION)
229  {
230  throw soci_error("Binding for use elements must be either by position or by name.");
231  }
232  statement_.use_binding_method_ = details::db2::BOUND_BY_NAME;
233 
234  for (std::vector<std::string>::iterator it = statement_.names.begin();
235  it != statement_.names.end(); ++it)
236  {
237  if (*it == name)
238  {
239  position = count;
240  break;
241  }
242  count++;
243  }
244 
245  if (position != -1)
246  {
247  bind_helper(position, data, type);
248  }
249  else
250  {
251  std::ostringstream ss;
252  ss << "Unable to find name '" << name << "' to bind to";
253  throw soci_error(ss.str().c_str());
254  }
255 }
256 
258 {
259  // first deal with data
260  if (type == x_stdtm)
261  {
262  std::vector<std::tm> *vp
263  = static_cast<std::vector<std::tm> *>(data);
264 
265  std::vector<std::tm> &v(*vp);
266 
267  char *pos = buf;
268  std::size_t const vsize = v.size();
269  for (std::size_t i = 0; i != vsize; ++i)
270  {
271  std::tm t = v[i];
272  TIMESTAMP_STRUCT * ts = reinterpret_cast<TIMESTAMP_STRUCT*>(pos);
273 
274  ts->year = static_cast<SQLSMALLINT>(t.tm_year + 1900);
275  ts->month = static_cast<SQLUSMALLINT>(t.tm_mon + 1);
276  ts->day = static_cast<SQLUSMALLINT>(t.tm_mday);
277  ts->hour = static_cast<SQLUSMALLINT>(t.tm_hour);
278  ts->minute = static_cast<SQLUSMALLINT>(t.tm_min);
279  ts->second = static_cast<SQLUSMALLINT>(t.tm_sec);
280  ts->fraction = 0;
281  pos += sizeof(TIMESTAMP_STRUCT);
282  }
283  }
284 
285  // then handle indicators
286  if (ind != NULL)
287  {
288  std::size_t const vsize = size();
289  for (std::size_t i = 0; i != vsize; ++i, ++ind)
290  {
291  if (*ind == i_null)
292  {
293  indVec[i] = SQL_NULL_DATA; // null
294  }
295  else
296  {
297  // for strings we have already set the values
298  if (type != x_stdstring)
299  {
300  indVec[i] = SQL_NTS; // value is OK
301  }
302  }
303  }
304  }
305  else
306  {
307  // no indicators - treat all fields as OK
308  std::size_t const vsize = size();
309  for (std::size_t i = 0; i != vsize; ++i, ++ind)
310  {
311  // for strings we have already set the values
312  if (type != x_stdstring)
313  {
314  indVec[i] = SQL_NTS; // value is OK
315  }
316  }
317  }
318 }
319 
321 {
322  std::size_t sz = 0; // dummy initialization to please the compiler
323  switch (type)
324  {
325  // simple cases
326  case x_char:
327  {
328  std::vector<char> *vp = static_cast<std::vector<char> *>(data);
329  sz = vp->size();
330  }
331  break;
332  case x_short:
333  {
334  std::vector<short> *vp = static_cast<std::vector<short> *>(data);
335  sz = vp->size();
336  }
337  break;
338  case x_integer:
339  {
340  std::vector<int> *vp = static_cast<std::vector<int> *>(data);
341  sz = vp->size();
342  }
343  break;
344  case x_long_long:
345  {
346  std::vector<long long> *vp
347  = static_cast<std::vector<long long> *>(data);
348  sz = vp->size();
349  }
350  break;
352  {
353  std::vector<unsigned long long> *vp
354  = static_cast<std::vector<unsigned long long> *>(data);
355  sz = vp->size();
356  }
357  break;
358  case x_double:
359  {
360  std::vector<double> *vp
361  = static_cast<std::vector<double> *>(data);
362  sz = vp->size();
363  }
364  break;
365  case x_stdstring:
366  {
367  std::vector<std::string> *vp
368  = static_cast<std::vector<std::string> *>(data);
369  sz = vp->size();
370  }
371  break;
372  case x_stdtm:
373  {
374  std::vector<std::tm> *vp
375  = static_cast<std::vector<std::tm> *>(data);
376  sz = vp->size();
377  }
378  break;
379 
380  case x_statement: break; // not supported
381  case x_rowid: break; // not supported
382  case x_blob: break; // not supported
383  }
384 
385  return sz;
386 }
387 
389 {
390  if (buf != NULL)
391  {
392  delete [] buf;
393  buf = NULL;
394  }
395 }
void pre_use(indicator const *ind)
void prepare_indicators(std::size_t size)
void bind_helper(int &position, void *data, details::exchange_type type)
void bind_by_name(std::string const &name, void *data, details::exchange_type type)
void prepare_for_bind(void *&data, SQLUINTEGER &size, SQLSMALLINT &sqlType, SQLSMALLINT &cType)
void bind_by_pos(int &position, void *data, details::exchange_type type)


asr_lib_ism
Author(s): Hanselmann Fabian, Heller Florian, Heizmann Heinrich, Kübler Marcel, Mehlhaus Jonas, Meißner Pascal, Qattan Mohamad, Reckling Reno, Stroh Daniel
autogenerated on Wed Jan 8 2020 04:02:41