backends/db2/statement.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
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 
13 #ifdef _MSC_VER
14 #pragma warning(disable:4355)
15 #endif
16 
17 using namespace soci;
18 using namespace soci::details;
19 
20 
22  : session_(session),hasVectorUseElements(false),use_binding_method_(details::db2::BOUND_BY_NONE)
23 {
24 }
25 
27 {
28  SQLRETURN cliRC = SQL_SUCCESS;
29 
30  cliRC = SQLAllocHandle(SQL_HANDLE_STMT,session_.hDbc,&hStmt);
31  if (cliRC != SQL_SUCCESS) {
32  throw db2_soci_error("Error while allocation statement handle",cliRC);
33  }
34 }
35 
37 {
38  SQLRETURN cliRC = SQL_SUCCESS;
39 
40  cliRC=SQLFreeHandle(SQL_HANDLE_STMT,hStmt);
41  if (cliRC != SQL_SUCCESS) {
42  throw db2_soci_error(db2_soci_error::sqlState("Statement handle clean-up error",SQL_HANDLE_STMT,hStmt),cliRC);
43  }
44 }
45 
46 void db2_statement_backend::prepare(std::string const & query ,
47  statement_type /* eType */)
48 {
49  // rewrite the query by transforming all named parameters into
50  // the markers (:abc -> ?, etc.)
51 
52  enum { normal, in_quotes, in_name } state = normal;
53 
54  std::string name;
55 
56  for (std::string::const_iterator it = query.begin(), end = query.end();
57  it != end; ++it)
58  {
59  switch (state)
60  {
61  case normal:
62  if (*it == '\'')
63  {
64  query_ += *it;
65  state = in_quotes;
66  }
67  else if (*it == ':')
68  {
69  // Check whether this is a cast operator (e.g. 23::float)
70  // and treat it as a special case, not as a named binding
71  const std::string::const_iterator next_it = it + 1;
72  if ((next_it != end) && (*next_it == ':'))
73  {
74  query_ += "::";
75  ++it;
76  }
77  else
78  {
79  state = in_name;
80  }
81  }
82  else // regular character, stay in the same state
83  {
84  query_ += *it;
85  }
86  break;
87  case in_quotes:
88  if (*it == '\'')
89  {
90  query_ += *it;
91  state = normal;
92  }
93  else // regular quoted character
94  {
95  query_ += *it;
96  }
97  break;
98  case in_name:
99  if (std::isalnum(*it) || *it == '_')
100  {
101  name += *it;
102  }
103  else // end of name
104  {
105  names.push_back(name);
106  name.clear();
107  std::ostringstream ss;
108  ss << '?';
109  query_ += ss.str();
110  query_ += *it;
111  state = normal;
112 
113  }
114  break;
115  }
116  }
117 
118  if (state == in_name)
119  {
120  names.push_back(name);
121  std::ostringstream ss;
122  ss << '?';
123  query_ += ss.str();
124  }
125 
126  SQLRETURN cliRC = SQLPrepare(hStmt, const_cast<SQLCHAR *>((const SQLCHAR *) query_.c_str()), SQL_NTS);
127  if (cliRC!=SQL_SUCCESS) {
128  throw db2_soci_error("Error while preparing query",cliRC);
129  }
130 }
131 
134 {
135  SQLUINTEGER rows_processed = 0;
136  SQLRETURN cliRC;
137 
139  {
140  SQLSetStmtAttr(hStmt, SQL_ATTR_PARAMS_PROCESSED_PTR, &rows_processed, 0);
141  }
142 
143  // if we are called twice for the same statement we need to close the open
144  // cursor or an "invalid cursor state" error will occur on execute
145  cliRC = SQLFreeStmt(hStmt,SQL_CLOSE);
146  if (cliRC != SQL_SUCCESS)
147  {
148  throw db2_soci_error(db2_soci_error::sqlState("Statement execution error",SQL_HANDLE_STMT,hStmt),cliRC);
149  }
150 
151  cliRC = SQLExecute(hStmt);
152  if (cliRC != SQL_SUCCESS && cliRC != SQL_SUCCESS_WITH_INFO)
153  {
154  throw db2_soci_error(db2_soci_error::sqlState("Statement execution error",SQL_HANDLE_STMT,hStmt),cliRC);
155  }
156 
157  SQLSMALLINT colCount;
158  SQLNumResultCols(hStmt, &colCount);
159 
160  if (number > 0 && colCount > 0)
161  {
162  return fetch(number);
163  }
164 
165  return ef_success;
166 }
167 
170 {
171  numRowsFetched = 0;
172 
173  SQLSetStmtAttr(hStmt, SQL_ATTR_ROW_BIND_TYPE, SQL_BIND_BY_COLUMN, 0);
174  SQLSetStmtAttr(hStmt, SQL_ATTR_ROW_ARRAY_SIZE, (SQLPOINTER)number, 0);
175  SQLSetStmtAttr(hStmt, SQL_ATTR_ROWS_FETCHED_PTR, &numRowsFetched, 0);
176 
177  SQLRETURN cliRC = SQLFetch(hStmt);
178 
179  if (SQL_NO_DATA == cliRC)
180  {
181  return ef_no_data;
182  }
183 
184  if (cliRC != SQL_SUCCESS && cliRC != SQL_SUCCESS_WITH_INFO)
185  {
186  throw db2_soci_error(db2_soci_error::sqlState("Error while fetching data", SQL_HANDLE_STMT, hStmt), cliRC);
187  }
188 
189  return ef_success;
190 }
191 
193 {
194  SQLLEN rows;
195 
196  SQLRETURN cliRC = SQLRowCount(hStmt, &rows);
197  if (cliRC != SQL_SUCCESS && cliRC != SQL_SUCCESS_WITH_INFO)
198  {
199  throw db2_soci_error(db2_soci_error::sqlState("Error while getting affected row count", SQL_HANDLE_STMT, hStmt), cliRC);
200  }
201  else if (rows == -1)
202  {
203  throw soci_error("Error getting affected row count: statement did not perform an update, insert, delete, or merge");
204  }
205 
206  return rows;
207 }
208 
210 {
211  return numRowsFetched;
212 }
213 
215  std::string const &query)
216 {
217  return query;
218 }
219 
221 {
222  SQLSMALLINT numCols;
223  SQLNumResultCols(hStmt, &numCols);
224  return numCols;
225 }
226 
228  data_type & type, std::string & columnName )
229 {
230 SQLCHAR colNameBuffer[2048];
231  SQLSMALLINT colNameBufferOverflow;
232  SQLSMALLINT dataType;
233  SQLULEN colSize;
234  SQLSMALLINT decDigits;
235  SQLSMALLINT isNullable;
236 
237  SQLRETURN cliRC = SQLDescribeCol(hStmt, static_cast<SQLUSMALLINT>(colNum),
238  colNameBuffer, 2048,
239  &colNameBufferOverflow, &dataType,
240  &colSize, &decDigits, &isNullable);
241 
242  if (cliRC != SQL_SUCCESS)
243  {
244  throw db2_soci_error(db2_soci_error::sqlState("Error while describing column",SQL_HANDLE_STMT,hStmt),cliRC);
245  }
246 
247  char const *name = reinterpret_cast<char const *>(colNameBuffer);
248  columnName.assign(name, std::strlen(name));
249 
250  switch (dataType)
251  {
252  case SQL_TYPE_DATE:
253  case SQL_TYPE_TIME:
254  case SQL_TYPE_TIMESTAMP:
255  type = dt_date;
256  break;
257  case SQL_DOUBLE:
258  case SQL_DECIMAL:
259  case SQL_REAL:
260  case SQL_FLOAT:
261  case SQL_NUMERIC:
262  type = dt_double;
263  break;
264  case SQL_TINYINT:
265  case SQL_SMALLINT:
266  case SQL_INTEGER:
267  type = dt_integer;
268  break;
269  case SQL_BIGINT:
270  type = dt_long_long;
271  break;
272  case SQL_CHAR:
273  case SQL_VARCHAR:
274  case SQL_LONGVARCHAR:
275  default:
276  type = dt_string;
277  break;
278  }
279 }
280 
282  SQLCHAR colNameBuffer[2048];
283  SQLSMALLINT colNameBufferOverflow;
284  SQLSMALLINT dataType;
285  SQLULEN colSize;
286  SQLSMALLINT decDigits;
287  SQLSMALLINT isNullable;
288 
289  SQLRETURN cliRC = SQLDescribeCol(hStmt, static_cast<SQLUSMALLINT>(col),
290  colNameBuffer, 2048,
291  &colNameBufferOverflow, &dataType,
292  &colSize, &decDigits, &isNullable);
293 
294  if (cliRC != SQL_SUCCESS)
295  {
296  throw db2_soci_error(db2_soci_error::sqlState("Error while detecting column size",SQL_HANDLE_STMT,hStmt),cliRC);
297  }
298 
299  return colSize;
300 }
301 
303 {
304  return new db2_standard_into_type_backend(*this);
305 }
306 
308 {
309  return new db2_standard_use_type_backend(*this);
310 }
311 
314 {
315  return new db2_vector_into_type_backend(*this);
316 }
317 
319 {
320  hasVectorUseElements = true;
321  return new db2_vector_use_type_backend(*this);
322 }
void prepare(std::string const &query, details::statement_type eType)
exec_fetch_result fetch(int number)
db2_session_backend & session_
Definition: soci-db2.h:199
db2_vector_into_type_backend * make_vector_into_type_backend()
void describe_column(int colNum, data_type &dtype, std::string &columnName)
static const std::string sqlState(std::string const &msg, const SQLSMALLINT htype, const SQLHANDLE hndl)
db2_vector_use_type_backend * make_vector_use_type_backend()
std::string rewrite_for_procedure_call(std::string const &query)
db2_statement_backend(db2_session_backend &session)
db2_standard_into_type_backend * make_into_type_backend()
exec_fetch_result execute(int number)
SQLUINTEGER numRowsFetched
Definition: soci-db2.h:205
std::vector< std::string > names
Definition: soci-db2.h:203
SOCI_DB2_DECL db2_backend_factory const db2
Definition: db2/factory.cpp:24
db2_standard_use_type_backend * make_use_type_backend()


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