odbc/standard-use-type.cpp
Go to the documentation of this file.
1 // Copyright (C) 2004-2006 Maciej Sobczak, Stephen Hutton, David Courtney
2 // Distributed under the Boost Software License, Version 1.0.
3 // (See accompanying file LICENSE_1_0.txt or copy at
4 // http://www.boost.org/LICENSE_1_0.txt)
5 
6 #define SOCI_ODBC_SOURCE
7 #include <soci-platform.h>
8 #include "soci-odbc.h"
9 #include <cctype>
10 #include <cstdio>
11 #include <cstring>
12 #include <ctime>
13 #include <sstream>
14 
15 using namespace soci;
16 using namespace soci::details;
17 
18 #ifdef _MSC_VER
19 #pragma warning(disable:4996)
20 #define snprintf _snprintf
21 #endif
22 
23 
25  SQLLEN &size, SQLSMALLINT &sqlType, SQLSMALLINT &cType)
26 {
27  switch (type_)
28  {
29  // simple cases
30  case x_short:
31  sqlType = SQL_SMALLINT;
32  cType = SQL_C_SSHORT;
33  size = sizeof(short);
34  break;
35  case x_integer:
36  sqlType = SQL_INTEGER;
37  cType = SQL_C_SLONG;
38  size = sizeof(int);
39  break;
40  case x_long_long:
41  if (use_string_for_bigint())
42  {
43  sqlType = SQL_NUMERIC;
44  cType = SQL_C_CHAR;
45  size = max_bigint_length;
46  buf_ = new char[size];
47  snprintf(buf_, size, "%" LL_FMT_FLAGS "d",
48  *static_cast<long long *>(data_));
49  indHolder_ = SQL_NTS;
50  }
51  else // Normal case, use ODBC support.
52  {
53  sqlType = SQL_BIGINT;
54  cType = SQL_C_SBIGINT;
55  size = sizeof(long long);
56  }
57  break;
59  if (use_string_for_bigint())
60  {
61  sqlType = SQL_NUMERIC;
62  cType = SQL_C_CHAR;
63  size = max_bigint_length;
64  buf_ = new char[size];
65  snprintf(buf_, size, "%" LL_FMT_FLAGS "u",
66  *static_cast<unsigned long long *>(data_));
67  indHolder_ = SQL_NTS;
68  }
69  else // Normal case, use ODBC support.
70  {
71  sqlType = SQL_BIGINT;
72  cType = SQL_C_UBIGINT;
73  size = sizeof(unsigned long long);
74  }
75  break;
76  case x_double:
77  sqlType = SQL_DOUBLE;
78  cType = SQL_C_DOUBLE;
79  size = sizeof(double);
80  break;
81 
82  case x_char:
83  sqlType = SQL_CHAR;
84  cType = SQL_C_CHAR;
85  size = 2;
86  buf_ = new char[size];
87  buf_[0] = *static_cast<char*>(data_);
88  buf_[1] = '\0';
89  indHolder_ = SQL_NTS;
90  break;
91  case x_stdstring:
92  {
93  std::string* s = static_cast<std::string*>(data_);
94  sqlType = SQL_VARCHAR;
95  cType = SQL_C_CHAR;
96  size = s->size();
97  buf_ = new char[size+1];
98  memcpy(buf_, s->c_str(), size);
99  buf_[size++] = '\0';
100  indHolder_ = SQL_NTS;
101  }
102  break;
103  case x_stdtm:
104  {
105  std::tm *t = static_cast<std::tm *>(data_);
106 
107  sqlType = SQL_TIMESTAMP;
108  cType = SQL_C_TIMESTAMP;
109  buf_ = new char[sizeof(TIMESTAMP_STRUCT)];
110  size = 19; // This number is not the size in bytes, but the number
111  // of characters in the date if it was written out
112  // yyyy-mm-dd hh:mm:ss
113 
114  TIMESTAMP_STRUCT * ts = reinterpret_cast<TIMESTAMP_STRUCT*>(buf_);
115 
116  ts->year = static_cast<SQLSMALLINT>(t->tm_year + 1900);
117  ts->month = static_cast<SQLUSMALLINT>(t->tm_mon + 1);
118  ts->day = static_cast<SQLUSMALLINT>(t->tm_mday);
119  ts->hour = static_cast<SQLUSMALLINT>(t->tm_hour);
120  ts->minute = static_cast<SQLUSMALLINT>(t->tm_min);
121  ts->second = static_cast<SQLUSMALLINT>(t->tm_sec);
122  ts->fraction = 0;
123  }
124  break;
125 
126  case x_blob:
127  {
128 // sqlType = SQL_VARBINARY;
129 // cType = SQL_C_BINARY;
130 
131 // BLOB *b = static_cast<BLOB *>(data);
132 
133 // odbc_blob_backend *bbe
134 // = static_cast<odbc_blob_backend *>(b->getBackEnd());
135 
136 // size = 0;
137 // indHolder_ = size;
138  //TODO data = &bbe->lobp_;
139  }
140  break;
141  case x_statement:
142  case x_rowid:
143  // Unsupported data types.
144  return NULL;
145  }
146 
147  // Return either the pointer to C++ data itself or the buffer that we
148  // allocated, if any.
149  return buf_ ? buf_ : data_;
150 }
151 
153  int &position, void *data, exchange_type type, bool /* readOnly */)
154 {
155  if (statement_.boundByName_)
156  {
157  throw soci_error(
158  "Binding for use elements must be either by position or by name.");
159  }
160 
161  position_ = position++;
162  data_ = data;
163  type_ = type;
164 
165  statement_.boundByPos_ = true;
166 }
167 
169  std::string const &name, void *data, exchange_type type, bool /* readOnly */)
170 {
171  if (statement_.boundByPos_)
172  {
173  throw soci_error(
174  "Binding for use elements must be either by position or by name.");
175  }
176 
177  int position = -1;
178  int count = 1;
179 
180  for (std::vector<std::string>::iterator it = statement_.names_.begin();
181  it != statement_.names_.end(); ++it)
182  {
183  if (*it == name)
184  {
185  position = count;
186  break;
187  }
188  count++;
189  }
190 
191  if (position == -1)
192  {
193  std::ostringstream ss;
194  ss << "Unable to find name '" << name << "' to bind to";
195  throw soci_error(ss.str().c_str());
196  }
197 
198  position_ = position;
199  data_ = data;
200  type_ = type;
201 
202  statement_.boundByName_ = true;
203 }
204 
206 {
207  // first deal with data
208  SQLSMALLINT sqlType;
209  SQLSMALLINT cType;
210  SQLLEN size;
211 
212  void* const sqlData = prepare_for_bind(size, sqlType, cType);
213 
214  SQLRETURN rc = SQLBindParameter(statement_.hstmt_,
215  static_cast<SQLUSMALLINT>(position_),
216  SQL_PARAM_INPUT,
217  cType, sqlType, size, 0,
218  sqlData, 0, &indHolder_);
219 
220  if (is_odbc_error(rc))
221  {
222  throw odbc_soci_error(SQL_HANDLE_STMT, statement_.hstmt_,
223  "Binding");
224  }
225 
226  // then handle indicators
227  if (ind != NULL && *ind == i_null)
228  {
229  indHolder_ = SQL_NULL_DATA; // null
230  }
231 }
232 
234 {
235  if (ind != NULL)
236  {
237  if (gotData)
238  {
239  if (indHolder_ == 0)
240  {
241  *ind = i_ok;
242  }
243  else if (indHolder_ == SQL_NULL_DATA)
244  {
245  *ind = i_null;
246  }
247  else
248  {
249  *ind = i_truncated;
250  }
251  }
252  }
253 }
254 
256 {
257  if (buf_ != NULL)
258  {
259  delete [] buf_;
260  buf_ = NULL;
261  }
262 }
virtual void bind_by_name(std::string const &name, void *data, details::exchange_type type, bool readOnly)
virtual void bind_by_pos(int &position, void *data, details::exchange_type type, bool readOnly)
void * prepare_for_bind(SQLLEN &size, SQLSMALLINT &sqlType, SQLSMALLINT &cType)
bool is_odbc_error(SQLRETURN rc)
Definition: soci-odbc.h:399
virtual void pre_use(indicator const *ind)
virtual void post_use(bool gotData, indicator *ind)
#define LL_FMT_FLAGS
Definition: soci-platform.h:14


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