odbc/vector-into-type.cpp
Go to the documentation of this file.
1 //
2 // Copyright (C) 2004-2006 Maciej Sobczak, Stephen Hutton, David Courtney
3 // Distributed under the Boost Software License, Version 1.0.
4 // (See accompanying file LICENSE_1_0.txt or copy at
5 // http://www.boost.org/LICENSE_1_0.txt)
6 //
7 
8 #define SOCI_ODBC_SOURCE
9 #include "soci-odbc.h"
10 #include <soci-platform.h>
11 #include <cassert>
12 #include <cctype>
13 #include <cstdio>
14 #include <cstring>
15 #include <ctime>
16 #include <sstream>
17 #include <stdio.h> // sscanf()
18 
19 using namespace soci;
20 using namespace soci::details;
21 
23 {
24  if (size == 0)
25  {
26  throw soci_error("Vectors of size 0 are not allowed.");
27  }
28 
29  indHolderVec_.resize(size);
30  indHolders_ = &indHolderVec_[0];
31 }
32 
34  int &position, void *data, exchange_type type)
35 {
36  data_ = data; // for future reference
37  type_ = type; // for future reference
38 
39  SQLLEN size = 0; // also dummy
40 
41  switch (type)
42  {
43  // simple cases
44  case x_short:
45  {
46  odbcType_ = SQL_C_SSHORT;
47  size = sizeof(short);
48  std::vector<short> *vp = static_cast<std::vector<short> *>(data);
49  std::vector<short> &v(*vp);
50  prepare_indicators(v.size());
51  data = &v[0];
52  }
53  break;
54  case x_integer:
55  {
56  odbcType_ = SQL_C_SLONG;
57  size = sizeof(SQLINTEGER);
58  assert(sizeof(SQLINTEGER) == sizeof(int));
59  std::vector<int> *vp = static_cast<std::vector<int> *>(data);
60  std::vector<int> &v(*vp);
61  prepare_indicators(v.size());
62  data = &v[0];
63  }
64  break;
65  case x_long_long:
66  {
67  std::vector<long long> *vp =
68  static_cast<std::vector<long long> *>(data);
69  std::vector<long long> &v(*vp);
70  prepare_indicators(v.size());
71  if (use_string_for_bigint())
72  {
73  odbcType_ = SQL_C_CHAR;
74  size = max_bigint_length;
75  std::size_t bufSize = size * v.size();
76  colSize_ = size;
77  buf_ = new char[bufSize];
78  data = buf_;
79  }
80  else // Normal case, use ODBC support.
81  {
82  odbcType_ = SQL_C_SBIGINT;
83  size = sizeof(long long);
84  data = &v[0];
85  }
86  }
87  break;
89  {
90  std::vector<unsigned long long> *vp =
91  static_cast<std::vector<unsigned long long> *>(data);
92  std::vector<unsigned long long> &v(*vp);
93  prepare_indicators(v.size());
94  if (use_string_for_bigint())
95  {
96  odbcType_ = SQL_C_CHAR;
97  size = max_bigint_length;
98  std::size_t bufSize = size * v.size();
99  colSize_ = size;
100  buf_ = new char[bufSize];
101  data = buf_;
102  }
103  else // Normal case, use ODBC support.
104  {
105  odbcType_ = SQL_C_UBIGINT;
106  size = sizeof(unsigned long long);
107  data = &v[0];
108  }
109  }
110  break;
111  case x_double:
112  {
113  odbcType_ = SQL_C_DOUBLE;
114  size = sizeof(double);
115  std::vector<double> *vp = static_cast<std::vector<double> *>(data);
116  std::vector<double> &v(*vp);
117  prepare_indicators(v.size());
118  data = &v[0];
119  }
120  break;
121 
122  // cases that require adjustments and buffer management
123 
124  case x_char:
125  {
126  odbcType_ = SQL_C_CHAR;
127 
128  std::vector<char> *v
129  = static_cast<std::vector<char> *>(data);
130 
131  prepare_indicators(v->size());
132 
133  size = sizeof(char) * 2;
134  std::size_t bufSize = size * v->size();
135 
136  colSize_ = size;
137 
138  buf_ = new char[bufSize];
139  data = buf_;
140  }
141  break;
142  case x_stdstring:
143  {
144  odbcType_ = SQL_C_CHAR;
145  std::vector<std::string> *v
146  = static_cast<std::vector<std::string> *>(data);
147  colSize_ = statement_.column_size(position) + 1;
148  std::size_t bufSize = colSize_ * v->size();
149  buf_ = new char[bufSize];
150 
151  prepare_indicators(v->size());
152 
153  size = static_cast<SQLINTEGER>(colSize_);
154  data = buf_;
155  }
156  break;
157  case x_stdtm:
158  {
159  odbcType_ = SQL_C_TYPE_TIMESTAMP;
160  std::vector<std::tm> *v
161  = static_cast<std::vector<std::tm> *>(data);
162 
163  prepare_indicators(v->size());
164 
165  size = sizeof(TIMESTAMP_STRUCT);
166  colSize_ = size;
167 
168  std::size_t bufSize = size * v->size();
169 
170  buf_ = new char[bufSize];
171  data = buf_;
172  }
173  break;
174 
175  case x_statement: break; // not supported
176  case x_rowid: break; // not supported
177  case x_blob: break; // not supported
178  }
179 
180  SQLRETURN rc
181  = SQLBindCol(statement_.hstmt_, static_cast<SQLUSMALLINT>(position++),
182  odbcType_, static_cast<SQLPOINTER>(data), size, indHolders_);
183  if (is_odbc_error(rc))
184  {
185  throw odbc_soci_error(SQL_HANDLE_STMT, statement_.hstmt_,
186  "vector into type define by pos");
187  }
188 }
189 
191 {
192  // nothing to do for the supported types
193 }
194 
196 {
197  if (gotData)
198  {
199  // first, deal with data
200 
201  // only std::string, std::tm and Statement need special handling
202  if (type_ == x_char)
203  {
204  std::vector<char> *vp
205  = static_cast<std::vector<char> *>(data_);
206 
207  std::vector<char> &v(*vp);
208  char *pos = buf_;
209  std::size_t const vsize = v.size();
210  for (std::size_t i = 0; i != vsize; ++i)
211  {
212  v[i] = *pos;
213  pos += colSize_;
214  }
215  }
216  if (type_ == x_stdstring)
217  {
218  std::vector<std::string> *vp
219  = static_cast<std::vector<std::string> *>(data_);
220 
221  std::vector<std::string> &v(*vp);
222 
223  char *pos = buf_;
224  std::size_t const vsize = v.size();
225  for (std::size_t i = 0; i != vsize; ++i)
226  {
227  v[i].assign(pos, strlen(pos));
228  pos += colSize_;
229  }
230  }
231  else if (type_ == x_stdtm)
232  {
233  std::vector<std::tm> *vp
234  = static_cast<std::vector<std::tm> *>(data_);
235 
236  std::vector<std::tm> &v(*vp);
237  char *pos = buf_;
238  std::size_t const vsize = v.size();
239  for (std::size_t i = 0; i != vsize; ++i)
240  {
241  std::tm t;
242 
243  TIMESTAMP_STRUCT * ts = reinterpret_cast<TIMESTAMP_STRUCT*>(pos);
244  t.tm_isdst = -1;
245  t.tm_year = ts->year - 1900;
246  t.tm_mon = ts->month - 1;
247  t.tm_mday = ts->day;
248  t.tm_hour = ts->hour;
249  t.tm_min = ts->minute;
250  t.tm_sec = ts->second;
251 
252  // normalize and compute the remaining fields
253  std::mktime(&t);
254  v[i] = t;
255  pos += colSize_;
256  }
257  }
258  else if (type_ == x_long_long && use_string_for_bigint())
259  {
260  std::vector<long long> *vp
261  = static_cast<std::vector<long long> *>(data_);
262  std::vector<long long> &v(*vp);
263  char *pos = buf_;
264  std::size_t const vsize = v.size();
265  for (std::size_t i = 0; i != vsize; ++i)
266  {
267  if (sscanf(pos, "%" LL_FMT_FLAGS "d", &v[i]) != 1)
268  {
269  throw soci_error("Failed to parse the returned 64-bit integer value");
270  }
271  pos += colSize_;
272  }
273  }
274  else if (type_ == x_unsigned_long_long && use_string_for_bigint())
275  {
276  std::vector<unsigned long long> *vp
277  = static_cast<std::vector<unsigned long long> *>(data_);
278  std::vector<unsigned long long> &v(*vp);
279  char *pos = buf_;
280  std::size_t const vsize = v.size();
281  for (std::size_t i = 0; i != vsize; ++i)
282  {
283  if (sscanf(pos, "%" LL_FMT_FLAGS "u", &v[i]) != 1)
284  {
285  throw soci_error("Failed to parse the returned 64-bit integer value");
286  }
287  pos += colSize_;
288  }
289  }
290 
291  // then - deal with indicators
292  if (ind != NULL)
293  {
294  std::size_t const indSize = statement_.get_number_of_rows();
295  for (std::size_t i = 0; i != indSize; ++i)
296  {
297  if (indHolderVec_[i] > 0)
298  {
299  ind[i] = i_ok;
300  }
301  else if (indHolderVec_[i] == SQL_NULL_DATA)
302  {
303  ind[i] = i_null;
304  }
305  else
306  {
307  ind[i] = i_truncated;
308  }
309  }
310  }
311  else
312  {
313  std::size_t const indSize = statement_.get_number_of_rows();
314  for (std::size_t i = 0; i != indSize; ++i)
315  {
316  if (indHolderVec_[i] == SQL_NULL_DATA)
317  {
318  // fetched null and no indicator - programming error!
319  throw soci_error(
320  "Null value fetched and no indicator defined.");
321  }
322  }
323  }
324  }
325  else // gotData == false
326  {
327  // nothing to do here, vectors are truncated anyway
328  }
329 }
330 
332 {
333  indHolderVec_.resize(sz);
334  switch (type_)
335  {
336  // simple cases
337  case x_char:
338  {
339  std::vector<char> *v = static_cast<std::vector<char> *>(data_);
340  v->resize(sz);
341  }
342  break;
343  case x_short:
344  {
345  std::vector<short> *v = static_cast<std::vector<short> *>(data_);
346  v->resize(sz);
347  }
348  break;
349  case x_integer:
350  {
351  std::vector<int> *v = static_cast<std::vector<int> *>(data_);
352  v->resize(sz);
353  }
354  break;
355  case x_long_long:
356  {
357  std::vector<long long> *v =
358  static_cast<std::vector<long long> *>(data_);
359  v->resize(sz);
360  }
361  break;
363  {
364  std::vector<unsigned long long> *v =
365  static_cast<std::vector<unsigned long long> *>(data_);
366  v->resize(sz);
367  }
368  break;
369  case x_double:
370  {
371  std::vector<double> *v
372  = static_cast<std::vector<double> *>(data_);
373  v->resize(sz);
374  }
375  break;
376  case x_stdstring:
377  {
378  std::vector<std::string> *v
379  = static_cast<std::vector<std::string> *>(data_);
380  v->resize(sz);
381  }
382  break;
383  case x_stdtm:
384  {
385  std::vector<std::tm> *v
386  = static_cast<std::vector<std::tm> *>(data_);
387  v->resize(sz);
388  }
389  break;
390 
391  case x_statement: break; // not supported
392  case x_rowid: break; // not supported
393  case x_blob: break; // not supported
394  }
395 }
396 
398 {
399  std::size_t sz = 0; // dummy initialization to please the compiler
400  switch (type_)
401  {
402  // simple cases
403  case x_char:
404  {
405  std::vector<char> *v = static_cast<std::vector<char> *>(data_);
406  sz = v->size();
407  }
408  break;
409  case x_short:
410  {
411  std::vector<short> *v = static_cast<std::vector<short> *>(data_);
412  sz = v->size();
413  }
414  break;
415  case x_integer:
416  {
417  std::vector<int> *v = static_cast<std::vector<int> *>(data_);
418  sz = v->size();
419  }
420  break;
421  case x_long_long:
422  {
423  std::vector<long long> *v =
424  static_cast<std::vector<long long> *>(data_);
425  sz = v->size();
426  }
427  break;
429  {
430  std::vector<unsigned long long> *v =
431  static_cast<std::vector<unsigned long long> *>(data_);
432  sz = v->size();
433  }
434  break;
435  case x_double:
436  {
437  std::vector<double> *v
438  = static_cast<std::vector<double> *>(data_);
439  sz = v->size();
440  }
441  break;
442  case x_stdstring:
443  {
444  std::vector<std::string> *v
445  = static_cast<std::vector<std::string> *>(data_);
446  sz = v->size();
447  }
448  break;
449  case x_stdtm:
450  {
451  std::vector<std::tm> *v
452  = static_cast<std::vector<std::tm> *>(data_);
453  sz = v->size();
454  }
455  break;
456 
457  case x_statement: break; // not supported
458  case x_rowid: break; // not supported
459  case x_blob: break; // not supported
460  }
461 
462  return sz;
463 }
464 
466 {
467  if (buf_ != NULL)
468  {
469  delete [] buf_;
470  buf_ = NULL;
471  }
472 }
virtual void post_fetch(bool gotData, indicator *ind)
bool is_odbc_error(SQLRETURN rc)
Definition: soci-odbc.h:399
#define LL_FMT_FLAGS
Definition: soci-platform.h:14
virtual void define_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