sqlite3/standard-use-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 #include "soci-sqlite3.h"
9 #include <soci-platform.h>
10 #include "rowid.h"
11 #include "blob.h"
12 // std
13 #include <cstdio>
14 #include <cstdlib>
15 #include <cstring>
16 #include <ctime>
17 #include <limits>
18 #include <sstream>
19 #include <string>
20 
21 #ifdef _MSC_VER
22 #pragma warning(disable:4355 4996)
23 #define snprintf _snprintf // TODO: use soci-platform.h
24 #endif
25 
26 using namespace soci;
27 using namespace soci::details;
28 
29 void sqlite3_standard_use_type_backend::bind_by_pos(int& position, void* data,
30  exchange_type type, bool /*readOnly*/)
31 {
32  if (statement_.boundByName_)
33  {
34  throw soci_error(
35  "Binding for use elements must be either by position or by name.");
36  }
37 
38  data_ = data;
39  type_ = type;
40  position_ = position++;
41 
42  statement_.boundByPos_ = true;
43 }
44 
46  void* data, exchange_type type, bool /*readOnly*/)
47 {
48  if (statement_.boundByPos_)
49  {
50  throw soci_error(
51  "Binding for use elements must be either by position or by name.");
52  }
53 
54  data_ = data;
55  type_ = type;
56  name_ = ":" + name;
57 
58  statement_.reset_if_needed();
59  position_ = sqlite3_bind_parameter_index(statement_.stmt_, name_.c_str());
60 
61  if (0 == position_)
62  {
63  std::ostringstream ss;
64  ss << "Cannot bind to (by name) " << name_;
65  throw soci_error(ss.str());
66  }
67  statement_.boundByName_ = true;
68 }
69 
71 {
72  statement_.useData_.resize(1);
73  int const pos = position_ - 1;
74 
75  if (statement_.useData_[0].size() < static_cast<std::size_t>(position_))
76  {
77  statement_.useData_[0].resize(position_);
78  }
79 
80  if (ind != NULL && *ind == i_null)
81  {
82  statement_.useData_[0][pos].isNull_ = true;
83  statement_.useData_[0][pos].data_ = "";
84  statement_.useData_[0][pos].blobBuf_ = 0;
85  statement_.useData_[0][pos].blobSize_ = 0;
86  }
87  else
88  {
89  // allocate and fill the buffer with text-formatted client data
90  switch (type_)
91  {
92  case x_char:
93  {
94  buf_ = new char[2];
95  buf_[0] = *static_cast<char*>(data_);
96  buf_[1] = '\0';
97  }
98  break;
99  case x_stdstring:
100  {
101  std::string *s = static_cast<std::string *>(data_);
102  buf_ = new char[s->size() + 1];
103  std::strcpy(buf_, s->c_str());
104  }
105  break;
106  case x_short:
107  {
108  std::size_t const bufSize
109  = std::numeric_limits<short>::digits10 + 3;
110  buf_ = new char[bufSize];
111  snprintf(buf_, bufSize, "%d",
112  static_cast<int>(*static_cast<short*>(data_)));
113  }
114  break;
115  case x_integer:
116  {
117  std::size_t const bufSize
118  = std::numeric_limits<int>::digits10 + 3;
119  buf_ = new char[bufSize];
120  snprintf(buf_, bufSize, "%d",
121  *static_cast<int*>(data_));
122  }
123  break;
124  case x_long_long:
125  {
126  std::size_t const bufSize
127  = std::numeric_limits<long long>::digits10 + 3;
128  buf_ = new char[bufSize];
129  snprintf(buf_, bufSize, "%" LL_FMT_FLAGS "d",
130  *static_cast<long long *>(data_));
131  }
132  break;
134  {
135  std::size_t const bufSize
136  = std::numeric_limits<unsigned long long>::digits10 + 2;
137  buf_ = new char[bufSize];
138  snprintf(buf_, bufSize, "%" LL_FMT_FLAGS "u",
139  *static_cast<unsigned long long *>(data_));
140  }
141  break;
142  case x_double:
143  {
144  // no need to overengineer it (KISS)...
145 
146  std::size_t const bufSize = 100;
147  buf_ = new char[bufSize];
148 
149  snprintf(buf_, bufSize, "%.20g",
150  *static_cast<double*>(data_));
151  }
152  break;
153  case x_stdtm:
154  {
155  std::size_t const bufSize = 20;
156  buf_ = new char[bufSize];
157 
158  std::tm *t = static_cast<std::tm *>(data_);
159  snprintf(buf_, bufSize, "%d-%02d-%02d %02d:%02d:%02d",
160  t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
161  t->tm_hour, t->tm_min, t->tm_sec);
162  }
163  break;
164  case x_rowid:
165  {
166  // RowID is internally identical to unsigned long
167 
168  rowid *rid = static_cast<rowid *>(data_);
169  sqlite3_rowid_backend *rbe =
170 static_cast<sqlite3_rowid_backend *>(rid->get_backend());
171 
172  std::size_t const bufSize
173  = std::numeric_limits<unsigned long>::digits10 + 2;
174  buf_ = new char[bufSize];
175 
176  snprintf(buf_, bufSize, "%lu", rbe->value_);
177  }
178  break;
179  case x_blob:
180  {
181  blob *b = static_cast<blob *>(data_);
182  sqlite3_blob_backend *bbe =
183  static_cast<sqlite3_blob_backend *>(b->get_backend());
184 
185  std::size_t len = bbe->get_len();
186  buf_ = new char[len];
187  bbe->read(0, buf_, len);
188  statement_.useData_[0][pos].blobBuf_ = buf_;
189  statement_.useData_[0][pos].blobSize_ = len;
190  }
191  break;
192  default:
193  throw soci_error("Use element used with non-supported type.");
194  }
195 
196  statement_.useData_[0][pos].isNull_ = false;
197  if (type_ != x_blob)
198  {
199  statement_.useData_[0][pos].blobBuf_ = 0;
200  statement_.useData_[0][pos].blobSize_ = 0;
201  statement_.useData_[0][pos].data_ = buf_;
202  }
203  }
204 }
205 
207  bool /* gotData */, indicator * /* ind */)
208 {
209  // TODO: Is it possible to have the bound element being overwritten
210  // by the database?
211  // If not, then nothing to do here, please remove this comment.
212  // If yes, then use the value of the readOnly parameter:
213  // - true: the given object should not be modified and the backend
214  // should detect if the modification was performed on the
215  // isolated buffer and throw an exception if the buffer was modified
216  // (this indicates logic error, because the user used const object
217  // and executed a query that attempted to modified it)
218  // - false: the modification should be propagated to the given object.
219  // ...
220 
221  // clean up the working buffer, it might be allocated anew in
222  // the next run of preUse
223  clean_up();
224 }
225 
227 {
228  if (buf_ != NULL)
229  {
230  delete [] buf_;
231  buf_ = NULL;
232  }
233 }
virtual void bind_by_pos(int &position, void *data, details::exchange_type type, bool readOnly)
details::rowid_backend * get_backend()
Definition: rowid.h:33
virtual void bind_by_name(std::string const &name, void *data, details::exchange_type type, bool readOnly)
virtual std::size_t read(std::size_t offset, char *buf, std::size_t toRead)
virtual void pre_use(indicator const *ind)
details::blob_backend * get_backend()
Definition: blob.h:39
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